Текст
                    100%
: > Г г—> Т* И * «.ui—
ИСЧЕРПЫ ВАЮЩЕ
ДОСТОВЕРНО
ТО, ЧТО НУЖНО
function toHex(dec) {
hex harf±= "(П2341WABCDEF'
Л11II UWII
концепции JavaScript
и объектной модели
с помощью приложения
The Evaluator,
специально
разработанного для
этих целей

Пор«а ut
пользователей
возможностями,
предоставляемыми
новыми Web-
технологиями, добавив
на страницы
специальные эффекты
и интерактивные
элементы
сценарии для
последних версий
современных
браузеров
1энни Гудман, Майкл Моррисон
Предисловие Брендана Эйха, разработчика JavaScript
На
прилагаемом
компактдиске:
•	22 дополнительные главы на
русском языке
•	более 300 готовых примеров
• девять полноценных приложений,
написанных на JavaScript
,ж nexuwrs.
’	||«|lll| | I I 'PHll|l|l| I |.<h nil
1...........и i
return result
IMf 1
.......нН 1ш4гм|||< Г)
-П|Ш| t Vol' I	11 n| t|
H..,.-..	.'hl Illi |
. II I i V
Scrint

JavaScript' Библия пользователя 5-е издание Дэнни Гудман, Майкл Моррисон Предисловие Брендана Эйха, создателя JavaScript ИдцдлЕктикд Москва ♦ Санкт-Петербург ♦ Киев 2006
ББК 32.973.26-018.2.75 Г93 УДК 681.3.07 Компьютерное издательство “Диалектика” . Главный редактор С.Н. Тригуб Зав. редакцией В.Р. Гинзбург Перевод с английского и редакция И.В. Василенко По общим вопросам обращайтесь в издательство “Диалектика” по адресу: info@dialektika.com, http://www.dialektika.com 115419, Москва, а/я 783; 03150, Киев, а/я 152 Гудман, Дэнни, Моррисон, Майкл. Г93 JavaScript. Библия пользователя, 5-е издание. : Пер. с англ. — М. : ООО “И.Д. Ви- льямс”, 2006. — 1184 с. : ил. — Парал. тит. англ. ISBN 5-8459-1027-7 (рус.) Эта книга адресована широкому кругу читателей Web-дизайнеров, которые ре- шили детально изучить язык JavaScript. Она имеет все шансы завоевать титул пол- ного справочного руководства по JavaScript не только в глазах его разработчиков, но и в сердцах пользователей. В издании подробно описаны практически все сред- ства разработки сценариев JavaScript, используемые в современных и уже устарев- ших браузерах. Изложение материала начинается с истории и особенностей языка JavaScript и заканчивается описанием сложных приложений, используемых для ре- шения таких задач, как создание формы заказа, обработка XML-данных и др. Осо- бое внимание в книге уделено созданию межбраузерных сценариев, которые мак- симально эффективно выполняются в подавляющем большинстве используемых в настоящее время браузеров. На прилагаемом к книге компакт-диске предоставлены дополнительные 22 гла- вы на русском языке, все листинги, описанные в книге, некоторые вспомога- тельные материалы и программы, которые помогут читателю изучить сложные те- мы и практические примеры. ББК 32.973.26-018.2.75 Все названия программных продуктов являются зарегистрированными торговыми марками соответствующих фирм. Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в ка- кой бы то ни было форме и какими бы то ни было средствами, будь то электронные или ме- ханические, включая фотокопирование и запись на магнитный носитель, если на это нет письменного разрешения издательства JOHN WILEY&Sons, Inc. Copyright © 2006 by Dialektika Computer Publishing. Original English language edition Copyright © 2004 by Danny Goodman. All rights reserved including the right of reproduction in whole or in part in any form. This translation is published by arrangement with Wiley Publishing, Inc. ISBN 5-8459-1027-7 (pyc.) ISBN 0-7645-5743-2 (англ.) © Компьютерное изд-во “Диалектика”, 2006, перевод, оформление, макетирование © Danny Goodman, 2004
Оглавление Предисловие 24 Введение 27 ЧАСТЬ I. ЗНАКОМСТВО С JAVASCRIPT 35 ГЛАВА 1. Роль JavaScript в World Wide Web 36 ГЛАВА 2. Творческие изыскания в сложных полевых условиях 44 ГЛАВА 3. Первый собственный сценарий 52 ЧАСТЬ II. РУКОВОДСТВО ПО JAVASCRIPT 61 ГЛАВА 4. Объекты документа и браузера 62 ГЛАВА 5. Сценарии и документы HTML 83 ГЛАВА 6. Основы программирования. Часть 1 94 ГЛАВА 7. Основы программирования. Часть 2 105 ГЛАВА 8. Объекты документа и окна 118 ГЛАВА 9. Формы и их элементы 131 ГЛАВА 10. Строки, математические выражения и даты 145 ГЛАВА 11. Работа с окнами и фреймами 155 ГЛАВА 12. Изображения и динамический HTML 165 ЧАСТЬ III. ОБЪЕКТЫ ДОКУМЕНТА * 175 ГЛАВА 13. Основы JavaScript 176 ГЛАВА 14. Основы объектной модели документа 196 ГЛАВА 15. Основные объекты HTML-элементов 235 ГЛАВА 16. Объекты window и frame 392 ГЛАВА 17. Объекты history и location 512 ГЛАВА 18. Объекты document и body 535 ГЛАВА 19. Объекты ссылки и анкера 613 ГЛАВА 20. Объекты изображения, области и карты изображений 622 ГЛАВА 21. Объект form и вложенные в него объекты 650 ГЛАВА 22. Объект кнопки 671 ГЛАВА 23. Текстовые объекты формы 692 ГЛАВА 24. Объекты select, option и fileupload 713
ГЛАВА 25. Объекты событий 737 ГЛАВА 26. Таблица стилей и объекты стилей 810 ЧАСТЬ IV. ОБЪЕКТЫ ЯЗЫКА JAVASCRIPT 867 ГЛАВА 27. Объект string 868 ГЛАВА 28. Объекты Math, Number и Boolean 895 ГЛАВА 29. Объект Date 908 ГЛАВА 30. Объект Array 924 ГЛАВА 31. Управляющие структуры и обработка исключительных ситуаций 945 ГЛАВА 32. Операторы JavaScript 975 ГЛАВА 33. Функции и пользовательские объекты 996 ГЛАВА 34. Глобальные функции и выражения 1024 ГЛАВА 35. Текстовые объекты тела страницы 1039 ЧАСТЬ V. ПРИЛОЖЕНИЯ 1121 ПРИЛОЖЕНИЕ А. Справочник по объектам браузера и JavaScript 1122 ПРИЛОЖЕНИЕ Б. Зарезервированные слова JavaScript 1135 ПРИЛОЖЕНИЕ В. Ответы к упражнениям 1136 ПРИЛОЖЕНИЕ Г. Internet-ресурсы, посвященные JavaScript и DOM 1150 ПРИЛОЖЕНИЕ Д. Содержимое компакт-диска 1153 ЧАСТЬ VI. ДОПОЛНИТЕЛЬНЫЕ ГЛАВЫ НА КОМПАКТ-ДИСКЕ 1157 Предметный указатель 1159 6 Оглавление
Содержание Об авторах Предисловие Введение Структура и особенности этого издания Благодарности Ждем ваших отзывов! 23 24 27 27 33 34 ЧАСТЬ 1. ЗНАКОМСТВО С JAVASCRIPT 35 ГЛАВА 1. Роль JavaScript в World Wide Web Конкуренция в Web Другие Web-технологии Что такое HTML Серверные сценарии Вспомогательные приложения и надстройки JavaScript: язык для всех Как LiveScript стал JavaScript В мире Microsoft JavaScript: правильное средство для правильной работы ГЛАВА 2. Творческие изыскания в сложных полевых условиях Полная неразбериха Тенденции Проблема совместимости сегодня Базовый язык и объекты Стандарт базового языка Объектная модель документа Каскадные таблицы стилей Динамический HTML Создание межбраузерных сценариев ГЛАВА 3. Первый собственный сценарий Программное обеспечение Выбор текстового редактора Выбор браузера Настройка среды разработки Система Windows Система MacOS X Особенности перезагрузки Что будет делать первый сценарий 36 37 37 38 38 39 40 41 41 42 44 45 46 46 46 47 48 49 50 50 52 52 52 53 53 54 55 55 56
Создание первого сценария - 56 Исследование сценария 58 Дескриптор <script> 58 Сценарий для всех браузеров 58 Отображение текста 59 Улыбнемся вместе 60 ЧАСТЬ II. РУКОВОДСТВО ПО JAVASCRIPT 61 ГЛАВА 4. Объекты документа и браузера 62 Сценарии, которые творят чудеса 62 JavaScript в действии 63 Интерактивный интерфейс 63 Поиск данных 64 Проверка правильности введенных данных 65 Интерактивные данные 65 Многофреймовые документы 66 Динамический HTML 67 Принципы использования JavaScript 68 Объектная модель документа 69 Структура HTML и DOM 70 Объектная модель окна документа 71 Загрузка документа 72 Простой документ 72 Добавление элемента абзаца 72 Добавление в абзац текста 73 Создание нового элемента 74 Связывание объектов 74 Именование объектов 75 Ссылка на объект 75 Терминология, используемая при управлении узлами 76 Что такое узел 76 Отцы и дети 76 Понятия, определяющие объект 77 Свойства 78 Методы 79 Обработчики событий 80 Упражнения 81 ГЛАВА 5. Сценарии и документы HTML 83 Размещение сценариев в документах 83 Дескрипторы сценария <script> 83 Размещение дескрипторов 84 Особенности использования старых браузеров 86 Операторы JavaScript 87 Выполнение операторов сценария 87 Немедленное выполнение операторов в процессе загрузки документа 88 Отсроченные сценарии 88 Просмотр ошибок сценария 90 8 Содержание
Различие между написанием сценариев и программированием 91 Упражнения 92 ГЛАВА б. Основы программирования. Часть 1 94 Язык программирования 94 Способы управления информацией 95 Переменные 95 Создание переменной 96 Названия переменных 97 Выражения и их вычисление 97 Выражения в сценарии scriptl.htm 98 Выражения и переменные < 99 Преобразование типов данных 100 Преобразование строк в числа 101 Преобразование чисел в строки 101 Операторы 102 Арифметические операторы 102 Операторы сравнения 102 Упражнения ЮЗ ГЛАВА 7. Основы программирования. Часть 2 105 Решения и циклы 105 Управляющие структуры 106 Условный оператор if 106 Условный оператор if...else 107 Циклы Ю8 Функции Ю9 Параметры функций 109 Диапазон действия переменных 110 Использование фигурных скобок 112 Массивы ИЗ Создание массива 113 Получение доступа к данным массива 114 Параллельные массивы 114 Объекты документа в массиве 116 Упражнения 117 ГЛАВА 8. Объекты документа и окна 118 Объекты окна документа 118 Объект окна 118 Получение доступа к свойствам и методам окна 119 Создание окна 120 Свойства и методы окна 121 Свойство window.status 122 Метод window.alert() 122 Метод window.confirm() 123 Метод window.prompt() 123 Обработчик события onload 124 Объект location 124 Объект navigator 125 Содержание 9
Объект документа 125 Свойство documentforms[] 126 Свойство document.images[] 126 Метод document. write() 127 Методы document.createElement() и document.createNode() 129 Метод document.getElementBy!d() 129 Упражнения 130 ГЛАВА 9. Формы и их элементы 131 Объект form 131 Форма как объект и контейнер 132 Доступ к свойствам формы 132 Свойство form.elements[] 133 Элементы формы — это тоже объекты 133 Текстовые объекты 134 Объект кнопки 136 Объект флажка 136 Объект переключателя 137 Объект элемента select 139 Передача функциям данных форм н элементов 140 Отправка данных форм и проверка их правильности 142 Упражнения 144 ГЛАВА 10. Строки, математические выражения и даты 145 Объекты базового языка 145 Строковые объекты 146 Объединение строк 146 Методы строковых объектов 147 Объект Math 149 Объект Date 150 Определение даты 152 Упражнения 153 ГЛАВА 11. Работа с окнами и фреймами 155 Окна: отцы и дети 155 Ссылки на другие объекты 157 Ссылки из родительского фрейма на дочерний 157 Ссылки из дочернего фрейма на родительское окно 157 Ссылка из дочернего фрейма на дочерний фрейм 158 Полезные советы 158 Элемент iffame 159 Способы управления многофреймовыми документами 159 Дополнительные сведения о ссылках 162 Упражнения 163 ГЛАВА 12. Изображения и динамический HTML 165 Объект изображения 165 Изменяемые изображения 166 Предварительная загрузка изображений 166 Создание ролловеров 168 Оператор j avascript: псевдо-URL 171 10 Содержание
Больше динамизма в HTML 172 Изменение настроек таблицы стилен 172 Динамическое содержимое узлов W3C DOM 173 Свойство innerHTML 173 Упражнения 174 ЧАСТЬ III. ОБЪЕКТЫ ДОКУМЕНТА 175 ГЛАВА 13. Основы JavaScript 176 Версии JavaScript 176 Стандарт базового языка — ECMAScript 177 Встроенные в HTML-документы сценарии 177 Дескриптор сценария <script> 178 Дескриптор <script foi> 179 Особенности написания кода при работе со старыми типами браузеров 179 Что значит “спрятать” сценарий 180 Библиотеки сценариев (файлы .js) 181 Определение версии браузера 182 Проверка поддержки JavaScript 182 Написание сценариев для разных браузеров 184 Обеспечение совместимости 189 Использование экспериментальных версий браузеров 190 Приложение The Evaluator Sr. 191 Принципы совместимости 192 Особенности языка JavaScript 192 Вперед, к объектным моделям документов! 195 ГЛАВА 14. Основы объектной модели документа 196 Иерархическая структура объектной модели 196 Иерархия и структурная схема объектов 197 Структура объектной модели документа 198 Создание объектов в документе 199 Свойства объектов 199 Методы объекта 200 Обработчики событий объектов 201 Обработчики событий как методы 201 Обработчики событий как свойства 202 Разнообразие объектных моделей 203 Базовая объектная модель 203 Базовая объектная модель, поддерживающая изображения 204 Расширенная модель NN4 205 Модель перехвата событий 205 Объект Layer 206 Расширенная модель IE4+ 207 Объекты элементов HTML 207 Иерархия содержимого элементов 208 Каскадные таблицы стилей < 209 И еще о событиях 210 События и сценарии 211 Расширенная модель IE5+ 211 Содержание 11
Модель W3C DOM 212 Поколения DOM 213 Неизменная часть 213 Недоступные элементы 214 “Новая” практика HTML 214 НовЬте концепции DOM 215 Фактический стандарт: innerHTML 223 Статичные объекты 224 Двунаправленная модель событий 225 Комбинирование объектных моделей 227 Консервативный подход 227 Умеренная концепция 228 Радикальный подход 231 Обработка событий 233 Режимы совместимости стандартов 233 Мы поедем, мы помчимся... 234 ГЛАВА 15. Основные объекты HTML-элементов 235 Общие объекты 236 Синтаксис 238 Описание объектов 238 Свойства 239 Методы 295 Обработчики событий 357 ГЛАВА 16. Объекты window и frame 392 Терминология 392 Фреймы 393 Создание фреймов 393 Объектная модель фрейма 393 Ссылки на фреймы 394 Объект top против объекта parent 395 Предотвращение использования фреймов 395 Проверка загрузки фреймов 396 Включение и отключение фреймов 396 Наследование 396 Синхронизация фреймов 397 Пустые фреймы 397 Просмотр исходного кода фрейма 398 Фреймы и элементы frame 398 Объект window 399 Синтаксис 400 Описание объекта 400 Свойства 402 Методы 435 Обработчики событий 485 Элемент frame 490 Синтаксис 491 Описание объекта 491 Свойства 492 12 Содержание
Элемент frameset 497 Синтаксис 498 Описание объекта 498 Свойства 499 Элемент iframe 503 Синтаксис 503 Описание объекта 504 Свойства 504 Объект popup 508 Синтаксис 508 Описание объекта 508 Свойства 509 Методы 510 ГЛАВА 17. Объекты history и location 512 Объект location 513 Синтаксис 513 Описание объекта 513 Свойства 515 Методы 526 Объект history 529 Синтаксис 529 Описание объекта 529 Свойства 530 Методы 531 ГЛАВА 18. Объекты document и body 535 Объект document 536 Синтаксис 538 Описание объекта 538 Свойства 539 Методы 576 Обработчики событий 599 Элемент body 600 Синтаксис 601 Описание объекта 601 Свойства 602 Методы 607 Обработчики событий 608 Объект treewalker 609 Синтаксис 610 Описание объекта 610 Свойства 611 Методы 611 ГЛАВА 19. Объекты ссылки и анкера 613 Объекты элементов link, anchor и а , 614 Синтаксис 614 Описание объектов 615 Свойства 617 Содержание 13
ГЛАВА 20. Объекты изображения, области и карты изображений 622 Изображения и элементы img 622 Синтаксис 623 Описание объекта 624 Свойства 626 Обработчики событий 641 Объект элемента area 642 Синтаксис 643 Описание объекта 643 Свойства 645 Объект элемента тар 646 Синтаксис 646 Описание объекта 646 Свойства 647 ГЛАВА 21. Объект form и вложенные в него объекты 650 Объект form в объектной модели 650 Элемент form 651 Синтаксис 651 Описание объекта 652 Ссылка на элементы управления формы 652 Передача форм и элементов в функции 653 Отправка форм по электронной почте 656 Изменение атрибутов формы 657 Кнопки на формах 658 Перенаправление данных после отправки 658 Массивы элементов формы 659 Описание объекта элемента input 659 Свойства 660 Методы 664 Обработчики событий 666 Объекты элементов fieldset и legend 668 Синтаксис 668 Описание объектов 668 Объект элемента label 669 Синтаксис 669 Описание объекта 670 Свойства 670 ГЛАВА 22. Объект кнопки 671 Объект элемента button, объекты button, submit и reset 671 Синтаксис 671 Описание объектов 672 Свойства 674 Методы 675 Обработчики события 675 Объект checkbox 677 Синтаксис 677 Описание объекта 677 Свойства 678 14 Содержание
Методы Обработчики события Объект radio Синтаксис Описание объекта Свойства Методы Обработчики события Объект image Синтаксис Описание объекта Свойства 681 681 684 684 684 685 688 689 690 690 691 691 ГЛАВА 23. Текстовые объекты формы Объект text Синтаксис Описание объекта. Текстовые поля и события Свойства Методы Обработчики событий Объект password Синтаксис Описание объекта Скрытый объект input Синтаксис Описание объекта Объект textarea Синтаксис Описание объекта Возврат каретки в текстовых областях Свойства Методы ГЛАВА 24. Объекты select, option и fileupload Объект элемента select Синтаксис Описание объекта Изменение опций объекта select (NN3+, IE4+) Изменение опций объекта select (IE4+) Изменение опций объекта select (W3C DOM) Свойства Методы Обработчики событий Объект элемента option Синтаксис Описание объекта ' Свойства Объект элемента optgroup Синтаксис 692 693 693 693 694 696 702 705 708 708 708 708 708 709 709 710 710 711 712 712 713 713 714 714 716 719 721 722 729 730 731 731 732 732 733 733 Содержание 15
Описание объекта , 733 Свойства 733 Объект элемента ввода файла 735 Синтаксис 735 Описание объекта 736 ГЛАВА 25. Объекты событий 737 Понятие события 738 Свойства событий 738 Статичные объекты событий 739 Передача событий 739 Передача событий в NN4 740 Передача событий в IE4 749 Передача событий в NN6+ 753 Ссылки на объект события 758 Ссылки на объект события в IE4+ 758 Ссылки на объект события в W3C 758 Совместимость объектов event 759 Сравнение моделей событий 761 Межплатформенное определение клавиш-модификаторов 761 Межплатформенное определение клавиш 762 Типы событий 763 Старые версии браузеров 764 Типы событий в IE4+ и NN6+/W3C 765 Объект события в NN4 766 Синтаксис 766 Описание объекта 766 Свойства 766 Объект события в IE4+ 771 Синтаксис 772 Описание объекта 772 Свойства 773 Объект события в NN6+ 790 Синтаксис 791 Описание объекта 791 Свойства 792 Методы 807 ГЛАВА 26. Таблица стилей и объекты стилей 810 Имена объектов 811 Импортированные таблицы стилей 812 Получение свойств стиля 813 Объект элемента style 814 Синтаксис 814 Описание объекта 814 Свойства 814 Объект stylesheet 815 Синтаксис 815 Описание объекта 815 16 Содержание
Свойства 816 Методы 822 Объекты cssrule й rule 824 Синтаксис 824 Описание объектов 824 Свойства 825 Объекты currentstyle, runtimestyle и style 827 Синтаксис 827 Описание объектов 827 Свойства стиля 828 Значения свойств 829 Свойства текста и шрифта 832 Свойства вида и макета документа 839 Свойства позиционирования 844 Свойства фона 846 Свойства границ и полей 847 Свойства списков 851 Свойства полосы прокрутки 852 Свойства таблиц 853 Свойства страницы и печати 854 Дополнительные свойства 855 Акустические свойства 855 Объект фильтра 856 Синтаксис 856 Описание объекта 857 Изменение синтаксиса фильтров в IE5.5 862 ЧАСТЬ IV. ОБЪЕКТЫ ЯЗЫКА JAVASCRIPT 867 ГЛАВА 27. Объект string 868 Типы данных string и number 868 Простые строки 868 Создание длинных строковых переменных 869 Объединение строк и переменных 869 Специальные символы 870 Объект string 871 Синтаксис 872 Описание объекта 872 Свойства 873 Методы синтаксического анализа 875 Функции обработки строковых данных 891 Методы форматирования 892 Кодирование и декодирование строк URL 894 ГЛАВА 28. Объекты Math, Number и Boolean 895 Числа в JavaScript 895 Целые числа и числа с плавающей точкой ’ 896 Шестнадцатеричные и восьмеричные целые числа 897 Преобразование строк в числа 898 Содержание 17
Преобразование чисел в строки 899 Когда число совсем не число 900 Объект Math 900 Синтаксис 900 Описание объекта 900 Свойства 901 Методы 901 Генерирование случайных чисел 902 Сокращенный вариант использования объекта Math 902 Объект Number 903 Синтаксис 903 Описание объекта 904 Свойства 904 Методы 905 Объект Boolean 907 Синтаксис 907 Описание объекта 907 ГЛАВА 29. Объект Date 908 Временные зоны и GMT 908 Объект Date 909 Создание объекта даты 910 Естественные свойства и методы объекта 911 Методы объекта Date 911 Учет временных зон 914 Строковые даты 914 Удобные форматы даты в ранних версиях браузеров 915 Еще раз о преобразованиях 916 Арифметика даты и времени 916 Подсчет дней 917 Ошибки, связанные с управлением датой 920 Проверка дат, вводимых в формы 920 ГЛАВА 30. Объект Array 924 Структурированные данные 924 Создание пустого массива 925 Заполнение массива данными 925 Расширенные возможности создания массивов в JavaScript 926 Удаление элементов массива 927 Параллельные массивы 927 Многомерные массивы 930 Свойства объекта Array 931 Методы объекта Array 932 ГЛАВА 31. Управляющие структуры и обработка исключительных ситуаций 945 Конструкции if и if...else 946 Простые решения 946 Условные выражения 947 Составные решения 947 Вложенные выражения if... else 948 18 Содержание
Условные выражения 950 Циклы повторения операций (for) 951 Использование счетчика цикла 952 Выход из цикла 954 Управление циклом с помощью оператора continue 954 Цикл while 955 Цикл do-while 956 Просмотр свойств (цикл for-in) 957 Оператор with 958 Маркированные операторы 958 Оператор switch 960 Обработка исключительных ситуаций 963 Исключительные ситуации и ошибки 963 Механизм обработки исключительных ситуаций 964 Использование конструкций try-catch-finally 965 Исключительные ситуации на примерах 967 Переход к исключительным ситуациям 968 Объект ошибки 972 Синтаксис 972 Описание объекта 972 Свойства 973 Методы 974 ГЛАВА 32. Операторы JavaScript 975 Категории операторов 975 Операторы сравнения 976 Равенство несоизмеримых типов данных 977 Арифметические операторы 979 Операторы присвоения 981 Булевы операторы 983 Булева математика 983 Применение булевых операторов 985 Побитовые (или поразрядные) операторы 986 Объектные операторы 987 Комплексные операторы 990 Приоритеты операторов 992 ГЛАВА 33. Функции и пользовательские объекты 996 Объект функции 996 Синтаксис 996 Описание объекта 997 Создание функций 997 Вложенные функции 998 Параметры функции 999 Свойства 999 Методы 1002 Замечания по применению функций ' 1004 Вызов функции 1004 Переменные: глобальные и локальные 1005 Переменные параметров 1007 Содержание 19
Рекурсия в функциях 1008 Преобразование функций в библиотеки 1008 Пользовательские объекты 1009 Пример “объектов планет” 1010 Создание массива объектов 1014 Добавление пользовательских методов 1015 Несколько дополнительных способов создания объектов 1016 Определение в объекте получателя и определителя свойства 1017 Применение пользовательских объектов 1019 Концепция объектно-ориентированного программирования 1019 Добавление прототипа 1019 Наследование прототипа 1020 Вложенные объекты и наследование прототипа 1020 Объект Object 1022 Синтаксис 1022 Описание объекта 1022 Методы 1023 ГЛАВА 34. Глобальные функции и выражения 1024 Функции 1025 Выражения 1032 ГЛАВА 35. Текстовые объекты тела страницы 1039 Объекты элементов blockuote и q 1040 Синтаксис 1040 Описание объектов 1040 Свойство 1040 Объект элемента Ьг 1040 Синтаксис 1041 Описание объекта 1041 Свойство 1041 Объект элемента font 1041 Синтаксис 1041 Описание объекта 1042 Свойства z 1042 Объекты элементов hl-h6 1044 Синтаксис 1045 Описание объектов 1045 Свойство 1045 Объект элемента hr 1045 Синтаксис 1046 Описание объектов 1046 Свойства 1046 Объект элемента label 1049 Синтаксис 1049 Описание объекта 1050 Свойства 1050 Объект элемента marquee 1051 Синтаксис 1051 Описание объекта 1051 20 Содержание
Свойства 1051 Методы 1055 Обработчики событий 1055 Объект Range 1056 Синтаксис 1057 Описание объекта 1057 Управление выделениями 1058 Свойства 1059 Методы 1062 Объект selection 1078 Синтаксис 1078 Описание объекта 1078 Свойства 1079 Методы 1081 Объекты Text и TextNode 1084 Синтаксис 1084 Описание объектов 1084 Свойства 1085 Методы 1085 Объект TextRange 1089 Синтаксис 1090 Описание объекта 1090 Управление текстовыми областями 1091 Совместимость с браузерами 1092 Свойства 1093 Методы 1096 Объект TextRectangle 1118 Синтаксис 1 1118 Описание объекта 1118 Свойства 1119 ЧАСТЬ V. ПРИЛОЖЕНИЯ 1121 ПРИЛОЖЕНИЕ А. Справочник по объектам браузера и JavaScript 1122 ПРИЛОЖЕНИЕ Б. Зарезервированные слова JavaScript 1135 ПРИЛОЖЕНИЕ В. Ответы к упражнениям 1136 Глава 4 1136 Глава 5 1137 Глава 6 1139 Глава 7 1139 Глава 8 1143 Глава 9 1144 Глава 10 1147 Глава 11 1148 Глава 12 t 1149 ПРИЛОЖЕНИЕ Г. Internet-ресурсы, посвященные JavaScript и DOM 1150 Узел поддержки и обновлений для книги 1150 Группы новостей 1151 Содержание 21
Наиболее часто задаваемые вопросы (FAQs) 1151 Документация 1151 World Wide Web 1152 ПРИЛОЖЕНИЕ Д. Содержимое компакт-диска 1153 Системные требования 1153 Содержимое диска 1153 Листинги JavaScript для текстовых редакторов 1154 Приложение А (в электронном формате) 1154 Электронная версия книги 1154 Устранение неполадок 1155 ЧАСТЬ VI. ДОПОЛНИТЕЛЬНЫЕ ГЛАВЫ НА КОМПАКТ-ДИСКЕ 1157 Предметный указатель 1159 22 Содержание
Об авторах Дэнни Гудман — автор большого количества широко известных книг. Среди них такие популярные издания, как The Complete HyperCard Handbook, Danny Goodman’s AppleScript Handbook, Dynamic HTML: The Definitive Reference и JavaScript & DHTML Cookbook. Дэнни также является общепризнанным экспертом и высококлассным преподавателем в области языков программирования. Талант писателя и опыт педагога приносят ему постоянные диви- денды со стороны как читателей, так и коллег по всему миру. Чтобы быть постоянно в форме и держать руку на пульсе событий, Дэнни частенько практикует как консультант по програм- мированию и разработке сайтов в паутине World Wide Web и интранет. Делает он это прямо из своей штаб-квартиры в Сан-Франциско. Майкл Моррисон — писатель, разработчик, изобретатель игрушек и автор большого количества книг, посвященных языку Java, Web-сценариям, проектированию игр, ActiveX и карманным ПК. Ему принадлежат такие книги, как Faster Smarter HTML and XML, Teach Yourself XML in 24 Hours и The Complete Idiot’s Guide to Java 2. Майкл также является осно- вателем компании Stalefish Labs (www.stalefishlabs.com), занимающейся разработкой традиционных игр и игрушек.
Предисловие Как создатель JavaScript, я бы хотел сказать несколько слов о том, что такое JavaScript, как появился этот язык и для чего нужен. Книга, которую вы держите в руках, поможет вам освоить новые вершины программирования. JavaScript — это плод неуемного желания предоставить разработчикам HTML-документов средства динамического управления всеми его объектами, которые описывались бы исключи- тельно в коде Web-страницы. Теперь такой подход кажется простым и очевидным, но весной 1995 года эта идея была весьма нестандартная. Она была связанна с серьезными несоответст- виями между принятыми прописными истинами (принципы HTML предписывают создавать только документы со статической структурой) и принципами динамического изменения до- кументов (речь идет об аплетах Java, признанных единственным реальным способом “оживить” и расширить возможности Web-страницы). Раз уж пришлось затронуть подобные вопросы развития среды Internet, то рассмотрим детальнее особенности языка JavaScript. В первую очередь, он имеет облегченный синтаксис языка Java. Синтаксис “натураль- ного языка” HyperTalk представлялся мне вполне приемлемым. Но после того, как один мой хороший знакомый одолжил мне книгу The Complete HyperCard Handbook, написанную Дэнни Гудманом, я все больше стал склоняться к мысли об использова- нии в качестве базиса для нового языка именно Java, особенно в свете бурного его раз- вития. Если разрабатываемый язык синтаксически будет подобен Java, то с точки зре- ния тех программистов, которые переориентируются с одного языка на другой, такое совпадение будет только приветствоваться. Однако обязательность принципа деклари- рования классов и типов Java или использования точки с запятой после каждого опе- ратора в месте окончания строки не вызвала у меня должного восторга. Ведь создание сценариев для большинства пользователей сродни написанию коротких отрывков ко- да — оно должно выполняться быстро и четко. События для HTML-элементов. Кнопки должны управляться обработчиками события onClick. Документы загружаются в окна и выгружаются из них, так что в сценарии должны быть представлены еще и обработчики события onLoad и onUnload. Поль- зователи в сценарии используют различные формы — отсюда вытекает необходимость в обработчике события onSubmit. Хотя в принципе и не обходя по гибкости систему сообщений HyperCard (обработчики последнего ориентированы на использование систе- мы обозначений типа onEvent), события в JavaScript позволяют разработчикам HTML- документов взаимодействовать с пользователями с помощью удаленных серверов и бы- стро реагировать на их действия и операции, выполняемые браузером. С использовани- ем рекомендаций по обработке событий W3C DOM 2 в современных браузерах уда- лось посредством JavaScript полностью реализовать гибкий контроль над событиями. Объекты без классов. Язык программирования Self оправдал идею использования ос- нованного на прототипах принципа наследования. Для JavaScript я хотел использовать один прототип для одного объекта (для большей простоты и надежности), который основывается по умолчанию на функции, вызываемой с помощью оператора new (для
согласованности с Java). Чтобы обойтись без характерных для такой ситуации методов и функций, все функции задают объекты, вызывающие свойства с помощью ключево- го слова this. Хотя свойства активно не использовались вплоть до версии NN3, их прототип уже был заложен во второй версии в виде заключаемого в кавычки текста, который интерпретировался как объект (прототип объекта String, к которому поль- зователь мог присоединять методы). Генерирование HTML-кода. Внедрение JavaScript в HTML способствовало развитию следующей идеи. А что, если HTML-код будет генерироваться в результате загрузки обычного текста (задаваемого в сценарии) в ходе его выполнения? Возможности этого подхода вышли далеко за пределы простого управления датой или временем внесения последних изменений. Эта простая идея позволила создавать сложные программные конструкции, позволяющие отслеживать данные многоуровневой структуры таблиц, где все повторяемые элементы задаются в цикле сценария, в то время как вся инфор- мация, заносимая в таблицы, обрабатывается в JavaScript минимальным набором опе- раторов и сохраняется в файлах каталогов или мини-базах данных. Вначале я полагал, что JavaScript найдет себе применение, прежде всего, в качестве средства ввода данных на HTML-формах. Но через некоторое время был удивлен, узнав, сколько дизай- неров, работающих с Web, используют его в своих проектах и применяют готовые JavaScript- приложения в HTML-документах для решения самых разнообразных задач. Web-дизайнеры давно искали способы быстрого и эффективного создания серьезных приложений с помощью минимального набора простых операторов. О популярности языка можно было судить по от- ветной реакции пользователей. В конечном счете разработчики (а также пользователи) настояли на реализации браузерной поддержки спецификации, известной под названием Dynamic HTML (презабавнейшим образом она описана по адресу: http: / /www. j avascript -games. org/). В то время как армия Web-разработчиков примерялась к возможностям JavaScript, стало яв- ным несомненное преимущество среды создания сценариев над старым программным достоя- нием. Это относится не только к большой относительной простоте языков HTML и JavaScript, но также и к минимальным требованиям к разработчику Web-страниц. Ему не нужно обладать опытом программирования, чтобы управлять изображениями, обрабатывать события и создавать красочные эффекты, что невозможно при создании больших приложений с помощью гро- моздких языков, программируемых традиционным способом. Превосходство JavaScript в Web сегодня подтверждает нашу безоглядную веру в ценность языка создания сценариев для разработчиков HTML-документов. Удерживая на низком уров- не планку “требований”, среда HTML (вместе с JavaScript) сделала дизайнерами миллионы обычных граждан. Позволяя “обрабатывать события”, JavaScript помог тысячам дизайнеров стать настоящими программистами. Гарантом подобности Web-программирования и разра- ботки сложных приложений является браузер Mozilla, в котором все элементы графического интерфейса и даже некоторые специальные элементы, а также программные модули полно- стью управляются средствами JavaScript, каскадных таблиц стилей (CSS), специальных язы- ков, созданных на основе XML. JavaScript является общим языком, применимым даже вне среды HTML и XML. Он поддержи- вается многими серверами, инструментальными средствами автоматизации, надстройками брау- зеров, а также браузерами других типов (это касается даже таких, казалось бы, “отстраненных” концепций как, например, управление трехмерным текстом). Соответствующим международным стандартом является ЕСМА-262 (ISO 16262), он уже доработан до третьего издания. Но, по сравнению с такими языками, как Perl или даже Java, он все еще относительно молодой. Работа в рамках технического комитета ЕСМА над четвертой версией, в которой должны поддержи- ваться типы, классы, а также средства организации разработки новых поколений программных Предисловие 25
средств, идет полным ходом (посмотрите документацию в разделе JS2 на узле технической под- держки комитета ЕСМА по адресу http: / /www .mozilla. org/ j s/language/ j s20/). Совершенно очевидно, по крайней мере для меня, что JavaScript не удержался бы на плаву без продуктивной, лояльной й терпеливой поддержки консорциума разработчиков. Должен выразить им свою искреннюю признательность. Те из них, кто тестировал бета-версию Netscape Navigator 2, распространял в виде почтовых сообщений и сообщений групп ново- стей жизненно важные доработки и затрагивал ключевые вопросы, по праву могут считаться крестными родителями языка. Поддержка разработчиков и постоянная обратная связь с ко- нечными пользователями способствует заслуженному успеху JavaScript. Книга, которую читатель держит в своих руках, является результатом тех “бессонных но- чей”, через которые прошли разработчики языка, опытные эксперты и преподаватели. Дэнни не мог и предположить, какое впечатление произведет на меня его книга о HyperCard. Имен- но она была моим настольным пособием в процессе создания JavaScript в 1995 году. Его энергия, участие и легкость изложения материала помогли мне удержаться в русле создания языка “для всех”. Поэтому чрезвычайно приятно писать предисловие к пятому изданию этой книги, которая стоит проведенных им “бессонных ночей”. Настоятельно рекомендую всем, кто хочет освоить, JavaScript, прочитать книгу Дэнни Гуд- мана JavaScript. Библия пользователя. Особенно это относится к тем, кто работает с HTML и успел “набросать” несколько сценариев или программ, — у вас есть уникальная возможность пройти по тернистой дороге создания сценариев вместе с опытным проводником и учителем. Брендан Эйх The Mozilla Organization (http: //www.mozilla.org) 26 Предисловие
Введение Примерно 20 лет назад я написал книгу, о которой давно думал и которая должна была по- мочь мне освоить новую технологию. Я всегда старался вникнуть в основы новых программных средств и средств разработки, почувствовать растущие достижения и разделить с читателями плоды своего труда. Пятое издание книги JavaScript. Библия пользователя призвано донести до читателя те знания и опыт, которые были наработаны в течение пяти лет каждодневной работы в JavaScript и постоянного поиска в группах новостей каверзных вопросов, нерешенных про- блем и другого, । достойного внимания разработчика сценариев. Моя цель— помочь читателю избежать тех разочарований и мучительной головной боли, которые в свое время испытал не только я сам, но и многие другие, кто работал с различными поколениями браузеров. В то время как предыдущие издания этой книги были, в основном, ориентированы на доми- нирующие в то время браузеры Netscape Navigator, современные тенденции развития браузер- ных технологий все больше указывают на преобладание Microsoft Internet Explorer. В то же вре- мя, Netscape удалось завершить превосходную задачу по восстановлению собственного браузера в свете быстрого развития стандартов индустрии. Как результат этих тенденций, существенно пересмотренное и расширенное пятое издание книги в равной степени ориентировано на оба типа браузеров как на эквивалентные технологии, которые вполне соответствуют приоритетам пользователей. Читатель столкнется с моими положительными отзывами или критикой разных версий браузеров и поддерживаемых ими технологий. Но мое самое страстное желание, на са- мом деле, — это научить читателя создавать документы и разрабатывать производительные сценарии, эффективно выполняемые в любой версии браузера. Поэтому данная книга содер- жит детальное описание специальных и стандартных методов, позволяющих решать любые поставленные задачи. По моему мнению, это именно то, что больше всего волнует читателей. На случай, если вы усмотрите в этой книге спорные моменты, то не забывайте о том, что соз- даваемые сценарии должны выполняться в максимально возможном числе браузеров. Структура и особенности этого издания Подобно предыдущему изданию, настоящее пятое издание книги JavaScript. Библия поль- зователя содержит намного больше информации, чем можно поместить даже в самую тол- стую книгу по JavaScript. Полная версия приведена на компакт-диске (в электронном виде), прилагаемом к этой книге. Обновленное издание книги лучше структурировано (это в основ- ном касается информации, представленной в бумажной части книги). В частности, все лис- тинги кодов, которые ранее можно было найти только в виде материалов на компакт-диске, теперь вставлены в текст книги в местах его непосредственного описания. В бумажную часть книги вынесены все главы, в которых рассматриваются основы языка и фундаментальные принципы программирования на JavaScript. В электронных главах книги на компакт-диске описаны узкоспециализированные методы разработки сценариев на JavaScript. Ниже .речь пойдет о структурных особенностях книги.
Часть I. Знакомство с JavaScript Часть I этой книги начинается с главы, в которой продемонстрированы связи JavaScript с Java и определяется их роль в World Wide Web. С того момента, как на рынке Web-технологий впервые появился JavaScript, в браузерах Web и среде создания сценариев произошли суще- ственные изменения. Поэтому глава 2 посвящена тем изменениям, которые наиболее сущест- венным образом влияют на методы создания сценариев и в большей степени определяют бы- стро изменяющиеся стандарты приложений, поддерживаемые разными браузерами. В главе 3 вы совершите первое знакомство с основами JavaScript; после ее изучения вы сможете само- стоятельно создать первый в своей жизни сценарий. Часть II. Руководство по JavaScript Часть П полностью посвящена наставлениям для начинающих программистов на JavaScript. В ней приведено девять уроков, позволяющих читателю последовательно изучить внутрен- нюю структуру браузера, освоить навыки программирования и ознакомиться с основными принципами JavaScript. С помощью всего нескольких явно описанных элементов языка в этих уроках на высоком профессиональном уровне рассматривается весь диапазон принципов создания сценариев, выполняемых во многих браузерах, которые поддерживают технологию JavaScript В конце каждого урока приведены упражнения, которые позволяют закрепить полученные зна- ния и проверить качество их освоения читателем. Вы также сможете попрактиковаться в ис- пользовании изученных средств (ответы приведены в приложении В). Цель этого учебного по- собия — научить читателя создавать простые страницы еще до того момента, как дело дойдет до подробного рассмотрения сложных примеров, приведенных в конце книги. В последнем уроке части вы узнаете, как управлять многофреймовыми документами и создавать эффекты ролловеров — изображений, изменяющихся при наведении на них указателя мыши. Часть III. Объекты документа Часть Ш — это наибольшая часть книги, которая посвящена всестороннему освещению объектных моделей документа, реализуемых в браузерах и обеспечивающих до настоящего времени средства создания динамических документов. Во всех справочных разделах совмес- тимость описываемых средств JavaScript с разными версиями браузера задается в специаль- ной таблице. В главе 15 приведен справочный материал, который используется практически во всех остальных главах части Ш. Часть IV. Объекты языка JavaScript В части IV приведена справочная информация по базовому языку JavaScript. Как и в части Ш, будут представлены таблицы совместимости браузеров с описываемыми средствами языка JavaScript. Ключевые слова в нижней части страниц помогут читателю быстро отыскать нуж- ный термин, описываемый на странице. Часть V. Приложения Несколько приложений, приведенных в конце книги, предоставят довольно важный спра- вочйый материал. В них включена справка по JavaScript и объектам браузера (приложение А), список зарезервированных в JavaScript слов (приложение Б) и ответы на упражнения части П (приложение В). В приложении Г представлен список Internet-ресурсов, посвященных JavaScript, а в приложении Д описано содержимое компакт-диска и электронных глав книги. 28 Введение
Прилагаемый компакт-диск Прилагаемый к книге компакт-диск — это кладезь полезной информации. На диске вы найдете все главы дополнительной части VI, представленной только в электронном виде. В этих главах рассмотрены следующие вопросы. Специальные объекты DOM, XML и JavaScript. Возможности DHTML, методы проверки данных и защита сценариев. Методы разработки и отладки профессиональных Web-приложений. Девять полноценных приложений JavaScript, используемых в реальной жизни. Более того, на компакт-диске, прилагаемом к книге, содержится электронная версия на- стоящей книги (на английском языке, в формате PDF). Вы также найдете на нем огромное количество готовых к использованию HTML-документов, которые послужат примером соз- дания Web-страниц в большинстве объектных моделей документа. Все они созданы с исполь- зованием зарезервированных слов JavaScript и методов, описанных в частях Ш и IV настоя- щей книги. Эти примеры можно запускать непосредственно в браузере, по умолчанию поддерживающем JavaScript. Однако обязательно убедитесь, что в папке листингов (как шлюз для их запуска) используется страница index.html. Эта страница определяет те брау- зеры, которые совместимы с приведенными в папке листингами. Она содержит немного ин- формации, но ознакомиться с ней перед запуском остальных сценариев советуем всем поль- зователям. Просмотр полноценных HTML-документов (даже достаточно простых) просто необходим для полного усвоения всех описанных в книге принципов. Листинги из учебного раздела этой книги (часть П) умышленно опущены, чтобы привлечь читателя к самостоятельно- му написанию сценариев. Вы многому научитесь, даже просто вводя листинги, приведенные в книге, — стоит только начать. На компакт-диске представлены листинги из частей I и V. Не забудьте проверить папку с листингами для главы 13. Эта папка содержит весьма ин- тересный файл evaluator.html, созданный специально для этой книги. Читатель может познакомиться с результатом использования этого приложения на практике, чтобы получить детальные сведения о его эффективности. Справочное руководство из приложения А также представлено на диске в формате .pdf. Это позволяет распечатать его и использовать в качестве настольного пособия. На диске так- же содержится программа Adobe Acrobat Reader, позволяющая просматривать содержимое файлов в формате .pdf. Наконец, для упрощенного поиска на диске в том же формате пред- ставлен текст всей книги. Что потребуется для изучения JavaScript Для чтения этой книги совсем не обязательно иметь опыт программирования, однако чем больше читатель создал с помощью HTML Web-страниц, тем легче ему будет понять, как JavaScript взаимодействует с разными программными элементами, размещенными на странице. Иногда, чтобы ощутить все прелести написания сценариев, придется несколько видоизменять HTML- дескрипторы. Если вам ранее приходилось работать с этими дескрипторами, то изучение новых особенностей, добавляемых JavaScript, не представит для вас особых сложностей. В большинстве стандартных разработок JavaScript формы и их элементы (текстовые поля, кнопки и списки выбора) играют особенно важную роль. Читателю стоит внимательно ознакомиться с этими элементами и их атрибутами в HTML. К счаствю, вам не потребу- ется разбираться в тонкостях составления серверных сценариев и способах отправки информации с формы на сервер. В данном случае основной акцент сделан на написании Введение 29
сценариев, выполняемых на стороне клиента (после полной загрузки браузером, поддержи- вающим JavaScript, в составе страницы они управляются независимо от сервера). Вам также потребуются знания основных стандартов HTML. Например, при описании ос- нов управления фреймами, главный упор делается на написании сценариев для соответст- вующих структурных элементов, а не на методах оформления с их помощью готовых стра- ниц. Более детально данная тема описана в документации от Microsoft, Netscape и т.п. Для тех, кому не приходилось программировать Если вы изучали азы работы в HTML несколько лет назад по тоненькому справочнику, то размеры этой книги могут вас просто испугать. Может быть, JavaScript далеко не самый про- стой для изучения язык в мире, но, вне всяких сомнений, он ни в какое сравнение не идет с такими фундаментальными средами программирования, как Java или С. В отличие от разра- ботки завершенных приложений (которые практически каждому из вас приходилось приоб- ретать на компакт-дисках), с помощью JavaScript можно экспериментально создавать не- большие фрагменты программного кода, используемые в качестве компонентов более сложных программ. Интерпретатор JavaScript, который встроен во все браузеры, поддержи- вающие сценарии, выполнит за вас большую часть черновой работы. Программирование заключается в создании серии инструкций для выполнения их компь- ютером. Если проводить аналогию с повседневной жизнью, то люди постоянно следуют ин- струкциям, даже если сами этого не подозревают. Путешествие к дому друга является приме- ром следования последовательности несложных инструкций: пройти три квартала в одном направлении; возле аптеки повернуть налево; после прохождения ее повернуть направо. Вы- полняя эти инструкции, вам приходится принимать определенные решения: если на светофо- ре горит красный свет, то нужно остановиться; если — зеленый, то можно идти; если — жел- тый, то следует приготовиться к движению или остановке. Время от времени некоторые действия приходится повторять по несколько раз (как, например, хождение по улицам в по- исках заветной аптеки). Программа для компьютера содержит не только последовательность основных действий, но и предопределяет, какие решения принимать или какова повторяе- мость действий (как, например, реагировать на сигналы светофора или как вести себя в слу- чае, если рядом расположено две аптеки) для достижения целей, стоящих перед программой. Первым препятствием на пути к освоению азов программирования является та точ- ность, с какой в языках программирования представлены в инструкциях слова и числа. Со- ответствующие правила (как и в обычных языках) определяют синтаксис языка програм- мирования. Хотя современные компьютеры являются весьма производительными, по своей натуре они до безобразия точны. Поэтому они не очень-то прощают, когда с ними разговари- вают на непонятном для них языке. Если вы, разговаривая с другим человеком, допускаете в предложении стилистические ошибки, то вы все же, рассчитываете, что собеседник вас полностью поймет. В большинстве случаев так и происходит. Совсем иначе дело обстоит с компьютерами. Если синтаксис не является идеальным (или, по крайней мере, не откло- няется от стандарта в пределах очевидной корректировки), компьютер самым нахальным образом заявит, что вами допущена синтаксическая ошибка. Оптимальным вариантом в такой ситуации является изучение допущенных синтаксиче- ских ошибок. Ведь даже самые опытные программисты делают ошибки. При таком подходе каждая допущенная синтаксическая ошибка добавляет знаний и опыта в программировании на используемом языке. Тем, кто уже немного программировал Наличие опыта работы с такими процедурными языками программирования, как BASIC или Pascal, может, скорее, вызвать головную боль, чем помочь в изучении JavaScript. Вы мо- жете иметь достаточно полное представление о синтаксисе языка, однако важно и то, что 30 Введение
общая концепция выполнения программ в этих языках радикально отличается от принятой в JavaScript. Частично это определяется обычными задачами, решаемыми с помощью сцена- риев (программирование действий в ответ на выполняемые пользователем манипуляции на странице Web). Однако большой объем работы реализуется посредством объектно-ориенти- рованного программирования. В типичной программе с использованием процедур программист непосредственно несет ответственность как за то, что появляется на экране, так и за те действия, которые непосред- ственно выполняются программой. При первом запуске программы огромная часть кода предназначена для того, чтобы определить графическую среду. На экране при этом может располагаться несколько текстовых полей и кнопок. Чтобы определить, на какой кнопке щелкнул пользователь, программа должна знать координаты точки, на которой был выполнен щелчок, а затем сравнить эти координаты на совпадение с координатами одной из кнопок на экране. В зависимости от того, какая кнопка используется, выполняются заранее определен- ные для текущего случая инструкции. Объектно-ориентированное программирование представляет собой нечто совершенно про- тивоположное. Кнопка интерпретируется как объект — вещь вполне реальная. Объект имеет свойства (надпись, размер, событие и т.п.). Объект также может содержать сценарий. В то же время, системные программы и браузеры могут посылать объекту сообщения — в зависимо- сти от того, что делает пользователь, —' для запуска сценария. Например, если пользователь щелкает мышкой на записи текстового поля, то система или браузер сообщает полю, что кто-то щелкает там (это значит, что данное поле активизируется), передавая полю полномочия по по- воду принятия решения, что ему следует делать в ответ на такое действие. Именно здесь в силу вступают сценарии. Сценарий связан с полем и содержит инструкции, которые выполняются при активизации поля. Другой набор инструкций может использоваться для контроля данных, вводимых пользователем в поле, или на вкладке, или в результате щелчка на опции. Некоторые из создаваемых сценариев по своей структуре могут напоминать процедуры: они содержат простые инструкции, которые поочередно выполняются. Однако когда вы пе- рейдете к управлений» данными формы, то поймете, что инструкции JavaScript выполняются исключительно как объектно-ориентированные. Каждая форма является объектом. Это же относится ко всякому элементу управления (например, переключателю или текстовому по- лю). В этом случае для выполнения запланированной работы сценарий вызывает свойства со- ответствующих объектов. Переход от процедурного к объектно-ориентированному программированию может быть самым трудным моментом^ в обучении пользователя. Когда несколько лет назад мне самому пришлось столкнуться с объектно-ориентированным программированием, не могу сказать, что у меня все получилось. Но когда я во всем разобрался (а в этом мне помог напряженный и от- ветственный труд), в моей голове появилось столько “грандиозных” идей, что, я уверен, буду реализовывать их еще много лет. С тех пор я полностью уверен, что объектно-ориентированное программирование является единственным целесообразным способом написания программ. Тем, кто программировал на С По причине занудности синтаксиса Java (который, кстати сказать, походит от С и C++), в JavaScript можно найти много синтаксических характеристик С. Поэтому знакомые с язы- ком С программисты будут чувствовать себя, как рыба в воде. Символы операторов, услов- ные конструкции и циклы выдержаны исключительно в традициях С. При этом в JavaScript, по сравнению с С, можно меньше беспокоиться о типах данных. В JavaScript задаваемые пе- ременные не ограничены конкретным типом данных. Поскольку очень многое в синтаксисе JavaScript будет вам знакомо, tq сконцентрируйтесь на концепциях объектной модели документа, что является абсолютно новым понятием для С-программиста. Кроме того, для реализации своих навыков в JavaScript на практике совету- ем основательно изучить HTML (особенно это касается дескрипторов элементов форм). Введение 31
Для тех, кто работал в Java Несмотря на очень похожие названия, данные языки имеют только поверхностное сходст- во. Это касается организации циклов и условных конструкций, обращения к объектам с ис- пользованием точки (как это делается в С), фигурных скобок для выделения групп, некото- рых ключевых слов и ряда других атрибутов. Что же касается объявления переменных, то они совершенно различны. Такая ситуация имеет место по той причине, что JavaScript в этом смысле является достаточно прогрессивным языком. Переменная может содержать целочис- ленное значение с одной стороны оператора сравнения и строчные данные — с другой (хотя это и не всегда хорошо). В тех случаях, когда Java обращается к чему-то как к методу, JavaScript вызывает методы (когда они связаны с предопределенным объектом) или функции (для опре- деленных в сценарии действий). Методы и функции JavaScript могут возвращать значения любых типов без предварительного их объявления. Возможно, при работе с JavaScript наиболее важным наследием Java является объектно- ориентированное представление о классах, наследовании, экземплярах и передаче сообщений. Эти понятия при написании сценариев просто неактуальны. Тем не менее, JavaScript-дизайнеры хорошо знают, что всегда нужно подстраховываться. Например, хотя в JavaScript и не требуется в конце каждой строки ставить точку с запятой, однако, если в исходном коде JavaScript пароч- ка-другая их все же “проскакивает”, то интерпретатор JavaScript от этого хуже работать не станет. Тем, кто писал сценарии и макросы Опыт создания сценариев с помощью других средств программирования или макросов в прикладных программах является хорошей основой при освоении всевозможных концепций JavaScript. Наиболее важной из них, пожалуй, является концепция комбинирования действий или обработки данных определенного типа с помощью нескольких операторов. Например, B'Microsoft Excel можно написать макрос, который будет выполнять преобразование данных финансовых отчетов, поступающих из другого компьютера, для отображения в виде диа- грамм. Макрос встраивается в меню Макрос, и запускать его нужно, выбрав соответствую- щую опцию меню, независимо от того, когда поступают новые показатели. Более сложные сценарии, который можно создать с помощью Toolbook или HyperCard, мак- симально соответствуют объектно-ориентированной концепции JavaScript. В этих средах объекты экрана содержат сценарии, которые выполняются при взаимодействии пользователя с этими объектами. Большое число создаваемых в JavaScript сценариев будут выдержаны в рамках описанной ниже концепции. Фактически, эти среды напоминают оболочку выпол- няющего сценарии браузера, обеспечивая использование набора предопределенных объектов, которые имеют фиксированные свойства и атрибуты. Эта предопределенность применяется для строгого определения характеристик всей среды, а потому способствует более эффектив- ному и производительному выполнению приложений. Соглашение о представлении данных и имен Листинги сценариев и их фрагменты представлены в этой книге специальным шрифтом. Это сделано для того, чтобы облегчить их поиск на фоне остального текста. По причине ог- раниченности ширины страниц строки в листингах иногда будут неестественным образом прерываться. В этих случаях разорванная строка продолжается на следующей строке, как это делается в текстовом редакторе при переносе слов. Если при введении сценария из-за этого у вас возникают проблемы, можно воспользоваться этим же сценарием, размещенным на компакт-диске, прилагаемом к книге. Когда читатель доберется до части Ш книги, может оказаться, что дальше, чем на одну страницу после описания объектных моделей или средств языка, требующих определенной 32 Введение
версии браузеров, ему продвинуться не удается. Чтобы указать, какой же в данном случае не- обходим браузер и его версия, используется двухсимвольная система аббревиатур с указани- ем числовой версии. Например, IE5 означает Internet Explorer 5 для всех операционных сис- тем, a NN6 означает Netscape Navigator 6, опять же, для всех операционных систем. Если сценарий или отдельное средство поддерживается определенной версией браузера и всеми последующими версиями, то после номера версии стоит знак (+). Например, если средство помечено как IE4+, то это означает, что для его поддержки вам потребуется как минимум Internet Explorer 4, но средство совместимо и с IE5, и с IE5.5 и т.д. Случается, что средство или некоторый атрибут применим только, в определенной операционной системе. К примеру, если для средства использована пометка WinIE4+, то это значит, что оно выполняется в Internet Explorer версии 4 и выше, но только в Windows. Как пример ссылок, первыми работающими со сценариями браузерами были NN2, WinIE3 и Мас1Е3.01. Эти условные обозначения в пер- вую очередь можно увидеть на сравнительных диаграммах в справочных разделах. Пиктограммы “На заметку", ‘'Совет” и “Внимание" вре- мя от времени появляются в книге для отображения наиболее важных моментов. Благодарности Конечно, такую толстенную книгу, которую вы держите в своих руках, мне никогда не удались бы написать самостоятельно за те короткие сроки, которые устанавливаются конъ- юнктурой рынка печатных изданий. .В процессе изучения терминологии и подготовки обу- чающих примеров к этой книге мне приходилось неоднократно консультироваться с Майк- лом Моррисоном — таким же автором, как и я сам. С его помощью проект приобрел тот вид, который имеет сейчас. Технический редактор Дэвид Уолл на протяжении многих лет занима- ется подготовкой книги JavaScript. Библия пользователя к изданию, на что у него уходит очень много сил и почти все рабочее время. Хотелось бы также отметить и многих других со- трудников Wiley Publishing, принимавших участие в написании и подготовке к печати этой книги. Среди них Дебра Вильямс Коли, Мэри Бет Уэйкфилд и Анжела Смит. И наконец, я ис- кренне признателен всем тем читателям предыдущих изданий книги, которые принимали ак- тивное участие в ее обсуждении: присылали электронные письма, в которых выражали свои замечания и пожелания. Ваш опыт работы с JavaScript оказался просто неоценим! Введение 33
Ждем ваших отзывов! Вы, читатель этой книги, и есть главный ее критик и комментатор. Мы ценим ваше мне- ние и хотим знать, что было сделано нами правильно, что можно было сделать лучше и что еще вы хотели бы увидеть изданным нами. Нам интересно услышать и любые другие замеча- ния, которые вам хотелось бы высказать в наш адрес. Мы ждем ваших комментариев и надеемся на них. Вы можете прислать нам бумажное или электронное письмо либо просто посетить наш Web-сервер и оставить свои замечания там. Од- ним словом, любым удобным для вас способом дайте нам знать, нравится вам эта книга или нет, а также выскажите свое мнение о том, как сделать наши книги более интересными для вас. Посылая письмо или сообщение, не забудьте указать название книги и ее авторов, а также ваш обратный адрес. Мы внимательно ознакомимся с вашим мнением и обязательно учтем его при отборе и подготовке к изданию последующих книг. Наши координаты: E-mail: info@dialektika.com WWW: http://www.dialektika.com Адреса для писем: из России: 115419, Москва, а/я 783 из Украины: 03150, Киев, а/я 152
Знакомство с JavaScript
Роль JavaScript в World Wide Web ногие современные технологии, которые сделали возможным само существование World Wide Web, давно превзошли возлагавшиеся на них первоначально надежды. Вначале Web разрабатывалась как сетевая среда управления статическими текстами и изображениями. Она постоянно улучшается, изменяется и популяризируется разработчиками Web-технологий. Ради достижения поставленных целей разра- ботчики идут на любые ухищрения, берутся за выполнение са- мой “грязной работы” по установке соединений и перекачке битов данных между серверами и компьютерами клиентов, а в минуты отчаяния, вместе с пользователями, по-доброму мечтают о тех временах, когда возможности соединений по- зволят, наконец, поддерживать новые приложения с системно- независимой платформой, которые не будут иметь ограниче- ний на расширение и использование ресурсов Web. Не являет- ся удивительным и тот факт, что сообщество разработчиков взяло под серьезный контроль права собственности на новые технологии и использует их для создания поистине удивитель- ных вещей. Паутина Web обладает огромной популярностью. Кроме того, к высоким технологиям имеет доступ каждый обычный, даже начинающий, пользователь. Среди обычных пользователей есть немало таких, чьи интригующие и беспре- цедентные выдумки способствуют превращению Web из сла- бой издательской среды в высоко интерактивную, системно- независимую среду разработки программных средств. Примером современных технологий в Web является язык JavaScript После внедрения в компьютер клиента этот язык мо- жет превратить страницу со статическим содержимым в при- влекательный, интерактивный и весьма разумный документ. Приложения (они же сценарии) JavaScript при этом могут быть настолько вежливыми, что будут приветствовать новых посетителей узла словами “Доброе утро!”, если в часовом поя- се, в котором расположен компьютер клиента, сейчас утро (даже несмотря на то, что в часовом поясе, в котором распо- ложен сервер, полдень или полночь). Приложения JavaScript позволяют сделать Web-страницы нагляднее. Например, при
создании презентации, которая отображается в виде слайд-шоу, JavaScript управляет после- довательностью транзакций по скрытию, отображению отдельных слайдов и другими ди- намическими эффектами. Конечно, JavaScript не единственный способ вдохнуть жизнь в безжизненные статические объекты в Web. Поэтому важно понимать, на каком именно уровне происходит взаимодейст- вие JavaScript с различными стандартами, программными средствами и другими технология- ми. Альтернативными технологиями, описываемыми в этой главе, являются HTML, сервер- ные приложения, надстройки и программные модули, а также аплеты Java. В большинстве случаев JavaScript совместим со всеми перечисленными технологиями на самом высоком уровне. Уповать на абсолютность совместимости JavaScript с другими средствами все же не стоит, хотя случаи сбоев наблюдаются весьма редко. В этой книге вы узнаете об истоках раз- вития JavaScript и той роли, которую он играет в среде современных браузерных технологий. Конкуренция в Web Нет большего счастья для создателей Web-страниц, чем увеличивающееся количество посе- тителей их узла. Независимо от качества содержимого Web-страницы, можно, безо всякого сомне- ния, утверждать, что узел, который в течение недели регулярно посещают порядка 10 000 раз, по- пулярнее, чем тот, который за это же время посетили всего 1000 раз. Даже если точное число посетителей неизвестно, относительную популярность при желании всегда можно установить. Заинтересовать посетителей к частому посещению узла — это первейшая задача Web-разра- ботчика. Примеров жесткой конкуренции в Web можно привести огромное количество. Речь идет не только о конкуренции в Web, подобной той, что имеет место на телевидении (где коли- чество каналов достаточно велико, поэтому даже при всем своем желании и технических возможностях ни один из телезрителей не сможет просмотреть их все за всю свою жизнь). Пользователи развлекательных программ, мультимедийных энциклопедий, экзотических представлений, которые исходно создаются максимально привлекательными, уже привыкли к высококачественным эффектам и первокласснейшим презентациям. Чаще всего описанные выше проекты не обходятся без насыщенных графических изображений, анимации, потоко- вых видеоклипов и загружаемых звуковых эффектов. В отличие от описанного выше, стан- дартные HTML-страницы мало чем могут порадовать пользователя, избалованного качест- венным представлением информации. Даже с учетом последних достижений и разработок в области динамического HTML и каскадных таблиц стилей, размещение статических рисун- ков даже на форматированном тексте предоставляет ограниченное количество возможностей дизайнерам, по сравнению с тем, что предлагают настольные издательские системы, с кото- рыми вам, возможно, уже приходилось сталкиваться. Независимо от качества содержимого документов, созданных в издательских системах, они красочнее и представительнее даже са- мых качественных “старомодных” HTML-документов. Интерактивность последних, в лучшем случае, обеспечивается ограниченным набором ссылок и формами, содержимое которых по- сле заполнения данными все равно исчезает в пучинах Web-серверов. Другие Web-технологии При наличии такого большого набора возможностей для внесения разнообразия на Web- страницы конкуренты, пытающиеся “отбить” потенциальных посетителей, во что бы то ни ста- ло пытаются перещеголять чужой узел. Даже те организации, которые поставляют эксклюзив- ную информацию высокого уровня востребованности, находятся в постоянном напряжении, изобретая новые методы, позволяющие привлечь как можно большую часть аудитории. Для Глава 1. Роль JavaScript в World Wide Web 37
тех, кто обеспечивает Web-структуру корпоративных локальных сетей, это соперничество выражается в постоянном повышении продуктивности и качества работы по сравнению с те- ми коллегами, которые используют для выполнения этих же задач внешние Web-узлы. Все описанные выше причины должны побудить вас к стремлению использования макси- мального количества Web-технологий для создания привлекательных Web-страниц, качест- веннсхи информативно выделяющихся на фоне остальных проектов. Теперь самое время об- ратиться к основным положениям, которые .следует знать каждому Web-дизайнеру. Что такое HTML Язык HTML (Hypertext Markup Language — язык гипертекстовой разметки), который про- исходит от SGML (Standard Generalized Markup Language — стандартный обобщенный язык разметки), рассматривается, в основном, исключительно как язык форматирования или раз- метки документов (заключения данных в дескрипторы). Дескрипторы (это то, что находится внутри символов о) используются для задания инструкций программе просмотра докумен- тов (браузеру или клиентской программе), в которых детально описывается способ отобра- жения текстовых фрагментов и рисунков на экране. Низведение HTML к категории языков разметки позволяет с его помощью не только оформлять высококачественные Web-страниц, но и обеспечивать интерактивное взаимодей- ствие с пользователями. Согласно некогда популярной точке зрения, все наборы команд и другие синтаксические правила, предназначенные для организации управления цифровыми данными, относятся исключительно к программированию. При использовании HTML автор Web-страницы задает сферу влияния пользователя на данные (содержимое страницы) точно так же, как программисты, создавшие Microsoft Excel, позволяют пользователям процессора баз данных изменять содержимое таблиц и выполнять функции обработки числовых данных. В последних усовершенствованиях стандартов HTML (HTML 4 и выше) сделана попытка сузить область абсолютного влияния HTML на содержимое документов и передать формати- рование внешним подключаемым средствам, например, таблицам стилей. Другими словами, HTML не должен определять, какой текстовый фрагмент выделить курсивным начертанием, — следует указать фактор, определяющий фрагменты, которые необходимо выделить курсивом. Например, с помощью дескрипторов можно задать подчеркивание фрагмента текста, независи- мо от того, что задает такое начертание, — таблица стилей или используемый браузер. XHTML— это самая совершенная версия языка HTML, которая включает в себя под- держку стилистических соглашений, принятых в XML (extensible Markup Language — рас- ширяемый язык разметки документов). В HTML вы найдете новые дескрипторы, хотя основ- ные принципы их применения для задания форматирования документов остаются прежними. Серверные сценарии Один из способов повышения эффективности работы по управлению пользователем со- держимым страницы — это установление соединения с Web-сервером, который обслуживает страницу. Предназначение серверных сценариев — самое широкое, начиная с проверки вве- денного имени пользователя и пароля и до задержки выполнения определенного действия. Написание специальных серверных сценариев обычно требует навыков программирования. Ряд таких сценариев создается с использованием фундаментальных языков программирова- ния — Perl, Python, Java, С или C++. Вам не удастся самостоятельно создать серверные при- ложения, если вы не знакомы с такими технологиями, как PHP, ASP, .Net, JSP и Coldfusion. Очень немногие серверы позволяют выполнять серверные сценарии, написанные на JavaScript. Независимо от того, какой язык используется для написания серверного сценария, реше- ние поставленной перед ним задачи требует обязательного вмешательства разработчика Web- 30 Часть I. Знакомство с JavaScript
страницы или администратора Web-сервера, которые настраивают вспомогательные програм- мы (подобные базам данных), применяемые для обработки поступающей информации и со- хранения готовых данных. Даже при наличии новых средств разработки, ориентированных на поддержку Web-сервера, создание CGI-сценариев для привыкших к стилю простого форма- тирования документов с помощью HTML-дизайнеров — это сложнейшее задание, для реше- ния которого потребуется опыт профессионального программиста. Настолько же интересной и полезной, как написание сервером сценариев, является задача обработки сервером запросов. Полностью загруженный сервер может обрабатывать одновре- менно сотни сценариев. При этом компьютеры клиентов (персональные компьютеры, в которых запускаются браузеры) откровенно “простаивают”, отображая простенькую анимацию или даже статическое изображение в ожидании обработанных данных. Это негативно сказывается на эф- фективности работы конечного компьютера, особенно если запущенный на сервере процесс не требует получения доступа к большим базам данных или другим внешним ресурсам. Вспомогательные приложения и надстройки На ранних этапах развития World Wide Web перед браузером ставилась задача отображать только небольшое количество типов данных. Вся система по форматированию текста (заключенного в дескрипторы HTML) и рисунков (представленных в таких популярных форма- тах, как GIF и JPEG) была встроена в браузер и предназначалась'для управления исключительно операционной системой настольного компьютера. Ограниченные числом используемых ти- пов данных разработчики приложили немало усилий, чтобы добиться расширения возможно- стей браузеров клиентов по обработке данных, представленных в других форматах. Тогда ка- залось несбыточной мечтой, что когда-нибудь удастся создать браузер, которьш сможет загружать и обрабатывать, скажем, звуковые файлы хотя бы в одном из существующих форматов. Одним из способов решения данной проблемы было разрешение на использование в браузе- ре системы определения типа данных входящего файла и запуска в компьютере клиента специ- альных приложений, обеспечивающих обработку его содержимого. Если такое вспомогательное приложение установлено на компьютере клиента (а в браузере указано использовать его для от- крытия файлов определенного типа данных), то браузер сможет запустить нужную программу и переслать ей входящий файл. В этом случае можно для воспроизведения звуковых MIDI- файлов использовать одно вспомогательное приложение, а для файлов в формате WAV—другое. Начиная с Netscape Navigator 2 (начало 1996 года), применение в браузерах программных надстроек позволило разработчикам расширить возможности браузеров без всякой необхо- димости внесения существенных изменений в их исходный код. В отличие от вспомогатель- ных приложений, с помощью надстройки (или внедряемого модуля) можно реализовать плавное перемещение содержимого файла в HTML-документ. Наиболее распространенный пример надстройки — это программные модули, которые исполь- зуются для воспроизведения звуковых и видеоклипов, расположенных на сервере. Музыка теперь повсеместно включается на страницы для фонового воспроизведения в процессе загрузки и ото- бражения документа. Это же относится и к воспроизведению потокового звука, который чем-то срЬдни радиотрансляции. Видеоклипы и анимация тоже вполне могут отображаться на страни- це. При их воспроизведении с помощью надстроек браузер принимает минимальное участие. В современных браузерах отмечается тенденция к массовому использованию надстроек, позволяющих производить декодирование звуковых файлов большинства существующих ти- пов. Разработчики надстроек для Internet Explorer, запускаемого в Windows, обычно реализу- ют программные модули в виде средств управления ActiveX. Хотя разница в реализации над- стройки важна с точки зрения поддержки операционной системой, для конечного пользователя она несущественна. Глава 1. Роль JavaScript в World Wide Web 39
Надстройки и вспомогательные приложения могут использоваться не только для воспроизве- дения звука и видеоклипов. Популярное вспомогательное приложение— Adobe Acrobat Reader, которое отображает файлы, отформатированные в таком виде, в каком они выводятся на печать, — стало незаменимым помощником не только дизайнеров, но и рядовых пользователей. Для обеспе- чения красочности и интерактивности разработчики все чаще обращаются к надстройке Flash компании Macromedia. Созданные с использованием специализированной программной среды Macromedia Flash документы в формате Flash могут содержать интерактивные области, реаги- рующие на щелчки мышью, а также перемещаемые элементы. Некоторым авторам даже удается реализовать во Flash художественные видеоигры и мультфильмы. Браузеры, оснащенные над- стройками Flash, отображают данные в прямоугольной области, вставленной на страницу. Один из недостатков создания интерактивных объектов разработок во Flash или другой по- добной среде заключается в невозможности отображения их в браузере, в котором не установ- лена соответствующая надстройка. Кроме того, на загрузку анимации тратится больше времени, чем на загрузку других объектов, вставленных на страницу. В результате после установки над- стройки загрузка клиентом высококачественной анимационной графики и других данных (особенно при автоматическом соединении) может занять намного больше времени, чем рас- считывали пользователи. Это один из тех случаев, когда приходится выбирать между художест- венными изысканиями и стремлением предоставить пользователю максимум интерактивности. Еще одна технология, запускаемая на стороне клиента, — аплеты Java — была весьма по- пулярна в начале 1990-х годов, но по многим причинам (техническим, экономическим, внут- рикорпоративным и т.д.) она утратила свою привлекательность. Но это никоим образом не сказалось на популярности языка Java при написании серверных приложений и даже про- грамм, запускаемых в современных мобильных телефонах. Этот язык уже давно перестал быть достоянием разработавшей ее компании — Sun Microsystems. JavaScript: язык для всех Истоки языка Java — в С и C++, полностью завершенной среде программирования. Ис- пользуют его, в основном, опытные программисты. Когда я впервые обратился к изучению спецификации Java, это вызвало просто недоумение. Мне больше бы подошел язык, который легко мог освоить каждый — от программиста-любителя до создателя сценариев, свободно владеющего графическими программными средствами (например, Apple HyperCard и Micro- soft Visual Basic). Появление подобных средств для разработчика способствовало бы тому, что армия непрофессиональных и неопытных программистов сразу же создала бы немало не- замысловатых, но чрезвычайно действенных приложений, решающих узконаправленные, специфические задачи, над которыми профессионалы не станут ломать себе голову. Большие дела часто начинаются с решения очень частных нужд. И начинаются они в классной комна- те, офисе, чулане или даже гараже. Однако все это не относится к Java. Подобные размышления повторно возникли в моей памяти несколькими месяцами позже, в ноябре 1995 года, когда я услышал о проекте создания языка написания сценариев для браузе- ров Netscape. Этот язык, вначале названный LiveScript, разрабатывался параллельно с про- граммным обеспечением для Web-сервера Netscape. Язык имел единый синтаксис и должен был служить двум целям. Первой целью было создание такой среды разработки сценариев, которую администраторы Web-серверов могли бы использовать для управления работой сервера и подклю- чения к другим службам — удаленным базам данных и средствам поиска информации. Расширив марку “действенного” (т.е. “Live”) в названии, Netscape стала использовать термин Live Wire для обозначения среды JavaScript, применяемой сервером для подключения к базам данных. С точки зрения клиента (в рамках HTML-документов), разработчики для улучшения Web- страниц теперь могли самыми различными способами использовать сценарии, написанные 40 Часть I. Знакомство с JavaScript
с использованием этого нового языка. Например, с помощью LiveScript разработчик мог про- контролировать, соответствует ли вводимая пользователем на форме информация необходи- мому типу данных. Сервер или база данных не будет преобразовывать данные к приемлемому виду (происходит обязательный обмен данными между браузером клиента и сервером) — все необходимые расчеты выполняет компьютер пользователя, уменьшая тем самым загружен- ность ресурсов. В сущности, LiveScript способен обеспечить пользователя тем же уровнем взаимодействия, что и HTML. Как LiveScript стал JavaScript В начале декабря 1995 года в преддверии формального выхода в свет NN2 компании Netscape и Sun любезно объявили, что язык создания сценариев в дальнейшем будет имено- ваться как JavaScript. И хотя у компании Netscape были некоторые причины маркетингового характера для такого изменения названия, столь резкий шаг вызвал намного большее замеша- тельство в рядах сторонников Java и HTML, чем кто-либо ожидал. Уже перед самым этим заявлением язык был в некотором смысле ориентирован на Java. Многие базовые элементы синтаксиса языка создания сценариев напоминали стиль Java, бе- рущий свое начало от С и C++. С точки зрения использования клиентом, область применения языка существенно отличалось от таковой в Java. Особенно это касается программных кодов, которые интерпретировались непосредственно в HTML, а не в виде отдельного аплета, кото- рому на странице отводилась фиксированная прямоугольная область. В отличие от полного и развитого программного словаря языка Java (и концептуально более трудного для изучения принципов объектно-ориентированного программирования), JavaScript имел ограниченный словарь зарезервированных терминов и легче усваиваемую программную модель. Как выяснилось, намного труднее оказалось ясно показать широкому кругу интересую- щихся разницу между Java и JavaScript. Очень многие компьютерные журналисты, прямо или косвенно заявив, что JavaScript обеспечивает более простой способ создания аплетов Java, сделали грубую ошибку. И до сих пор многие программисты думают, что JavaScript является синонимом Java— ведь они отправляют запросы Java в группу новостей Internet и списки рассылки, созданные с помощью JavaScript. На сегодня фактом остается то, что Java и JavaScript имеют больше отличий, чем сходств. Эти два языка используют для выполнения строк кода совершенно различные интерпретаторы. В мире Microsoft Несмотря на то, что язык JavaScript ориентирован, в основном, на Netscape, Microsoft все же признала его потенциальные возможности и обеспечила популярность JavaScript, включив его (под именем JScript) в Internet Explorer 3. Даже если Microsoft будет продолжать использо- вать язык VBScript (Visual Basic Script) намного больше, чем это принято во всем мире (как в версии IE для Windows), несомненным остается факт, что JavaScript доступен большему числу браузеров и операционных систем. Это способствует тому, что именно на него падает выбор всех, кому приходится заниматься Web-дизайном, потребляемым массовым пользователем. Придерживаясь традиций соперничества на рынке браузеров Web, Netscape и Microsoft продолжают созывать под свои знамена разработчиков, опираясь при этом на разные концеп- ции. На момент написания этой книги Netscape выдвинула лозунг в поддержку общепризнан- ных стандартов Web. Microsoft же, со своей стороны, обеспечивает только частичную под- держку стандартов и делает упор на разработке многих собственных направлений, что весьма актуально особенно для клиентов, которые используют исключительно операционные систе- мы серии Win32. Если вам потребуется разрабатывать страницы для тех, кто использует оба Глава 1. Роль JavaScript в World Wide Web 41
типа браузеров, запускаемых в разных операционных системах, это только будет способство- вать дальнейшим исследованиям. Разговор на данную тему пойдет далее, поэтому сейчас мы не будем останавливаться на этом вопросе. JavaScript: правильное средство для правильной работы Умение правильно подобрать средство разработки для решения поставленных задач явля- ется важным моментом для каждого грамотного разработчика Web-страниц. Дизайнер Web- страниц, который игнорирует в своей работе JavaScript, похож на того водопроводчика, кото- рый расшибает свои пальцы, мучаясь с плоскогубцами, вместо того, чтобы порыться в своей сумке и найти более подходящий инструмент. Проще говоря, JavaScript не в состоянии воплотить в жизнь абсолютно любую мечту. Чем больше понимаешь замысел создания JavaScript и границы его применения, тем чаще к нему обращаешься даже в тех случаях, когда он кажется неприменим. В частности, к помощи JavaScript имеет смысл обратиться в следующих случаях. Если нужно реализовать прямую или ответную реакцию Web-страницы на действия пользователя при управлении элементами формы (полями, текстовыми .областями, кнопками, переключателями, элементами списка, списками меню) и гиперссылками. Этот класс приложений можно назвать бессерверными сценариями. Если необходимо организовать небольшие наборы данных в определенные структуры (например, базы данных) и предоставить для управления ими дружественный интерфейс. Для управления многофреймовыми документами, надстройками или аплетами Java в зависимости от предпочтений пользователя и настроек браузера. Для организации предварительной обработки данных перед отправкой их на сервер. Для внесения динамических изменений в содержимое документа и стили, применяе- мые в браузерах, в ответ на действия пользователя. В то же время, следует помнить, какие задачи JavaScript выполнить не может. Создатели сценариев, используя JavaScript, тратят много времени на решение задач, для которых этот язык не предназначен в принципе. Большинство ограничений связано с попытками защиты посетителей от покушений на интеллектуальную собственность и несанкционированного доступа к компьютерам. Поэтому, если только посетитель не использует современный брау- зер и недвусмысленно дает разрешение на доступ к защищенным данным на диске компью- тера, JavaScript не сможет выполнить ни одну из перечисленных ниже операций. Установить или настроить предпочтительные параметры браузера, значения свойств, параметры командных кнопок и печати. Запустить приложения на компьютере клиента. Считать или записать файлы и папки на компьютере клиента или на сервере. Перехватить потоки данных с сервера. Отправить себе почтовые скрытые сообщения от посетителей Web-узла. Создатели Web-узлов постоянно находятся в поисках средств повышения привлекательно- сти результатов своего труда. При этом планируется тратить на работу минимум усилий. Более реальной является ситуация, когда эту задачу приходится решать людям, больше знакомым 42 Часть I. Знакомство с JavaScript
с графическим дизайном и оформлением документов, чем когда за дело берутся профессио- нальные программисты. Не каждый Web-мастер может привлечь опытных программистов для решения проблемы внесения очень специфических изменений в данные узла. Точно так же не каждый Web-разработчик может контролировать Web-сервер, который содержит много коллекций графических и HTML-файлов, разобраться в которых порой очень сложно. JavaScript позволяет реализовать страсть к программированию каждому, кто знаком с HTML, даже если сервер на другом конце телефонной линии представляется ему черным ящиком. Глава 1. Роль JavaScript в World Wide Web 43
Творческие изыскания в сложных полевых условиях стория развития поддерживающих сценарии браузе- ров достаточно коротка. Поэтому те, кто начинает знакомиться с JavaScript именно с этого момента, имеет по сравнению с остальными и ряд преимуществ, и ряд недос- татков. Преимуществом является то, что в распоряжении пользователя сейчас под рукой оказались уникальные сред- ства, поддерживаемые последними версиями браузеров от Netscape и Microsoft. С другой стороны, необходимо знать о процессе развития средств разработки Web-страниц от са- мых ранних версий (весьма простых, несовершенных и по- стоянно несовместимых с другими средствами ввиду отсут- ствия единых стандартов). Вам еще только предстоит изучить основы создания универсальных сценариев, рабо- тающих в браузерах самых различных типов. Если вы не обес- печите совместимость сценария с разными версиями браузе- ров, то вам гарантированно придется сталкиваться с жалобами, приходящими в виде почтовых сообщений от посетителей, в которых будут явно (и гневно) указаны все неполадки, воз- никающие при выполнении ваших приложений в браузерах других типов и поколений или операционных системах. Таков реальный мир создания сценариев JavaScript для Web-страниц. На тот случай, если конечные пользователи приложения используют разные типы браузеров, чтобы изба- вить себя от головной боли, следуйте простым, но действен- ным советам, приведенным в этой книге. В настоящей главе вы познакомитесь с основными методами правильного напи- сания сценариев (это необходимо сделать перед тем, как в собственном сценарии вы введете первый символ кода JavaScript). Единственное, чего я опасаюсь, — это то, что по- сле такого лихого начала вы можете передумать и оставите изучение JavaScript. Но с точки зрения разработчика, начавшего
работу с JavaScript “с осложнениями” еще на ранних этапах его развития и становления, мне не хочется с самого начала предоставлять вам некорректные сведения. Более того, хотелось бы подчеркнуть значимость для дальнейшего изучения языка материала, который изложен в самом начале книги. Верю, если читателю удастся прочувствовать сложность ситуации, сложившейся в среде Web-дизайна к концу 2004 года, то ему не составит труда овладеть на- выками использования JavaScript при создании собственных приложений для Web. Полная неразбериха Проблема совместимости браузеров встала перед Web-дизайнерами еще на ранних этапах развития Web, задолго до появления JavaScript. Несмотря на то; что разработчики браузеров и другие заинтересованные стороны высказывали свои пожелания еще на стадии формирования стандартов, авторы HTML не смогли добиться идентичного отображения HTML-документа на всех клиентских компьютерах. Ведь одно дело утвердить набор стандартных дескрипторов для определения заголовков разных уровней, задания разрывов строк и т.д., и совершенно другое — добиться совпадения содержимого этих дескрипторов в разных типах браузеров. Когда страсти накалились и разработка браузеров для Web превратилась из дела добро- вольного в весьма прибыльный бизнес, появились умельцы, которые разработали новые ха- рактеристики и новые дескрипторы, с помощью которых авторы смогли разрабатывать более гибкие и прекрасно оформленные страницы. Как это часто случается в любой отрасли ком- пьютерной индустрии, темпы развития коммерчески выгодных технологий быстро опередили темпы эволюционирования всесторонне продуманных стандартов. В среде создателей брау- зера стало привычным сначала встроить новое средство HTML в браузер и только после это- го предлагать данное средство для включения в систему стандартов. Web-дизайнеры могли использовать (и повсеместно использовали) это средство (иногда даже в бета-версиях браузе- ра) еще до того, как оно официально включалось в стандарты. Как только вид содержимого документа стал в большинстве своем зависеть от интерпре- татора, который установлен в браузере клиента, получающего данные, Web-дизайнеры сразу столкнулись с серьезными проблемами. В отличие от отдельного компьютера, где функцио- нальность программы можно расширять и даже вносить в нее новые возможности, Web- сервер, на котором размещаются данные Web-страниц, полностью отвечает за их содержи- мое, а также обеспечивает его соответствие с функциональными возможностями браузера. Если Web-сервер не обеспечивает совместимость своего содержимого с браузерами, у разра- ботчиков возникают жалобы, подобные следующим: “Если не все браузеры, отображающие определенную страницу, поддерживают новое средство HTML, то следует ли в данном случае это злополучное средство “исключить” из HTML?” и “Если в браузере реализуется новое средство, то как поступать со старыми версиями документов и браузеров?”. Web-дизайнеры, разрабатывавшие страницы на ранних этапах становления Web, борются с проблемами внедрения новых свойств HTML не один год, поэтому подобные трудности вос- принимаются ими как нечто вполне естественное. Сразу же вспоминаются таблицы и фреймы, которые так болезненно внедрялись на Web-страницы. В конечном счете стандарты определяют только направление развития HTML, хотя не для всех дизайнеров подобный путь по душе. Несмотря на бесспорное лидерство Microsoft на рынке браузеров, многие пользователи отдают свое предпочтение программным решениям сторонних производителей. Некоторые последние версии независимых разработчиков (NN7 и Forebird) основываются на открытом коде браузера с громким названием Mozilla. В операционные системы платформ Macintosh отныне встраивается собственный браузер — Safari (представлен в 2003 году). Независимый браузер Opera лишь отдаленно можно считать альтернативой указанным двум. Для этих ком- паний ставки высоки как никогда ранее — разделение рынка, привлечение инвесторов и т.п. Глава 2. Творческие изыскания в сложных полевых условиях 45
Нетрудно понять и причины подобной конкуренции. То, что началось много лет назад с обычной неразберихи (задолго до признания Microsoft прогрессивности Web), сегодня обернулось самой настоящей войной браузерных технологий. Тенденции Иногда трудно даже сказать, в какой именно технологии Web на этой неделе происходит самое жаркое сражение, и где оно будет проходить на следующей. Новости от противоборст- вующих сторон, поступающие с рынка продаж, не всегда и не всеми трактуются однозначно. Трудно сказать, когда статистические сведения станут способствовать развитию по-настоя- щему новой корпоративной стратегии, а когда это просто уловка в ответ на действия конку- рента. С одной стороны пользователи выдвигают собственные требования к конечному про- граммному продукту, а с другой— разработчику приходится реализовывать программные решения, поддерживая огромное количество технологий, без которых современный браузер будет просто лишен всякой возможности на существование. В результате простая задача (все, что необходимо пользователям) загрузки данных Web-страницы оборачивается головной бо- лью для разработчика и неразберихой на рынке программного обеспечения. Индустриальные стандарты хотя и несколько упорядочили технологии, однако никоим образом не облегчили жизнь разработчиков браузеров. С одной стороны без поддержки стан- дартов просто не обойтись, а с другой — далеко не все браузеры совместимы с различными технологиями. Если же учесть то, что в сами стандарты далеко не всегда включаются техно- логии, чаще всего используемые на рынке, то легко понять, что до полного контроля над си- туацией в данной отрасли еще далеко. В данном случае выигрывает тот, кто первым успел представить в своем браузере средства, востребованные конечными пользователями. Вскоре используемые этим разработчиком технологии становятся стандартными де-факто, что при- водит к полному перераспределению сфер влияния на рынке браузеров. Как это случается на войне, когда в ход идет тяжелая артиллерия, жертвы среди мирных жителей растут. Линия фронта в течение нескольких лет изменилась самым драматическим образом. Огромный сегмент рынка, принадлежавший ранее команде Netscape, теперь попал в руки Microsoft (без сомнения, поддержанной миллионами американских пользователей, по- лучивших IE как составную часть программного пакета AOL). В то время, когда между ста- рыми версиями обеих браузеров можно обнаружить определенное сходство, их новые версии вызывают серьезные опасения у тех разработчиков, которые пытаются создавать продукты, совместимые с каждым из двух типов браузеров. Проблема совместимости сегодня Всегда необходимо учитывать текущее состояние дел в области совместимости Netscape Navigator и Microsoft Explorer. Материал, представленный в следующих нескольких разделах, умышленно не затрагивает глубокого анализа специфики технологических особенностей со- ставления сценариев, поскольку он рассчитан на тех пользователей, которые не очень сильны в программировании. Во многих главах частей Ш и IV можно найти решения, позволяющие использовать сценарии в обоих типах браузеров. Базовый язык и объекты Поскольку первые разработчики, создающие приложения на JavaScript, воспринимали за- дачу составления клиентского сценария как нечто подобное программированию элементов страницы, основное внимание уделялось усовершенствованию браузеров. На сегодняшний 46 Часть I. Знакомство с JavaScript
день существует четкое разграничение между спецификацией базового языка JavaScript и опи- сываемыми в сценарии операторами (например, задающими кнопки и поля формы). С одной стороны, такое разграничение нужно приветствовать. Это значит, что для базовой программной концепции существует одна спецификация и синтаксис, позволяющий применять язык в любых средах, даже тех, которые пока еще не существуют. Базовый язык можно срав- нить с электропроводкой. Если известно, как устроена проводка электрической сети* то к ней можно подключить электрические приборы всех типов и любой мощности, включая и те, кото- рые пока еще не изобретены. Точно так же JavaScript сегодня используется для того, чтобы свя- зывать вместе элементы страницы в документе HTML. Вполне может быть, что завтра операци- онные системы будут использовать базовый язык для соединения приложений, запускаемых в компьютерах конечных пользователей, которые будут автоматически обмениваться информацией. В настоящее время JavaScript используется для внедрения на Web-страницы и обеспече- ния функциональности разрозненных ее элементов. На жаргоне программистов эти элементы называются объектами документа. Если разъединить объекты документа на отдельные со- ставляющие, то впоследствии на их основе можно будет создавать другие типы приложения (это подобно применению телефонных аппаратов с разными типами наборов, включая и те, которые пока еще не разработаны). В настоящее время в телефонных аппаратах используется тональный или импульсный набор. Хорошим примером такого разделения особенностей язы- ка является Internet Explorer, набор объектов документа которого допускает использование как JavaScript, так и VBScript. Объекты, по сути, одни и те же, а способы их объединения в работающие структуры — разные. Разграничение базового языка и моделей объектов документа способствует тому, что каждая спецификация имеет свои собственные стандарты и пути развития. Но даже при наличии реко- мендаций по использованию стандартов в каждом из случаев любой разработчик браузеров в состоянии эти стандарты нарушить или даже видоизменить. Более того, может оказаться, что дизайнеры будут тратить больше усилий на создание версии страницы или сценария, работаю- щих в обоих браузерах, по сравнению с созданием разных сценариев для каждого из случаев. Стандарт базового языка Относительно короткая история развития языка JavaScript охватывает три версии, разра- ботанные Netscape. Политика касается версии Microsoft и попыток согласования стандартов. Первая версия JavaScript (в NN2) — это 1.0, однако номер не был включен в название языка. JavaScript 1.0 был просто JavaScript. Нумерация версий установилась после выхода в свет NN3. С этой версией NN связан JavaScript 1.1. Как вы в дальнейшем узнаете в этой книге, в некоторых случаях в дескрипторах HTML, используемых в сценарии, следует указывать номер версии. Смена поколения браузеров на NN4.X привела к изменению версии языка на JavaScript 1.2. Деятельность Microsoft у начинающих программистов JavaScript вызывает некоторое за- мешательство. Первая версия Internet Explorer, в которую была включена поддержка сценари- ев,— это Internet Explorer 3. Время появления Internet Explorer 3 совпало с появлением Netscape Navigator 3. Но, как в этом очень скоро смогли убедиться разработчики, уровень поддержки сценариев в Microsoft оказался на порядок ниже. Microsoft не лицензировала на- звание JavaScript. Как результат, компания назвала свой язык JScript. Тем не менее, атрибуты дескрипторов HTML в Internet Explorer, требующих указания название языка, допускают ис- пользование как JScript, так и JavaScript. В любом случае Internet Explorer 3 поймет сценарий, написанный на JavaScript для Netscape Navigator 2. Во время царствования Netscape Navigator 3 и Internet Explorer 3 многие разработчики сценариев испытывали недоумение, поскольку полагали, что язык должен быть один и тот же. К огромному их сожалению, в версии JavaScript 1.1 представлены средства, которые не- доступны в более поздних версиях JavaScript для Internet Explorer 3. Спустя некоторое время Глава 2. Творческие изыскания в сложных полевых условиях 47
компания Microsoft улучшила JavaScript в ЕЕЗ, модернизировав файл .dll, определяющий синтаксис языка. Тем не менее, иногда трудно определить, какой именно файл . dll установ- лен в ЕЕЗ в конечном компьютере. Ситуация улучшилась при появлении Internet Explorer 4. Синтаксис его базового языка был максимально приближен к версии JavaScript 1.2 в NN4. Прн этом Microsoft продолжает называть свой язык JScript. Почти все средства, которые бы- ли впервые представлены в NN4 (включая атрибуты дескрипторов, идентифицирующих JavaScript 1.2), прекрасно воспринимались при загрузке в Internet Explorer 4. Пока неразбериха со стандартами и версиями JavaScript продолжалась, Netscape, Microsoft и другие заинтересованные стороны встретились для того, чтобы определиться со стандартом базового языка. В Швейцарии уже давно зарегистрирована организация ЕСМА (European Computer Manufacturer's Association — Европейская ассоциация производителей компьюте- ров), которая занимается разработкой и внедрением стандартов. В середине 1997 года была одобрена и обнародована первая формальная спецификация языка (ЕСМА-262). С целью обеспечения прав уже лицензированного названия JavaScript было решено использовать для нового стандарта название ECMAScript. Если не считать незначительных, понятных лишь узкому кругу специалистов различий, ECMAScript представлял собой копию JavaScript 1.1 в варианте NN3. Как NN4, так и IE4 под- держивали стандарт ECMAScript. Более того, как это часто бывает, когда коммерческие ин- тересы пересекаются с необходимостью поддержки стандартов, оба браузера разрослись да- леко за пределы стандарта ECMAScript. К счастью, базис обоих языков имеет много общего, что несколько упрощает работу разработчиков, их использующих. Браузеры Netscape Navigator 4.06-7.х тяготеют к использованию JavaScript 1.3, что также справедливо и для браузеров Ш5, 5.5 и 6. В это же время многие новые средства языка, пред- ставленные в JavaScript 1.5, были полностью реализованы только в браузерах, основанных на коде Mozilla (включая NN6 и выше). Большинство современных браузеров поддерживают практически все новые средства язы- ка JavaScript, за исключением некоторых малоиспользуемых технологий. Это упрощает рабо- ту в современных версиях браузеров, однако абсолютно не влияет на старые версии браузе- ров, которые “страдают” недостаточной поддержкой любых новых технологий. Объектная модель документа Насколько близки базовые версии языка JavaScript в NN и IE, настолько же далеки объек- ты документа. В Internet Explorer 3 объектная модель документа (D0M — Document Object Model) совпадает с той, что используется в NN2. Именно эта версия стала базовой для созда- ния стандарта языка. Когда компания Netscape добавила несколько новых объектов в NN3, эти новшества вызвали недовольство неопытных создателей сценариев, которые полагали, что эти же объекты появятся и в Internet Explorer 3. Пожалуй, самыми востребованными объ- ектами в Internet Explorer 3 были элементы управления изображениями, которые позволяют сценариям изменять изображения в ответ на проведение пользователем определенных действий. В браузерах четвертого поколения, тем не менее, объектная модель документа Microsoft ушла намного вперед по сравнению с объектной моделью Netscape, реализованной в NN4. Наиболее революционными достижениями в IE4 является это возможность виртуального описания в сценарии каждого элемента HTML-документа и переформатирование страницы при выполнении пользователем определенных действий. Таким образом, для HTML был от- крыт путь к уникальной на то время динамичности, не требующей перезагрузки текущей страницы в окне браузера. В NN4 была реализована только малая доля функции динамизма, без предоставления доступа в сценарии ко всем элементам и возможности изменения страниц в режиме реального времени. Содержимое документов в NN6 не могло так изменяться, как в IE4. Можно сказать, что IE4 стал недостижим для NN. 48 Часть I. Знакомство с JavaScript
В то же время стандарт DOM попал под покровительство консорциума World Wide Web Consortium (W3C). У разработчиков появилась надежда, что стандарт вскоре оформится как завершенная единая спецификация, позволяющая проще программировать динамические элементы для разных браузеров, поддерживающих ее. Компания Netscape серьезно отнеслась к новой тенденции развития технологии и создала практически новый браузер — NN6. В него вошли все наработки W3C DOM 1 и большая часть из уровня 2. Несмотря на то, что Microsoft участвовала в разработке стандарта W3C DOM, в Е5 были реализованы только некоторые из его положений, в объеме, который делает возможным создание межбраузерных сценариев только в рамках спецификации. Конечно, этот стандарт не является идеальный, тем не менее, вместе с ним в DOM появилось несколь- ко концептуально новых средств создания сценариев. Если все это принять во внимание, а также учесть, какое количество старых браузеров все еще продолжает использоваться, то окажется, что создание сценариев для объектов HTML — дело достаточно непростое. При этом нужно хорошо понимать, как обеспечивается совместимость сценариев с браузерами (именно в этом вам поможет данная книга). Несмотря на то, что компания Microsoft и принимала активное участие в разработке стан- дарта W3C DOM, в Е5 и Е5.5 реализована поддержка далеко не всех ее возможностей. Если быть до конца честным, то в браузерах Microsoft объектная модель W3C DOM реализована только до того уровня, начиная с которого эти браузеры можно назвать соответствующими стандартам — не больше и не меньше. Впоследствии W3C DOM была включена в Е6, хотя тоже не в том объеме, как того требовал современных рынок. При всем этом объектная мо- дель документа в таком браузере, как Safari, представляет собой нечто среднее из того, что можно найти в Е6 и Mozilla. Конечно, и данном случае нельзя говорить о полной поддержке, поскольку было упущено даже то, что представлено в Е4. Каскадные таблицы стилей Netscape Navigator 4 и Internet Explorer 4 были первыми браузерами, претендующими на совместимость с технологией W3C, называемой Cascading Style Sheets 1 (CSS 1 — каскадные таблицы стилей уровня 1). Эта технология подразумевает специальную организацию содер- жимого во всем документе (а поэтому минимизирует количество атрибутов, используемых в каждом дескрипторе). Также в ней предпринята попытка расширить традицию использова- ния стандартного HTML для управления статичным содержимым страницы. В конечном ито- ге оказалось, что в NN4 есть много недоработок. Особенно это становится заметным при по- пытке совместного использования каскадных таблиц стилей с таблицами других типов. Конечно, Е4 тоже не отличался особой надежностью, особенно это относится к сравнитель- ным результатам применения таблицы стилей в Windows и Macintosh. В CSS2 функциональные возможности, заложенные в стандарт, значительно расширены. Именно поэтому Е5 и NN6, в основном, поддерживают только ее. Одни и те же стили теперь более подобны в обоих браузерах, что достигалось за счет строгого соблюдения правил при- менения стилей. Поскольку объектные модели браузеров Е4+, Mozilla и Safari разрешают проводить ди- намическое изменение стилей, примененных к любому типу содержимого, то совершенно очевидно, что это изменение реализуется с помощью JavaScript. Информация, содержащаяся в таблицах стилей, является частью объектной модели и поэтому доступна и полностью управляема с помощью JavaScript. Глава 2. Творческие изыскания в сложных полевых условиях 49
Динамический HTML Пожалуй, самым существенным усовершенствованием в поколении HTML 4, на основе которого в той или иной степени построены объектные модели Netscape и Microsoft, является концепция динамического HTML (Dynamic HTML или DHTML). Первоначальная задача ис- пользования DHTML заключалась в предоставлении сценариям возможности управления со- держимым документов, их расположением и отображением в ответ на действия пользователя. С этой целью организацией W3C (как расширение стандарта CSS) был разработан другой стан- дарт, обеспечивающий точное позиционирование элементов HTML на странице. Такие реко- мендации по позиционированию были совмещены со стандартом CSS, а затем оба они вошли во второе поколение CSS. Благодаря позиционированию стало возможным задавать точное распо- ложение элементов на странице, указывать, какие элементы должны отображаться, а какие скрываться, а также определять порядок наложения и перекрывания всех элементов. Браузер IE4+ больше ориентирован на использование стандарта позиционирования, он предоставляет сценарию возможность управления позиционируемыми элементами. NN4 так- же следует этому стандарту, однако в нем реализована альтернативная методика с использо- ванием совершенно нового и в конечном счете не утвержденного дескриптора описания сло- ев. Позиционируемые элементы в NN4 также остаются доступными для сценариев, хотя сам синтаксис сценария при этом во многом отличается от того, что используется в IE4. К сча- стью тех, кто работает с DHTML, Mozilla, благодаря поддержке стандарта CSS, понимает синтаксис дескрипторов стилей DHTML, применяемых в IE4+. Создание межбраузерных сценариев с помощью единого синтаксиса все еще остается нелегкой задачей, хотя вполне возможной. После выпуска компанией Microsoft браузера IE6 многое изменилось, хотя на рынке появилось несколько независимых игроков (Mozilla и Safari), в которых поддержка DHTML и JavaScript реализована на столь же высоком уровне, как и у “законодателя моды”. Главное — это четко осознавать возможности каждой спецификации и использовать только те средства, которые поддерживаются в большинстве браузеров. Создание межбраузерных сценариев Браузеры последнего поколения объединяют все то, что досталось им в наследство от предыдущих версий, стандартов и собственных наработок компаний-производителей. Если вы попытаетесь создать сценарий, рассчитанный на самые общие средства языка, то исполь- зуемый код, скорее всего, не будет поддерживаться ни ранними версиями базового языка JavaScript, ни объектными моделями документов новых браузеров. Поэтому наиболее важным заданием для тех, кто сегодня старается создавать межбрау- зерные сценарии, является определение круга пользователей, на который будет рассчитано создаваемое приложение. В главе 13 описан набор методов, позволяющих производить пере- направление пользователей по структуре своего Web-узла с целью отображения нужной вер- сии страницы в их браузере. В главе 14 показан ряд альтернативных решений, зависящих от используемой версии (или версий) объектной модели и специфических характеристик, для которых необходимо реализовывать поддержку. Каждое новое поколение браузеров прино- сит в этот мир набор новых удивительных средств языка, которые используются при созда- нии страниц. К сожалению, это приводит к фрагментации аудитории посетителей узла. После выхода каждого нового пакета обновления браузера далеко не все пользователи захотят за- гружать мегабайты данных просто для того, чтобы иметь самую последнюю версию браузера. Для большинства первопроходцев (и уж точно неспециалистов) причины, побуждающие об- новить версию браузера, довольно примитивны. Разве что такое обновление может связы- ваться с покупкой нового компьютера или обновлением операционной системы. 50 Часть I. Знакомство с JavaScript
На данном этапе можно считать, что подавляющее большинство пользователей склоняет- ся к установке современных версий браузеров, в которых в полной мере реализована под- держка W3C DOM и DHTML. Не факт, что это так на самом деле, но ведь вам никогда не удастся удовлетворить запросы конечной аудитории на все 100%. Буквально это означает следующее: вам достаточно разработать Web-страницы, которые будут открываться у подав- ляющего большинства пользователей и по мере возможностей у всех остальных. В идеаль- ном случае Web-документы будут доступны всем, а вот специальные их средства — только счастливым обладателям браузеров с поддержкой JavaScript-сценариев и других современных технологий. Таким образом, в ваши задачи входит намного больше, чем создание красочных Web-страниц. Вам придется изрядно потрудиться, чтобы сделать свои приложения полно- стью интерактивными, максимально производительными, информационно востребованными и, конечно же, поддерживаемыми большинством современных браузеров. Глава 2. Творческие изыскания в сложных полевых условиях 51
Первый собственный сценарий [Э . этой главе речь пойдет об установке на компьютер программных продуктов, позволяющих с высокой производительностью создавать сценарии, а также выпол- нять их. Мы также постараемся написать простой сценарий, результат выполнения которого можно просмотреть в любом совместимом с JavaScript браузере. Благодаря отличиям в работе разных операционных систем, основные настройки среды будут ориентированы на использова- ние двух наиболее популярных систем: Win32 (Windows 95-ХР) и MacOS X. В большинстве случаев изменение операцион- ной системы, вплоть до выбора Linux и UNIX, никак не по- влияет на решение и результат поставленных задач. Безус- ловно, для разных браузеров и операционных систем могут наблюдаться некоторые незначительные различия в структуре представления параметров, однако базисные положения ос- танутся неизменными. Большинство рисунков, а также гра- фически иллюстрируемые результаты, полученные в браузере, в этой книге выполнены для Internet Explorer 6 в Windows ХР. Поэтому, если вы используете другой браузер и результаты его в окне не соответствуют приведенным в книге, то это не должно вас тревожить. Программное обеспечение Лучший способ изучения JavaScript— введение кода сце- нария непосредственно в текстовом редакторе. Выбор самого редактора остается всецело за вами, хотя в следующем разделе представлены некоторые соображения по этому поводу. Выбор текстового редактора С точки зрения материала данной книги, читателю пока сле- дует избегать графических программных средств создания Web- страниц типа WYSIWYG (What You See Is What You Get — Что видишь, то и получаешь) — FrontPage или Dreamweaver.
Эти средства определенно понадобятся вам в будущем, когда у вас будет опыт представления эле- ментов страницы в ваде кода. Тогда для формирования основного содержимого документа и маке- та они вам особо пригодятся. Примеры, приводимые в данном издании, основаны на создании сценариев, которые в любом случае придется вводить вручную, поэтому у знатоков кода HTML в этом смысле проблем возникать не должно. Файлы листингов готовых Web-страниц, описан- ных в этой книге (кроме учебных глав), вы найдете на прилагаемом компакт-диске. Важным фактором при выборе текстового редактора является удобство, с каким он по- зволяет вводить и сохранять стандартные текстовые файлы с расширением . html. В случае использования Windows любая программа, если только она сохраняет текстовые файлы, по умолчанию позволяет добавлять к ним расширение . htm или . html, т.е. способна избавить вас от проблемы выбора специального редактора. Если, к примеру, выбрать программу Microsoft Word, то при сохранении текстовых файлов она попытается представить их в дво- ичном виде — такой файл не в состоянии загрузить ни один браузер Web. Чтобы первона- чально сохранить файл как текстовый с расширением .html, вам придется провести некото- рые настройки в диалоговом окне Save As (Сохранить как). А это раздражает. Нет ничего страшного в использовании обычного текстового редактора. В той же Windows, предлагающей редактор WordPad, можно установить и более совершенные продукты для введения кодов листингов (например, испытательную версию программы TextPad). Для сис- темы MacOS X вполне подойдет TextEdit, хотя отсутствие функции поиска и замены может привести к ряду трудностей при управлении кодами Web-страниц. Наиболее популярной сре- ди разработчиков HTML и создателей сценариев, использующих Мас, является программа BBEdit (от Bare Bones Software), в состав которой входит большое количество вспомогатель- ных средств для составления сценариев (например, опции нумерации строк, которые помо- гают при отладке кода JavaScript). Выбор браузера Другим компонентом, необходимым при изучении JavaScript, является браузер. Для того чтобы протестировать собственные сценарии с помощью браузера, совсем необязательно быть подключенным к Internet. Все тестирование можно вполне выполнить и в автономном режиме. А это значит, что изучать JavaScript и создавать с использованием сценариев по- настоящему привлекательные Web-страницы можно с помощью небольшого портативного компьютера — прямо хоть в лодке посреди океана. Тип используемого браузера и его версия целиком определяются вкусами читателя. При разработке страниц советуем устанавливать максимально современный браузер (IE5 и выше для Windows и Macintosh, любой Mozilla-браузер, включая NN7 и выше, и Apple Safari). / В примерах листингов в этой книге используются свойства языка или объектные /нахмтд модели документа (DOM), которые доступны только в определенных браузерах • и их версиях. Поэтому проверяйте совместимость введенного кода с используе- мой версией языка или моделью DOM, чтобы убедиться, что для загрузки стра- ницы был применен подходящий браузер. Настройка среды разработки Чтобы облегчить себе задачу по тестированию сценариев, убедитесь, что в компьютере установлено достаточно памяти для одновременного запуска браузера и текстового редакто- ра. При экспериментировании и устранении всевозможных ошибок, которые могут быть до- пущены в сценарии и, вам нужно будет быстро переключаться между редактором и браузе- ром. В обычном рабочем режиме вам придется выполнить такие действия. Глава 3. Первый собственный сценарий 53
1. Ввести в текстовом редакторе документа исходный HTML-код и код сценария. 2. Сохранить последнюю версию кода на диске. 3. Переключиться на браузер. 4, Дальше можно поступить несколькими способами. Если это новый документ, то от- кройте его с помощью команды Open (Открыть) браузера. Если же этот файл уже за- гружен, перезагрузите его в окне браузера. Последовательность действий, описанную в пп. 2-4, придется повторять довольно часто. Так и хочется назвать эту трехэтапную последовательность сохрани-перключись-перезагрузи. Такую последовательность действий при создании сценариев придется выполнять столь часто, что в конце концов эта физическая процедура будет выполняться вами подсознательно. Как именно организовывать окна приложений на экране и выполнять последовательность действий сохра- ни-переключись-перезагрузи, зависит от конкретной используемой операционной системы. Система Windows В этом случае для “получения полного эффекта” не следует постоянно держать разверну- тыми на весь экран окна редактора или браузера. Работать будет удобнее, если настроить размеры и расположение окон так, чтобы они имели достаточно большой размер, но при этом оставалась возможность щелкать мышью на заголовках окон. В любом случае можно обра- титься за помощью к панели задач и щелкнуть на кнопке соответствующего приложения, чтобы перейти к необходимому окну (рис. 3.1). Если выставить разрешение монитора боль- шим, чем 800x600 пикселей, то это добавит места для окон и панели задач. Рис. 3.1. Расположение окон редактора и браузера при использовании Windows На практике, тем не менее, наличие используемой в Windows для переключения между выполняемыми приложениями комбинации клавиш <Alt+Tab> приводит к тому, что реализо- вать последовательность сохрани-переключись-перезагрузи становится очень просто. Если вами используется система Windows, в которой запущен совместимый с ней текстовый ре- дактор (в котором, скорее всего, для сохранения документа используется комбинация клавиш <Ctrl+S>), то выполнить последовательность сохрани-переключись-перезагрузи будет очень 54 Часть I. Знакомство с JavaScript
просто, даже без использования мыши: для сохранения исходного файла нужно нажать <Ctrl+S>, затем переключиться на браузер с помощью комбинации <Alt+Tab> и после этого перезагру- зить сохраненный файл, нажав <Ctrl+R>. Чтобы обратно переключиться из окна браузера к окну текстового редактора, еще раз на- жмите <Alt+Tab>. Система MacOS X В MacOS X для переключения между программами вам придется использовать средство Dock или комбинацию клавиш <3€+ТаЬ>. Если одновременно запущено только два приложе- ния, то для перехода от одной из них к другой нажмите <8€+ТаЬ> (рис. 3.2). Рис. 3.2. Расположение окон редактора и браузера на экране Macintosh В таком случае последовательность сохрани-переключись-перезагрузи потребует уже не- которых усилий. 1. Нажмите <3€+S>, сохранив тем самым исходный файл. 2. Щелкните мышью на окне браузера. 3. Нажмите <38+R> и перезагрузите сохраненный исходный файл. Для того чтобы вернуться к редактированию исходного файла, нажмите <3€+ТаЬ>. Особенности перезагрузки В большинстве случаев простой перезагрузки страницы вполне достаточно для тестиро- вания измененного сценария. Но в некоторых случаях в кэш-памяти браузера (с используе- мыми по умолчанию настройками) могут при перезагрузке сохраниться некоторые из преды- дущих атрибутов страницы, даже если ее исходный код изменен. Для выполнения более основательной перезагрузки при использовании кнопки перезагрузки браузера Reload/Refresh Глава 3. Первый собственный сценарий 55
(Перезагрузить/Обновить) удерживайте нажатой клавишу <Shift>. Альтернативой является отключение кэш-памяти браузера в разделе установок. Однако такие изменения могут нега- тивно сказаться на общем характере функционирования браузера в сеансах работы в Web. Что будет делать первый сценарий Сценарий, который будет рассматриваться в следующем разделе, относится к тем, кото- рые запускаются автоматически при загрузке браузером HTML-страницы. Поскольку в дан- ном случае вся работа, связанная со сценарием и загрузкой, выполняется в автономном ре- жиме, то поведение страницы будет таким же, как если бы исходный файл был размещен на сервере и кто-то получал к нему доступ с помощью Web. На рис. 3.3 показано, как будет выглядеть готовая страница. Правда, если используется операционная система, отличная от Windows ХР, или в качестве браузера задействован не Internet Explorer, то некоторые несущественные детали могут слегка отличаться. Та часть страницы, что в HTML определяется обычным способом, не содержит ничего особенного: за- головок уровня <Ы> с горизонтальным разделителем под ним. Если используется браузер, не поддерживающий JavaScript, то все, что можно будет увидеть, так это указанные заголовок и горизонтальный разделитель. Если вами используется совсем уж старомодный браузер, то в этом случае на странице могут появиться еще и некоторые операторы сценария. Рис. 3.3. Завершенная страница первого сценария JavaScript Под разделителем сценарий отобразит текстовую информацию, состоящую из неформа- тированных данных сведений о браузере, используемом для загрузки документа. Сценарий записывает поток данных HTML в браузер, включая дескрипторы для отображения некото- рых фрагментов текста полужирным начертанием. Хотя на странице текстовая информация разбита на две строки, передается она как одна строка — ситуация, подобная той, что имеет место при жестком форматировании текста в HTML. Создание первого сценария Итак, пришло время начать работу над первым собственным сценарием JavaScript. Для этого сначала запустите текстовый редактор и браузер. Если браузер предлагает соединиться с провайдером Internet (Internet Service Provider или ISP) или начинает делать это автоматически, 56 Часть I. Знакомство с JavaScript
то операцию следует отменить и выйти’из программы установки соединения. Если в браузере активна кнопка Stop (Остановить), то для пресечения возможных попыток браузера устано- вить соединение следует незамедлительно ею воспользоваться. При этом может появиться диалоговое окно с сообщением о том, что адрес URL для начальной страницы браузера (обычно такая страница является страницей издателя браузера, если только пользователем не были внесены изменения в настройки) не определен. Это нормально. Ведь вам нужно было всего-навсего запустить браузер, а не соединиться с ISP. Если вы используете автоматическое соединение через местную локальную сеть, то ничего страшного. Более того, пока что сетевое соединение вам не потребуется. Ниже приведена последовательность операций, по- зволяющих создать и просмотреть первый собственный сценарий JavaScript. 1. Запустите текстовый редактор и создайте новый пустой документ. 2. Введите в окне документа сценарий, как это показано в листинге 3.1. <html> <head> <title>My First Script</title> <style type="text/css"> .highlight {font-weight: bold} </style> </head> <body> <hl>Let's Script...</hl> <hr> <script type="text/javascript"> <!-- скрытие сценария от старых браузеров document.write("This browser is version " + navigator.appVersion); document.write( of <span class='highlight'>" + navigator.appName + "</span>."); // завершение кода скрытия сценария от старых браузеров --> </script> </body> </html> 3. Сохраните документ под именем scriptl. htm. 4. Перейдите в браузер. 5. В меню File (Файл) браузера воспользуйтесь опцией Орел (Открыть). В некоторых браузерах этот пункт называется Open File (Открыть файл). Затем необходимо вы- брать файл scriptl. htm. В некоторых браузерах для отображения диалогового окна открытия файла нужно сначала щелкнуть на кнопке Browse (Обзор). Если все строки были введены согласно приведенному выше образцу, то документ в окне браузера должен выглядеть так, как показано на рис. 3.3 (с учетом небольших поправок на разные версии используемой операционной системы и браузера). Если же браузер выдает со- общение о том, что при загрузке документа имеет место ошибка, то на данном этапе ничего предпринимать по этому поводу не нужно. Если появилось диалоговое окно ошибки, просто щелкните на кнопке ОК. Сначала лучше разобраться с тем, как устроен весь документ, понять особенности его выполнения и только после этого переходить к отладке. Глава 3. Первый собственный сценарий 57
Исследование сценария Сразу следует предупредить: не старайтесь запомнить все команды или тот синтаксис, ко- торые будут описываться в этом разделе. Напротив, немного расслабьтесь и посмотрите, как строки кода превращаются в то, что отображается в окне браузера. В листинге 3.1 все строки вплоть до дескриптора <script> являются примером кода обычного HTML. К нестандарт- ному дескриптору относится только <style>, который входит в спецификацию CSS. Дескриптор <script> Каждый раз при включении в документ HTML переменных JavaScript соответствующие строки кода потребуется заключить между парой <script>.. </script>. Эти дескрипто- ры сообщают программе браузера, что содержащийся между ними текст нужно интерпрети- ровать как сценарий. Поскольку другие языки составления сценариев (такие, как VBScript компании Microsoft) также могут в полной мере использовать преимущества данных деск- рипторов, то вам обязательно необходимо указать точное название того языка, который использован для создания кода. Поэтому, когда браузер получает сообщение о том, что в сценарии используется язык JavaScript, он использует для обработки кода встроенный интерпретатор JavaScript. Проведем такую аналогию с реальной жизнью: если у вас под рукой есть разго- ворник французского языка, то нужно, чтобы ваш собеседник тоже говорил по-французски. Если попутчик, скажем, из Испании, то французский разговорник вряд ли будет полезен. Точно так же: если используемый браузер имеет только интерпретатор JavaScript, он не смо- жет понять код, написанный на VBScript. Далее мы остановимся на еще одном аспекте использования JavaScript, который важен при работе со сценариями. JavaScript чувствителен к регистру (различает большие и малень- кие символы). Поэтому необходимо при вводе кода сценария JavaScript следить не только за самими терминами, но и за состоянием регистра, т.е. не путать прописные и строчные лите- ры. В дескрипторах HTML (включая и <script>) могут использоваться оба регистра по ус- мотрению разработчика, но все, что является кодом JavaScript, чувствительно к регистру. Ес- ли строка кода JavaScript не выполняется, сначала следует проверить, правильный ли регистр был использован для ее представления1. Всегда следует сравнивать введенный вручную код с теми листингами, которые приведены в книге или других источниках. Сценарий для всех браузеров Следующая после дескриптора <script> строка в листинге 3.1 напоминает HTML-де- скриптор начала комментария. Так оно и есть, только интерпретатор JavaScript трактует дескрип- торы комментариев особым образом. Хотя JavaScript послушно игнорирует строки, начинаю- щиеся с дескриптора начала комментария HTML, он воспринимает следующую строку как пол- ноправную строку сценария. Если нужно в код JavaScript вставить комментарий, то этот ком- ментарий должен начинаться с двойной косой черты (//). Такой комментарий может располагаться в конце строки (например, после оператора JavaScript, который должен интерпре- тироваться браузером) или занимать отдельную строку. Как легко заметить, в конце сценария используется последний вариант. Строка комментария начинается с двух косых черт. Если теперь внимательно присмотреться, то можно заметить, что внутри дескрипторов комментария стандартного HTML-кода (<! - - комментарий- - >) размещен целый сценарий Стили XHTML, если вы планируете использовать их в своих приложениях, требуют введения имен дескрипторов и имен атрибутов в нижнем регистре. Это соглашение вы встретите повсемест- но в настоящей книге. 58 Часть I. Знакомство с JavaScript
(с собственными комментариями). Смысл такой организации сценария сразу не совсем поня- тен. Но это до тех пор, пока вы не столкнетесь с браузером, который не поддерживает язык JavaScript. В этом случае браузер игнорирует дескриптор < script> как новый непонятный для него элемент. А вот текст сценария он интерпретирует как обычный текст, который нуж- но отображать на странице. Если заключить этот текст в дескрипторы комментария HTML, то большинство устаревших браузеров не отобразит строки сценария на странице. Однако некоторые старые браузеры (далеко не все могут себе позволить обновлять про- граммное обеспечение вовремя) иногда не реагируют на такое развитие событий, но выводят на экран непонятные сведения. Это происходит потому, что они интерпретируют отдельный символ > (а не весь символ - - > как целое) в качестве символа окончания комментария. Следует, кроме того, помнить, что некоторые пользователи просто не имеют доступа к современным браузерам (если, например, используют текстовые браузеры Lynx для UNIX или аналогичные Lynx-браузеры в переносных компьютерах). Если выделить строки сцена- рия в качестве комментария, то при использовании относительно современных, но не совмес- тимых с JavaScript браузеров, страница, все же, не будет выглядеть как некорректная. ! Обратите внимание на то, что строки комментария, содержащие операторы, ко- /назммгку торые предотвращают выполнение сценариев в старых браузерах, расположены • внутри дескрипторов «script». .«/script». Нельзя строки комментария вы- носить за пределы этих дескрипторов. Иначе этот метод не сработает. И еще несколько замечаний о способах скрытия комментариев, описанных в этой книге. Чтобы сэкономить место, в большинстве примеров не были приведены комментарии. Но, как в этом можно убедиться на примере реальных приложений (главы 48-57, приведенные на прилагаемом к книге компакт-диске), комментарии в них присутствуют. Если же сценарий создается для общих нужд, следует всегда добавлять комментарии в код сценария. Отображение текста В сценарии листинга 3.1 есть две строки одного типа, которые используются для отображения текста в данном документе. Это строки document .write (). О самом же объекте document речь пойдет в главе 18. Когда бы ни запрашивался объект (в данном случае это document) с целью выполнения определенного задания,' после названия задания обязательно поставьте круглые скобки. В ка- честве примера можно привести оператор write () — JavaScript должен знать, с какими данным его нужно применять. После имени задания указываются эти данные, называемые также параметрами. Поэтому если в документе нужно отобразить имя первого президента Соединенных Штатов, то сделать это можно так. document.write("George Washington") Строка текста, которую сценарий выводит на экран, начинается с некоторого предопреде- ленного фрагмента "This browser is version" (Это браузер версии), в который впо- следствии добавляется версия браузера. Далее на экран снова выводится статический текст, содержащий дескриптор HTML ("of «span class='highlight1 >"), затем более зна- чимый текст (название приложения), после чего — закрывающий дескриптор HTML и точка в конце предложения ("«/span»."). В JavaScript символ “плюс” (+) используется для объе- динения (конкатенации) фрагментов текста в одну большую строку текстовых символов, ко- торые отображаются в документе. Ни JavaScript, ни тем более символ + ничего не знают об используемых словах и пробелах, поэтому сценарий полностью отвечает за выделение нуж- ного места, что и отражается в параметрах. Обратите внимание, что после слова "version" в параметре первого оператора document. write () оставлено свободное место. Также сво- бодное место вы увидите с обеих сторон от "of" во втором операторе document. write (). Глава 3. Первый собственный сценарий 59
Для получения информации о версии браузера и названии, которые используются в пара- метрах, укажите JavaScript извлечь соответствующие свойства объекта navigator. Извлечь свойство можно, если добавить его через точку после имени объекта (в данном случае это navigator). Извлекаемые имена в приведенном примере разделены пробелом. Если вам тяжело сориентироваться в записи, то попробуйте прочитать ее справа налево. В этом случае то, что находится справа, является свойством расположенного слева. В нашем случае appVersion является свойством объекта navigator. Этот ‘'точечный” синтаксис во мно- гом напоминает вызов операторов действий (к примеру, document, write О), но только после имени свойства не нужно ставить круглые скобки. В любом случае, ссылка на свойство в сценарии дает указание JavaScript вставить значение этого свойства туда, откуда сделан за- прос. При первом обращении JavaScript-сценарий запросит информацию о браузере, предста- вит ее в виде текстовой строки и отобразит в документе. Наконец, обратите внимание на точку с запятой в конце каждого оператора JavaScript. На самом деле вводить ее совсем не обязательно. Ничего плохого в последнем случае не произойдет. Тем не менее, если вы планируете изучать более серьезные языки программирования, например, C++, то использование точек с запятой в конце операторов будет обязательным требованием. Улыбнемся вместе Если при первой попытке загрузить в браузер данный документ произошла ошибка, сле- дует вернуться в текстовый редактор и проверить строчка за строчкой сценарий, сравнив его с листингом 3.1. При этом помните о том, что было рассказано выше. Может оказаться, что один из символов расположен не на своем месте или вместо символа верхнего регистра введен символ нижнего регистра, или наоборот. В листинге могут отсутствовать кавычки или скобки. Чтобы увидеть, насколько динамичен сценарий scriptl.htm, вернитесь в текстовый редактор и замените слово "browser" на "client software". Теперь для отображения изменения в тексте документа нужно все сохранить, перейти в браузер и перезагрузить стра- ницу. Вы можете смело заменять любой текст, приведенный в кавычках в виде параметра в операторе document. write (). Параметры оператора document. write () являются текстом HTML, поэтому в нем можно использовать дескриптор "<Ьг>" для разрыва строк. При этом помните, что для отображения на экране любых внесенных изменений нужно со- хранить документ, перейти в браузер, а затем перезагрузить сохраненную страницу. 60 Часть I. Знакомство с JavaScript
Руководство по JavaScript
Объекты документа и браузера Зта глава является первой из девяти учебных глав (которые составляют часть П) и предназначена для тех, кто имеет, по крайней мере, базовые представления о HTML, их атрибутах и CSS. В данной главе можно будет найти несколько полезных приложений JavaScript, а также выяснить, как брау- зер, поддерживающий JavaScript, интерпретирует в качестве объектов, которыми можно управлять с помощью сценариев, старые добрые элементы HTML. Все, что изложено в этом ру- ководстве, может непосредственно использоваться в под- держивающих сценарии браузерах Internet Explorer 5 и выше (Windows и Macintosh), а также Mozilla и Apple Safari. Сценарии, которые творят чудеса Тот, кто уже создавал с помощью HTML документы, дол- жен знать, что именно дескрипторы HTML влияют на способ отображения данных, интерпретируемых браузером. При за- грузке страницы браузер производит опознание дескрипто- ров по угловым скобкам, которые содержат инструкции относительно выполнения требуемого форматирования. Инст- рукции эти считываются последовательно от начала докумен- та, а элементы, определяемые в документе HTML, появляются на экране в том порядке, в каком они расположены в исходном коде документа. Создатель документа только заносит в доку- мент дескрипторы; на этом его задача заканчивается. Браузер выполняет намного больший объем работы при отображении данных, причем делает это при каждой загрузке страницы. Представим себе, что один из элементов на странице являет- ся полем формы для ввода текста. Предполагается, что пользо- ватель должен ввести в это поле некоторый текст, после этого щелкнуть не кнопке Submit (Отправить) для отправки инфор- мации на Web-сервер. Если этой информацией должен быть почтовый адрес в Internet, возникает вопрос: как убедиться в том, что пользователь использовал в записи адреса символ @?
Одним из способов решения является использование CGI-программы (Common Gateway Interface — общий шлюзовой интерфейс). Эта программа проводит проверку формата пре- доставляемых серверу данных. Если пользователь, по неизвестным причинам, не применил символ ®, то CGI-программа отправит запрос назад браузеру, но на этот раз уже с требовани- ем включить указанный символ в адрес. В этом “обмене любезностями”, в принципе, нет ни- чего страшного, но для пользователя это означает существенную задержку во времени. Она вызвана необходимостью проверки наличия в адресе злополучного символа. Более того, для выполнения такой проверки и отправки ответа Web-серверу нужно задействовать дополни- тельные ресурсы. Web-узлы, как правило, достаточно загружены, поэтому процесс получения пользователем ответа занимает определенное время. Представим также, что после ввода текста (перед предоставлением его серверу) введенная пользователем запись может проверяться на наличие символа ® на стороне клиента. Соответст- вующая программа должна быть реализована непосредственно в документе. Браузер должен знать, как запускать эту программу. Например, она может запускаться в ответ на определенные действия пользователя (скажем, когда пользователь щелкает мышью на кнопке Submit). Если программа запускается средствами браузера и при этом обнаруживается отсутствие символа @, на экране должно появиться предупреждающее сообщение, адресованное пользователю. Та же программа должна определять, можно ли продолжать процесс предоставления текущих данных, или следует подождать, пока в поле будет введен корректный почтовый адрес. Такой способ предварительной проверки корректности вводимых данных является только одним из практических методов, часто реализуемых с помощью JavaScript. Рассматривая этот пример, можно прийти к выводу, что в сценарии должна предусматриваться возможность про- смотра содержимого текстового поля и управления процессом ввода данных. Браузер, способ- ный запускать программы JavaScript, без труда интерпретирует такие элементы, как текстовые поля, в качестве объектов. Сценарий JavaScript управляет поведением и функциональными воз- можностями объектов. Большинство из них можно увидеть на экране в окне браузера. JavaScript в действии Объектами на экране можно управлять. Для этого достаточно добавить несколько строк кода JavaScript в документ HTML. Чтобы у вас сложилось правильное представление о воз- можностях JavaScript по созданию приложений, обязательно изучите приложения, пред- ставленные на прилагаемом к книге компакт-диске (в папках для глав 48-57). Запустите эти приложения (откройте с помощью браузера) и проанализируйте, как они работают. Ссылки на файлы приложений, расположенные на компакт-диске, можно найти на странице tutorl. htm в папке с листингами программ. Интерактивный интерфейс Гиперссылки HTML вам пригодятся при исследовании Web, но их использование далеко не всегда позволяет наиболее удачным образом составить оглавление для узла или документа. Если привлечь к выполнению этой задачи JavaScript, то можно создать интерактивное разво- рачиваемое оглавление, отображающее иерархическую структуру большого объема данных (рис. 4.1). Подобно текстовым листингам (или деревьям просмотра), отображающимся в ок- нах менеджеров файлов операционных систем, разворачиваемое оглавление позволяет поль- зователю видеть ровно столько структурных элементов, сколько нужно. Для того чтобы просмотреть опции меню, следует щелкнуть на серой кнопке. Конечная оп- ция меню помечена специальной пиктограммой. Опции на схеме структуры могут содержать ссылки на другие страницы или информацию описательного характера. Шрифты отдельных за- писей можно изменять по своему усмотрению. Это обычная процедура в HTML. В прошлом Глава 4. Объекты документа и браузера 63
такие структуры обрабатывались сервером. Поэтому ответная реакция на щелчок мышью на опции реализовывалась со значительной задержкой. Если вы используете описанный выше способ предварительной обработки информации и разместите нужную программу на страни- це, то после первой загрузки все на странице будет открываться и закрываться очень быстро. Рис. 4.1. Так выглядит развернутое оглавление Поиск данных Стандартное приложение в Web, использующее CGI-программы, предоставляет в распо- ряжение пользователей окно, с помощью которого они получают доступ к базам данных на сервере. Большие хранилища данных рекомендуется размещать на сервере, где расположены специальные поисковые системы и другие вспомогательные средства управления, соответст- вующие наиболее часто решаемым задачам. Если страница используется как внешний интерфейс для поиска небольшого объема данных, можно рассмотреть целесообразность внедрения по- добных средств в документ (на странице они явно отображаться не будут) и задействовать JavaScript в качестве посредника между пользователем и этими данными. Такой подход реализован в префиксной системе поиска Social Security (Социальное стра- хование) — рис. 4.2. В этом случае данные распечатанной таблицы, состоящей примерно из 55 записей, конвертированы в список JavaScript, который занял всего несколько сотен байт. Ко- гда посетитель узла вводит в соответствующее поле трехсимвольный префикс номера собст- венного страхового полиса, сценарий, расположенный “за сценой”, сравнивает его с теми 55 (или около того) записями, которые представлены в таблице. Когда сценарий обнаруживает совпадение, то во втором поле выводится соответствующая регистрационная информация. Если приложение находится на сервере, и там же, в базе данных сервера, хранится нужная информация, то каждый щелчок на кнопке поиска — Search (Поиск) — означает задержку в несколько (а может и больше) секунд, которые уходят на обработку сервером запроса, по- лучение информации из базы данных и внесения изменений на страницу. Конечный результат 64 Часть II. Руководство по JavaScript
предоставляется пользователю спустя довольно длительное время. Если вместо всего этого использовать приложение JavaScript, то после первой загрузки страницы сценарии мгновенно выполнят все необходимые операции по поиску данных. Рис. 4.2. Поиск данных в небольшой таблице Проверка правильности введенных данных О проверке правильности введенных данных на форме мы уже говорили как об удачном использовании JavaScript. Поле ввода данных на странице поиска Social Security (см. рис. 4.2) создается в сценарии системой проверки корректности вводимых значений. Точно так же, как CGI-программа для каждого случая должна выполнять проверку равенства полученного зна- чения трехзначному числу, программа JavaScript обязана выполнить соответствующую про- верку любых поступающих извне сведений. Если в записи обнаруживается ошибка (палец мог соскользнуть с нужной клавиши и нажать другой символ), посетитель будет уведомлен об ошибке и ему предложат ввести данные еще раз. Сценарий проверки правильности данных может даже удалить в тексте ненужный или неправильный символ, поэтому посетителю узла останется лишь часть от исходно запрашиваемой комбинации символов. Интерактивные данные JavaScript предоставляет средства превращения статичных данных в йнтерактивную инфор- мацию. На рис. 4.3 показан графический калькулятор определения параметров электрического элемента (называемого резистор) в том случае, если известна только его цветовая маркировка. Глава 4. Объекты документа и браузера 65
Изображение в нижней части страницы состоит из семи изображений, расположенных ря- дом друг с другом на вертикальных ломтиках. Четыре ломтика представляют собой разно- цветные полосы, в то время как остальные три фрагмента — это выводы резистора и разде- лители между полосами. После того как пользователь выберет цвет из выпадающего списка в верхней части окна, для определенного изображения указанный ломтик изменит свою окра- ску. При этом значение сопротивления рассчитывается в соответствии с новой маркировкой, а результат выводится на экран. После загрузки страницы ответная реакция на действия пользователя следует незамедли- тельно. Если же вами используется размещенная на сервере версия приложения-калькуля- тора, то на изменение цвета уйдет не одна секунда. Более того, JavaScript обладает средства- ми предварительной загрузки всех используемых вариантов изображений в кэш-память брау- зера. Данная задача выполняется при загрузке основной страницы. Впоследствии это приво- дит к незначительному увеличению времени, отведенного на загрузку дополнительных изображений. Однако в дальнейшем при выборе посетителем нового цвета изменения вступят в силу незамедлительно. С таким приложением можно решать определенный круг задач, на которые оно непосредственно рассчитано. Многофреймовые документы Как известно, фреймы попадают в сферу управления HTML, однако они позволяют вы- полнить намного больше задач, когда за их управление берется JavaScript. Приложение Decision Helper (Помощник принятия решений), представленное на рис. 4.4, в полной мере реализует предоставляемые JavaScript возможности. 66 Часть II. Руководство по JavaScript
Рис. 4.4. Окно приложения Decision Helper Приложение Decision Helper содержит вполне профессиональный сценарий, использую- щий четыре вложенных окна (или фрейма) для ввода данных и одно вложенное окно, которое отображает результаты некоторых сложных вычислений, которые основываются на данных, вводимых в остальные четыре фрейма. Результат отображается как в числовом, так и в гра- фическом виде (в качестве диаграмм) — рис. 4.4. Взаимодействие между тремя фреймами основного окна реализуется с помощью JavaScript. Предположим, что пользователь щелкает мышью на кнопке со стрелкой в левом верхнем фрейме. При этом изменится не только документ, отображаемый в правом верхнем фрейме, но и инструкция, расположенная в нижнем фрейме. В нижнем фрейме отображается область анкера, определяемая в соответствии с содержимым фрейма, в который вводятся исходные данные. При составлении сценариев для документов, размещаемых в правом верхнем фрей- ме, используются различные технические приемы, позволяющие сохранить данные записей в процессе навигации. Такой подход напоминает путешествие по универсаму с корзинкой для выбора товаров. Только в данном случае используется диалоговый подход — сначала обраба- тываются данные о заказанных на нескольких страницах каталогах товаров, а затем они сум- мируются вместе в структурированной и упорядоченной форме. В принципе, работая с подобными приложениями, можно отказаться от использования про- грамм, запускаемых на сервере. Однако помните, что уровень взаимодействия и расчетов, который необходимо обеспечивать при обмене данными между пользователем и приложением, может в определенном случае привести к выполнению сценария с леденящей душу медлительностью. Динамический HTML Начиная с четвертой версии, браузеры Netscape и Microsoft предоставляют все больше и больше возможностей для изменения с помощью клиентских сценариев содержимого страниц. На рис. 4.5, например, показано, как с помощью сценариев реализовано перемещение областей карты Глава 4. Объекты документа и браузера 67
на рисунке. При выборе определенного штата его область подсвечивается соответствующим образом. Панель управления в окне приложения расположена справа, дополнительные элементы появятся только в том случае, если все области карты расположены в необходимых местах. Рис. 4.5. С помощью сценариев и динамического HTML можно создать такую игру Такой высокий уровень взаимодействия браузера со сценариями удается поддерживать благодаря использованию динамического HTML (Dynamic HTML или просто DHTML). При этом JavaScript становится соединительным мостиком между пользователем и используемы- ми в динамическом режиме элементами на экране. В подобных ситуациях нецелесообразно обращаться к программам, запускаемым на сервере, поскольку приложение должно мгновен- но реагировать на манипуляции пользователя с мышью и элементами страницы. И делать это нужно на высоком программном уровне. Принципы использования JavaScript Приведенные выше примеры продемонстрировали широкий диапазон функций JavaScript. Однако JavaScript может выполнить не все задачи. Управлять элементами HTML в Web с по- мощью JavaScript имеет смысл в таких случаях. Проверка корректности данных, введенных на форме. Если в поле формы нужно ввести данные для дальнейшей обработки сервером, поручите сценариям клиента про- вести предварительную проверку соответствия введенных на форме данных установ- ленному для такого случая формату. Не использующие сервер CGI-программы. В данном случае нужно либо использо- вать JavaScript для создания приложения, любо применить CGI-программы, запускае- мые на сервере. В последнем случае скорость выполнения операций низкая, поскольку необходимо поддерживать интерактивный режим между программой и пользователем. В него входят такие задачи, как поиск данных небольших объемов, внесение изменений 68 Часть II. Руководство по JavaScript
в изображения, а также генерирование HTML-кода на основе введенных пользовате- лем данных в других окнах и фреймах. Интерактивная работа в динамическом HTML. Если элементы на странице имеют жесткую привязку, то использовать средства DHTML и создавать сценарии для их управления не стоит. Если предполагается, что содержимое будет двигаться по стра- нице произвольным образом, то хороший сценарий будет просто необходим. Создание прототипов CGI-сценариев. Иногда необходимо, чтобы CGI-программа была внедрена в приложение, поскольку это потенциально устраняет проблемы несо- вместимости между типами и версиями браузеров. Еще проще создать с помощью JavaScript прототип CGI-программы. Эту возможность следует использовать для того, чтобы довести “до ума” пользовательский интерфейс перед тем, как реализовать при- ложение в качестве серверного CGI-сценария. Разгрузка сервера. Если вами используется очень загруженный Web-узел, то следует отказаться от частого обращения к CGI-программе в пользу применения сценариев JavaScript, выполняющих те же действия. После того как страница загружена, сервер освобождается для обслуживания других посетителей узла. Это снимает загружен- ность не только сервера, но также позволяет пользователям остальных CGI-программ быстрее получить ответ на введенные ранее данные. Обеспечение динамизма в “мертвых” страницах. Сам по себе язык HTML очень не- затейливый. Выделение цветом фрагментов текста удивляет только вначале. Исполь- зование анимации с изображениями в формате GIF скорее отвлекает и редко вызвано конкретной необходимостью представления данных. Но если обеспечить страницу пусть даже небольшими интерактивными средствами, то это поможет привлечь поль- зователей и дать им повод посетить страницу снова или порекомендовать своим друзьям сделать то же самое. Создание “интеллектуальных” Web-страниц. Если позволить воображению разгу- ляться, то можно разработать новые, интригующие способы обучения своих страниц “интеллектуально” обрабатывать данные. Например, в приложении главы 54 можно увидеть, как (без использования серверной CGI-программы или баз данных) страница HTML “запоминает” последние посещения страницы пользователем. При этом все эле- менты, которые были изменены после последнего посещения (независимо от их количе- ства), будут восстановлены в первоначальном виде. Это пример “интеллектуальной” HTML-страницы, который наглядно демонстрирует возможности JavaScript. Объектная модель документа Перед тем как приступить к созданию серьезных сценариев, составьте правильное пред- ставление о тех объектах, непосредственно для которых и будут писаться сценарии. Рабо- тающий со сценариями браузер выполняет огромную работу по программному созданию объектов, которые потом, в основном, и реализуются в качестве отображаемых на HTML- странице элементов. Объектами являются элементы управления форм (текстовые окна и кнопки), а также (в последних версиях браузеров) изображения. Тем не менее, в модели пред- ставлены и другие объекты, которые не столь наглядны с точки зрения внешнего вида стра- ницы и его программной основы. Их назначение, однако, становится вполне понятным, если рассматривать дескрипторы, которые используют в HTML элементы, предназначенные для генерирования содержимого страницы (примером может служить многофреймовая страница). Для того чтобы позволить сценарию управлять всеми этими объектами, а также помочь разработчикам страниц как-то упорядочить огромное количество объектов на страницах. Глава 4. Объекты документа и браузера 69
создатели браузеров придумали объектную модель документа (document object model или DOM). Эта модель является прототипом или структурой организации объектов на странице. Недостаточный уровень совместимости браузеров разных типов и версий повергает соз- дателей сценариев в отчаяние, особенно если (с самого начала) они изучают объектную мо- дель только для последней версии одного типа браузеров — не принимая во внимание огра- ниченные возможности ранних версий браузеров и браузеров других производителей. Усилия всевозможных организаций по разработке стандартов (вспомните только W3C) привели к соз- данию спецификаций для синтаксиса и набора свойств объектных моделей, что обеспечило, по сравнению с оригинальными разработками, большую гибкость. Концепция DOM, постро- енная на основе стандартной объектной модели, с которой можно познакомиться в данном руководстве, реализована с разной степенью поддержки во всех современных браузерах. Если бы на рынке доминировали исключительно браузеры, которые поддерживают стандарт W3C DOM (о том, что это не так, вы узнаете в главе 9), то это бы значительно упростило процесс создания межбраузерных решений и высокодинамичных документов. Однако в любом слу- чае, чтобы иметь достаточный багаж знаний, предстоит многому научиться. Структура HTML и DOM Главное предназначение языка HTML состоит в определении форматирования и структу- ры документа на уровне составляющих его элементов. Те дни, когда HTML применялся ис- ключительно для определения вида текстовых строк на экране, давно ушли. Сейчас сложно представить себе ситуацию, когда для отображения текстового фрагмента шрифтом большо- го размера нужно применять только дескриптор <Ы> и никакой другой. Дескриптор <hl> имеет специальное назначение в браузере— он определяет в HTML-документе заголовки первого уровня. К счастью, в настоящий момент вам не обязательно для отображения текста абзаца шрифтом большого размера обозначать его как заголовок определенного уровня. Вы всегда можете заключить текст в дескриптор абзаца (<р>), а затем определить форматирова- ние текста этого абзаца с помощью стиля CSS. Подобная практика также распространяется на дескрипторы <Ь> и <i>, с помощью которых задается полужирное и курсивное начертание. Вместо того чтобы заключать форматируемый текст в соответствующий дескриптор, вы мо- жете спокойно применять стили CSS, указывающие все необходимое форматирование. Результатом структурированности HTML является вложение отдельных элементов доку- мента соответственно заранее определенной иерархической таблице. Например, пустой HTML-документ имеет следующую иерархическую структуру. <html> <headx/head> <bodyx/body> </html> Рис. 4.6. Иерархическая структура пустого HTML-документа Как видите, элемент html содержит два вложен- ных элемента: head и body. Иерархическую структу- ру подобного документа можно представить в более наглядном виде с помощью организационной диа- граммы, как показано на рис. 4.6. Подобно семейному фамильному дереву, в такой иерархической структуре можно легко продемонстрировать родительско-дочер- ние отношения. В случае HTML-документа элемент html является родителем двух вложенных в него дочерних элементов head и body. 70 Часть II. Руководство по JavaScript
Объектная модель окна документа Как и предполагает название, формальная DOM описывает, в основном, HTML-документ и его содержимое. Но уже вскоре вам придется в своих приложениях обращаться не только к элементам документа, но и к элементам среды — окнам браузера. На самом высоком уровне окна браузера располагается объект window. Общая иерархическая структура объектной мо- дели современных браузеров выглядит так, как показано на рис. 4.7. Рис. 4.7. Базовая объектная модель современных браузеров На данном этапе ознакомления с JavaScript нет необходимости запоминать модель. Вам необходимо проанализировать общие методы представления объектов. Ниже описаны неко- торые ключевые объекты, показанные на рис. 4.7, и описаны их связи с другими объектами. Объект окна (window). Вверху иерархической структуры находится окно (window). Этот объект представляет ту часть окна браузера, в которой отображается содержимое HTML-документа. В многофреймовой среде каждый фрейм (или кадр) также является окном (детально это пока рассматривать не будем). Поскольку все события, относящиеся к документу, происходят именно в окне, то оно и является самым общим элементом в иерархической структуре объектов. В нем, в буквальном смысле, размещен документ. Объект navigator. С помощью этого объекта определяется браузер, в котором вы- полняется сценарий. Он содержит сведения о производителе и версии браузера. Этот объект имеет атрибут только чтения (чтобы “зловредные” сценарии не могли получить доступ к свойствам браузера). Объект экрана (screen). Это еще один объект с атрибутом только чтения. Объект screen позволяет определить физическую среду, в которой запускается браузер. На- пример, с его помощью определяется разрешение экрана. Объект history. Каждый браузер сохраняет сведения об уже посещенных страницах (кнопка Back (Назад) на панели инструментов) в специальном стеке, представленном объектом history. Как и следовало ожидать, этот объект функционально дублирует кнопки Back (Назад) и Forward (Вперед). Объект location. С помощью этого объекта проще всего загрузить в текущее окно целевую страницу или фрейм. Сведения об URL-адресе документа представлены та- ким образом, чтобы в сценарии нельзя было отследить защищенные Web-узлы. Объект документа (document). Каждый HTML-документ, загружаемый в окно брау- зера, становится объектом document (документ). В иерархической структуре поло- жение объекта документа (рис. 4.7) является весьма важным. В объекте document со- держится большинство остальных типов объектов модели. Со стороны это выглядит просто здорово: в документе находится то, что используется в сценарии. Глава 4. Объекты документа и браузера 71
Загрузка документа Языки программирования (например, JavaScript) являются прекрасными посредниками между представлениями пользователя о том, как работают программы, и тем, что происходит при этом в компьютере на самом деле. Внутри компьютера каждый оператор в листинге про- граммного кода приводит к записыванию и перемещению битов данных (этих легендарных ну- лей и единиц компьютерного двоичного мира) из одного раздела оперативной памяти в другой. Языки и объектные модели, с точки зрения использования их в самом компьютере (или, в слу- чае использования JavaScript, в области памяти, выделяемой в компьютере для браузера) нужны для того, чтобы программистам было легче представить, как программа работает, и каков будет результат ее выполнения. Ситуация очень похожа на ту, когда нужно проехать автомобилем из пункта А в пункт Б. При этом можно и не знать, как работает двигатель внутреннего сго- рания, рулевой привод и вся остальная начинка автомобиля. Вояж можно осуществить, управляя автомобилем с помощью одних только основных элементов: ключа зажигания, ры- чага переключения передач, педалей газа, сцепления и тормоза, а также руля управления. Конечно, программирование существенно отличается от управления автомобилем с авто- матической трансмиссией. Даже для написания сценария нужно (продолжим проводить ана- логию) уметь открыть капот и проверить ту же трансмиссию или заменить масло. Поэтому сейчас самое время открыть капот и разобраться, что же происходит с объектной моделью документа при загрузке страницы в браузер. Простой документ На рис. 4.8 приведен код HTML и соответствующая ему объектная модель для очень просто- го документа. Когда происходит загрузка соответствующей страницы, в памяти браузера реали- зуется поддержка структуры объектов, сгенерированных согласно использованным в документе дескрипторам HTML. На рисунке показана только часть иерархической структуры окна доку- мента, начиная с объекта document. Этот объект детально будет описан позже, а сейчас про- сто имейте в виду, что он существует, поскольку это часть объектной модели в памяти брау- зера. На диаграмме он выделен полужирным начертанием. В приведенном примере в объект document вложено три объекта, один из которых, html, расположен на более высоком уровне. <html> <headx/head> <body></body> </html> Рис. 4.8. Простой документ и структура его объектов Добавление элемента абзаца Теперь можно переделать файл HTML так, чтобы он содержал пустой элемент абзаца. На рис. 4.9 показано, как при этом изменится документ HTML (изменения выделены полужирным начертанием) и соответствующая ему структура объектов, создаваемая браузером. Даже если 72 Часть II. Руководство по JavaScript
между дескрипторами формы <р> ничего не введено, одного их наличия достаточно для того, чтобы браузер создал объект абзаца в объекте body. Обратите внимание также на то, что объект body, согласно текущей иерархической структуре, является дочерним для объекта документа. <html> <headx/head> <body> <рх/р> </body> </html> Рис. 4.9. Если добавить абзац, то получится такая струк- тура объектов Добавление в абзац текста Продолжаем вносить изменения в файл — на этот раз добавим в абзац текст и разместим его между открывающим и закрывающим дескрипторами. Результат выполнения этой проце- дуры можно увидеть на рис. 4.10. Добавление текста между дескрипторами приводит к до- бавлению в DOM специального типа объектов, называемого текстовым узлом (node). Для текстового узла всегда определяется объект, в котором содержится текст, — контейнер. При- меняя стандартную терминологию, можно сказать, что текстовый узел является дочерним по отношению к контейнеру р. <html> <head></head> <body> < p>This is the one and only paragraph.</p> </body> </html> Puc. 4.10. Добавление в абзац текста Глава 4. Объекты документа и браузера 73
Создание нового элемента Последнее изменение файла состоит в добавлении в текст абзаца дескриптора <ет>, с помощью которого фрагмент абзаца выделяется другим начертанием (рис. 4.11). Даже такая простая операция вызывает изменение в иерархической структуре документа. Обратите вни- мание, что теперь объект р имеет три вложенных объекта: два текстовых узла и элемент ме- жду ними. В W3C DOM текстовый узел не может иметь дочерних объектов, а потому не со- держит других элементов. Наряду с этим текст, заключенный в дескриптор <ет>, не является дочерним по отношению к объекту р, а вкладывается в объект ет. Таким образом, текстовый узел элемента ет расположен на два уровня ниже элемента абзаца. <html> <headx/head> <body> <p>This is the <em>one and only</em> paragraph.</p> </body> </html> Puc. 4.11. Добавление в текстовый узел элемента Надеемся, у вас уже сложилось определенное представление о том, как в соответствии с дескрипторами HTML создаются объекты в памяти браузера. Далее мы перейдем к рас- смотрению способов взаимодействия сценария с этими объектами. Отметим, что создание сценариев является одним из основных методов управления объектами. Связывание объектов Если документ загружен в браузер, все его объекты надежно размещены в памяти соглас- но той внутренней иерархии, которая определяется объектной моделью документа браузера. Чтобы сценарий мог управлять любым из этих объектов, должен существовать способ полу- чения доступа к объекту и взаимодействия с ним. Примерно так: “Привет, мистер Текстовое Поле! Что там ввел пользователь?”. Если в сценарии необходимо определить расположение одного из этих объектов, то сценарий должен указать тот путь, по которому следует двигать- ся для установления контакта с нужным объектом. Это именно то, что называется в сценарии ссылкой на объект, которая задается браузером. 74 Часть II. Руководство по JavaScript
Именование объектов Наилучший способ создания в сценариях ссылок на объекты заключается в том, чтобы присвоить каждому управляемому в документе HTML-объекту в сценарии собственное имя. В W3C DOM (и текущей спецификации HTML) для определения элементу имени применяют атрибут id (идентификатор). Этот атрибут необязательный, но он позволяет однозначно при- своить каждому объекту собственное имя. Если вы планируете получать в сценарии доступ к элементам страницы, то без него вам не обойтись. Ниже приведен пример использования атрибута id вместе с обычными дескрипторами. < р id=nfirstParagraph" > <img id=nlogon src="images/logo,jpg" alt="Corp Logo"> <div class="draggable" id="puzzlePiece"> При присвоении имен (названий, идентификаторов) придерживаются следующих правил. Имена не могут содержать пробелы. В именах не должны использоваться символы пунктуации, за исключением символов подчеркивания. При их присвоении в качестве значения атрибуту name они должны заключаться в кавычки. Имена не должны начинаться с цифры. Процесс присвоения имен можно сравнить с ситуацией, когда на конференции всем ее участникам выдают бейджи с именами. Чтобы найти необходимого вам человека, вам нужно встать у входа и быстро просмотреть бейджи каждого входящего. Вы также можете поискать в зале в надежде найти того, кто вам нужен. Ссылка на объект В W3C. DOM вы быстро получите доступ к любому именованному элементу документа. Если вы ранее не занимались программированием, то ссылка на объект может вас обескура- жить своей сложностью. Как бы там ни было, вам придется смириться с предложенным в W3C синтаксисом — вы будете использовать его в JavaScript повсеместно. Ниже приведен пример используемой в JavaScript ссылки на объект. window.document.getElementByld("ИдентификаторОбъекта") В этом коде элемент определяется по идентификатору, задаваемому выражением ИдентификаторОбъекта. Например, если вы хотите обратиться в сценарии к элементу аб- заца с идентификатором f irstParagraph, то используйте следующую ссылку. window.document.getElementByld("firstParagraph") Обратите внимание на то, что имена ключевых слов в JavaScript чувствительны к регистру. В методе getElementByld () используется три буквы в верхнем регистре (хотя так и хочется написать не Id, a ID). Метод getElementByld () относится к объекту document. Таким образом, с его по- мощью вы можете найти любой элемент документа, идентификатор которого вам известен. В JavaScript для разделения элементов иерархической ссылки используется точка. Каждая ссылка обычно начинается с наиболее глобального уровня (здесь объект document) и даль- ше с использованием точки (.) в качестве разделителя выполняется все большая конкретиза- ция ссылки. Каждый объект имеет свой набор вложенных объектов (детально с ними, вы мо- жете ознакомиться в приложении А). Глава 4. Объекты документа и браузера 75
Атрибут name и идентификатор id До спецификации HTML 4.0, в которой впервые был представлен атрибут id, доступ к объек- там в сценарии реализовался с помощью атрибута name. Элементы, которые поддерживают атрибут пате, обычно предназначены для управления изображениями, формами и фрейма- ми. Детально с атрибутом name объектов вы ознакомитесь в главе 9. На самом деле боль- шинство браузеров по-прежнему распознают этот атрибут. Более того, только с его помощью во многих системах можно передать на сервер данные, которые введены в текстовые поля, выбранные в списках пользовательской формы. Исходя из этого, настоятельно рекомендует- ся одному и тому же объекту назначать одинаковые атрибуты id и name. Терминология, используемая при управлении узлами В терминологии W3C DOM для описания иерархической структуры объектов применяют некоторые метафорические приемы. С одним из них вы должны ознакомиться на самых пер- вых этапах изучения языка JavaScript. Речь идет об узлах. Еще одним важным понятием яв- ляются родительско-дочерние отношения между объектами. Что такое узел Словарь английского языка фиксирует несколько значений слова узел. Одно из них (наиболее близкое к используемому в W3C DOM) — нарост, почка на ветке дерева. Обычно такое образование на ветке впоследствии приводит к возникновению нового листика или по- бега. Если говорить о листике, то мы получаем тупиковую ситуацию, в которой дальнейшее раз- витие узла невозможно (из листа не вырастет другая ветка). А вот из побега мы имеем шанс по- лучить другие ветки или листья, т.е. дочерние узлы. При определении структуры HTML- документа вы также определяете его узлы (создаете так называемое дерево узлов, расположение веток и листьев на котором полностью зависит от используемых в документе элементов). В W3C DOM основным элементом является простой узел. В документе HTML нам при- дется работать преимущественно с двумя специальными типами узлов — узлами элементов и текстовыми узлами. В первом случае узел соответствует элементу документа, а во вто- ром — тексту, введенному между открывающим и закрывающим дескрипторами элемента. Зачастую вы будете управлять узлами обоих типов, даже не догадываясь об этом. Предлагаем вернуться к уже рассмотренной ранее модели, иерархическая структура кото- рой отображена на диаграмме (рис. 4.12). Каждый блок диаграммы представляет отдельный объект документа. К узлам элементов относятся document, html, head, body, p и em. Три текстовых узла представлены блоками на нижних уровнях структуры: они содержат текст, за- ключенный в кавычки. Как вы видели ранее, после добавления в длинную текстовую строку нового элемента (em) один текстовый узел был разделен на три небольших текстовых узла. Два текстовых узла остались на том же уровне иерархической структуры, и только один сме- стился на уровень ниже — тот, который помещается в добавленный элемент em. Отцы и дети Внимательно изучите элемент р на рис. 4.12 — он имеет три дочерних узла. Первый и по- следний представлены текстовыми узлами, а второй — узлом элемента. Если элемент имеет несколько дочерних (вложенных) узлов, то их порядок перечисления определяется исключительно 76 Часть II. Руководство по JavaScript
порядком их представления в HTML-коде. Таким образом, первый дочерний объект элемента р — это текстовый узел, содержащий фразу “This is the ”. В случае элемента ет долго гадать не приходится — он имеет только один дочерний узел. <html> <head></head> <body> <p>This is the <em>one and only</em> paragraph.</p> </body> </html> Puc. 4.12. Дерево узлов документа HTML Дочерними объектами элемента далеко не всегда выступают текстовые узлы. На рис. 4.12 объект html имеет два дочерних узла элементов body и head. Первый из них содержит все- го один вложенный узел — р. Несмотря на то, что объект head является тупиковой ветвью, он представляет узел элемента, а потому может включать в себя другие узлы элементов и тек- стовые узлы (например, элемент title). Как нетрудно заметить, дескриптор HTML пред- ставляет узел элемента, независимо от того, имеет ли он дочерние узлы. Наряду с этим, тек- стовый узел — это всегда тупиковая ветвь иерархической структуры. Обратите также внимание, что дочерний узел всегда содержится в узле элемента. Этот контей- нер представляет собой родительский узел. Таким образом, в рассмотренной выше иерархической структуре элемент ет имеет один дочерний текстовый узел и родительский узел элемента р. Чтобы детально разобраться в терминологии W3C (см. главу 14), вам необходимо хорошо ориентировать- ся в иерархической структуре создаваемого документа. Например, в DHTML для редактирования текста, добавленного в элемент ет (рис. 4.12), ссылка на необходимый фрагмент будет начинаться с обращения к контейнеру текстового узла: document .getElementByld (). При этом пред- полагается, что элементу ет уже назначен атрибут Id. Если вы этого eifte не поняли, то я попробую удивить вас тем, что объект document в нача- ле ссылки также является узлом элемента. Как правило, его называют узлом документа. Каж- дый документ имеет только один узел документа, и именно этот узел предоставляет программи- сту доступ к остальным узлам документа. Поэтому нет ничего удивительного в том, что ссылка на объекты в документе по атрибуту id начинается именно с указания узла document. Понятия, определяющие объект Если при загрузке страницы браузер обнаруживает в исходном коде дескриптор HTML, который определяет объект, то для этого объекта в памяти будет выделена специальная об- ласть. Однако понятно, что объект — это нечто более сложное, чем, скажем, обычное число, Глава 4. Объекты документа и браузера 77
записанное в память. Объект должен представить некоторую “структуру”. Поскольку в JavaScript приходится иметь дело с элементами, которые появляются в окне браузера, то объектами мо- гут быть текстовые поля для ввода данных, кнопки или даже весь документ HTML. Выходя за рамки ограниченного мира браузера, поддерживающего JavaScript, важно отметить, что объект может представлять и довольно абстрактные понятия (например, записи в программе электрон- ного календаря или слой графических изображений в графическом редакторе). Каждый объект неповторим в своем роде, даже если в браузере такие объекты выглядят очень похоже. Существует три основных фактора, которые непосредственно определяют объект. Они дают представление о том, чем является данный объект, как он выглядит и как с помощью сценариев им можно управлять. Этими тремя определителями являются свойст- ва, методы и обработчики событий. С точки зрения работы в JavaScript, они очень важны. В приложении А приведены полные данные о свойствах, методах и обработчиках событий для каждого элемента объектных моделей, используемых в различных поколениях браузеров. Свойства Каждый реальный физический объект, который читателю приходилось когда-либо дер- жать в руках, обладает особыми характеристиками, которые определяют его поведение. Мо- нета, например, имеет определенную форму, диаметр, толщину, цвет, вес, чеканное изобра- жение на каждой стороне и огромное количество других атрибутов, которые отличают ее, скажем, от пера птицы. Каждая такая характеристика называется свойством. Каждому свой- ству соответствует определенное значение (даже если это значение не определено, то свойст- во равно null). Например, свойством для формы монеты можно определить “круглая” — в этом случае оно принимает текстовое значение. В качестве значения свойства, определяю- щего достоинство монеты, скорее всего будет использована числовая величина. При написании кода HTML (для использования в поддерживающих сценарии браузерах) свойства объектов устанавливаются даже без явного использования кода JavaScript. Наиболее общий способ начальной установки свойств объектов HTML состоит в использовании атри- бутов дескрипторов. Например, следующий дескриптор HTML применяется для того, чтобы определить объект кнопки button. Здесь же присваиваются значения для двух свойств. <input type="button" id="clicker" name="clicker" value="Hit Me..."> В JavaScript свойства id и name имеют значение clicker, в то время как для свойства value определено текстовое значение Hit Me..., которое будет отображено на кнопке. На самом деле кнопка имеет более двух свойств, однако необходимости устанавливать сразу все свойства для каждого объекта нет. Для большинства свойств предусмотрены используемые по умолчанию значения, которые им автоматически и присваиваются, если ничего другого в коде HTML или в сценарии им не назначено. Значение некоторых свойств может быть изменено в процессе загрузки документа и взаи- модействия пользователя со страницей. Рассмотрим такой пример с использованием деск- риптора описания текстового поля. <input type="text" id="entry" name=" entry" value="User Name?"> Свойства id и name данного объекта имеют значение entry. Когда происходит загрузка страницы, текстовое значение атрибута value будет выведено в текстовом поле. Это пример поведения текстового поля в HTML с использованием атрибута value. Но если пользователь введет в текстовое поле что-то другое, то значение свойства value изменится — однако не в HTML, а в поддерживаемой браузером копии объектной модели, хранящейся в памяти. По- этому, если сценарий обращается к текстовому полю с целью получения значения свойства value, браузер выдаст текущее значение свойства. В случае если пользователем вносились изменения в текст, то это будет далеко не то значение, что указано в коде HTML. 78 Часть II. Руководство по JavaScript
Для получения доступа к свойству объекта используется тот же тип синтаксиса с исполь-, зованием точек, что и в иерархической структуре, описанной ранее для объектов. Каждое свойство принадлежит своему объекту, а ссылка на свойство состоит из ссылки на данный объект плюс еще одно дополнительное расширение, указывающее на нужное свойство. По- этому для описанных выше дескрипторов кнопок и текстовых объектов ссылки на различные их свойства выглядят так. document.getElementByld("clicker").name document.getElementByld("clicker").value document.getElementByld("entry").value Отсутствие в ссылке указателя на window может вызвать удивление. Как уже отмечалось, одно окно может содержать только один документ. Поэтому при ссылке на объект внутри до- кумента вы можете не использовать указатель window в ссылке — начинайте сразу с document. Тем не менее, пропустить в ссылке указатель на document нельзя. Ссылки в Internet Explorer В W3C DOM Microsoft предложила ссылку на элемент объекта заменить простым указанием атрибута id для данного элемента (если такой элементу присвоен). В таком случае код бу- ' дет легче читать и понимать даже спустя некоторое время после его написания. Такой поход, тем не менее, уместен только в Internet Explorer 4 и выше. Чаще всего ссылка на объект по атрибуту id начинается с выражения document .all. Вы можете встретить и другие вари- анты, но все они будут справедливы только для последних версий браузеров Microsoft. На- пример, если элемент абзаца имеет идентификатор myParagraph, то в коде к нему можно обратиться с помощью следующего выражения. document.all.myParagraph Вы всегда вправе опустить первую часть выражения и оставить только значение атрибута id. myParagraph Как ни странно, но ни один из вариантов синтаксиса не соответствует стандарту W3C DOM. Только в IE5 и выше реализована полная поддержка обоих вариантов ссылок. Забегая напе- ред, скажу, что вам придется “подгонять” подобный синтаксис под стандарты W3C, чтобы он корректно выполнялся в большинстве браузеров. Методы Если свойство объекта можно сравнить с прилагательным, то метод будет соответство- вать глаголу. Под методом понимают все, что имеет отношение к действиям объекта. Метод может, скорее, выполнить что-то для объекта или с объектом, чем воздействовать на другие компоненты сценария или документа. По своей сути это команды, но способ и характер их выполнения связаны с конкретным объектом. С объектом можно связать любое количество методов (или их может не быть вообще). Чтобы задействовать метод (обычно это называется вызовом метода), в операторе JavaScript нужно сделать на него ссылку— через соответствующий объект с использованием после имени метода пары скобок (см. следующий пример). document.getElementByld("orderForm").submit() document.getElementByld("entry").focus() В первом случае сценарий используется для того, чтобы по щелчку на кнопке Submit (Отправить) отправить форму (которая называется orderForm) на сервер. Во втором случае производится выделение текста в текстовом поле с именем entry. В некоторых случаях для выполнения поставленной задачи, методу необходимо сообщить дополнительную информацию. Каждая порция такого рода данных, передаваемых методу, называется параметром или аргументом (можно использовать эти термины параллельно). Глава 4. Объекты документа и браузера 79
Пример использования параметров можно найти в первом сценарии, описанном в предыду- щей главе, где был задействован метод write () объекта document. document.write("This browser is version " + navigator.appVersion) document.write(" of <b>" + navigator.appName + "</b>.") Когда страница загружается в браузер, каждый метод document .write О отправляет в те- кущий документ весь содержащийся в скобках текст. В обоих приведенных примерах содержи- мое будет отправлено как параметр, состоящий из обычного текста (заключенного в кавычки) и значения двух свойств объекта: это свойства appVersion и appName объекта navigator. Некоторым методам нужно указать больше одного параметра. В таком случае параметры следует отделять друг от друга запятыми. Например, в версиях браузеров, начиная с четвер- той, объектом window поддерживается метод, который перемещает окно к определенной точке на экране. Эта точка задается двумя числами (координатами), которые указывают ко- личество пикселей от левого и верхнего краев экрана, соответственно, до точки, где должен располагаться левый верхний угол окна. Для перемещения окна браузера на 50 пикселей вле- во и на 100 пикселей вниз можно использовать такой код. window.moveTo(50,100) , При изучении особенностей работы в JavaScript и описываемых объектов документа сле- дует обращать особое внимание на те методы, которые применяются для каждого подобного объекта. Это поможет определить функции объекта и способы управления им в сценариях. Обработчики событий Еще одной важной характеристикой объектов в JavaScript являются обработчики собы- тий. Событиями называется все, что происходит в документе. Как правило, это результат действий пользователя. Общим примером действий пользователя, продуцирующих события, является щелчок мышью на кнопке или введение в текстовое поле символа. Другие события (например, процесс загрузки документа в окно браузера или появление ошибки при загрузке изображения) столь очевидными не являются. В документе практически все объекты JavaScript получают сообщения того или иного рода (см. приложение А, раздел справочных сведений). Чтобы определить, как должен реагировать объект на событие, воспользуйтесь дополнительным атрибутом, который вводится в HTML при описании объекта. Этот атрибут состоит из имени события, знака равенства (как и любой атри- бут в HTML), после которого следует инструкция, указывающая на то, что же нужно делать при наступлении конкретного события. В листинге 4.1 приведен пример очень простого документа, где отображается всего одна кнопка, для которой определен единственный обработчик события. 4.1, Кпапка собрав | <html> <body> <form> cinput type="button" value="click me" onclick="window.alert (’ouchI ') " > </form> </body> </html> Описание формы внешне ничем не отличается. Однако стоит обратить внимание на по- следний атрибут onclick="window.alert ('Ouch! ') ". Объекты кнопок (как в этом можно будет убедиться в главе 22) реагируют на щелчки мышью. Когда пользователь щелкает 80 Часть II. Руководство по JavaScript
на кнопке, браузер отправляет кнопке сообщение о щелчке. В описании этой кнопки с помо- щью специального атрибута указано следующее: когда бы кнопка ни получила такое сообще- ние, она должна задействовать один из методов объекта окна window с именем alert (). Метод alert () отображает обычное диалоговое окно предупреждения, содержимым кото- рого является текст, указанный в качестве параметра данного метода. Как и большинство ар- гументов атрибутов HTML, значения в правой части после знака равенства заключаются в ка- вычки. Если при этом нужно еще раз использовать кавычки (как в данном случае, когда в качестве параметра передается еще и текст), то в качестве таких внутренних разделителей ис- пользуются одинарные кавычки. В принципе, для JavaScript особой разницы нет, какие кавычки используются — одинарные или двойные. Просто нужно придерживаться принципа соответст- вия типов кавычек. Это значит, что можно описать атрибут таким образом. onclick='alert("Ouch!")1 Упражнения 1. Какую из приведенных далее задач с точки зрения клиента можно выполнить с помо- щью JavaScript? Ответ объясните. а) Воспроизведение музыки. б) Средство подсчета посетителей Web-узла. в) Комната бесед. г) Графическое средство переведения показаний градусника из градусов Фаренгейта в градусы Цельсия. д) Все из вышеперечисленного. е) Ни одно из вышеперечисленных. 2. Какие имена являются корректными в JavaScript? Ответ объясните. a) lastName. б) company_name. в) IstLineAddress. г) zip code. д) today' s_date. 3. Используя диаграмму на рис. 4.12 в качестве основы, нарисуйте диаграмму иерархиче- ской структуры, представляющей следующий HTML-код. Напишите ссылку на эле- мент второго абзаца в стандарте W3C DOM. <html> <head> <title>Search Form</title> </head> <body> <p id=" logoPar" ximg src="images/logo.jpg" height="90" width="300" alt="Logo" /x/p> ' <p id="formPar"> «form name="searchForm" action="cgi-bin/search.pl" method="POST"> Search for: <input type="text" name="searchText" /> <input type="submit" value="Search" /> </form> Глава 4. Объекты документа и браузера 81
</р> </body> </html> 4. Приведите две общие характеристики для текстового узла и узла элемента. Назовите две разные характеристики этих типов узлов. 5. Напишите дескриптор HTML для элемента кнопки с именем Hi, на которой отобража- ется надпись Howdy (Привет), а обработчик события onclick вызывает диалоговое окно предупреждения, содержащее строку Не Но to you, too! (Привет и тебе!). 82 Часть II. Руководство по JavaScript
Сценарии и документы HTML i® этой главе вы узнаете, как сценарии встраиваются в HTML-документы и из чего состоит код сценариев. Речь также пойдет о том, как при загрузке документа или в ответ на действия пользователя эти операторы выполняются. Кроме того, будут описаны способы поиска ошибок в сценариях. Размещение сценариев в документах В главе 4, к сожалению, вопрос о том, как именно выгля- дят сценарии или в каком месте их следует добавлять в до- кумент HTML, не затрагивался. В данной главе мы наверста- ем упущенное. Дескрипторы сценария <script> Чтобы браузер мог узнать те строки кода в документе HTML, которые соответствуют сценарию, этот код следует выде- лить с помощью дескрипторов <script>... <\script>. Та- кой подход является общим в HTML. Между открывающим и закрывающим дескрипторами размещается определенное содержимое, которое находится под управлением этих деск- рипторов. В этом можно убедиться хотя бы на примере опи- сания форм и абзацев текста. Для управления сценарием в дескрипторе <script> можно использовать различные атрибуты, которые зависят от типа используемого браузера. Один из атрибутов, которые под держивают браузеры, управляющие сценариями, является type (тип). Данный атрибут имеет огромное значение, по- скольку в разных типах и версиях браузеров указываются различные параметры для используемого языка написания сценариев (это может быть, например, VBScript, в Internet Explorer). Один из параметров, который воспринимают все поддерживающие сценарии браузеры, приведен ниже. <script type="text/javascript">
Обязательно убедитесь, что в код добавлен дескриптор окончания сценария. Все строки кода JavaScript должны располагаться между двумя дескрипторами начала и завершения сценария. «script type=”text/javascript"> одна или больше строк кода JavaScript </script> Если не поставить дескриптор завершения сценария, то он может просто не запуститься, а документ HTML на странице будет выглядеть довольно странно. Будущие атрибуты Вы можете использовать в коде сценария еще один атрибут определения языка — language. Он часто применяется вместо атрибута type. Например, чтобы указать браузерам четверто- го поколения (поддерживают JavaScript 1.2) обрабатывать сценарии, необходимо добавить в HTML-код следующий дескриптор. «script language="JavaScriptl.2">...«/script> Атрибут language поддерживается только в спецификации HTML 4.0, которая уже давно не считается современной. В стандарте W3C DOM (например IE5+ и NN6+) активно применяет- ся атрибут type. Вместе с тем, атрибут language все еще используется и будет использо- ваться довольно долго, поскольку с атрибутом type знакомы только новые версии браузеров. Существует еще один атрибут, который используется в коде для включения содержимого внешнего файла со сценарием в текущий документ. На данном этапе он использоваться не будет, но знать о нем нужно. Атрибут src (аналогичный атрибуту src дескриптора <img>) указывает на файл, содержащий код сценария. Такие файлы должны иметь расширение . j s. Дескриптор выглядят при этом следующим образом. «script type="text/javascript" src="myscript.js">«/script> Все строки кода находятся во внешнем файле, поэтому в документе между дескрипторами начала и завершения сценария никакие данные не вводятся. Размещение дескрипторов Так где же в документе нужно размещать дескрипторы? Ответ такой: везде, где это необ- ходимо. Иногда имеет смысл разместить их между дескрипторами <head>. . .</head>. В других случаях требуется разместить сценарий в весьма специфических частях раздела <body>...</body>. Следующие четыре листинга (реализуемые с помощью шаблонного документа HTML) яв- ляются примерами того, как и где размещать дескрипторы сценария <script>. Несколько позже мы детально объясним, как, в зависимости от предъявляемых к сценарию требований, выбрать место размещения сценария в документе. В листинге 5.1 приведена общая схема наиболее распространенного способа использова- ния дескрипторов сценария <script> в разделе <head>. Заголовок страницы (второй вари- ант) является хорошим местом для тех дескрипторов, которые непосредственно влияют на параметры страницы, напрямую не связанные с ее содержимым. Это так называемые управ- ляющие HTML-элементы — дескриптор <meta> или имя документа. Однако здесь удобно размещать и сценарии, которые впоследствии вызываются в ответ на действия пользователя. 84 Часть II. Руководство по JavaScript
Лиетвнг 6.1. Сценарий < разделе загодрма <html> <head> «title>A Document«/title> «script type="text/javascript"> //здесь размещаются строки кода «/script> «/head> <body> </body> С другой стороны, если нужно, чтобы сценарий запускался при загрузке страницы и гене- рировал ее содержимое, его следует разместить в разделе <body> — листинг 5.2 (см. главу 3, в которой сценарий размещен именно в указанном разделе). Дело в том, что сценарий должен получить информацию о браузере и отобразить результат на странице при ее загрузке. Листинг 5.2, Сценарий* тше документа <html> <head> «title>A Document«/title> </head> <body> «script type="text/javascript"> //здесь размещаются строки кода </script> «/script> </body> </html> Приятно осознавать, что в документе может быть размещено неограниченное количество дескрипторов «script >. Например, в листинге 5.3 сценарий размещается как в разделе за- головка, так и в теле документа. Размещение сценария в теле документа целесообразно, если, скажем, при загрузке страницы нужно создать динамические структуры. На тот случай, если документ содержит кнопки, при щелчке на которых будет запускаться другой сценарий, то этот сценарий необходимо добавить в раздел заголовка. <html> <head> <title>A Document«/title> «script type="text/javascript"> //здесь размещаются строки кода </script> </head> <body> «script type="text/javascript"> //здесь размещаются строки кода Глава 5. Сценарии и документы HTML 85
</script> </body> </html> He существует ограничения также на то, сколько дескрипторов сценария <script> раз- мещать в разделах заголовка и тела документа. В документ можно включить столько деск- рипторов < script >, сколько того требует приложение. В листинге 5.4 в качестве примера показано использование двух пар дескрипторов < script > в теле документа, между которы- ми расположены фрагменты HTML-кода. ЛистшГ S.4. Др сценария « iwe досдотц <html> <head> <title>A Document</title> </head> <body> «script type="text/javascript"> //здесь размещаются строки кода </script> «more html> //код HTML <scrlpt type="text/javascript"> //здесь размещаются строки кода </script> </body> </html> Особенности использования старых браузеров Только те браузеры, которые оснащены средствами под держки JavaScript, знают, как интер- претировать в виде сценария строки кода между парой дескрипторов <script>. . </script >, и не путают их с текстом HTML, отображаемым в браузере. Это значит, что браузеры, которые появились раньше JavaScript, не только игнорируют дескрипторы, но и трактуют код JavaScript как содержимое страницы. Результат может быть весьма плачевным. Чтобы уменьшить риск отображения старыми версиями браузеров строк кода сценария на странице, можно воспользоваться нехитрым приемом. Основная его идея состоит в том, чтобы за- ключить строки кода сценария между символами комментария HTML, как это показано в листин- ге 5.5. Большинство не поддерживающих сценарии браузеров игнорируют то, что находится между дескрипторами комментариев <! - - и - - >, в то время как под держивающие сценарии брау- зеры игнорируют эти символы, если они появляются внутри дескрипторов сценария < script >. Листинг Б.5. Так сценарий можно tqpm •*Spajfsepoa«щипавши < ~ «script type="text/JavaScript"> <!-- //здесь размещаются строки кода //--> </script> 86 Часть II. Руководство по JavaScript
Странная конструкция перед самым дескриптором окончания сценария требует некото- рых пояснений. Две косые черты являются символами комментария в JavaScript. Эти симво- лы необходимо использовать, поскольку в противном случае JavaScript, будет пытаться ин- терпретировать закрывающие символы (-->) комментария HTML. Поэтому косые линии дают указание JavaScript полностью пропустить всю строку. Браузеры же старых версий будут интер- претировать эти символы как часть комментария HTML, которую нужно игнорировать. Несмотря на то, что такая методика скрывает сценарии, все же полностью сценарий при этом не маскируется. Все клиентские сценарии JavaScript являются частью документа HTML и загружаются в браузер подобно другим элементам HTML. Более того, их можно просмат- ривать как составную часть исходного кода. Таким образом, описанным выше способом вы не спрячете сценарий от любопытных глаз. Операторы JavaScript Виртуально, каждая строка кода, расположенная между парой дескрипторов <script>. . . </script>, является оператором JavaScript. Более опытные пользователи могут обеспечить более удобную работу, если в конце каждого оператора JavaScript (подобно другим языкам программирования) будут ставить точку с запятой. К счастью, начинающим пользователям, использовать эту точку с запятой не обязательно. Символа возврата каретки в конце оператора JavaScript вполне достаточно, чтобы понять, что он завершен. В сценарии каждый оператор выполняет определенную задачу, делает что-то, имеющее непосредственное отношение к сценарию. Операторы используются, как правило, чтобы: определить или инициализировать переменную; присвоить значение свойству или переменной; изменить значение свойства или переменной; запустить функциональную программу; принять решение. Если не все из перечисленного выше пока понятно, не волнуйтесь — вскоре все станет ясно. Подчеркнем еще раз— использование любого оператора в сценарии должно быть обосновано. Единственный оператор, который явно не выполняет ни одного действия, — это комментарий. Пара косых черт (без пробела между ними) — это наиболее простой способ включения комментария в сценарий. Комментарии в сценарий разработчики программных продуктов добавляют для собственного удобства. В них, как правило, объясняется назначение отдельных операторов или целых групп. Цель состоит в следующем; даже по прошествии шести месяцев вы сможете быстро восстановить в памяти принципы работы сценария. Выполнение операторов сценария Теперь, когда выяснен вопрос о том, где в документе размещаются сценарии, наступило самое время узнать, как же эти сценарии запускаются. В зависимости от целей, с которыми используется сценарий, существует четыре способа определения момента запуска сценария: при загрузке документа; сразу после загрузки документа; в ответ на действия пользователя; при вызове в результате выполнения оператора другого сценария. Определяющим фактором в данном случае является то, где операторы вызова сценария размещены в документе. Глава 5. Сценарии и документы HTML 87
Немедленное выполнение операторов в процессе загрузки документа Первый сценарий в главе 3 (воспроизведенный в листинге 5.6) запускается при загрузке документа в браузер. Для этого приложения важно то, что сценарий проверяет некоторые свойства объекта navigator и включает значения этих свойств в содержимое страницы при загрузке. Поэтому имеет смысл включить дескрипторы <script> и описание сценария в ос- новной раздел тела документа. Операторы, которые выполнятся при загрузке страницы, мож- но было бы назвать операторами немедленного выполнения. Листинг 5 6. Страница ИЛЛ. с опвумтчмйи наацдломимо <html> <head> <title>My First Script«/title> //Мой первый сценарий «style type="text/css"> .highlight {font-weight: bold} </style> </head> <body> <hl>Let's Script...</hl> //Составим сценарий... <hr> <script type="text/javascript"> <!-- Чтобы скрыть от браузеров старых версий document.write("This browser is version " + navigator.appVersion); document.write(" of «span class=’highlight'>" + navigator.appName + "</span>."); // Окончание скрытия сценария --> </script> </body> </html> Отсроченные сценарии Три другие способа выполнения операторов сценария можно отнести к группе отсроченных сценариев. Чтобы объяснить принципы использования таких отсроченных сценариев, придется задействовать концепцию, которая подробно изложена в главе 7. Речь идет о функциях. Функ- ция — это блок операторов сценария, вызываемых через некоторое время после того, как эти операторы загружены в браузер. Функции легко заметны внутри дескрипторов <script>, по- скольку определение каждой функции начинается со слова function, после которого следует ее имя (и скобки). Как только функция будет загружена в браузер (обычно она находится в разделе за- головка, поскольку он загружается раньше), она готова к вызову, когда бы он ни последовал. Например, функция может вызываться для выполнения сразу после загрузки страницы. Объект окна window имеет обработчик события, который называется onload. В отличие от большин- ства обработчиков событий, которые выполняются как ответ на действия пользователя (например при щелчке на кнопке), обработчик события onLoad задействуется в тот самый мо- мент, когда все компоненты страницы (включая изображения, аплеты Java и встроенные муль- тимедийные ресурсы) загружаются в браузер. Обработчик события onload размещается внутри дескриптора <body>, как это показано в листинге 5.7. В главе 4 (листинг 4.1) речь шла о том, как с помощью обработчика события непосредственно выполнить операторы сценария. Но если 88 Часть II. Руководство по JavaScript
обработчик события должен запустить сразу несколько операторов, то иногда удобнее помес- тить эти операторы в описание функции. Теперь обработчик события будет вызывать данную функцию. Это и продемонстрировано в листинге 5.7: после завершения загрузки страницы обработчик события onLoad запускает функцию done (). Эта функция (весьма упрощенная для данного примера) отображает диалоговое окно с предупреждением. Лчсмнг 5.7. Запуск сценария с romouum обработчика onload chtml> <head> <title>An onLoad script«/title> «script type="text/JavaScript"> <!-- function done() { alert("The page has finished loading."); //Загрузка завершена } И -> </script> </head> «body onload="done()"> Текст страницы. </body> «/html> He стоит беспокоиться по поводу использования фигурных скобок и других непонятных конструкций в листинге 5.7. Это не принципиально. Обратите внимание на структуру доку- мента и порядок выполнения операций. Страница полностью загружается без выполнения операторов сценария, хотя при этом в память и загружается функция done (). Так что ее можно запустить в любой момент. После загрузки документа браузер вызывает обработчик события onload, который и запускает функцию done (). Только после этого пользователь увидит диалоговое окно с предупреждением. Запустить сценарий в ответ на действия пользователя можно практически так же, как в предыдущем примере — отсроченный сценарий выполнялся сразу после загрузки докумен- та. Идея заключается в том, что в разделе заголовка определяется только функция сценария, а обработчик события (скажем, элемента формы) вызывает эту функцию из тела страницы. В листинге 5.8 приведен пример сценария, который запускается прй щелчке на кнопке. «html> «head> «title>An onClick script«/title> «script type="text/javascript"> «! - - function alertUserO { alert("Ough!"); } //--> «/script> </head> «body> Текст страницы. «form> «input type="text" name="entry"> Глава 5. Сценарии и документы HTML 89
«input type="button" name="oneButton" value="Press Me!" onclick="alertUser()"> </form> </body> </html> He все объекты должен иметь обработчик события, определяемый в HTML (листинг 5.8), а только те из них, которые используются в сценарии. Согласно коду в листинге 5.8, ни один оператор сценария не будет выполняться до того момента, пока пользователь не щелкнет на кнопке. Функция alertUserO определяется при загрузке страницы и находится в ожида- нии запуска на протяжении всего времени, пока страница загружена в браузер. Если ее не за- пустят, никакого вреда от этого не будет. Последний рассматриваемый сценарий также подразумевает использование функций. Только в этом случае функция вызывается с помощью оператора другого сценария. Подроб- нее об этом речь пойдет в главе 6. Просмотр ошибок сценария На ранних этапах использования JavaScript в браузерах ошибки, обнаруживаемые при за- грузке в сценарии, отображались в наглядных диалоговых окнах. Эти окна весьма полезны для тех разработчиков страниц, которые занимаются отладкой сценариев. Но если ошибка появлялась на странице пользователя, который мало знаком с основами создания сценариев, то такого рода диалоговое окно с сообщением об ошибке не только не приносило никакой пользы, но и просто наводило ужас. В результате производители браузеров попытались мак- симально уменьшить отображаемый в окне браузера эффект извещения о наличии ошибок — к несчастью, для создателей сценариев, поскольку в результате найти ошибки в сценарии ста- ло труднее. Часто ошибки бывают не так очевидны, как кажется сначала. В последних верси- ях IE и NN предусмотрено несколько способов отслеживания ошибок в сценариях. Браузер IE5+ можно настроить так, что сценарий не будет отображать диалоговые окна оши- бок. Для этого выберите Toolsslntemet OptionssAdvancedsBrowsing (Сервис=>Свойства обозревателя^Дополнительно^Обзор) и найдите опцию Display a notification about every script error (Отображать подробные сообщение об ошибках). Даже с отключен- ным режимом отображения сообщений об ошибках в левой части строки состояния окна браузера обнаруженные ошибки все равно регистрируются. В строке состояния появляется значок предупреждения и соответствующее сообщение. Если дважды щелкнуть на этом знач- ке, то появится диалоговое окно извещения об ошибке (рис. 5.1). Детальную информацию о возникшей проблеме можно получить, если щелкнуть на кнопке Show Details (Подробнее) этого диалогового окна. Если режим отображения диалоговых окон не включен, то каждый раз при загрузке страницы и запуске сценария необходимо внимательно следить за строкой состояния и отслеживать появление ошибок. При работе в браузерах Mozilla выберите команду ToolsSWeb Developments JavaScript Console (Сервис^М/еЬ-разработка^Консоль JavaScript). В результате для отображения детальной информации об ошибках будет открыто окно консоли отладчика JavaScript (отлич- ное от консоли Java), как показано на рис. 5.2. При необходимости это окно можно сделать постоянно открытым. Если окно периодически не очищать, то в нем будут постоянно появ- ляться сообщения о новых ошибках. Браузер Safari 1.0 регистрирует ошибки в сценариях, но по умолчанию не отображает их на экране. Для начала вам необходимо получить доступ к меню отладки (Debug), введя сле- дующую команду в утилите Terminal. defaults write com.apple.Safari IncludeDebugMenu 1 90 Часть II. Руководство no JavaScript
Рис. 5.1. Развернутое окно сообщения об ошибке в Internet Explorer Рис. 5.2 Окно консоли JavaScript в браузерах Mozilla Впоследствии при запуске Safari вам необходимо выбрать в меню Debug команду Log JavaScript Exceptions (Регистрировать ошибки JavaScript). Далее отобразите окно программы MacOS X Con- sole, в котором и будут выводиться сообщения об ошибках выполнения JavaScript-кода. Будем надеяться, что в будущих версиях браузера Safari эта процедура станет менее обременительной. Изучение сообщений об ошибках и их устранение — довольно серьезная тема (см. гла- ву 45). В этом издании речь также идет о том, как использовать сообщения об ошибках в ка- честве индикатора неправильности вводимых сценариев. Различие между написанием сценариев и программированием Может сложиться впечатление, что создавать сценарии намного проще, чем писать про- граммы. Слово сценарий звучит проще и дружелюбнее, чем программа или даже приложение. И во многих отношениях это так и есть. В качестве аналогии приведем пример с коллекционером, Глава 5. Сценарии и документы HTML 91
который собирает модели самолетов из подручных материалов, и его коллегу, который для этого же использует специальные промышленные заготовки. Тот, который собирает модели из подручных материалов, аккуратно вырезает и подгоняет каждый кусочек дерева или ме- талла, чтобы воплотить задуманную идею и придать модели нужную форму. Коллекционер, использующий промышленные заготовки, комбинирует их для того, чтобы получить конеч- ный продукт. Когда оба заканчивают свою работу, не всегда можно с уверенностью сказать, какая модель собрана из подручных материалов, а какая — из деталей фабричного производ- ства. В конце концов, оба моделиста используют подобную технику сборки и у каждого есть повод гордиться своей работой. Браузер предоставляет создателям сценариев много заранее заготовленных компонентов, на основе которых можно успешно создавать сценарии. Если вы не используете браузер, то это говорит о том, что высококлассный программист, который может разработать на основе подручных средств собственное приложение, позволяющее обслуживать данные и предла- гающее широкие возможности по взаимодействию с пользователем. Но и в том, и в другом случае приложения должны иметь весьма профессиональный вид. За пределами рамок объектной модели документа, тем не менее, “настоящее программи- рование” сжигает все мосты на пути к миру сценариев. Это происходит потому, что сценарии (и программы) работают не только с объектами. Когда выше в этой главе утверждалось, что каждый оператор сценария JavaScript должен нести функциональную нагрузку, то под этим подразумевалось управление определенного рода данными. Данными называется любая ин- формация, связанная с объектами или другими частями информации, которую сценарий ис- пользует при выполнении очередного оператора. Данные могут принимать самые разные формы. В JavaScript общими типами данных яв- ляются числа, текст (строчный тип string), объекты (как принадлежащие объектной моде- ли, так и создаваемые с помощью сценариев), а также логические или булевы (Boolean): true (правда) и false (ложь). Каждый язык программирования или создания сценариев определяет целый ряд структур и, разумеется, накладывает ограничения для каждого типа данных. К счастью для начинающих JavaScript-программистов, тот объем знаний, которыми необходимо обладать для успешного создания сценариев, намного меньше по сравнению с таковым для программирования в фунда- ментальных средах (например таких, как Java). В то же время, все, чему вы научитесь в JavaScript, сразу же найдет себе применение и при изучении других языков программирования — нельзя допускать даже мысли о том, что изучение методов создания сценариев пройдет впустую. Поскольку на профессиональном уровне процесс составления сценария сродни програм- мированию, то чтобы стать хорошим разработчиком сценариев в JavaScript, необходимо иметь основные представления о принципиальных подходах, используемых в программиро- вании. В следующих главах уклон будет сделан от объектной модели документа к принципам программирования, которые важны как в JavaScript, так и в других языках. Упражнения 1. Создайте полный сценарий, в котором использовался бы такой оператор: document.write("Hello, world."); 2. Создайте HTML-документ, включив в него сценарий из предыдущего задания. Сцена- рий должен запускаться при загрузке страницы. Результат выполнения сценария нуж- но проверить, открыв документ в браузере. 3. В описанный выше сценарий необходимо добавить комментарий, поясняющий прин- цип выполнения операторов этого сценария. 92 Часть II. Руководство по JavaScript
4. Создайте HTML-документ, который сразу после загрузки страницы будет отображать диалоговое окно с предупреждением. Другое диалоговое окно должно отображаться при щелчке пользователя на кнопке формы. 5. Внимательно изучите документ в листинге 5.9. Не выполняя ввод и загрузку докумен- та, ответьте на такие вопросы. а) Как будет выглядеть страница. б) Как пользователь будет взаимодействовать со страницей. в) Как работает сценарий. Затем введите текст сценария в текстовом редакторе, как показано ниже (обратите вни- мание на регистр символов и пунктуацию). Не вводите символ возврата каретки по- сле знака равенства "=" в описании функции upperME. Не следует также добав- лять разрывы строки — все должно быть представлено, как показано в листин- ге. Символ возврата каретки можно использовать между парами имя=значение, как показано в первом дескрипторе < input >. Теперь сохраните документ как HTML- файл, после чего загрузите этот файл в браузер. JMcrw* 5*9. Как устроена эта страница <html> <head> «title>Text Object Value«/title> «script type=,,text/javascript"> <! - - function upperMeO { document.getElementByld("output").value = document.getElementById("input").value.toUpperCase(); } II --> </script> </head> <body> Enter lowercase letters for conversion to uppercase:«br> <form name="converter"> «input type="text" name="input" id="input" value="sample" onchange= "upperMeO " /xbr /> «input type="text" name="output" id="output" value="" /> «/form> «/body> «/html> Глава 5. Сценарии и документы HTML 93
Основы программирования. Часть 1 м а данном этапе изучения JavaScript вопросы, непо- V V средственно связанные с HTML-документами, следует оставить на потом — основное внимание мы уделим анализу принципов программирования. Это важный момент с прак- тической точки зрения, а полученные навыки могут в даль- нейшем быть использованы в любом языке при составлении сценариев или написании программ. Для начала мы позна- комимся с переменными, выражениями, типами данных и операторами — названия эти могут звучать несколько не- привычно для тех, кому не приходилось еще писать про- граммы. Однако беспокоить это не должно. Наличие даже небольшого опыта работы быстро сделает перечисленные выше термины простыми и понятными. Язык программирования Используемым нами языком программирования будет JavaScript. У языка JavaScript есть еще несколько названий, с которыми, возможно, читателю уже приходилось сталкивать- ся. Версия компании Microsoft этого языка называется JScript. В последней из названия языка было убрано “ava”, чтобы не получать лицензию на использование названия “Java” у вла- дельца торговой марки — компании Sun Microsystems. В настоящее время основной ориентир для любого языка программирования (независимо от его называния) — это стан- дарт ЕСМА. Документ, в котором прописаны все детальные требования к языку, называется ЕСМА-262 (это 262-ой стан- дарт, разработанный ЕСМА). Как JavaScript, так и JScript под- держивают стандарт ЕСМА-262. Некоторые браузеры очень ранних версий демонстрируют весьма незначительное отклоне- ние от стандарта ЕСМА-262 (который появился позже, чем эти браузеры). Наиболее существенные несоответствия описаны в справочных разделах по базовому языку в части IV этой книги.
Способы управления информацией За очень редким исключением, каждый используемый оператор JavaScript выполняет оп- ределенные действия с различными наборами информации или данных. Данные могут быть представлены текстовой информацией, отображаемой на экране с помощью соответствую- щих операторов JavaScript, или в виде флажка на форме (включен или выключен). Каждая отдельная часть информации в программировании называется значением. В обычном пони- мании термин значение ассоциируется с числом, характеризующим количество чего-либо. В программировании, тем не менее, этот термин не настолько упрощен. Например, текстовая строка является значением. Отдельное число является значением. Опция элемента управления (которая либо активна, либо нет) также является значением. В JavaScript значения могут быть нескольких типов. В табл. 6.1 приведены формальные типы данных JavaScript и в качестве примеров те их значения, которые будут время от време- ни описываться в этой книге. Зеблица <Л. Тиш 1лМиык АшбпНpt Тип данных Пример Описание Строковый "Howdy" Последовательность символов, заключенных в кавычки Числовой 4.5 Любое число без кавычек Булев (логический) true Логическое да (true) или нет (false) Null null Отсутствие значения Объект Программный объект, определяемый своими свойствами и методами (массивы также являются объектами) Функция Определение функции Использование языка, в котором задействовано такое незначительное количество типов данных, упрощает решение многих задач программирования. Особенно если сравнивать его с другими языками программирования, где столь часто разработчики сталкиваются с пробле- мами, связанными с несогласованностью типов данных (целочисленных, действительных чи- сел или чисел с плавающей запятой). В некоторых примерах книги иногда используются формальные ссылки или условные имена объектов и переменных. В настоящих сценариях и программах их можно заменить собственными именами. Все строки заключаются в кавычки. Встречаются ситуации, когда тип значения напрямую связан с используемым сценарием. Например, если пользователь вводит в текстовом поле формы число, то браузер запомнит это число как значение строкового типа string. Если в сценарии предусмотрено выполнение некоторых арифметических действий с этим числом, то перед использованием данного числа в математических преобразованиях его необходимо сначала привести к числовому типу number. Примеры подобного преобразования типов представлены ниже. Переменные Приготовление по определенному рецепту блюд на кухне имеет, по сравнению с подготов- кой данных для использования в программе, одно преимущество. На кухне вы имеете дело с вполне реальными вещами: морковкой, молоком или филе из лосося; при этом повар должен только следовать готовому рецепту. Компьютер, если проводить аналогию, тоже следует инструкциям Глава 6. Основы программирования. Часть 1 95
при управлении данными. Иногда такие данные представляют что-то вполне реальное (например, текст, введенный в текстовое поле формы). Однако как только нужное значение будет получено программой, изменить заранее определенный набор действий — не так и просто. На самом деле данные, с которыми работает программа, являются простым набором би- тов (единиц и нулей, если хотите) в памяти компьютера. Если выражаться более точно, то данные в модернизированных с помощью JavaScript Web-страницах занимают часть памяти компьютера, специально выделяемой для использования браузером. В былые времена про- граммистам нужно было знать конкретные адреса в оперативной памяти, по которым храни- лись значения и откуда (в случае необходимости) их можно было востребовать. Поскольку на внутреннем уровне организации программы степень сложности осталась прежней, использо- вание современных программных языков (например JavaScript) призвано избавить програм- мистов от такой рутиной работы. Наиболее удобным способом использования данных в сценарии является такой, при кото- ром данные присваиваются в качестве значения переменной. Переменную можно представить себе в виде контейнера, в котором хранится информация. Как долго эта переменная будет хранить информацию, зависит от нескольких факторов. Когда Web-страница удаляется с эк- рана (или окна), все используемые ею переменные немедленно удаляются из памяти. Создание переменной В JavaScript создать переменную можно несколькими способами. Но только один из них применим практически во всех случаях. Этот способ подразумевает использование ключево- го слова var, после которого указывается имя, которое будет присвоено переменной. Напри- мер, чтобы таким образом определить переменную с именем myAge, нужно воспользоваться следующим оператором JavaScript. var myAge; Этот оператор указывает браузеру, на то что данную переменную можно использовать для последующего хранения информации. Любые данные, присвоенные этой переменной, могут в дальнейшем изменяться. Чтобы присвоить переменной значение, используются операторы присвоения. Наиболее распространенным среди них является знак равенства. Если описанной выше переменной myAge нужно присвоить значение сразу при описании (такой комбинированный процесс описания и присвоения значения еще называется инициализацией переменной), то в описании переменной используется еще и оператор присваивания. var myAge = 45; С другой стороны, если переменная описана в одном месте, а позже ей нужно присвоить другое значение, то сделать это можно следующим образом. var myAge; myAge = 45; Ключевое слово var для данной переменной в документе используется один-единствен- ный раз: при описании или инициализации. Переменные в JavaScript могут принимать значения любого типа. В отличие от многих дру- гих языков, в JavaScript нет необходимости при описании переменной указывать тип ее зна- чений. Тип переменной может меняться в процессе выполнения программы. Эта либераль- ность просто сводит с ума некоторых классических программистов, которые привыкли и для данных, и для переменных указывать тип. 96 Часть И. Руководство по JavaScript
Названия переменных Название для описываемых переменных следует выбирать весьма осторожно. Всегда можно найти сценарии, в которых используются переменные с именами, состоящими из от- дельных букв. За исключением нескольких специфических случаев, где использование в качестве имени переменной только одной буквы бывает оправдано (например, переменной i для счетчи- ка в операторе цикла в главе 7), я бы порекомендовал выбирать такие имена переменных, кото- рые реально отображали бы их назначение. Подобная практика позволяет отслеживать со- стояние данных в большом наборе операторов и переходов, особенно в сложных сценариях. Ряд ограничений, налагаемых на имена переменных, также способствует выработке у на- чинающих программистов корректного стиля именования переменных. Во-первых, в качест- ве имен переменных нельзя использовать зарезервированные в JavaScript слова. Это относит- ся как к тем ключевым словам, которые уже используются в языке, так и к тем, которые зарезервированы для использования в будущих версиях JavaScript. Дизайнеры JavaScript, тем не менее, не смогли бы предусмотреть абсолютно все ключевые слова, которые будут ис- пользоваться в будущем, даже если бы очень захотели. Однако, используя в качестве имен своих переменных термины, которые приведены в списке зарезервированных служебных слов (см. приложение Б), вы гарантировано обеспечите себе неприятности в будущем. В именах переменных нельзя использовать пробелы. С этой точки зрения оптимальными именами являются те, которые состоят из одного слова. Если у вас возникла необходимость в имени переменной использовать более одного слова, то для преобразования нескольких слов имен в одно можно воспользоваться рядом хитростей. Один из способов подразумевает использование между словами в качестве разделителя символа подчеркивания. Другой метод заключается в том, чтобы начинать комбинацию слов в имени с маленькой буквы, а потом каждое новое слово начинать с большой буквы. При этом между словами разделители вооб- ще не ставятся. Это так называемый слитный формат (interCap format). Внизу приведены имена переменных, образованные согласно описанным выше правилам. my_age myAge Второй вариант является более предпочтительным. Такие имена гораздо легче вводить при написании кода JavaScript, а потому легче и воспринимать. С точки зрения возможности воз- никновения конфликта со служебными словами будущих версий JavaScript, использование в ка- честве имен переменных нескольких слов является неплохой идеей. Ведь вероятность появления таких “многословных” комбинаций в списке зарезервированных терминов достаточно невелика. Кроме того, на имена переменных накладывается и ряд других существенных ограниче- ний. В них, кроме прочего, следует избегать всех знаков пунктуации, кроме символа подчер- кивания. Первый символ в имени переменной не может быть числом. Если эти ограничения показались вам знакомыми, то это потому, что они идентичны правилам задания идентифи- каторов элементов HTML, о которых рассказывалось в главе 4. Выражения и их вычисление К другой концепции, имеющей непосредственное отношение к переменным и их значени- ям, относится концепция вычисления выражений. Возможно, это один из самых важных мо- ментов в понимании методов программирования. Выражения используются повсеместно в нашем ежедневном общении. В фильма The Beverly Hillbillies есть такая интересная песенка. Глава 6. Основы программирования. Часть 1 97
Then one day he was shootin' some food And through the ground came а-bubblin' crude Oil that is. Black gold. Texas tea. (Голодный, хлеба он искал, А отыскал источник счастья. То нефть была — Техасский чай, На цвет черна и золота прекрасней.) В конце этой песни можно найти различные ссылки: “источник счастья” (crude), “нефть” (oil), “черное золото” (black gold), “Техасский чай” (Texas tea). Везде подразумевается нефть. Эти все выражения используются для обозначения понятия нефть. Стоит упомянуть одно из них, и все окружающие поймут, о чем вдет речь. В нашем воображении мы вычисляем эти выражения и сводим их к одному значению — нефть. В программировании переменные всегда ценны их содержимым или значением. Напри- мер, после присвоения значения переменной, определяющей возраст автора книги, var myAge = 45; каждый раз, когда эта переменная будет использоваться в выражении, ее значение (4 5) авто- матически будет применяться в любом операторе. Если известно, что, например, читатель на 15 лет моложе, то можно ввести новую переменную, значение которой будет рассчитываться исходя из указанной выше информации и уже известной переменной. var yourAge = myAge - 15; При следующем использовании в сценарии переменной yourAge ее значение будет рассчи- тано и окажется равным 3 0. Если позже в сценарии значение переменной myAge будет измене- но, то на переменную yourAge эти изменения никак не повлияют, поскольку при описании переменной yourAge и расчете ее значения значение переменной myAge было равно 4 5. Выражения в сценарии script 1 .htm Возможно, на это в свое время никто не обратил внимания, но уже в главе 3 в первом приведенном сценарии можно было отследить вычисление выражения. Речь идет о втором операторе сценария document. write (). document.writeC of " + navigator.appName + При использовании метода document .write () (под этим термином в JavaScript подра- зумевается команда) следует указать в скобках все необходимые параметры. В данном случае это текстовая строка, которая будет отображаться на Web-странице. В использованном при- мере параметр является одним выражением, состоящим из трех отдельных строк. " of " navigator.appName Использование знака “плюс” (+) в JavaScript является одним из способов объединения строк. Перед тем как JavaScript сможет отобразить данную строку, нужно выполнить несложные расчеты. Первым этапом является вычисление значения свойства navigator.appName. Это значение равно строке, содержащей название используемого браузера. Когда соответст- вующее значение будет успешно преобразовано к строковому типу, JavaScript сможет завер- шить процесс объединения трех строк в одно целое. Такая результирующая строка и будет отображена на Web-странице. 98 Часть II. Руководство по JavaScript
Проверка вычислений Поэкспериментировать с тем, как в JavaScript выполняются вычисления выражений, можно с помощью специального программного средства, которое называется The Evaluator Jr. (Jr. — "младший", см. следующий рисунок). Более совершенная (Senior, "старшая") версия этого средства будет описана в главе 13. В верхнем текстовом поле нужно ввести любое выраже- ние JavaScript, после чего нажмите <Enter> или щелкните на кнопке Evaluate (Вычислить). Приложение The Evaluator Jr. предназначено для тестирования выражений В The Evaluator Jr. используется 26 предопределенных переменных (от прописной литеры а до z), поэтому с его помощью можно присваивать переменным значения, тестировать операторы срввнения и даже выполнять нехитрые математические операции. Используя приводивший- ся выше в этой главе пример с переменной, “запоминающей” возраст, можно повторить все выполненные выше расчеты и проверить, что будет отображаться в поле Result (Результат). При этом не забывайте проверять регистр символов. а = 45; а; Ь = а - 15; а - Ь; а > Ь; Для повтора щелкните на кнопке Reload (Перезагрузить). Выражения и переменные Использование вычисляемых выражений позволяет реализовать более гибкий, по сравне- нию с примененным ранее, способ вызова метода document .write (). Вместо того, чтобы в качестве параметра метода document .write () указывать объединяемые строки в явном виде, можно сохранить эти строки в отдельную переменную, а потом уже задать эту пере- Глава 6. Основы программирования. Часть 1 99
менную в качестве параметра метода. Вот как будет выглядеть наш метод в том случае, если предварительно объявить переменную и задать ей значение. var textToWrite '= " of " + navigator.appName + docunment.write(textToWrite) Этот метод будет выполняться, поскольку значение переменной textToWrite преобра- зуется к необходимому типу данных. Метод docunment.write О примет значение этой переменной строкового типа и выполнит свою часть работы по отображению данных на эк- ране. Это довольно показательный пример. Он еще раз доказывает, что при ознакомлении со сценариями или их отладке следует всегда обращать внимание на то, как именно производит- ся в сценарии вычисление каждого выражения (переменной, значения, свойства объекта). В противном случае при изучении JavaScript (или любого другого языка) немало времени у вас уйдет на попытку разобраться, откуда в сценарии появилось то или иное значение переменной. Преобразование типов данных Как уже отмечалось ранее, тип данных существенно влияет на выполнение операторов сценария, особенно если один из операндов принадлежит не к тому типу, который можно ожидать в данном конкретном случае. Хотя в JavaScript предпринята серьезная попытка раз- решить подобного рода проблемы путем преобразования типов данных, следует понимать, что мысли пользователей JavaScript все же угадать не сможет. Если пользователь склонен трактовать переменную несколько иначе, чем это делает JavaScript то вряд ли он может рас- считывать на получение приемлемого результата. Представим, например, сложение чисел, которые могут быть записаны в текстовом стро- ковом формате. В самом обычном случае арифметическая операция сложения двух чисел проблем не вызывает, в ее результате можно получить вполне ожидаемый результат. 3+3 // результат = 6 Но если одним из чисел является строка, то JavaScript попытается преобразовать и второй операнд в строковый тип. В этом случае арифметическая операция по сложению чисел пре- вращается в процесс слияния двух строк. Поэтому в выражении 3 + "3" // результат = "33" “стройность” второго операнда “задает тон” всей операции. Первое значение автоматически преобразуется в строковый тип, а результатом операции является объединение двух строк. В этом можно убедиться самостоятельно, воспользовавшись услугами приложения The Evaluator Jr. Если такой процесс несколько расширить и рассмотреть сумму из трех слагаемых 3 + 3 + "3" // результат = "63" то вначале полученное конечное значение может показаться нелогичным. Однако логика все же есть. Выражения вычисляются слева направо. Поэтому первый знак “плюс” связан с первы- ми двумя числами, и результатом выполнения такой операции является число 6. Поскольку к числу 6 прибавляется строчное выражение "3", то конечным результатом, по причине ис- пользования в JavaScript правила “стройность”, будет " 63 ". Большинство из того, что с точки зрения типов данных будет важно в дальнейшей работе, имеет непосредственное отношение к математическим операциям, описанным выше. Тем не менее, некоторые методы требуют, чтобы в качестве параметров в них указывались данные одного или двух конкретных типов. JavaScript предоставляет довольно широкие возможности по преобразованию типов, однако на данном этапе имеет смысл более детально ознакомиться с двумя способами такого преобразования — чисел в строки и строк в числа. 100 Часть II. Руководство по JavaScript
Преобразование строк в числа Сразу необходимо отметить следующее: если числовое значение сохранено в качестве стро- ки (например, при введении значения в текстовое поле), у сценария могут появиться проблемы при попытке использовать это значение в математических операциях. В JavaScript предусмотре- ны две встроенные функции; которые можно применить для преобразования чисел, представ- ленных в виде строки, к числовому формату: это функции par selnt () и parseFloat (). В JavaScript существует разница между целыми числами и числами с плавающей точкой. Целые числа (integer) всегда являются целыми. У них нет десятичной точки и справа от це- лой части у них ничего не задается. Числа с плавающей точкой (floating-point), в проти- воположность целым, могут содержать дробную часть справа от десятичной точки. С точки зрения вычисления арифметических операций, в JavaScript разницы между целыми числами и числами с плавающей точкой нет. Различать целые и нецелые числа необходимо лишь при передаче их в качестве параметров в некоторых методах, которые не могут обрабатывать дробную часть. Например, параметры метода scroll О должны быть числами целыми, поскольку они определяют число пикселей по вертикали и горизонтали, на которые нужно прокрутить окно. А на часть пикселя окно прокрутить не удастся даже самому ловкому пользователю. Чтобы использовать любую из указанных функций преобразования типов, ей в качестве параметра следует передать ту строку, которую нужно преобразовать к числовому формату. Например, внизу приведен код, использующий функцию parselnt (), преобразования двух различных строк в числовые значения. parselnt("42") // результат = 42 parselnt("42.33") // результат = 42 Несмотря на то, что во второй строке передается строчный вариант числа с плавающей точкой, возвращаемое функцией значение соответствует целочисленному типу. В данном случае округление не использовалось (хотя другие математические функции могли бы помочь и в этом). Десятичная точка и все, что стоит за ней, просто отбрасывается. В качестве результата функция parseFloat (), если это возможно, возвращает целое число. В противном случае в качестве результата возвращается число с плавающей точкой, как это и показано ниже. parseFloat("42") // результат = 42 parseFloat("42.33") // результат = 42.33 Поскольку эти две функции преобразуются к возвращаемому результату, то в тех местах, где нужно выполнить преобразование строковой переменной в числовое значение, следует просто вставить одну из этих функций. В отношении используемого ранее примера суммиро- вания трех значений, одним из которых была строка, данную рекомендацию можно реализо- вать следующим образом. 3 т 3 + parselnt("3") // результат = 9 Преобразование чисел в строки Как правило, преобразовывать числа в строки приходится намного реже, чем строки в числа. Как можно было убедиться на приведенных выше примерах, JavaScript больше при- вязан к строковым типам данных, а не к числовому формату, чем можно эффективно пользо- ваться при смешанном применении типов данных в операторах. В любом случае, это является еще одним хорошим способом уберечь собственный код от различных недоразумений и не- соответствия типов. Наиболее простой способ преобразования чисел в строки был описан Глава 6. Основы программирования. Часть 1 101
в приведенных выше примерах; он основан на исключительной “любви” JavaScript к строкам. Путем добавления пустой строки к числу из последнего можно получить строковый эквивалент. ("" + 2500) // результат = "2500" ("" + 2500).length // результат = 4 В последнем примере особенности вычисления выражений проиллюстрированы довольно наглядно. Наличие кавычек приводит к тому, что числовое выражение преобразуется к стро- ковому типу. Строка string в JavaScript является объектом, который имеет связанные с ним свойства. Одно из этих свойств— length, значение которого равно количеству символов в строке. Количество символов в строке "2500" равно 4. Обратите внимание на то, что длина length — это число, а не строка. Операторы В выражениях используется огромное число операторов. Ранее операторы нами уже ис- пользовались. Например, знак равенства (=) применялся в качестве оператора присвоения значения переменной. В предыдущем примере со строками символ “плюс” (+) использовался для объединения двух строк. Оператор выполняет, как правило, определенного рода вычис- ления (операции) или сравнивает два значения (значение с каждой стороны оператора назы- вается операндом) с целью получения третьего. В данной главе будут описаны два типа опе- раторов — арифметические и операторы сравнения. В главе 32 будет представлено значительно большее количество операторов. В данный момент вам необходимо понять, как функционируют базовые элементы. Тогда и работа остальных станет намного доступнее. Арифметические операторы Может показаться странным описание текстовых строк в контексте “арифметических” вычислений. Но выше уже приводился пример использования оператора (+) в тех случаях, когда одним из операндов была строка. Оператор в виде знака “плюс” дает указание JavaScript объединить две строки именно в том месте, где размещен оператор. Оператор объединения строк ничего не знает о словах и пробелах, поэтому программисту нужно заранее позаботить- ся о том, чтобы любые две объединяемые строки имели достаточное количество *пробелов — даже если для этого придется добавлять пробелы специально. firstName = "John" lastName = "Doe" fullName = firstName + " " lastName В JavaScript для обозначения арифметической операции сложения тоже используется знак “плюс”. Если двумя операндами являются числа, JavaScript будет трактовать операцию как ариф- метическое сложение двух чисел, а не как объединение строк. В JavaScript встроены арифме- тические операторы сложения (+), вычитания (-),.умножения (*) и деления (/). Операторы сравнения Довольно важным типом являются операторы, с помощью которых выполняется сравне- ние двух или более значений на предмет совпадения. Такое сравнение в качестве результата продуцирует значение логического типа Boolean— true (истина) или false (ложь). В табл. 6.2 представлен список операторов сравнения. Оператор, с помощью которого можно определять эквивалентность двух элементов, состоит из пары знаков равенства (чтобы отли- чать его от знака равенства, используемого в операторе присвоения). 102 Часть II. Руководство по JavaScript
Символ Описание == Равно 1 = Не равно > Больше >= Больше или рано < Меньше <= Меньше или равно Наиболее часто операторы сравнения применяются в тех конструкциях сценария, где принимаются решения. Для сравнения: повар на кухне такие процедуры выполняет очень часто (если соус слишком жидкий, нужно добавить муки). С операторами сравнения вы де- тальнее ознакомитесь в следующей главе. Упражнения 1. Укажите, какой из приведенных ниже способов описания и инициализации перемен- ных является приемлемым? Объясните, почему так, а не иначе. Если способ непра- вильный, что нужно сделать, чтобы исправить ситуацию? a) my_name = "Cindy"; б) var how many = 25; в) var zipCode = document.forml.zip.value; r) var laddress = document.nameForm.addressi.value; % 2. Для каждого из приведенных ниже выражений укажите, как изменится выражение some Vai после выполнения следующих операторов JavaScript. var someVal = 2; someVal = someVal + 2; someVal = someVal * 10; someVal = someVal + "20"; someVal = "Robert"; 3. Назовите две функции JavaScript, которые выполняют преобразование строк в числа. Как можно задать функцию преобразования строчного значения в число? 4. Наберите код согласно листингу 6.1 и загрузите HTML-страницу. Введите трехзначное число в два верхних поля и щелкните на кнопке Add (Сложить). Изучите код и скажи- те, в чем ошибка сценария. Как его исправить, чтобы он правильно считал сумму двух чисел, вводимых в указанные поля? ' ....... ....... 1 <html> <head> <title>Sum Maker</title> <script type="text/javascript"> Глава 6. Основы программирования. Часть 1 103
function addlt() { var valuel = document.getElementByld("inputA").value; var value2 = document.getElementById("inputB").value; document.getElementByld("output").value = valuel + value2; } u -> </script> </head> <body> <form name="adder"» «input type="text" name= " inputA" id="inputA" value="0" size="4" /> <br / > «input type="text" name="inputB" id="inputB" value="0" size="4" /> «input type="button" value="Add" onclick="addlt()"> «Р >___________< /p > «input type="text" name="output" id="output" size="6" /> «/form» «/body» «/html» 5. Что значит термин объединение в программировании на JavaScript? 104 Часть II. Руководство по JavaScript
Основы программирования. Часть 2 о - этой главе знакомство с основами программирова- на' ния откроет перед вами новые горизонты. Например, будут рассмотрены вопросы принятия решений программа- ми; вы узнаете, почему некоторые операторы сценария нуж- но повторять снова и снова. В конце главы можно будет так- же узнать об одном из самых эффективных способов хранения информации в JavaScript — о построении массивов. Решения и циклы Ежедневно и ежечасно каждому из нас приходится при- нимать важные решения — и очень часто об этом мы даже не подозреваем. Наверное, с этим согласны не все. Тогда имеет смысл рассмотреть, какие решения принимаются по- купателем, скажем, в супермаркете от момента, когда он туда заходит, и до момента выхода. Без предварительного принятия решения никто в супер- маркет не заходит. В зависимости от количества и размера предполагаемых покупок, посетитель берет либо ручную сумку, либо тележку самообслуживания в углу возле стойки. Это решение позже может быть подвергнуто суровой само- критике, если по пути своего следования покупатель обна- ружит скидки на товары, которых по такой цене можно было бы купить больше, да вот сумочка доя ручной клади маловата. Теперь предположим, что покупатель подходит к продук- товому отделу. Прежде чем что-то выбрать, он проверяет нали- чие тех товаров, которые специально дома выписал на листочек, чтобы ничего не забыть. Если ассортимент покупателя устраи- вает, то он подойдет ближе и начнет искать нужный продукт. В противном случае покупатель пойдет к другому отделу. Дальше предположим, что покупатель направляется к овощ- ному отделу, чтобы купить спелых помидоров. Подойдя к лотку
с помидорами, он начинает выбирать — берет его, проверяет твердость, цвет, ищет изъяны. Если покупатель забраковал один овощ, он берет другой и повторяет описанные действия: до тех пор пока, наконец, не найдет то, что ищет. Последней остановкой покупателя является касса. “Пакет бумажный или пластиковый?” — спрашивает продавец. Это еще одно решение, которое нужно принять. От него будет зависеть, в какой сохранности покупки будут достав- лены из супермаркета прямо на кухню. Процесс принятия решений при посещении магазина напоминает то, через что проходит JavaScript при выполнении программы. Если основную идею описанного процесса вы уже поняли, то теперь самое время обратиться к особенностям синтаксиса JavaScript и способам реализации с его помощью программ. Управляющие структуры На программном языке все операторы, используемые для принятия решений, а также свя- занные с ними циклические команды повторения называются структурами управления (или управляющими структурами). Структуры управления с помощью последовательности опера- торов сценария направляют поток обработки данных в нужном направлении. В основе ис- пользуемых методов лежит схема принятия простых решений и других факторов. Важной частью каждой управляющей структуры является условный оператор. Точно так же, как к месту работы можно добираться несколькими путями, в зависимости от тех или иных условий (например погоды, времени суток или настроения), программа тоже иногда со- держит условные выражения, которые могут принимать значения true (истина) или false (ложь) — одно из логических значений булевого типа, уже упоминавшихся в главе 6. Как правило, в качестве подобных условных конструкций используются те, которые содержат оператор сравнения. В реальной жизни все происходит абсолютно аналогично: если истина заключается в том, что за окном мороз, то перед выходом на улицу лучше надеть пальто. В программировании сравнивают, как правило, числа или строки. Для разных программируемых ситуаций в JavaScript предусмотрены различные типы управляющих структур. Три наиболее часто используемые структуры — это условный опера- тор if, условный оператор if. . . else и оператор цикла for. Другие управляющие структуры детально описываются в главе 31. На данном же этапе мы остановимся только на трех упомянутых выше конструкциях. Условный оператор if Наиболее простой пример принятия решения в программе— это ситуация, в которой в зависимости от справедливости определенного условия в программе выбирается тот или иной алгоритм действий. Формальный синтаксис соответствующей структуры приведен ни- же. Текст, отображенный курсивом, в реальном сценарии следует заменить на выражения и операторы, соответствующие конкретной задаче. if (условие) { оператор[ы], выполняемый[е] , если условие справедливо } Не стоит беспокоиться по поводу наличия фигурных скобок —сконцентрируйтесь на ос- новной структуре. Ключевое слово if является обязательным. В круглых скобках вводится выражение, значение которого имеет булев тип. Это именно то условие, которое проверяется, когда процесс выполнения программы подходит к данному месту. Если значение выражения равно true (истина), то будет выполнен оператор или операторы, заключенные в фигурные скобки, а после этого программа перейдет к оператору, который находится после закрывающей 106 Часть II. Руководство по JavaScript
фигурной скобки. Если значение выражения равно false (ложь), то операторы внутри фи- гурных скобок игнорируются и процесс продолжается с первого оператора после закрываю- щей фигурной скобки. В приведенном далее примере подразумевается, что переменная myAge имеет значение, заданное ей ранее в сценарии (как именно, в данном случае не важно). В условном выраже- нии осуществляется проверка сравнения значения переменной myAge с числом 18. if (myAge < 18) { alert("Sorry, you cannot vote."); } Тип данных значения myAge должен соответствовать числу, чтобы процесс сравнения (с помощью оператора сравнения <) производился корректно. Во всех случаях, когда значе- ние myAge меньше 18, оператор в фигурных скобках будет выполнен, в результате на экране появится окно предупреждения. После того как пользователь закроет это диалоговое окно с предупреждением, выполнение сценария будет продолжено с того оператора, который рас- положен непосредственно после фигурной скобки, закрывающей условный оператор. Условный оператор if...else Не все решения в программах принимдются так просто, как это показано выше на приме- ре условного оператора if. Вместо того, чтобы определять направление программы только в случае выполнения или невыполнения условия, явно укажите оба пути для случая выполне- ния и невыполнения условия. Это не очень заметное но очень важное различие. В стандарт- ном условном операторе if в случае, если значение контрольного выражения равно false (ложь), специальный оператор не выполняется. Если же и при негативном ответе после про- верки условного выражения (значение false) нужно выполнить набор определенных дейст- вий, применяется конструкция if.. . el se. Ее синтаксис приведен ниже. if (условие) { оператор [ы] выполняемый[е] , если условие = true } else { оператор[ы] выполняемый[е], если условие = false } Здесь представлено все, что уже известно о конструкции if. Главным отличием от рас- смотренного выше случая является только наличие ключевого слова else. Оно введено доя того, чтобы указать альтернативный путь выполнения программы в том случае, если значение проверяемого условия равно false. Как пример использования структуры if.. .else приведен фрагмент кода, в котором оп- ределяется количество дней в феврале месяце в зависимости от того, високосный год или нет. Для упрощения примера в условии просто проверяется, делится ли номер года нацело на 4. (Настоящая проверка должна учитывать переход в новое столетие, но в данном случае это не- существенно). Оператор в виде знака процента (%) обозначает делением по модулю, и о нем речь пойдет в главе 32. Результат выполнения этого оператора — это остаток от деления одного числа на другое. Если остаток равен нулю, то первое число делится на второе нацело. var febDays; var theYear = 2004; if (theYear % 4 == 0) { febDays = 29; } else { febDays = 28; } Самое важное в этом примере происходит в конце кода, в конструкции if. . . else. Зна- чение переменной febDays устанавливается равным 28 или 29. Ни одно из других значений Глава 7. Основы программирования. Часть 2 107
не является возможным. Для тех лет, числа которых нацело делятся на 4, выполняется пер- вый встроенный оператор условной конструкции. Во всех других случаях выполняется вто- рой оператор. Процесс выполнения кода в любом случае продолжается с первого после окон- чания структуры if . . .else оператора. Циклы В реальной жизни циклы означают повторение последовательности определенных шагов или действий до тех пор, пока не выполнится определенное условие. Именно это условие по- зволяет разорвать заколдованный круг повторений. Так было в примере с посещением мага- зина, когда посетитель перебирал помидоры до тех пор, пока не находил для себя подходя- щий экземпляр. Это же можно сказать и о долгом пути по улицам города в поисках аптеки. Цикл дает сценарию инструкцию периодически повторять последовательность действий до тех пор, пока не будет выполнено определенное условие. Например, программа JavaScript проверки правильности данных может анализировать каждый символ, вводимый пользователем в текстовом поле, чтобы убедиться в его принадлежности к числовым данным. Если у вас есть набор данных, сохраненных в виде списка, то в цикле можно проверить, где в этом списке рас- полагается введенный символ. Как только условие выполнится, сценарий прекратит выполнение цикла и продолжит работу со следующей после последнего оператора цикла инструкции. Наиболее часто используемой в JavaScript циклической структурой является оператор for. Он получил свое имя по первому слову используемого в нем оператора. Оператор цикла for является мощным программным средством, поскольку с его помощью можно много раз под- ряд выполнять самые сложные операторы. Используется этот оператор следующим образом. for ([начальное выражение]; [условие]; [выражение обновления]) { операторы внутри цикла } Квадратные скобки указывают на то, что расположенные в них параметры не обязательны для введения. Тем не менее, пока у вас нет твердых навыков использования оператора цикла for, рекомендуем использовать эти опции в каждом случае. Раздел начальное выражение обычно используется для того, чтобы установить начальное значение для счетчика цикла. Под условием подразумевается такое же выражение, что использовалось в условной конструкции if. В данном случае это выражение определяет условие, при наступлении которого выполнение цикла прекращается. Наконец, выражение обновления представляет собой оператор, кото- рый выполняется каждый раз после выполнения всех вставленных в тело цикла операторов. Общий принцип использования цикла подразумевает инициализацию переменной i, зна- чение которой постоянно увеличивается по ходу выполнения цикла. Так продолжается до тех пор, пока это значение не превысит некоторой максимальной величины, как это показано в следующем примере. for (var i = начальное значение; i <= максимальное значение; i++) { операторы цикла } Под терминами начальное значение и максимальное значение в данном случае подразумевается произвольное числовое значение (в том числе явно заданные числа и перемен- ные с числовыми значениями). В выражении обновления использован оператор, с которым ра- нее мы сталкивались. Оператор ++ увеличивает значение i на 1 каждый раз после выполнения тела цикла. Это увеличение происходит обязательно после выполнения итерации цикла. Если значение начальное значение равно 1, то в первой итерации цикла значение i будет равно 1, во второй итерации — 2 и т.д. Если значение максимальное значение равно 10, то цикл будет повторяться ровно 10 раз (другими словами, до тех пор, пока значение i будет меньше 108 Часть II. Руководство по JavaScript
либо равно 10). Выражения в теле цикла могут также использовать значение переменной- счетчика. Позже в этой главе речь пойдет о переменной, которая играет ключевую роль в операторах тела цикла. В то же время, вы должны знать, как прервать выполнение цикла и в каких ситуациях это следует делать. Функции В главе 5 приведен пример использования в JavaScript функции. Под функцией подразу- мевают набор предопределенных действий. Функции используются повсеместно в сценарии обработчиками событий или операторами. Где это только возможно, все сложные наборы операторов стоит организовывать в функции, чтобы впоследствии использовать их в других документах. Функции— это те строительные блоки, которые применяются многократно. Тем, кто уже имеет опыт программирования, может показаться очевидным подобие функ- ций JavaScript и подпрограмм в других средах программирования. Но, в отличие от других языков, где используется разделение на процедуры (в которых выполняются последователь- ности действий) и функции (в которых выполняются действия и в качестве результата обяза- тельно возвращается значение), в JavaScript подобного разделения нет. Функция в JavaScript может возвращать значение в вызывающий ее оператор, однако это требование не является обязательным. Тем не менее, когда при использовании функции значение все же возвращает- ся, вызывающий ее оператор трактует эту функцию как обычное выражение — значение функции используется именно в том месте, откуда эта функция вызвана. Формальный синтаксис использования функций выглядит так. function имя^Функции ( [параметр!] . . . [параметр!^] ) { операторы } На имена, которые присваиваются функциям, накладываются те же ограничения, что и на имена элементов и переменных HTML. Можно порекомендовать использовать такое имя для функции, которое отображало бы задачи, возлагаемые на нее. Удобным при этом является использование имен из нескольких слов в слитном формате. В таком случае имя лучше начи- нать с глагола, поскольку функция выполняет действие (даже если она только получает или устанавливает значение определенной переменной). При написании функций полезно задать ей узкую специализацию. В принципе, можно сгенерировать функцию длиной в несколько сотен строк кода. Однако такие функции трудно обслуживать и отлаживать. Поэтому такие громадные конструкции следует разбить на не- большие, более сегментированные структуры. Параметры функций В главе 5 был приведен пример обработчика события, который вызывает функцию с по- мощью ее имени. Любой вызов функции, включая и функции из других операторов JavaScript, осуществляется по одной и той же схеме: в конце имени каждой функции следуют скобки. Можно определить функцию так, что она будет получать значения своих параметров не- посредственно из вызывающего ее оператора. В листинге 7.1 показан пример документа, в который добавлена кнопка. Обработчик события onCl ick этой кнопки вызывает функцию, передавая ей при этом текстовые данные в качестве параметра. Текстовая строка, используемая в вызове обработчиком события, является вложенной строкой — это набор одинарных кавычек внутри двойных кавычек, используемых во внешних атрибутах обработчика событий. Глава 7. Основы программирования. Часть 2 109
<html> <head> «script type="text/javascript"> function showMsg(msg) { alert("The button sent: " + msg); } </script> </head» <body> «forms «input type="button" value="Click Me" onelick="showMsg('The button has been clicked!')"s «/forms «/bodys «/htmls Параметры (известные также как аргументы) призваны обеспечить механизм “передачи” значения от одного оператора к другому в процессе вызова и выполнения функции. Если в определении функции вообще не используются параметры, то и в описании функции при ее вызове вы увидите пустую пару скобок (см. листинг 5.8 главы 5). Переменным, указанным на месте параметров в описании функции, присваиваются вво- димые в коде вызова функции значения. Рассмотрим, например, такой фрагмент кода сценария. function sayHiToFirst(a,b,с) { alert("Say hello, " + a); } sayHiToFirst("Gracia", "George", “Harry"); sayHiToFirst ("Larry" , "Moe" , "Curly" ) ,- Если функция определена в сценарии, в следующем операторе она будет вызвана. В каче- стве параметров ей при этом передается три строки. В силу определения функции любые зна- чения строк присваиваются параметрам а, b и с. Таким образом, еще до того, как будет вы- полнен оператор alert О внутри функции, значение а будет приравнено к "Gracia", значение b— "George", а значение с— "Harry". Поскольку в операторе alert О ис- пользуется только значение а, то в результате получим сообщение. Say hello, Gracia Когда пользователь закроет окно первого сообщения, согласно сценарию данная функция будет вызвана еще раз. На этот раз, тем не менее, функции передаются уже другие значения, которые и будут присвоены параметрам а, b и с. Диалоговое окно в этом случае содержит такое предупреждение. Say hello, Larry В отличие от других переменных, которые определяются в сценариях,'при инициализации параметров функции не нужно использовать ключевое слово var. Параметры инициализи- руются автоматически, в каком бы месте ни вызывалась функция. Диапазон действия переменных Говоря о переменных, самое время разграничить их на те, которые определяются внутри функций, и те, которые определяются вне функций. Переменные, определяемые вне функций, называются глобальными переменными. Переменные же, определяемые в рамках функций, на- зываются локальными переменными. 110 Часть II. Руководство по JavaScript
Глобальные переменные в JavaScript имеют совершенно иное, особое значение, по срав- нению с большинством других языков. В JavaScript пределы “глобальности” для переменных доходят до размеров текущего документа, загруженного в окно браузера. Поэтому инициали- зация переменной в качестве глобальной подразумевает, что все операторы страницы (включая и те, что расположены в описании функций) получают прямой доступ к значению этой переменной. Операторы могут восстанавливать и изменять значения глобальных пере- менных в любом месте страницы. Используя терминологию программирования, можно ска- зать, что эти переменные имеют глобальную область действия, поскольку буквально все элементы страницы могут их использовать для своих нужд. Помните, что в тот самый момент, когда страница выгружается, все глобальные перемен- ные, определенные на ней, будут удалены из памяти. Если нужно передать определенное зна- чение от одной страницы к другой, то для этого следует использовать другие технологии (например, глобальную переменную в документе многофреймовой структуры, о чем расска- зано в главе 16, или использовать метод, приведенный в главе 18). Ключевое слово var при инициализации глобальных переменных задавать необязательно, однако мы настоятельно ре- комендуем его использовать в любых ситуациях. Это поможет избежать недоразумений при работе с будущими версиями языка JavaScript. В отличие от глобальных переменных, локальные переменные определяются внутри функций. С тем, как в функциях описываются параметры, вам уже приходилось сталкиваться (в этом случае ключевое слово var при инициализации не использовалось). Что касается ос- тальных переменных, то их можно определить с помощью ключевого слова var (для локаль- ных переменных его использовать обязательно всегда). Диапазон легитимности локальных переменных не выходит за рамки операторов в теле описания функции. Ни одна другая функ- ция или оператор за пределами текущей не в силах получить доступ к локальной переменной. “Локальная область действия” определяется в тех случаях, когда для разных локальных переменных в рамках одного документа используются одинаковые имена. В большинстве случаев подобная практика весьма ущербна, поскольку приводит к очень неприятным ошиб- кам, которые крайне тяжело отслеживать. В то же время, в некоторых случаях удобно ис- пользовать одни и те же имена, скажем, для счетчиков в программном цикле for. Это вполне безопасно, поскольку такие счетчики в начале запуска цикла каждый раз заново инициализи- руются с начальным значением. Тем не менее, вставить один цикл for в другой такой же цикл, не использовав при этом отличную переменную для счетчика, вам не удастся. Для того чтобы продемонстрировать структуру и поведение локальных и глобальных пе- ременных, а также показать, почему крайне нежелательно использовать в документе для раз- ных переменных одинаковые имена, приведен листинг 7.2. В нем описаны две локальные и две глобальные переменные. При этом имена локальной переменной совпадают с именами глобальной переменной. <html> <head> <script type="text/JavaScript"» var aBoy = "Charlie Brown"; // глобальная переменная var hisDog = "Snoopy"; // глобальная переменная function demo () { // Это пример того, как поступать не следует var hisDog ="Gromit" // локальная версия переменной hisDog var output = hisDog + "does not belong to " aBoy + ",<br>"; document.write(output); } </script> Глава 7. Основы программирования. Часть 2 111
</head> <body> <script type="text/JavaScript"> demo(); // запускается при загрузке документа document.write(hisDog + "belongs to " + aBoy + </script> </body> </html> Когда страница загружается, сценарий в разделе заголовка инициализирует две глобаль- ные переменные (аВоу и hisDog) и создает в памяти функцию demo (). В теле документа эту функцию вызывает другой фрагмент сценария. Внутри функции инициализируются две локальные переменные, одна из которых (hisDog) имеет имя, совпадающее с именем гло- бальной переменной. В JavaScript такое двойное описание переменной приводит к тому, что везде в пределах данной функции приоритетным для всех операторов функции будет описа- ние локальной переменной. Однако следует обратить внимание на такой факт: если убрать ключевое слово var из локальной инициализации, то в результате глобальной версии этой переменной будет присвоено новое значение "Gromit". Другая локальная переменная output предназначена, скорее, для сохранения текста, чем для отображения его на экране. Аккумуляция текста переменной начинается с того момента, ко- гда вычисляется значение локальной переменной hisDog. Затем проводится объединение тек- стовых фраз (обратите внимание на дополнительные пробелы в конце строк). Затем определяет- ся значение глобальной переменной аВоу. Ни одна глобальная переменная не может быть вытеснена локальной переменной, доступной в данной функции. После этого определяется вы- ражение HTML, которое нужно отобразить на странице так, чтобы оно заканчивалось пробелом и дескриптором <br>. В последнем операторе функции содержимое выводится на странице. Когда стоящая перед функцией задача будет выполнена, следующий оператор тела доку- мента выведет на страницу еще одну строку. Поскольку этот оператор сценария имеет гло- бальную область действия (т.е. он находится вне функции), ему будут доступны все глобаль- ные переменные, включая и те, которые определены внутри других дескрипторов <script> данного документа. Когда загрузка всей страницы будет полностью завершена, на странице появится следующий текст. Gromit does not belong to Charlie Brown. Snoopy belongs to Charlie Brown. Использование фигурных скобок Вводить фигурные скобки ({}) и применять их в JavaScript (и многих других языках) не- сложно. Их обычно используют для выделения блоков кода, которые должны выполняться вместе. Наличие таких фигурных скобок позволяет программистам легче разобраться в по- следовательности выполнения операторов, кроме того, они помогают браузеру определить порядок группировки инструкций. Фигурные скобки вводятся только парами. Фигурные скобки используются, в основном, в описаниях функций и в управляющих структу- рах. В описании функции в листинге 7.2 фигурные скобки группируют вместе четыре оператора, которые выполняют все ее действия (включая и строки комментария). Закрывающая скобка указы- вает браузеру на то, что все расположенное после нее к функции никакого отношения не имеет. Если говорить о синтаксическом размещении фигурных скобок, то жестких правил в JavaScript на этот счет не существует (как вы уже наверняка убедились). Приведенные ниже описания функций трактуются браузером совершенно идентично. 112 Часть II. Руководство по JavaScript
function sayHiToFirst(a, b, c) { alert("Say hello, " + a); } function sayHiToFirst(a, b, c) { alert("Say hello, " + a); function sayHiToFirst(a, b, c) {alert("Say hello, " + a);} В этой книге мы будем придерживаться первого варианта, поскольку он является более простым при анализе кода сценария — особенно это относится к сценариям, в которых много вложенных управляющих структур. Массивы В JavaScript одним из наиболее полезных способов организации и хранения данных явля- ются массивы. Представить себе самый простой массив можно в виде одномерной таблицы. В каждом столбце строю/ такой таблицы содержатся данные, при этом каждый столбец про- нумерован. Для нумерации столбцов массива используется строгая числовая последователь- ность, в которой первый столбец имеет нулевой номер (программисты всегда начинают счи- тать с нуля). Эти номера столбцов массива еще называют индексами. Чтобы получить доступ к элементу массива, необходимо знать имя этого массива и номер столбца нужного элемента массива. Поскольку значения индексов начинаются с нуля, то общее количество элементов массива (определяется свойством массива length) всегда на единицу больше самого боль- шого индекса в массиве. Более совершенная концепция массивов позволяет создать подобие массива с несколькими строками в столбце. Такие структуры описаны в главе 30. На данном этапе имеет смысл ограничиться рассмотрением массивов, состоящих из одной строки. Данные, хранящиеся в качестве элементов массива в JavaScript, могут быть любого типа, в том числе и объектами. В отличие от большинства других языков программирования, в раз- личных столбцах массива JavaScript могут содержаться данные разных типов. Создание массива Массив определяется с помощью переменной. Поэтому при создании массива переменной присваивается объект нового массива. Да, массивы являются объектами JavaScript, но к базо- вому языку JavaScript они все же имеют большее отношение, чем к объектной модели доку- мента. При объявлении массива используется специальное ключевое слово new, которое по- могает вызвать специальную функцию JavaScript, генерирующую массив и выделяющую для него место в памяти. Необязательный параметр функции Array () позволяет указать еще на этапе создания массива, ориентировочное количество элементов, зарезервированных в дан- ном массиве. В этом смысле JavaScript является очень демократичным языком, поскольку размер массива можно изменить в любое время. Поэтому если при создании нового массива в качестве параметра ничего указано не будет, то сценарий от этого совершенно не пострадает. Для того чтобы наглядно продемонстрировать процесс создания массива, приведем код конструктора массива, элементами которого являются названия 50 штатов и одного округа Колумбия (всего 51 элемент). Первым делом создается массив; ему присваивается имя, кото- рое лучше всего характеризует содержащиеся в нем данные. var USStates = new Array (51)'; Начиная с этого момента, в памяти будет выделено место для массива с именем USStates, где содержится 51 элемент. Для того чтобы заполнить этот массив, каждому его элементу Глава 7. Основы программирования. Часть 2 113
нужно присвоить значение. Обращение к каждому элементу массива требует использования специального индекса: сначала указывают имя массива, а затем в квадратных скобках вводит- ся индекс нужного элемента. Первым элементом в массиве USStates будет USStates[0] Чтобы присвоить первому элементу массива первое по алфавиту название штата, необхо- димо воспользоваться обычным оператором присваивания USStates[0] = "Alabama"; Остальные элементы массива можно заполнить следующим способом. USStates[1] = "Alaska"; USStates[2] = "Arizona"; USStates[3] = "Arkansas"; USStates[50] = "Wyoming"; Если в документе нужно использовать таблицу данных, из которой сценарий впоследст- вии должен получать информацию, то исключить обращение к серверу можно, оформив ее в виде массива. Если сделать соответствующие операторы выполняющимися в процессе за- грузки документа, то к тому моменту, когда документ будет полностью отображен в браузере, массив данных уже будет создан и готов к использованию. Несмотря на то, что у вас может сложиться впечатление о необходимости использования в такой ситуации большого числа операторов, объем загружаемых данных, на самом деле, невелик. Он не представляет особых проблем, поэтому загрузка страницы проходит идеально даже у тех пользователей, которые используют каналы соединений со скоростью передачи данных 28,8 Кбит/с. Получение доступа к данным массива Индекс элемента массива является тем ключом, который позволяет получать доступ к не- му. Указав имя массива и индекс нужного элемента в квадратных скобках после имени, мож- но получить значение, записанное в соответствующем столбце массива. Например, после соз- дания массива USStates сценарий может вывести на экран окно сообщения с названием штата Аляска, для чего предназначается следующий код. alert("The largest state is " + USStates[1] + Точно так же, как вы добираетесь до значения элемента по имени массива и индексу, можно изменить значение элементов массива. Для этого нужно указать элемент и присвоить ему новое значение. Параллельные массивы Ниже показано, почему использование в качестве индексов массивов чисел в JavaScript является оптимальным вариантом. Для того чтобы пример был более наглядным, сгенерируй- те еще один массив наряду с уже существующим USStates. Этот новый массив также будет состоять из 51 элемента и содержать в качестве данных годы, в которые соответствующие штаты из первого массива USStates вступили в Конфедерацию. Выглядит описанная выше структура следующим образом. var stateEntered = new Array(51); stateEntered [0] = 1819; stateEntered [1] = 1959; stateEntered [2] = 1912; stateEntered [3] = 1836; stateEntered [50] = 1890; 114 Часть II. Руководство no JavaScript
Содержащиеся в памяти браузера две таблицы с данными можно представить так, как по- казано на рис. 7.1. Используя описанный принцип, добавьте любое количество дополнитель- ных массивов, параллельных текущим массивам. Например, это могут быть почтовые индек- сы или названия столиц штатов. Важно отметить, что нулевые элементы всех массивов соответствуют штату Алабама — первому штату массива USStates. USStates ''Alabama'’ "Alaska" "Arizona" "Arkansas" "Wyoming" Рис. 7.1. Вид двух взаимосвязанных таблиц Если на Web-странице используются обе эти таблицы и пользователю необходимо найти дату вступления конкретного штата в Конфедерацию, то сначала придется просмотреть все записи массива USStates, найти индекс нужного штата, а лишь затем по данному индексу из массива stateEntered вы узнаете нужную дату. В данном примере на страницу добавляется текстовое поле — в него пользователь может ввести название штата, дату вступления которого в Конфедерацию необходимо определить. В реальном приложении такой подход может привести к некоторым проблемам. Вы должны обязательно проверить правильность вводимого пользователем названия. В данном случае на такие “пустяки” пока отвлекаться не будем. Будем считать пользова- теля грамотным человеком. Конечно, при разработке настоящих приложений для Web таки- ми вещами пренебрегать нельзя. Обработчик события текстового поля или специальной кнопки (в данный момент это не важно) вызывает функцию, которая занимается поиском элемента для названия штата, определяет соответствующую дату и отображает окно, содер- жащее найденную информацию. function getStateDate() { var selectedState = document.entryForm.entry.value; for ( var i = 0; i < USStates.length; i++) { if (USStates[i] == selectedState) { break; } } alert("The state entered the Union in " + stateEntered[i] + " ”) ’ } В первом операторе функции переменной selectedState присваивается то значение, которое введено пользователем в текстовом поле. Такое длинное имя для переменной выбра- но для большей наглядности. Фактически, эта переменная используется только в цикле for, поэтому браузеру не нужно каждый раз преобразовывать длинную ссылку на текстовое поле, что в конечном счете способствует повышению эффективности сценария. Особенность функции заключается в цикле for. Именно в нем увеличение счетчика на каждом этапе выполнения цикла совмещается с использованием этого счетчика в качестве индекса для элементов обоих массивов. В параметрах цикла указывается следующее: началь- ным значением для переменной-счетчика i должен быть нуль. Цикл будет выполняться до тех пор, пока значение переменной i будет меньше длины массива USStates. Не забывайте, Глава 7. Основы программирования. Часть 2 115
что длина массива всегда на единицу больше, чем индекс последнего элемента в этом масси- ве. Поэтому, когда цикл запускается последний раз и значение переменной i равно 50 (что точно меньше длины массива, равной 51), то это будет соответствовать индексу последнего элемента массива. Каждый раз после выполнения очередной итерации значение переменной- счетчика будет увеличиваться на единицу. Внутри оператора цикла for используется условный оператор if, с помощью которого проверяется совпадение значения элемента массива с тем, что введено пользователем в тексто- вом поле. Каждый раз при запуске цикла условие проверяется для очередного элемента массива, начиная с элемента с индексом нуль. Другими словами, условие, используемое в операторе if, может проверяться десятки раз, пока совпадение не будет обнаружено. Но каждый раз при этом значение переменной i увеличивается на единицу по сравнению с предыдущим вариантом. Оператор проверки равенства (==) необычайно строг при сравнении строковых значений. В этом случае на совпадение проверяются символы с учетом регистра (т.е. строчные и про- писные буквы различаются). Для того чтобы в данном примере совпадение было обнаружено, название штата должно указываться пользователем абсолютно идентично тому, как оно пред- ставлено в массиве USStates. В главе 10 будут описаны методы, позволяющие ослабить жесткость требований при проверке равенства строковых значений. Если совпадение имен обнаружено, выполняется оператор, заданный внутри условного оператора if. Оператор break добавлен в сценарий на тот случай, если понадобится пре- рвать выполнение программы. В данном приложении при обнаружении совпадения оператор цикла for досрочно прекращает работу. Когда цикл for прерывается, значение переменной i фиксируется на том значении, которое соответствует элементу массива USStates, в кото- ром хранится нужная запись. Это значение впоследствии используется для получения доступа к элементу другого массива. Даже несмотря на то, что переменная-счетчик i специально инициализирована для использования в операторе цикла for, она остается доступной в пре- делах функции для всех операторов даже после выполнения цикла. Вот почему эту перемен- ную можно использовать для того, чтобы определить значение нужного элемента в массиве stateEntered и отобразить результат в окне сообщения. Приведенный пример использования в операторе for переменной-счетчика для указания индексов является довольно типичным для JavaScript. Поэтому внимательно изучите код и разберитесь, как он работает. Это имеет отношение не только к способам управления мас- сивами, но и к генерации браузерами массивов в объектных моделях документов. Объекты документа в массиве Если заглянуть в справочные разделы приложения А и найти там подраздел, описываю- щий объект document, то нетрудно заметить, что свойства некоторых объектов приведены в квадратных скобках после соответствующих имен. Это такие же квадратные скобки, кото- рые использовались выше для указания элементов массива. Дело в том, что при загрузке браузером в документе создаются объекты, подобные массивам. Например, если на странице используются два дескриптора формы <FORM>, то в документе появится две формы. В брау- зере будет поддерживаться массив объектов форм для данного документа. Ссылаться на та- кие формы можно следующим образом. document.forms[0] document.forms[1] Индекс значения для объектов документа присваивается в зависимости от очередности за- грузки объектов. В случае с объектами формы такой порядок определяется очередностью следования дескрипторов формы <FORM> в коде документа. Такая индексная форма записи является еще одним способом представления формы в структуре ссылки на объекты. Па- раллельно можно продолжать использовать имена форм, что намного удобнее, поскольку 116 Часть II. Руководство по JavaScript
в последнем случае изменение порядка их следования в коде HTML-документа никак не по- влияет на ссылки. Но если страница содержит, скажем, только одну форму, то можно исполь- зовать разные типы ссылок поочередно, как это показано на примере обращения к свойству length текстового поля формы. document. getElementsByld ( "entryForm'i) . elements. length document.forms[0].elements.length В многочисленных примерах этой книги можно найти ссылки самых разных типов и струк- тур. Однако подобное разнообразие редко применяется одновременно в серьезных про- граммных разработках. Упражнения 1. Получив информацию об использовании функций, обработчиков событий и управ- ляющих структур, воспользуйтесь фрагментами сценария этой главы, чтобы создать страницу, в которой представлена таблица всех штатов с датам их вступления в Кон- федерацию. Если у вас под рукой нет справочника с соответствующими датами, то ис- пользуйте любые числа, начиная с 1800. На странице нужно создать поле для ввода текста, в котором задается название штата, а также кнопку, щелчок на которой будет инициализировать начало поиска в массивах. 2. Исследуйте приведенное ниже описание функции. Есть ли в этом описании неточно- сти? Если да, то как их устранить? function format(ohmage) { var result; if ohmage >= le6 { ohmage = ohmage / le6; result = ohmage + " Mohms"; } else { if (ohmage >= le3) ohmage = ohmage / le3; result = ohmage + " Kohms"; else result = ohmage + " ohms"; } alert(result); 3. Разработайте собственный синтаксис для сценария выбора зрелого помидора в овощ- ном отделе супермаркета. Запишите цикл for для этого сценария. 4. Измените листинг7.2 так, чтобы внутри функции переменная hisDog повторно не использовалась. ч 5. Ниже приведена таблица с данными о некоторых планетах Солнечной системы. Нуж- но создать Web-страницу, на которой пользователь введет название планеты и по щелчку на кнопке получит окно сообщения с указанием расстояния этой планеты до Солнца и ее диаметр. Если получится, сделайте так, чтобы эта информация выводи- лась на странице в отдельных полях. Планета Расстояние до Солнца Диаметр Меркурий 52 млн. км 4 880 км Венера 108 млн. км 12100 км Земля 149 млн. км 12 750 км Марс 228 млн. км 6 800 км Глава 7. Основы программирования. Часть 2 117
Объекты документа и окна После изучения методологических основ программи- рования можно перейти к вопросу взаимодействия сценариев и объектов документа. Начиная с этой главы, мы обратимся к объектной модели документа. Более подробно мы остановимся на тех объектах, которые в дальнейшем бу- дут чаще всего использоваться в документе. Объекты окна документа Чтобы вспомнить, как выглядит самая общая иерархиче- ская структура объектов документа, взгляните в рис. 8.1. В этой главе ваше внимание будет сконцентрировано на верхней части этой структуры: на объектах window, location, navigator и document. Главная цель — не просто загру- зить вас багажом знаний, необходимых для решения простых задач, но также подготовить к глубокому и всестороннему исследованию как каждого объекта, так и его свойств, мето- дов, а также обработчиков событий. Последним посвящена часть Ш этой книги. Вы узнаете об основных свойствах, мето- дах и обработчики событий объектов — более подробную ин- формацию о них можно получить в части Ш. Примеры, приве- денные в этой главе, полностью основаны на материале предыдущих глав, посвященных основам написания программ. Объект окна В самом верхней части иерархической структуры объек- тов документа находится объект window. Этот объект зани- мает особое, привилегированное положение в наборе объектов, поскольку он представляет основной контейнер, в котором размещается все то, чем можно управлять с помощью Web- браузера. В течение всего времени, пока окно браузера от- крыто (даже если в нем не загружен ни один документ), объект window будет находиться в текущей объектной модели, хра- нящейся в памяти.
Рис. 8.1. Общая иерархическая структура объектов документа, используемая браузерами Область использования объекта окна достаточно широка — от регулирования содержимо- го окна до настройки его размеров. Размеры окна определяют область, в которой размещают- ся также полосы прокрутки, панели инструментов, строки состояния и меню (в Windows) т.е. все, что относится к атрибутам окна. Далеко не каждый браузер обладает средствами управления этими элементами главного окна браузера. Однако всегда можно написать сцена- рий, создающий дополнительное окно, размеры которого несложно изменить в соответствии с вашими требованиями, а также отобразить в нем только самые необходимые элементы. Несмотря на то, что о подокнах (или фреймах) речь пойдет только в главе 11, на данном этапе можно совершенно спокойно утверждать, что каждый фрейм может рассматриваться как отдельный объект window. Использовать систему фреймов весьма эффективно, посколь- ку в каждом фрейме могут содержаться отдельные готовые документы. Когда в одном из этих документов запускается сценарий, то в иерархической структуре объектов соответствующее подокно рассматривается как объект window. Как вы узнаете далее в этой главе, объект window удобно использовать для определения методов объектной модели документа, которые отображают вложенные диалоговые окна и управляют текстом, представляемым в строке состояния окна браузера. Методы объекта window позволяют создать отдельное окно, которое будет отображаться на экране. Основная же часть всех свойств, методов и обработчиков событий объекта window (см. главу 16) свя- зана с процессами отображения различных элементов окна. Получение доступа к свойствам и методам окна В сценарии ссылки на свойства и методы объекта window можно реализовать разными спо- собами. Это определяется, скорее, предпочтениями программиста и стилем, которого он придер- живается, чем определенными синтаксическими требованиями. Наиболее общим и логическим подходом является тот, в котором задается непосредственное обращение к объекту window. window.имяСвойства window.имяМетода([параметры]) К объекту window часто обращаются с помощью синонима. Делается это в тех случаях, когда в сценарии используются ссылки на окно, содержащее текущий документ. Синонимом является ключевое слово se 1 f. В таких случаях ссылки выглядят следующим образом. self.имяСвойства self.имяМетода([параметры]) Использовать подобные ссылки можно по собственному усмотрению. Однако целесооб- разно задавать ссылки с помощью self в сложных сценариях, в которых задействовано не- сколько фреймов или окон. Другими словами, идентификатор self используется для обозна- чения того текущего окна, в котором находится документ с данным сценарием. А это, в свою очередь, делает сценарий более читабельным, по крайней мере так думают многие разработ- чики программных продуктов. Глава 8. Объекты документа и окна 119
Как уже отмечалось в главе 4, поскольку объект window всегда присутствует “на месте” при запуске сценария, то в ссылке на объекты внутри текущего окна его имя можно опустить. В качестве примера ниже приведена синтаксическая модель обращения к свойствам и мето- дам текущего окна. имяСвойства имяМетода([параметры]) Принципы использования некоторых методов воспринимаются легче, если в ссылке не используется ключевое слово window. В этом случае методы выполняются так же эффектив- но, как и ранее. Создание окна Главное окно браузера в сценарии не создается. Это делает пользователь при запуске браузера, а также при открытии документа с определенным URL или другого файла (если ок- но браузера не было открыто до этого). Однако с помощью сценария можно сгенерировать любое число дополнительных окон (если главное окно открыто и в него помещен документ, новые окна открывает сценарий главного окна). Метод, с помощью которого можно генерировать новые окна, — window. open (). В этом методе используется до трех параметров, которые определяют такие характеристики окна, как URL загружаемого документа, его название, указываемое в атрибутах target дескрип- торов HTML, а также физические параметры (размер и содержимое). Более детально на этих параметрах мы пока останавливаться не будем (они рассмотрены в главе 16), однако одну важную особенность использования метода window, open () все же рассмотрим. Ниже приведен пример оператора, который открывает новое окно предопределенного размера с отображенным документом HTML, расположенным в той же папке на сервере, в которой хранится текущая страница. z var subWindow = window.open("define.html","def", "height=200, width=300"); Обратите внимание на то, что в приведенном выше коде используется оператор присваи- вания. С его помощью переменной subWindow присваивается некое значение. Оказывается, что при запуске метода window.open () не только открывается новое окно согласно ис- пользуемым параметрам, но также создается ссылка на новое окно. На языке программирова- ния можно сказать, что метод возвращает значение — в данном случае это самая настоящая ссылка на объект. Значение, возвращаемое методом, присваивается переменной. Теперь эта переменная может вполне законно использоваться как ссылка на второе окно. Если нужно получить доступ к одному из его свойств или методов, то следует использовать указанную ссылку как часть полной ссылки. Например, для того чтобы закрыть прямо из сце- нария главного окна данное подокно, можно воспользоваться методом close (). subWindow.close О ; Если в сценарии главного окна используются записи window, close (), self .close или просто close (), то будет закрыто главное окно, а вовсе не дополнительное. Поэтому для обращения к другим окнам следует использовать ссылку на нужное окно как часть общей ссылки. Этот момент важен при составлении, сценариев: часто требуется, чтобы переменная, содержащая ссылку на дополнительное окно, была доступна в течение всего времени, пока главный документ загружен в браузер. Чтобы обеспечить это, следует объявить данную пере- менную как глобальную, но ни в коем случае не внутри функции (хотя значение этой пере- менной можно присвоить и в пределах функции). В такой ситуации используйте одну функ- цию, чтобы открывать окна, а другую — для их закрытия. Листинг 8.1 описывает страницу, которая содержит кнопку открытия нового, пустого ок- на, которое впоследствии можно будет закрывать из главного. Вы увидите, как работает сценарий. 120 Часть II. Руководство по JavaScript
если зададите размеры главного окна браузера так, чтобы оно не было развернуто во весь эк- ран. Тогда при генерации нового окна можно будет разместить окна на экране таким образом, чтобы новое окно было видно даже в том случае, когда основное находится на переднем пла- не. Если окно было при этом “скрыто” за основным, то для его отображения используйте ме- ню Window (Окно) браузера. В листинге 8.1 переменная newWindow объявлена как глобаль- ная, поэтому обе функции— makeNewWindow() и closeNewWindow() — без особых проблем получают к ней доступ. Если переменная объявляется без присвоения ей значения, то по умолчанию оно равно null. Значение null интерпретируется как эквивалентное false в условном операторе. С другой стороны, наличие в условном операторе любого не- нулевого значения интерпретируется как true. В функции closeNewWindow () перед ис- пользованием метода закрытия close () сначала проверяется, было ли вообще создано но- вое окно. Затем для выполнения очистки переменной newWindow присваивается значение null, поэтому при повторном щелчке на кнопке Close (Закрыть) закрытия уже несущест- вующего окна не произойдет. I." Листинг 8.1, Ссылка на объекты окна <html> <head> <title>Window Opener and Closer</title> <script type="text/javascript"> var newWindow function makeNewWindow() { newWindow = window.open"height=300,width=300"); } function closeNewWindow() { if (newWindow) { newWindow.close(); newWindow = null; } } </script> </head> <body> <form> cinput type="button" value="Create New Window" onclick="makeNewWindow()"> cinput type="button" value="Close New Window" onclick="closeNewWindow()"> </form> </body> </html> Свойства и методы окна Три описываемых в этой главе метода и одно свойство объекта window имеют непосред- ственное отношение к задачам, часто решаемым пользователями. Они доступны во всех брау- зерах, поддерживающих сценарии. Для каждого метода и свойства, подробно описанного в части Ш, в данной книге приведено немало примеров использования. Вы можете поэкспе- риментировать со сценарием, состоящим из единственного оператора, введя его в верхнем текстовом поле приложения The Evaluator Jr (см. главу 6). Глава 8. Объекты документа и окна 121
Свойство window.status Строка состояния в нижней части окна браузера при наведении на нее указателя мыши обычно отображает адрес URL ссылки. При загрузке документа, инициализации аплетов Java и подобных действиях в этой области отображаются другие сообщения. Тем не менее, с по- мощью JavaScript можно сделать так, что в определенные моменты в строке состояния будут отображаться собственные сообщения разработчика страницы, которые предоставляют по- лезную для пользователя информацию. Например, вместо того чтобы отображать адрес URL ссылки, можно вывести дружественное, доступное описание страницы (или комбинацию пер- вого и второго, чтобы удовлетворить самые изысканные запросы). Присвоить свойству window. status другое текстовое значение можно в любое время. Чтобы заставить текст в строке состояния изменяться каждый раз при наведении на ссылку указателя мыши, следует задать обработчик события onmouseover для объекта ссылки. В JavaScript такое поведение задается крайне редко, однако к таким мерам приходится прибе- гать, чтобы сценарий успешно перепрограммировал содержимое строки состояния. Поскольку свойство window.status установить достаточно просто, то наиболее общий подход для управления строкой состояния — это запуск внутри дескрипторов операторов об- работчика события. Это удобно при управлении небольшими сценариями, поскольку не тре- бует определения отдельных функций или добавления дескрипторов <scripts на страницу. В дескриптор <а> оператор обработчика события добавляется без предварительного задания дескриптора сценария. <а href="http://www.microsoft.com" onmouseover= "window.status='Visit the Microsoft Home page (microsoft.com)' "> Microsoft</a> Обратите особое внимание на операторы, используемые в обработчике события onmouseover. Речь идет о двух следующих выражениях. window.status=’Visit the Microsoft Home page (microsoft.com)' При запуске этих операторов внутри обработчика события нужно разделять их точкой с запятой. Пробел после точки с запятой ставить не обязательно, однако он улучшает чита- бельность кода. Важно даже то, что весь набор операторов заключен в двойные кавычки ("..."). Чтобы вставить в двойных кавычках строку, присвоенную в качестве значения свойству window.status, следует заключить эту строку в одинарные кавычки ('...'). Настройка строки состояния в будущем принесет значительные дивиденды, а для этого нуж- но всего-то ввести несколько дополнительных строк кода. Как бы там ни было, а работа с ус- пехом завершена. Все! Метод window.alert() Рис. 8.2. Окно с предупреждением в JavaScript (устаревший стиль) В этом руководстве метод alert () уже использовался неоднократно. Он генерирует диалоговое окно, отобра- жающее тот текст, который передается методу в качестве параметра (рис. 8.2). Единственная кнопка ОК, надпись которой нельзя изменить предназначена для того, чтобы пользователь мог закрыть окно предупреждения. Внешний вид этого окна и двух других, которые бу- дут описаны ниже, очень изменился с момента появле- ния первого браузера, поддерживающего использование сценариев. В старых версиях браузеров (как на рис. 8.2) в явном виде указано, что это окно предупреждения JavaScript ([JavaScript Application]). Разные браузеры отображают разные 122 Часть II. Руководство по JavaScript
заголовки окон, что в сценарии изменить невозможно. Изменять допускается только со- держимое сообщений. Все три описанных в этой главе метода отображения диалоговых окон можно задать без указания в ссылке объекта window. Даже несмотря на то, что метод alert () технически является методом объекта window, никакой специальной взаимосвязи между диалоговым окном и окном, отображающим это диалоговое окно, не существует. В сценарии произволь- ного назначения обычно добавляют следующую ссыпку. alert("This is a JavaScript alert dialog"); //Это диалоговое окно предупреждения JavaScript Метод window.confirm() В диалоговом окне другого типа используются уже две кнопки. Для большинства версий браузеров и платформ это кнопки ОК и Cancel (Отмена). Называется такое окно диалоговым окном подтверждения (рис. 8.3). Важным для метода является то, что он возвращает значение true, ес- ли пользователь щелкает на кнопке ОК, и false, если пользователь щелкает на кнопке Cancel. Это диалоговое окно и значение, им возвращаемое, можно использовать для предоставления пользователю возможности управле- ния дальнейшими действиями сценария. Поскольку метод возвращает значение булевого типа, то оно может использоваться в каче- стве условного оператора в конструкции if или операторе if. . . else. Например, в приведен- ном ниже фрагменте кода у пользователя запрашивается подтверждение на запуск приложения. Результат подтверждения — это загрузка используемой по умолчанию страницы узла в браузере. if (confirm("Are you sure you want start over?")) { location.href = "index.html"; } Puc. 8.3. Диалоговое окно под- тверждения JavaScript (стиль IE6/WindowsXP) Метод window.prompt() Последним диалоговым окном объекта window является диалоговое окно запроса (рис. 8.4). В нем отображается определяемое разработчиком страницы сообщение и выводит- ся текстовое поле для ввода ответа. Две кнопки, которые присутствуют в диалоговом окне, ОК и Cancel, позволяют пользователю закрыть диалоговое окно с двумя взаимоисключаю- щими исходами: отменой всей операции или принятием того, что введено в текстовом поле. Рис. 8.4. Диалоговое окно запроса данных в JavaScript (стиль IE6/WindowsXP) Метод window.prompt () подразумевает использование двух параметров. Первый — сообщение, которое выводится пользователю в качестве подсказки. Второй параметр в виде строки используется для того, чтобы задать в текстовом поле предлагаемый по умолчанию Глава 8. Объекты документа и окна 123
ответ пользователя. Если по умолчанию предлагать ответ пользователю не предусмотрено, то в этом случае отображается пустая строка (две двойные кавычки без пробелов между ними). Этот метод возвращает только одно значение при щелчке пользователем на любой из кнопок. Щелчок на кнопке Cancel возвращает значение null независимо от того, что поль- зователь ввел в текстовом поле. Если пользователь щелкнул на кнопке ОК, то в качестве зна- чения будет возвращена введенная им в текстовом поле строка. Сценарии могут использовать эту информацию в конструкциях if или if. . . else. Значение null в условном операторе при этом трактуется как false. Пустая строка также трактуется как false. Это значение можно использовать для непосредственной проверки того, введены ли вообще в текстовом поле данные — см. следующий пример. var answer = prompt("What is your name?"); if (answer) { alert("Hello," + answer + "!"); } Единственная ситуация, в которой вызывается метод alert (), — пользователь ввел в диалоговое поле текст и щелкнул на кнопке ОК. Обработчик события onload Объект window реагирует на многочисленные события, генерируемые системой или пользователем. Но с одним событием придется работать чаще остальных. Оно возникает то- гда, когда все элементы страницы успешно загружены. Это событие состоится только после того, как все изображения, аплеты Java и файлы данных будут полностью загружены в брау- зер. Получение из сценария доступа к элементам документа в процессе загрузки страницы та- ит в себе опасность: если объект еще не загружен (возможно, по причине использования пло- хого сетевого соединения или низкопроизводительного сервера), то в сценарии произойдет ошибка. Преимущество использования события onload состоит именно в том, что оно по- зволяет использовать функции, обеспечивая наличие объектов документа в объектной моде- ли. Все обработчики событий окна размещаются внутри дескрипторов <body>. Даже если установилась четкая связь атрибутов дескриптора <body> со свойствами объекта документа document, следует помнить, что обработчики событий окна window также располагаются внутри этих дескрипторов. Объект location Иногда создается впечатление, что объект в иерархической структуре не представляет ни- чего такого, что может нести реальный физический смысл. Именно это относится к объекту location. Данный объект содержит адрес URL загруженного в окне документа. Он сущест- венно отличается от объекта документа document (см. далее) хотя бы потому, что документ имеет реальное содержимое, location — это только URL. Если вы не являетесь экспертом в области Web-технологий, то можете даже не подозревать, что URL состоит из многих компонентов, которые определяют расположение ресурса и методы отправки данных файла. В состав URL входят сведения о протоколе (например, http:)и имени узла (например, www. giantco. com). Получить отдельный доступ ко всем этим элементам можно как к обычным свойствам объекта location. Но, как правило, практический интерес представляет только одно свойство — href, которое определяет URL полностью. Ссылаться на другие страницы сценарий сможет только тогда, когда правильно задано свойство location.href. location.href = "http://www.dannyg.com" 124 Часть II. Руководство по JavaScript
Путешествовать по страницам в пределах собственного Web-узла можно, указывая только относительный URL (т.е. адрес относительно текущей страницы), и для этого совсем не обязатель- но использовать полный URL со всеми его протоколами и информацией об узле. Для представле- ния страниц за пределами домена текущей страницы нужно обязательно указывать полный URL. Если загружаемая страница будет находиться в другом окне или фрейме, то ссылка на ок- но должна содержать его адрес. Например, если сценарий открывает новое окно и присваива- ет на него ссылку переменной newWindow, то оператор, загружающий страницу в подокно, будет выглядеть следующим образом. newWindow.location.href = nhttp://dannyg.com" Объект navigator Несмотря на созвучие с названием браузера Netscape Navigator, объект navigator под- держивается во всех современных браузерах. С помощью его свойств в сценарии можно лег- ко определить, а потому и передать на сервер сведения об используемом браузере и компью- терной системе. Так, свойство navigator. userAgent возвращает в виде текстовой строки основные сведения о программной среде браузера. Например, если сценарий выполняется в браузере Internet Explorer 6, запущенном в Windows ХР, то свойство navigator. userAgent будет содержать следующее значение. Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461) Этот же сценарий, запущенный в браузере Mozilla в Macintosh, возвратит следующие сведения. Mozilla/5.0 (Macintosh; U; РРС Mac OS X Mach-O; en-US; rv:1.4) Gecko/20030624 В первом сценарии главы 3 вы уже использовали два свойства объекта navigator (appVertion и appName). В главе 38 на прилагаемом к книге компакт-диске вы найдете полное описание этого объекта и его свойств. Обратите внимание, что браузеры обрабатыва- ют данные по-разному (см. главу 14). Объект документа В объекте документа document хранится все реальное содержимое страницы. Свой- ства и методы объекта document, в основном, воздействуют на внешний вид и содер- жимое страницы, загруженной в окне. В браузерах W3C DOM можно с помощью сценария получать доступ к тексту страницы только в том случае, если документ полностью загру- жен. Тем не менее, как это было замечено еще в самом первом сценарии главы 3, метод document, write О позволяет динамически создавать содержимое в процессе загрузки страницы. Многие свойства объекта document являются другими объектами документа. Это позволяет получить к ним доступ несколькими более простыми способами (с помощью метода document. getElementByld () ). Получить доступ к свойствам и методам объекта document достаточно просто, как это и показано ниже. [window.]document.имяСвойства [window.J document.имяМетода([параметры] ) Ссылка на окно [window. ] при получении сценарием доступа к содержащему его объ- екту document является необязательной. Если нужно с помощью браузера выполнить пред- варительный просмотр свойств объекта document, то следует в верхнем текстовом поле приложения The Evaluator Jr. ввести document и нажать клавишу <Enter>. В поле Result (Результат) будут отображены свойства объекта и их текущие значения. Глава 8. Объекты документа и окна 125
Свойство document.forms[] Еще один тип объектов, содержащихся в документе,— это объекты элементов форм form. Поскольку на странице может использоваться более одной формы, то все они собира- ются в виде массива свойств документа document. forms []. Как читатель, наверное, пом- нит из главы 7, числовой индекс внутри квадратных скобок указывает на один из элементов массива. Чтобы выяснить, сколько всего форм form используется в данном документе, мож- но обратиться к следующей команде. document.forms.length Для получения доступа, скажем, к первой форме документа, следует использовать та- кую ссылку. document.forms[0] Все современные браузеры позволяют обращаться к форме по имени (идентификатору, сохраненному в атрибуте name дескриптора <form>). Причем эту задачу можно выполнить двумя способами. В первом случае используется синтаксис, близкий к используемому при управлении массивами. document.forms["имяФормы"] В следующих главах вы узнаете о том, как назначить имя форме. Чтобы не ошибиться с формой, рекомендуем вместо имени использовать индекс элемента массива. Второй способ более простой, поскольку имя формы указывается сразу после ключевого слова document. document.имяФормы Использование указанных способов приведет к одинаковому результату. Если в сценарии нужно сделать ссылку на элемент внутри формы, то полный адрес объекта обязательно дол- жен содержать ссылку на document и на саму форму. Свойство document.images[] Подобно тому, как в документе сохраняются сведения о формах (массив элементов), в объекте document содержится коллекция (массив) изображений, которые вставляются в документ с помощью дескриптора <img>. Изображения, представленные массивом document. images, доступны в программном коде по числовому индексу или имени элемента img. Как и в случае с формами, текстовый атрибут name однозначно идентифицирует элемент в наборе объектов. Поддержка браузером свойства document. images гарантирует загрузку и отображение им изображений стандартных для Web. Таким образом, данное свойство можно успешно использо- вать в качестве флага, указывающего на способность текущего браузера к загрузке и возмож- ность последующего управления изображениями. Чтобы выполнить в сценарии подобную про- верку, заключите операторы управления изображениями в конструкцию if, как показано ниже. If (document.images) { //операторы управления изображениями } Старые браузеры не распознают вложенных операторов, а использование конструкции if предотвращает возникновение ошибки, отображаемой на экране. 126 Часть II. Руководство по JavaScript
Метод document.write() Метод document .write () используется как непосредственно в исполняемых сценари- ях для создания содержимого загружаемой страницы, так и в сценариях, которые создают но- вое содержимое в текущем или другом окне. Для использования метода нужно указать один строчный параметр, который является элементом HTML, вводимым в окно или фрейм. В ка- честве указанных строчных параметров могут использоваться переменные или другие выра- жения, которые преобразуются в строки. Очень часто к ним относятся HTML-дескрипторы. Помните, что после загрузки страницы, выходной поток браузера автоматически закрывает- ся. После этого каждый новый вызов метода document .write () будет приводить к откры- тию нового потока, что, в свою очередь, вызывает немедленную очистку текущей страницы (вместе со всеми переменными и другими значениями в исходном документе). Поэтому, если вам нужно переместить текущую страницу с помощью генерируемого в сценарии HTML- кода, представьте этот переменной и отобразите соответствующий текст с помощью метода document. write (). Не стоит выполнять очистку документа в явном виде и открывать новый поток данных. Для этого достаточного одного вызова метода document. wri t e (). Еще один полезный совет, относящийся к использованию метода document. write (), имеет отношение к его “сородичу” и “собрату” — методу document. close (). Сценарий должен-закрывать выходной поток по окончании записи содержимого в окно (как своего, так и чужого). После последнего вызова метода document .write () в сценарии следует ис- пользовать метод document .close О . В противном случае может оказаться, что изобра- жения и формы не будут отображаться. Любое использование метода document .write () впоследствии способствует только добавлению данных на страницу, что предпочтительнее по сравнению с очисткой содержимого и записью его заново. В качестве примера использования метода document .write () приведено две версии одного приложения. В первом случае за- пись производится в тот же документ, который содержит сценарий. Во втором случае, запись производится в отдельное окно. Введите в текстовом редакторе необходимые документы, со- храните файлы с расширением . html и откройте их с помощью браузера. В листинге 8.2 используется кнопка, которая вызывает новое содержание HTML для доку- мента, включая дескрипторы HTML для заголовка нового документа и атрибуты цвета дескрип- тора <body>. В листинге присутствует оператор, который ранее не описывался. Это оператор +=. Данный оператор добавляет к строке, содержащейся слева от него, строку, расположенную справа от оператора. Этот оператор позволяет быстро объединить длинные строки из несколь- ких отдельных операторов. Используя содержимое переменной newContent и всего один вы- зов метода document .write (), можно наполнить весь документ полностью новым содержи- мым, не оставив даже следа от содержимого листинга 8.2. Оператор document. close (), тем не менее, в обязательном порядке используется для нормального закрытия выходящего потока. Теперь загрузите документ, щелкните на кнопке и обратите внимание на то, как изменится на- звание документа в строке названия браузера. Если после этого щелкнуть на оригинале и за- тем снова воспользоваться кнопкой, то динамически заполняемая вторая страница будет за- гружаться намного быстрее, даже по сравнению с перезагрузкой исходного документа. ГЙпЙ 8.2.5ЙЛ0ЛЫЛВ1ИН ucre^fc<b3ciiifient.w<lte() <html> <head> <title>Writing to Same Doc</title> «script type="text/javascript"> function rewrite () { // Вызов содержимого для нового окна Глава 8. Объекты документа и окна 127
var newContent = "<htmlxheadxtitle>A New Doc«/titlex/head>; " newContent += "<body bgcolor= 1 aqua' xhl>this document is brand new.</hl>;" newContent += "Click the Back button to see original document"; newContent += "</bodyx/html>"; 11 Записывается HTML в новое окно документа document.write(newContent); document.close(); // Закрытие потока } </script> </head> <body> <form> «input type="button" value="Replace Content" onclick="reWrite()"> </form> </body> </html> В листинге 8.3 ситуация несколько сложнее, поскольку сценарий создает подокно, в которое записывается целый документ, сгенерированный сценарием. Чтобы ссылка на новое окно была доступна для всех функций, переменную newWindow объявляют как глобальную. Сразу после загрузки страницы, обработчик события onload вызывает функцию makeNewWindow (). Эта функция создает пустое подокно. Третьему параметру метода window. open () добавлено свойство, которое дает инструкцию строке состояния подокна на отображение данных. Кнопка на странице используется для вызова метода subWrite. Первым заданием, кото- рое он выполняет, является проверка свойства closed подокна. Это свойство (которое вве- дено только в последних версиях браузеров) возвращает значение true, если окно, на кото- рое сделана ссылка, закрыто. Если это так (пользователь самостоятельно закрыл окно), то будет вызвана функция makeNewWindow () и окно будет снова открыто. При открытом окне в виде строчной переменной вызывается новое содержимое. Как и в листинге 8.2, содержимое записывается в один подход (хотя это и не является обязательным для отдельного окна), после чего сразу вызывается метод close (). Обратите внимание на важную, особенность: как в методе write (), так и в методе close () подокно задается в явном виде. Лмммг аЖ йпммшмммеш doeiMwat .writ*(5 <html> <head> <title>Writing to Subwindow«/title> «script type="text/javascript"> var newWindow; function makeNewWindow() { newWindow = window.open("","","status,height=200,width=300"); function subWrite() { // Создается новое окно в том случае, если кто-то его закрыл if (newWindow.closed) { makeNewWindow(); } - // Выведение окна на передний план newWindow.focus(); 11 Вызов содержимого для нового окна var newContent = "<htmlxheadxtitle>A New Doc«/tilex/head>" ; newContent += "«body bgcolor='coral1> <hl>This document is brand new.«/hl>"; 128 Часть II. Руководство no JavaScript
newContent += "</body></html>"; // Запись HTML в новый документ окна newWindow.document.write(newContent); newWindow.document.close(); // Закрытие потока } </script> </head> <body on 1oad="makeNe wWindow()"> <form> «input type="button" value="Write to Subwindow" onclick="subWrite()"> </form> </body> </html> Методы document.createElement() и document.createNodef) Метод document. write () применяется к отдельной части Web-страницы на этапе ее первой загрузки в браузер. Любое повторное выполнение этого метода приводит к удалению содержимого Web-страницы и созданию новой страницы. Если вам необходимо изменить уже существующие данные страницы или дополнить ее новой информацией, то воспользуйтесь воз- можностью технологии Dynamic HTML, поддерживаемой в W3C-coBMecTHMbK браузерах. На первый взгляд задача не так уж и сложна: достаточно добавить новый узел, удалить старый или просто заменить часть уже существующей иерархической структуры документа. Большинство элементов объектов обладают соответствующими методами (детально они рассмотрены в главе 14). Если вам необходимо лишь добавить в документ новые данные, то достаточно создать эле- мент или текстовый узел. Объект document имеет для этого два специальных метода. Метод document. createElement () позволяет создать в памяти совершенно новый объект. Чтобы в точности указать тип создаваемого элемента, подставьте имя дескриптора этого элемента в строковый параметр метода. var newElem = document.createElement("р") В процессе создания элемента можно добавить к нему специальные характеристики (назначить ему свойства), сделав это еще до включения элемента в конечный документ. Как отмечалось в главе 4, многие объекты элементов в иерархической структуре имеют текстовое содержимое, заключенное между открывающими и закрывающими дескрипторами. В W3C DOM текстовое содержимое добавляется в результате создания нового текстового уз- ла с помощью метода document.createTextNode(). var newText = document.createTextNode("Всем привет!") Операция создания элементов и текстовых узлов сама по себе не приводит к изменению иерархической структуры документа. Чтобы вставить новые объекты в документ, вам необ- ходимо воспользоваться дополнительными методами (глава 14). Детально с ней вы ознако- митесь в последней главе этой части (глава 12). Метод document.getElementByld() В многих программных кодах, которые вам придется изучать, вы встретите метод document .getElementByld (). С его синтаксисом вы ознакомились в главе 14 при изу- чении способов обращения к объектам документа. Пусть вас не смущает столь длинное и за- Глава 8. Объекты документа и окна 129
пуганное имя. Наличие в нем большого количества символов смешанного регистра делает имя легким для запоминания и распознания в коде. Единственный параметр этого метода представляет собой текстовую строку, заключен- ную в кавычки. В этой текстовой строке указывается идентификатор элемента, на который в коде создается ссылка. Сам же метод возвращает значение, которое обычно подставляется в переменную, используемую в операторах сценария. var oneTable = document.getElementById("salesResults") После назначения переменной подобного значения она представляет в программном коде объект элемента. В дальнейшем с ее помощью можно назначить объекту все необходимые свойства и выполнить его методы. В следующей главе мы рассмотрим объекты более высокого иерархического уровня — формы. Упражнения 1. Какие из приведенных ниже ссылок являются корректными, а какие нет? Объясните, почему некоторые из них неверны. a) window.document.form[0 ] б) self.entryForm.submit() в) document.forms[2].name r) document.getElementByld("firstParagraph") д) newWindow.document.write("Howdy") 2. Напишите оператор JavaScript, который отображает сообщение в строке состояния, приветствующее новых посетителей Web-страницы. 3. Напишите оператор JavaScript, который отображает упомянутое выше сообщение, но уже на уровне заголовка <hl > страницы. 4. Создайте страницу, которая предлагает (в диалоговом окне) пользователю ввести его или ее имя, а после этого будет приветствовать его (ее) по имени. Приветствие должно отображаться в основной части страницы. 5. Создайте страницу, содержащую произвольный текст (какой хотите). Сразу после загрузки она должна автоматически выводить диалоговое окно с адресом URL текущей страницы. 130 Часть II. Руководство по JavaScript
Формы и их элементы Большая часть интерактивных взаимодействий между Web-страницей и пользователем происходит внутри формы. Это именно то место, где спрятана большая часть ин- терактивных возможностей любого браузера: текстовые поля, кнопки, флажки опций, переключатели, списки и т.д. Как уже отмечалось в предыдущих главах, для доступа к определенным объектам часто используется метод document. getElementByld О . Не являются исключе- нием объекты формы и элементов управления форм. Имен- но о последних мы и поговорим в настоящей главе. Наше внимание будет сосредоточено на старом варианте синтак- сиса (полностью совместимого с большим количеством ис- пользуемых браузеров) — его еще часто называют синтак- сисом DOM нулевого уровня. Объект form В базовом синтаксисе модели DOM нулевого уровня ссылка на объект формы form задается либо по его распо- ложению в массиве форм, содержащихся в документе, либо же по имени (если атрибуту name внутри дескриптора <form> присвоено значение). Если в документе использует- ся только одна форма, то она все равно является элементом массива (который состоит из одного элемента), и ссылка на нее будет выглядеть следующим образом. document.forms[0] Вы также можете обратиться к элементу по имени, ис- пользовав его в качестве индекса массива. document.forms[имяФормы] Обратите внимание на то, что в записи ссылки на объект в имени элемента массива используется множественная форма (т.е. forms а не form); после имени вводятся квадратные скобки с указанием в них числового индекса элемента (первый элемент всегда имеет индекс нуль). Но если форме было при- своено имя, то ссылку можно записать значительно проще. document.имяФормы
Форма как объект и контейнер В отличие от современной модели DOM, в которой доступ к любому элементу документа можно получить по идентификатору, в DOM нулевого уровня используется иерархический подход. Форма, с одной стороны, сама содержится в документе, а с другой — может содер- жать любое число элементов (называемых элементами управления формы). На рис. 9.1 пока- зана иерархическая структура элементов формы и ее место в объектной модели документа. Все эти интерактивные элементы используются для того, чтобы пользователь мог ввести ин- формацию или выбрать опцию непосредственно в объекте form. Подобный подход отобра- жает организационную структуру дескрипторов HTML, в которой элементы размещаются внутри пары дескрипторов <f orm> и </f orm>. В дополнение к большому количеству свойств и методов, свойственных любым HTML- элементам, объект form обладает уникальными характеристиками, присущими только ему одному. Практически все уникальные свойства объектов можно задать в сценариях с помо- щью атрибутов элемента form. Браузеры поддерживают управление свойствами формы на программном уровне, что позволяет разработчикам на более низком уровне настроить вид и поведение любых ее элементов. Рис. 9.1. Иерархическая структура объектов формы и ее элементов управления в DOM нулевого уровня Доступ к свойствам формы Формы на странице полностью создаются с помощью стандартных дескрипторов HTML. В них можно задать такие важные атрибуты, как name, target, action,.method и enctype. Каждый из них является свойством объекта form, доступ к которому можно 132 Часть II. Руководство по JavaScript
получить, воспользовавшись соответствующим ключевым словом, вводимым только строчными литерами (см. ниже). document.forms[0].action document.имяФормы.action Для изменения любого из этих свойств ему нужно просто присвоить новое значение. document.forms[0].action = "http://www.giantco.com/cgi/login.pl"; Свойство form.elements[] Кроме отслеживания поведения различных элементов в пределах формы, браузер также поддерживает список всех элементов управления формы. Этот список является еще одним массивом, в котором элементы располагаются в том порядке, в каком приведены их HTML- дескрипторы в исходном коде. Однако более эффективно использовать ссылки на этн эле- менты по именам. С другой стороны, иногда сценарий просматривает сразу все элементы формы. Это справедливо, если форма изменяется при последующей загрузке, особенно когда число текстовых полей зависит от типа используемого браузера. Например, сценарий может использовать метод document. write () для добавления на страницу дополнительного тек- стового поля с информацией, применяемой только пользователями системы Windows. Приведенный ниже фрагмент кода демонстрирует принцип использования свойства form, elements [] в цикле повторения for, который просматривает каждый элемент фор- мы и очищает содержимое всех текстовых полей. Сценарий не может просто “пройтись" по форме сверху вниз и задать ее содержимое или значение каждого элемента равным пустой строке (среди элементов формы могут встречаться, например, кнопки, не имеющие свойства value, которое нужно приравнять к пустой строке). var form = window.document.forms[0] for (var i = 0; i < form.elements.length; i++) { if (form.elements[i].type == "text") { form, elements [i] .value = } } В первом операторе создается переменная с именем form— она содержит ссылку на первую форму документа. Форма сохраняется в переменной на тот случай, если в дальней- шем придется делать ссылки на элементы формы. Ссылки по имени намного компактнее (и выполняются быстрее). Теперь имя переменной form можно использовать для задания ссылок на элементы, содержащиеся на форме. Далее выполнятся просмотр элементов массива elements данной формы. Каждый эле- мент формы имеет свойство type, которое и определяет тип объекта текущего элемента: текст, кнопка, переключатель, флажок и т.д. В данном случае нам нужно отобрать элементы тек- стового поля text. Для каждого из таких элементов значение свойства value устанавлива- ется равным пустой строке. К формам мы вернемся в этой главе несколько позже. Там будет показано, как создаются сценарии, не использующие кнопку Submit (Отправить), но все же отправляющие данные на сервер. Вы также узнаете, как происходит проверка данных формы, введенных пользователем. Элементы формы — это тоже объекты В объектных моделях документа всех браузеров представлено трн типа элементов HTML, используемых в дескрипторах формы <form>, которыми управляют в сценарии объекты. Большинство объектов обязаны своим существованием дескрипторам <input> исходного Глава 9. Формы и их элементы 133
кода страницы. Единственное значение, присвоенное атрибуту type дескриптора < input >, определяет, чем является элемент: текстовым нолем, полем введения пароля, скрытым полем, кнопкой, флажком или переключателем. К другим элементам управления формы относятся textarea и select, но они имеют собственные дескрипторы, задающие их в коде. Чтобы обратиться к определенному элементу управления формы с помощью синтаксиса DOM нулевого уровня, необходимо создать ссылку, начинающуюся с document (она содер- жит имя формы и название конечного элемента управления). Ранее было приведено несколько способов получения доступа к элементам формы, каждый нз которых требует использования ссылки строго определенной структуры. В случае применения только имен формы и элемен- тов управления ссылка будет выглядеть следующим образом. document.имяФормы.имяЭлементаУправления Для начала рассмотрим следующий фрагмент кода. <form name="searchForm" action="cgi-bin/search.pl"> <input type="text" name="entry"> cinput type="submit" name="sender" value="Search"> </form> Следующие ссылки позволяют получить доступ к текстовому полю описанной выше формы. document.searchForm.entry document.searchForm.elements[0] document.forms["searchForm"].elements["entry" ] document.forms["searchForm"].entry Как мы уже определили, элементы управления имеют несколько свойств общего характе- ра (стандартные свойства); некоторые свойства вводятся для определения специфических ха- рактеристик объектов элементов. Например, только объект select имеет свойство, указы- вающее, какой элемент в списке выбран в текущий момент. Флажки и переключатели имеют свойство, которое определяет, включена или выключена соответствующая опция. Точно так же, все текстовые поля используют одинаковые методы для чтения и изменения нх содержимого. Понимание принципов управления свойствами объектов элементов управления формы — это важный этап в изучении JavaScript. В следующем разделе описаны наиболее важные объ- екты управления формы и приведены способы их взаимодействия в сценариях. Текстовые объекты Каждый из четырех текстовых HTML элементов формы — текстовое поле, поле пароля, скрытое поле и текстовая область — это объект в иерархической структуре модели докумен- та. Все эти элементы, кроме скрытого поля, отображаются на странице, что позволяет поль- зователю ввести в них необходимые данные. Эти объекты также отображают текстовую ин- формацию, которая может изменяться по мере загрузки и использования страницы (Dynamic HTML в современных браузерах также предоставляет возможность с помощью сценариев из- менять основной текст документа). Поведение текстовых объектов Многие создатели сценариев обращаются за помощью к JavaScript в надежде решить про- блему некоторых дефектов или аномалий в поведении текстовых объектов формы. Только браузеры самых последних версий предоставляют сценариям полную возможность настройки шрифтов, их размеров, стилей и типа выравнивания текста в текстовых объектах. Изменения можно выполнять с помощью стилей соответствующих элементов (глава 26). В большинстве браузеров попытка контроля за поведением форм была реализованв много лет назад неформально. Если форма содержит только один объект input, использование 134 Часть II. Руководство по JavaScript
клавиши <Enter> при активном текстовом объекте приводит к автоматической отправке дан- ных формы. При наличии двух или более полей в браузерах, отличных от Мас1Е5 и Safari, для отправки данных необходимо использовать несколько другой способ. Например, задей- ствовать кнопку Submit (Отправить). Метод предоставления данных формы при наличии только одного текстового поля во многих случаях себя оправдывает, например, на страницах большинства поисковых систем в Web. Если вы экспериментируете только с простейшими формами, содержащими единственное поле, то данные формы можно легко отправить с по- мощью клавиши <Enter>. Создание формы, которая не выполняет никаких действий и не имеет конкретного назначения, приведет к тому, что страница выполнит безусловную пере- загрузку— удалит все данные, введенные нв форме. Тем не менее, отправку данных формы можно отменить; для этого следует воспользоваться обработчиком события формы onSubmit, как это будет продемонстрировано позже в этой главе. Кроме того, начиная с четвертой вер- сии браузеров, можно для каждого текстового поля задать реакцию на нажатие клавиши <Enter> и обеспечить отправку данных формы без специальной кнопки (глава 25). Чтобы объектами полей можно было управлять непосредственно из сценария, специаль- ных действий с их HTML-дескрипторами выполнять не придется — за исключением, может быть, присвоения значения атрибуту name. Рекомендуем присваивать всем элементам управ- ления формы необычные имена. Это удобно в том случае, если в сценарии устанавливаются свойства или вызываются методы этих элементов. Кроме того, если форма предоставляется программе сервера, которой фактически управляют данные элементов, атрибуту name просто необходимо присвоить значение. При управлении объектами этого типа обработчики событий должны реагировать на мно- гочисленные действия пользователей — активизацию поля (в поле появляется курсор ввода текста) и изменение текста (введение нового значения и выход нз поля). Большинство дейст- вий над текстовыми полями так или иначе связаны с изменением текста (обработчик события onchange). Если вы используете браузеры современных версий, то в них представлены об- работчики событий, позволяющие программировать реакцию на нажатие каждой отдельной клавиши или щелчок на кнопке. Вне всяких сомнений, наиболее часто используемым свойством текстовых элементов яв- ляется value. Это свойство представляет собой текущее значение текстового элемента. Сце- нарий может в любой момент вызвать это свойство и установить для него новое значение. Содержимое свойства value — это всегда строка. Может так пронзойтн, что эту строку придется преобразовывать в числовой формат (глава 6), если, например, текстовое поле ис- пользуется для введения числовых значений или выполнения математических операций. Для того чтобы продемонстрировать способы чтения и записи свойства value текстового поля, в листинге 9.1 приведено описание HTML-страницы с единственным полем введения данных. Обработчик события onchange в данном примере вызывает функцию upperMe (), которая преобразует текст в верхний регистр (все буквы прописные). В функции upperMe () первый оператор присваивает переменной field ссылку на текстовый объект, что выполня- ется исключительно с целью обеспечения удобства прн обращении к объекту поля. Многое скрыто и во втором операторе этой функции. То, что находится в правой части оператора присвоения, направлено на выполнение ряда ключевых задач. Ссылка на свойство value объекта (field, value) позволяет узнать, что именно в данный момент введено в текстовое поле. Затем эта строка передается одной из функций JavaScript, управляющих строковыми данными. В данном случае это функция toUpperCase (). Она преобразует символы текста в верхний регистр. Вычисленный результат выражения, указанного справа от оператора при- своения, присваивается затем второй переменной upperCaseVersion. Прн этом в тексто- вом поле не происходит никаких изменений. Изменения начинаются с третьего оператора, в котором свойству value текстового поля присваивается значение, содержащееся в пере- менной upperCaseVersion. Необходимости во втором операторе нет, и используегся он, Глава 9. Формы и их элементы 135
скорее, в целях большей наглядности, поскольку в этом случае весь описанный процесс от- четливо разбивается на отдельные этапы. На практике можно объединить второй н третий операторы в один. Выполнить это можно следующим образом. field.value = field.value.toUpperCase() ^ахиетихтвеатз объект» chtml> <head> <title>Text Object value Propertyc/title> <script type="text/javascript"> function upperMe() { var field = document.forms[0].converter; var upperCaseVersion = field.value.toUpperCase(); field.value = upperCaseVersion; } </script> </head> <body> <form onsubmit="return false"> cinput type="text" name="converter" value="sample" onchange="upperMe()"> </form> </body> </html> Позже в этой главе будет показано, как можно еще больше упростить в приведенном выше листинге 9.1 обращение к таким функциям, как upperMe (). Тем временем, имеет смысл под- робнее остановиться на обработчике события onsubmit в дескрипторе формы <form>. Далее мы неоднократно будем останавливаться на описании этого обработчика событий. В настоящий момент следует обратить ваше внимание на ту конструкцию, которая используется для пре- дотвращения отправки формы с единственным полем в результате нажатия клавиши <Enter>. Объект кнопки В этом руководстве элемент кнопки input уже применялся неоднократно. Кнопка, с точки зрения использования в сценарии, является одним из наиболее простых объектов. В упрощен- ной модели, описанной в данной книге, объект кнопки имеет ограниченное количество свойств, которые редко используются или изменяются в сценариях “повседневного назначения”. Подоб- но текстовому объекту, за визуальное отображение кнопки отвечает не HTML или сценарии, а операционная система, а также браузер, используемый пользователем при посещении страницы. Безусловно, самым полезным обработчиком событий для кнопки является onclick. Соответст- вующее событие наступает при щелчке пользователя на кнопке. Все просто. Никаких подвохов. Объект флажка Флажок опции — это достаточно простой объект элемента формы form, однако некото- рые его свойства не всегда правильно трактуются начинающими разработчиками. В отличие от свойства value объекта обычной кнопки (для кнопки это свойство определяет текстовую 136 Часть II. Руководство по JavaScript
надпись), в качестве свойства value элемента управления выступает любой текст, описы- вающий задаваемую опцию. Этот текст не отображается на странице ни в каком виде, однако свойство (первоначально устанавливаемое в атрибуте дескриптора value) имеет важное зна- чение в сценарии, которому необходимо больше “знать” о назначении этого элемента формы. Ключевое свойство элемента управления флажка определяет, выбран он или нет. Соот- ветствующее свойство checked принимает булево значение: true (истина), если элемент выбран, н false (ложь) — если нет. Как только в сценарии появляется булево свойство, сра- зу же приходит мысль использовать его в конструкциях типа if или if . . . else. В листин- ге 9.2 с помощью значения свойства checked определяется, какое диалоговое окно будет выведено пользователю. <html> <head> «title>Checkbox Inspector</title> «script type="text/javascript"> function inspectBoxf) { if (document.forms[0].checklhis.checked) { alert("The box is checked."); } else { alert("The box is not checked at the moment."); } } </script> </head> <body> <form> «input type="checkbox" name="checkThis">Check here«br> «input type="button" value="Inspect Box" onclick="inspectBox()"> «/form> «/body> </html> Флажки чаще используются для проведения настроек, а не в качестве переключателя дей- ствий. Поскольку флажок оснащен обработчиком события one lick, следует помнить, что последний редко применяется для выполнения радикальных операций (например, перехода к другой странице). Объект переключателя Использование в сценарии группы переключателей потребует от вас внимательностн. Чтобы браузер мог выставлять и снимать переключатели в группе, всем переключателям этой группы необходимо присвоить одинаковые имена. На форме можно использовать несколько групп переключателей, но в рамках каждой группы ее элементы должны иметь одно н то же имя. Присвоение элементам формы одинаковых имен приводит к тому, что браузер управляет ими иначе, чем остальными элементами управления с разными именами. В этом случае браузер использует для организации элементов с одинаковыми именами массивы. Название, присвоен- ное группе элементов, становится именем массива. Некоторые свойства применимы при этом к группе как к целому. Другие свойства применимы только к отдельным переключателем груп- Глава 9. Формы и их элементы 137
пы, и на них нужно ссылаться с помощью индекса элемента массива. Например, узнать, сколько переключателей находится в группе можно, используя значение свойства length всей группы. document.forms[0].имяГруппы.length Если необходимо определить, выставлен ли в данный момент какой-либо переключатель (для этого предназначено тако^ же, как и для флажка, свойство checked), нужно получить доступ к конкретному элементу. document.forms[0].имяГруппы[0].checked В листинге 9.3 проиллюстрированы некоторые аспекты управления переключателями, в ТОм числе способы поиска в группе переключателей выставленного в данный момент эле- мента. Также вы увидите, как используется атрибут value и соответствующее свойство для решения поставленных целей. Страница содержит три переключателя и одну обычную кнопку. Атрибут value каждого переключателя состоит из полного имени. Когда пользователь щелкает на кнопке, обработ- чик события one lick вызывает функцию fullName (). В этой функции первый оператор создает ссылку на форму. Дальше с помощью цикла for выполняется просмотр всех пере- ключателей группы stooges. Конструкция if используется для проверки свойства checked переключателей. Если переключатель выставлен, то оператор break даст инст- рукцию выйти из цикла for. При этом значение переменной-счетчика цикла i будет равно тому значению, при котором работа цикла прекращена. В диалоговом окне предупреждения используется свойство value элемента с номером, соответствующим последнему значению переменной i, поэтому в диалоговом окне будет отображено полное имя этого элемента. <html> <head> ctitle>Extracting Highlighted Radio Buttonc/title> <script type="text/javascript"> function fullName() { var form = document.forms[0]; for (var i = 0; i < form.stooges.length; i++) { if (form.stooges[i].checked) { break; } } alert("You chose " + form.stooges[i].value + "."); } </script> c/head> cbody> cform> cp>Select your favorite Stooge: <input type="radio" name="stooges" value="Moe Howard" checked>Moe cinput type="radio" name="stooges" value="Larry Fine">Larry cinput type="radio" name="stooges" value="Curly Howard">Curlycbr> cinput type="button" name="Viewer" value="View Full Name..." onclick="fullName()">c/p> с/form> c/body> c/html> 138 Часть II. Руководство no JavaScript
Объект элемента select Наиболее трудный элемент формы, с точки зрения использования в сценариях,— это объект элемента select. Как легко видеть на иерархической структуре объектов (рис. 9.1) bDOM W3C, объект select является объектом весьма общего характера: он содержит мас- сив объектов option. Более того, в HTML его можно использовать для отображения выпа- дающего меню или прокручиваемого списка— последний применяется для предоставления пользователю возможности множественного выбора. Чтобы упростить задачу, на данном этапе будем рассматривать применение его в качестве выпадающего меню, позволяющего сделать выбор только одной опции. Некоторые свойства относятся непосредственно ко всему объекту select, в то время как другие применимы только к отдельным его элементам. Если нужно определить, какую опцию выбрал пользователь, то используйте свойства как объекта select, так и option. Самое важное свойство всего объекта select — это selectedlndex, доступ к которо- му задается следующим образом. document.form[0].имяСписка.selectedlndex Его значение — это индекс выбранного в текущий момент элемента меню или списка. Как это имеет место в большинстве систем нумерации в JavaScript, первый элемент (в списке на- чиная сверху) имеет нулевой индекс. Значение selectedlndex является исключительно важным параметром для получения доступа к свойствам выбранной опции. В каждой опции чаще всего используются свойства text и value, которые вызываются следующим образом. document.form[0].имяСписка.options[n].text document.form[0].имиСписка.options[n].value Свойство text представляет собой строку, которая отображается в объекте select. Свойство text представлено необычным для объекта формы form образом, поскольку в HTML, генерирующем объект select, соответствующий текст определяется вне дескрип- тора <option>. Внутри дескриптора <option> можно установить только атрибут value, который, подобно переключателям, рассматривавшимся ранее, позволяет связывать его зна- чение в виде скрываемой строки с каждым элементом списка. Для того чтобы получить значение text или value для выбранной опции, можно ис- пользовать свойство selectedlndex объекта select в качестве значения индекса опции. Ссылки в таких случаях достаточно длинные. Поэтому, чтобы понять, как они выполняются, придется немного попрактиковаться. В приведенной ниже функции первый оператор необхо- дим для создания ссылки на объект select. Свойство selectedlndex объекта select заменяет затем значение index массива option того же самого объекта. function inspect() { var list = document.forms[0]choices; var chosenltemText = list.options[list.selectedlndex].text; } Чтобы “вдохнуть жизнь” в объект select, нужно воспользоваться обработчиком собы- тия onchange. Как только пользователь выберет новый элемент в списке, сценарий запустит обработчик события, связанный с ним. В листинге 9.4 приведен пример использования объекта select. Записи элементов списка указывают адреса, по которым проводится перемещение внутри и вне текущего Web-узла. В атрибуте value заданы адреса URL конечных Web- страниц. Когда пользователь выбирает из предложенного списка элемент, обработчик собы- тия onchange запускает сценарий, который извлекает свойство value выбранной опции и присваивает его значение объекту location (этот объект обеспечивает переход). Под управлением JavaScript переходы такого типа могут выполняться без использования на стра- нице специальной кнопки Go (Перейти). Глава 9. Формы и их элементы 139
s elect <html> <head> <title>Select Navigation</title> «script type="text/javascript"> function goThere() { var list = document.forms[0].urlList; location.href = list.options[list.selectedlndex].value; } </script> </head> <body> <form> Choose a place to go: «select name="urlList" onchange="goThere()"> coption selected value="index.html">Home Page «option value="store.html">Shop Our Store «option value="policies.html">Shipping Policies «option value="http://www.google.com">Search the Web </select> </form> </body> </html> I В последних версиях браузеров свойство value выбранной пользователем опции 'На заметку трактуется как свойство value объекта select. Это вполне логичный и удобный , прием, который можно смело применять в современных браузерах IE, Mozilla и Safari. Об объекте select можно говорить довольно долго. В новых браузерах даже предусмот- рена возможность изменения содержимого списков (см. главу 24). Передача функциям данных форм и элементов Во всех приведенных в этой главе примерах соблюдено следующее правило: когда обра- ботчик события вызывает функцию, которая управляет элементами формы, эти формы или их элементы указываются в функции в явном виде. Однако существуют вполне приемлемые спо- собы передачи информации такого рода от форм или ее элементов управления непосредст- венно в функции — эти методы основаны на системе сокращений. В таком случае нет необ- ходимости использовать длинные н неудобные ссылки, начинающиеся с уровня объектов окна window или документа document. В JavaScript представлено ключевое слово this. Оно может использоваться для ссылки на любой объект, содержащий сценарий с этим словом. Так, в обработчике события onchange для текстового поля при передаче в функцию ссылки на текстовый объект доста- точно вставить ключевое слово this в качестве параметра этой функции. «input type="text" name="entry" onchange="upperMe(this)"> 140 Часть II. Руководство no JavaScript
В результате функция определит параметрическую переменную, которая будет возвра- щать указанную ссылку в качестве значения для переменной (такую переменную в дальней- шем можно будет использовать в функции) function upperMe(field) { оператор(ы) } Название, которое присваивается переменной-параметру функции, является абсолютно произвольным. Однако часто полезно использовать такие имена, которые бы отображали смысл соответствующей ссылки. Важно, чтобы данная ссылка представляла “живую” связь с объектом. Поэтому с помощью соответствующих операторов в сценарии можно получать и устанавливать значения свойств объекта. Для других функций может возникнуть потребность получить ссылку на всю форму в целом, а не просто на объект, вызывающий функцию. Это особенно актуально, когда функция должна иметь доступ к другим элементам той же формы. Для обращения ко всей форме следует со- слаться на свойство form объекта input, при этом используется ключевое слово this. «input type="button" value="Click Here" onclick="inspect(this.form)”> В определении функции должна присутствовать переменная-параметр, которую исполь- зуют для присвоения ей ссылки на объект. Опять же, имя можно выбирать по своему усмот- рению. В данном случае предлагается использовать в качестве имени form, тогда легче за- помнить, на что указывает соответствующая ссылка. function inspect(form) { оператор (ы) } В листинге 9.5 продемонстрирован способ обращения как к отдельному элементу формы, так и к форме в целом (этот способ состоит из двух действий). Предполагается, что страница имеет непосредственный доступ к базе данных песен группы Beatles. По шелчку на кнопке Process Data (Передать данные) происходит передача объекта form, который в цикле for вызывается функцией processData () для получения доступа к группе переключателей. Дополнительная ссылка с использованием передаваемого объекта form вызывает свойство value выбранных переключателя и текстового поля. Текстовое поле имеет свой собственный обработчик события, который передает текстовое поле в функцию verifySong (). Обратите внимание на то, насколько компактна внутри функции ссылка на свойство value поля, содержащего название песни. <html> <head> <title>Beatle Picker«/title> «script type="text/javascript"> function processData(form) { for (var i = 0; i < form.Beatles.length; i++) { if (form.Beatles[i].checked) { break } } var beatle = form.Beatles[i].value var song = form.song.value alert("Checking whether " + song + “ features " + beatle + "...") } Глава 9. Формы и их элементы 141
function verifySong(entry) { var song = entry.value alert("Checking whether " + song + " is a Beatles tune...") } </script> </head> <body> <form onsubmit="return false"> <p>Choose your favorite Beatle: <input type="radio" name="Beatles" value="John Lennon" checked>John <input type="radio" name="Beatles" value="Paul McCartney">Paul <input type="radio" name="Beatles" value="George Harrison">George <input type="radio" name="Beatles" value="Ringo Starr">Ringo</p> <p>Enter the name of your favorite Beatles song:<br> <input type="text" name="song" value = "Eleanor Rigby" onchange="verifySong(this)"> <input type="button" name="process" value="Process Request..." onclick="processData(this.form)"</p> </form> </body> </html> Теперь вы знаете, как с использованием ключевого слова this передать функциям объек- ты формы form и ее элементов. Такая методика позволяет не только сократить объем кода, но и повышает надежность выполнения ссылок на нужные объекты. Отправка данных форм и проверка их правильности В сценарии процесс отправки формы реализуется с помощью метода submit (). Все, что нужно сделать, — это указать ссылку на форму и данный метод. document.forms[0].submit(); По идее, с помощью данного метода можно так организовать страницу, чтобы при посе- щении новым пользователем вашего Web-узла сценарий отправлял почтовое сообщение вла- дельцу узла. Однако не все так просто. Дело в том, что указанный метод требует использова- ния протокола mailto:, который позволяет извлекать почтовый адрес посетителя. Из соображений безопасности в современных браузерах он блокирован для использования. Перед тем, как форма будет отправлена, полезно выполнить предварительную проверку правильности введенных в нее данных или программных кодов (например, можно изменить в зависимости от предпочтений пользователя свойство формы action). Для этого воспользуй- тесь функцией, которая вызывается обработчиком события формы onsubmit. Сам код про- граммы проверки правильности содержащихся в форме данных в данной главе описываться не будет (однако этот вопрос детально рассмотрен в главе 43). Тем не менее, узнать, как работает обработчик события onsubmit, весьма полезно даже на данном этапе изучения JavaScript. В большинстве браузеров существует возможность применения функции проверки пра- вильности данных, которая позволяет отменить отправку формы в тех случаях, когда данные содержат ошибку или часть из них отсутствует. При таком управлении отправкой данных фор- мы обработчик события onsubmit должен вернуть значение true, иначе процесс будет счи- таться незавершенным. Если возвращается значение false, то отправка формы отменяется. 142 Часть II. Руководство по JavaScript
Все это вначале будет вызывать затруднения, поскольку в каждом конкретном случае требуется больше, чем просто с помощью обработчика события вызвать функцию, которая возвращает значение true или false. Возвращается значение с помощью ключевого слова return. В листинге 9.6 приведен пример программы проверки корректности данных, которая пе- ред тем, как разрешить отправку формы, просматривает все поля и проверяет наличие в них информации. Форма в этом примере вообще не имеет атрибута action, поэтому она в лю- бом случае на сервер отправляться не будет. Обратите особое внимание на то, как в обработ- чике события onsubmit (который в данном случае задает ссылку на объект form в виде па- раметра— ключевое слово this указывает на объект form, поскольку его дескрипторы содержат обработчик события) перед именем функции используется ключевое слово return. Если функция возвращает в качестве своего результата значение true или false, обработчик события преобразует это в return true или return false, соответственно. Листинг 9.6. Ямкпедм* проверка.дагянв мрев отрамр* формы <html> <head> «title>Validator«/title> «script type="text/javascript"> function checkForm(form) { for (var i = 0; i « form.elements.length; i++) { if (form.elements[i].value == "") { alert("Fill out ALL fields."); return false; } } return true; } </script> </head> <body> «form onsubmit="return checkForm(this)"> Please enter all requested information:«br> First Name:«input type="text" name="firstName"><br> Last Name:«input type="text" name="lastName"><br> Rank:«input type="text" name="rank">«br> Serial Number:«input type="text" name="serialNumber">«br> «input type="submit"> «/form> «/body> </html> Еще одна особенность поведения обработчика события onsubmit (казалось бы, вызы- вающегд метод submit ()) требует дополнительных пояснений. У вас могло сложиться впе- чатление (и с логической точки зрения оно было бы вполне обосновано), что метод submit () должен вызываться в сценарии после того, как пользователь щелкнет на кнопке Submit. Однако это не так. В NN использование метода submit () вообще не связано с об- работчиком события onsubmit. Если нужно выполнить проверку корректности данных пре- доставляемой формы посредством метода submit (), то следует вызвать функцию проверки формы, которая непосредственно вызовет метод submit (). Это все, что на данном этапе мне хотелось рассказать о формах и их элементах. В сле- дующей главе мы сделаем упор на некоторых завершенных средствах базового языка JavaScript (речь пойдет о строках, математических выражениях и датах). Глава 9. Формы и их элементы 143
Упражнения 1. Переделайте листинги 9.1—9.4 так, чтобы все функции сценария использовали наи- более удобную форму ссылок на формы и их элементы в задействованных обработ- чиках событий. 2. Укажите для следующей формы (предположительно единственной на странице) по меньшей мере 10 способов ссылки на текстовое поле. <form name="subscription" action="cgi-bin/maillist.pl" method="post"> <input type="text" id="email" name="email"> <input type="submit"> </form> 4. Какого рода информация в приведенном ниже HTML-дескрипторе, по вашему мне- нию, будет передана обработчиком события? Напишите функцию, отображающую в диалоговом окне предупреждение с предназначенной для передачи информацией. <input type="text" name="phone" onchange="format(this.value)"> 5. Документ содержит две формы с именами specifications и accessories. Фор- ма accessories включает поле с именем accl. Напишите две отдельные команды, которые устанавливали бы содержимое этого поля равным Leather Carrying Case. 6. Создайте страницу, в которой представлен объект select, используемый для изменения фона текущей страницы. Свойством, отвечающим за изменение цвета фона, является document .bgColor. Следует предложить использовать на выбор один из трех цветов: red (красный), yellow (желтый) и green (зеленый). В объекте select цвета должны отображаться как Stop (Стоять), Caution (Приготовиться) и Go (Идти), соответственно. 144 Часть II. Руководство по JavaScript
Строки, математические выражения и даты До этого момента большинство из рассмотренных в книге объектов имели непосредственное отношение к объектной модели документа. Однако, как это подчеркива- лось еще в главе 2, между объектной моделью документа и языком JavaScript существует различие. В языке использу- ются собственные объекты, которые полностью независимы от объектов модели документа. Эти объекты определяются таким образом: если разработчику сценария необходимо ис- пользовать JavaScript в качестве языка программирования для полноценного решения другой задачи, то в этом языке для управления текстом, проведения сложных математических вы- числений (выходящей за пределы элементарных математиче- ских операций) и задания дат можно использовать основные программные средства. Формальное описание соответствую- щих объектов приведено в инструкциях стандарта ЕСМА-262. Объекты базового языка Зачастую не только новичкам, но и вполне опытным поль- зователям, которым не приходилось сталкиваться ранее с объект- но-ориентированным программированием, крайне сложно привыкнуть к отдельным объектам. Например, довольно просто осознать, что кнопка на странице является объектом. Она имеет несколько свойств, которые поддаются логиче- скому восприятию. А вот как быть со строкой или симво- лом? В любой объектно-ориентированной среде (в том числе в JavaScript) все, что может изменяться, трактуется как объект, — каждый фрагмент данных, начиная с логических значений и заканчивая датами. Такой объект, вероятнее всего, имеет од- но или более свойств, которые призваны помочь в определе- нии его содержимого. Каждый объект также имеет методы, определяющие задачи, которые этот объект может выполнять.
Все объекты, не относящиеся к объектной модели документа, называются объектами ба- зового языка. Полный их перечень можно найти в приложении А. В этой главе основное внимание уделено объектам типа String, Math и Date. Строковые объекты В предыдущих главах строковые объекты String использовались неоднократно. Стро- кой считается любой текст, заключенный в кавычки. Кавычки могут быть двойными или одинарными. Это позволяет вставить одну строку в другую (что приходится часто выполнять при управлении обработчиками событий). В приведенном ниже примере методу alert () в качестве параметра нужно задать заключенную в кавычки строку. Но при этом сам вызов метода также осуществляется с использованием кавычек. onclick="alert('Hello, all’)" В JavaScript нет практических ограничений на количество символов в строке. Тем не ме- нее, в старых версиях браузеров существует максимально допустимое значение длины строки оператора сценария, равное 255 символам. Этот предел может превышаться, когда сценарий включает в себя длинные строки, требующие отображения на странице. В таких случаях эти строки следует разбить на более короткие (см. приемы, описанные ниже). Существует два способа присвоения значения строчной переменной. Наиболее просто эта задача решается с помощью оператора обычного присвоения. var myString = "Howdy"; Этот подход превосходно срабатывает во всех, за редким исключением, случаях. Начиная с NN3 и IE4, строки можно создавать с использованием более формального синтаксиса на ос- нове ключевого слова new и конструктора функции (конструктор создает новый объект). var myString = new String("Howdy"); Какой бы способ из описанных выше ни использовался для инициализации строковой пе- ременной, она становится доступной для всех методов объекта String. Объединение строк Соединение двух строк в одну называется объединением (или конкатенацией) строк. Этот термин уже встречался в главе 6. Для объединения строк нужно воспользоваться одним из двух предусмотренных для этого случая JavaScript-операторов. Уже в первом сценарии гла- вы 3 было продемонстрировано, как оператор сложения (+) использовался для объединения нескольких строк с целью создания на загружаемой Web-странице динамически отображае- мого текстового сообщения. document.write(" of <span class=’highlight’+ navigator.appName + "</span>."); Для этой цели используют еще один оператор. В основном, к нему обращаются в том слу- чае, когда в одной строке нужно объединить несколько длинных строк. Строка может быть настолько большой и громоздкой, что весь процесс придется разбить на несколько этапов. Объединяемыми фрагментами могут выступать строковый текст (строка в кавычках) или строковые переменные. Не самым эффективным в таком случае способом объединения строк (хотя и легко выполняемым в JavaScript) является использование оператора сложения для до- бавления к строке новых фрагментов текста. var msg = "Four score" msg = msg + " and seven" msg = msg + " years ago," 146 Часть II. Руководство no JavaScript
Другой оператор, оператор дополнения, предлагает более компактную форму записи. Символ этого оператора — это знак “плюс” и знак равенства, не разделенные пробелом (+=). Использование этого оператора эквивалентно добавлению в конец переменной, стоящей сле- ва от оператора, того выражения, которое находится справа от оператора. Поэтому команды из приведенного выше примера будут упрощены. var msg = "Four score"; . msg += " and seven"; msg += " years ago,"; При необходимости можно поступить еще проще. var msg = "Four score"; msg += * and seven" + " years ago"; Оператор приращения удобно использовать, когда для его отображения в текущем доку- менте или другом окне нужно собрать вместе фрагменты текста HTML. Методы строковых объектов Из всех основных объектов JavaScript объект String имеет наиболее богатый набор мето- дов. Многие из этих методов используются для извлечения фрагментов строк. Другая группа методов, которая применяется значительно реже, задается с помощью стилевых дескрипторов (эквивалент дескрипторов, определяющих размер шрифта, стиль и др. параметры, в сценарии). При использовании одного из методов строкового объекта строка задается с помощью ссылки, в конце которой указывается имя метода. Все методы возвращают значения опреде- ленного типа. В большинстве случаев возвращаемое значение — это преобразованная версия исходного строкового объекта, на который ссылается вызываемый метод (исходные строки при этом остаются неизменными). Чтобы сохранить такую измененную версию строки, ре- зультат вызова метода присвойте в качестве значения переменной. var result = string. имяМетодаО; В следующем разделе описано несколько полезных методов строковых объектов, которые доступны в браузерах всех типов и версий. Изменение регистра Существует два метода, которые преобразуют всю строку в символы верхнего или нижне- го регистра (т.е. все буквы становятся либо строчными, либо прописными соответственно). var result = string.toUpperCase(); var result = string.toLowerCase0; Названия этих методов говорят сами за себя (to upper case — в верхний регистр и to lower case — в нижний регистр). Указанные методы могут пригодиться в том случае, если нужно сравнить две строки без учета регистра символов (например, когда строка в таблице поиска сравнивается с введенной пользователем). Поскольку методы не изменяют содержимого ис- ходных строк, используемых в выражениях, в данном случае можно просто сравнить резуль- таты вызова соответствующих методов. var foundMatch = false; 1 if (stringA.toUpperCase() == stringb.toUpperCase()) { foundMatch = true; } Поиск строк Для того чтобы определить, содержится ли одна строка внутри другой, используется ме- тод string. indexOf (). Даже при работе с данными объектов JavaScript это весьма полезная и часто используемая информация. Например, свойство navigator. userAgent позволяет Глава 10. Строки, математические выражения и даты 147
узнать много интересного о браузере, с помощью которого выполняется загрузка страницы. Сценарий может проверить значение соответствующего свойства на наличие в нем, скажем, фрагмента Win. Полученные данные позволяют определить, какие операционные системы используются посетителем. Часто внутри очень длинной строки скрывается коротенький тек- стовый фрагмент особой важности, поэтому каждый сценарий должен определять, содержит- ся ли одна строка в другой — где бы она ни располагалась. Метод string. indexof () возвращает в качестве значения число, определяющее ин- декс (начальное значение нуль) того символа длинной строки, с которого начинается искомая вложенная строка. Если совпадение не обнаружено, то возвращается значение -1. Чтобы вы- яснить, содержится ли данная строка в длинном текстовом фрагменте, достаточно просто убедиться, что возвращаемое методом значение отлично от -1. В этом методе указываются две строки: короткая и длинная. Длинная строка что зада- ется в ссылке слева от имени метода. Более короткая, указывается в качестве параметра ме- тода indexof (). Чтобы продемонстрировать, как этот метод применяется на практике, при- ведем следующий фрагмент кода. В нем выясняется, использует ли пользователь операционную систему Windows. var isWindows = false; if (navigator.userAgent.indexof("Win") != -1) { isWindows = true,- } В условии конструкции if использован оператор неравенства (1 =). Он определяется, как “не равно”. Извлечение копий символов и подстрок Для того чтобы извлечь в определенной позиции строки отдельный символ, используется метод chartAt (). Параметр этого метода — индекс (начальное значение нуль) искомого символа. Выше мы указали на необходимость извлечь символ, однако это не подразумевает удаление. Извлечение, скорее, напоминает “фотографирование” символа. Исходная строка не изменится при этом никоим образом. Например, рассмотрим сценарий в основном окне, который проверяет переменную stringA другого окна (в последнем отображаются планы различных зданий). Когда в окне отражается план здания Building С, значение переменной stringA равно "Building С". Символ, обозначающий здание, всегда представлен в десятой позиции (т.е. индексом номер 9. если начинать отсчет с нуля), поэтому сценарию достаточно проверить только один этот сим- вол, чтобы идентифицировать карту, отображенную в текущий момент в окне. var stringA = "Building С"; var bldgLetter'= stringA.charAt(9); // Результат: bldgLetter = "C" Другой метод — строка. substring () — позволяет извлечь последовательность сим- волов по известному индексу начала и окончания той подстроки, копию которой нужно полу- чить. Здесь обязательно обратите внимание на тот факт, что последний символ такой под- строки (который соответствует конечному индексу) не извлекается. Все остальные символы, начиная с символа, соответствующего начальному индексу, и заканчивая символом, стоящим перед соответствующим конечному индексу, будут извлечены в виде единой подстроки. Строка, из которой извлекается фрагмент, в ссылке на метод располагается слева от имени метода. Два параметра, передаваемых методу, соответствуют начальному и конечному индек- су (если начинать отсчет с нуги) извлекаемой подстроки. var stringA = "banana daiquiri"; var excerpt = stringA.substring(2,6); // Результат: excerpt = "nana" 148 Часть II. Руководство no JavaScript
Операции со строками в JavaScript, по сравнению с некоторыми другими языками, выглядят несколько громоздкими. Такие высокоуровневые понятия, как слова, предложения или абзацы, просто отсутствуют. Очень часто управление строчными объектами реализуется с помощью не- многочисленных простых операторов, что создает впечатление небывалой просты выполняемых операций. Чтобы разубедит ься в этом, попробуйте применить полученные ранее знания о вычис- лении выражений для обработки текстовых структур нетривиального характера, вложенных одна в другую. Например, в следующем фрагменте нужно создать новую строку, полученную на основе более длинной строки, из которой исключено первое слово. Примите во внимание, что первое сло- во может иметь любую длину. Поэтому во втором операторе вы должны найти первый пробел, ис- пользовав метод string. indexOf (). К индексу первого пробела в строке прибавляется еди- ница, в результате определяется начальный индекс для метода string.substring (). Для определения второго параметра этого метода используется свойство length строки (оно на единицу больше того числа, которое передается в качестве параметра). var stringA = "The United States of America"; var excerpt = stringA.substring(stringA.indexOf(" ") + 1, stringA.length); // Результат: excerpt = "United States of America" Создание подобного рода кода иногда вызывает затруднения. В главе 27 продемонстри- рованы способы создания собственной библиотеки функций, управляющих строками, кото- рые впоследствии можно эффективно использовать при написании сценариев управления строковыми данными. Основные же средства обработки строковых данных, реализуемые в виде обычных выражений, поддерживаются во всех современных браузерах (глава 27 и 42). Объект Math В JavaScript представлен широкий набор программных средств для проведения математи- ческих вычислений. Все “уважающие себя” языки программирования включают подобные мощные программные средства, чтобы программисты имели возможность создавать окна, выдающие на экран числовые результаты. Все эти возможности предоставляются объектом Math. Он выгодно отличается от всех остальных объектов JavaScript — для работы с ним не нужно создавать его копии. Вместо этого просто вызываются методы и свойства единственного объекта Math. Объект Math яв- ляется производным от окна или фрейма, однако на ход выполнения сценария это совершен- но не влияет. Программисты называют такого рода фиксированные объекты статичными. Объект Math (пишется с большой буквы М) обязательно должен указываться в ссылке на свойство или метод. Свойства объекта Math— это постоянные значения (константы), на- пример число л или корень квадратный из 2. var piValue = Math.PI; var rootOfTwo = Math.SQRT2; Методы объекта Math выполняют широкий круг задач, вплоть до вычисления тригоно- метрических и других математических функций, управляющих числовыми значениями, кото- рые предопределены в сценарии. Например, следующим образом в сценарии определяется большее из двух чисел. var larger = Math.max(значение!, значение!); Таким образом число возводится в десятую степень. var result = Math.pow(значение!, 10) ; Ниже приведен очень эффективный метод, с помощью которого можно округлить значе- ние до ближайшего целого числа. var result = Math.round(значение!); Глава 10. Строки, математические выражения и даты 149
Еще один часто используемый метод — это генерирование случайного числа с помощью объекта Math. Хотя это свойство и недоступно в NN2 для Windows и Macintosh, во всех дру- гих браузерах его применение не вызывает затруднения. Метод Math. random () возвращает в качестве значения число с плавающей точкой в диапазоне от 0 до 1. Если вами создается сценарий карточной игры, то в нем обязательно понадобится сгенерировать случайные числа от 1 до 52. При бросании кубика задаются случайные числа в диапазоне от 1 до 6. Для того чтобы сгенерировать целое число в диапазоне от нуля до любого другого числа, можно вос- пользоваться следующей формулой. Math.floor(Math.random() * (n+l)> где n — верхний предел диапазона. Метод Math, floor () возвращает целую часть любого числа с плавающей точкой. Для генерирования случайных чисел в диапазоне между единицей и числом, большим единицы, используется формула Math.floor(Math.random() * n) +1 где n также является верхним пределом диапазона. Для игры с подбрасыванием кубика слу- чайное число в диапазоне 1-6 задается следующим образом. newDieValue = Math.floor(Math.random О * 6) +1; Чтобы увидеть результат, следует правую часть приведенного выше выражения ввести в верхнее поле приложения The Evaluator Jr. и щелкнуть на кнопке Evaluate (Вычислить). Единственное, в чем на JavaScript нельзя положиться, за исключением применения его в IE5.5 и Mozilla-совместимых браузерах, — это форматирование чисел. В числах с плаваю- щей точкой после десятичной может отображаться не больше десятка цифр. Добавьте также всевозможные погрешности в операциях с числами с плавающей точкой, которые зависят от используемой операционной системы, особенно для ранних версий браузеров. Для браузеров, созданных ранее IE5.5 и NN6, форматирование любого типа данных придется выполнять са- мостоятельно — для долларов и центов, например, с помощью отдельных сценариев. В гла- ве 28 приведены соответствующие примеры. Объект Date Работа с датами в JavaScript, выходящая за рамки простых задач, может быть весьма не- простым делом. Большинство проблем возникает по причине того, что дата и время рассчи- тываются непосредственно по Гринвичскому времени (Greenwich Mean Time — GMT). При этом подразумевается, что время на часах компьютера пользователя выставлено правильно (см. главу 29). В данной главе будут рассмотрены только основные способы управления объ- ектом Date в JavaScript. В браузерах, поддерживающих сценарии, присутствует только один глобальный объект Date (если точно, то один объект Date в одном окне), к которому можно обратиться в любое вре- мя. Объект Date является еще одним примером статичного объекта. Когда вам нужно полу- чить дату, например, для отображения ее на странице, вызовите конструктор объекта Date для получения экземпляра объекта Date, задающего определенную дату и время. Например, если вызвать конструктор без указания параметров, например, как в следующем случае. var today = new Date(); то в объекте Date будут сохранены показания системных часов компьютера, используемого посетителем; кроме того, будет возвращен соответствующий экземпляр объекта. Обратите внимание на разницу между объектом Date и экземпляром объекта, содержащим текущие дату и время. В переменной today “спрятано" не динамически изменяемое время, а значение, которое можно проверить, разбив на составляющие, и использовать в сценарии по своему усмотрению. 150 Часть II. Руководство по JavaScript
Значение экземпляра объекта даты — это время, выраженное в миллисекундах, начиная с 1 ян- варя 1970 года в зоне Гринвичского меридиана (всемирный стандарт для задания абсолютных дат и времен). Таким образом в объекте даты удается сразу запомнить и дату, и текущее время. С помощью объекта Date можно определить дату и момент времени как в прошлом, так и будущем, для чего полученная информация задается в качестве параметров функции конст- руктора объекта Date. var someDate = new DateC'Month dd, yyyy hh:mm:ss"); var someDate = new DateC'Month dd, yyyy"); var someDate = new Date(yy,mm,dd,hh,mm,ss); var someDate = new Date(yy,mm,dd); var someDate = new Date(GMT milliseconds from 1/1/1970); Если теперь попробовать просмотреть ряд объектов date, JavaScript преобразует соот- ветствующие значения в строку, которая содержит время текущего часового пояса (эта строка задается согласно настройкам папки Панель управления компьютера пользователя). Вос- пользуйтесь приложением The Evaluator Jr. и введите в верхнее поле следующий код. new Date(); Часы персонального компьютера представляют текущие дату и время в таком виде, как они задаются на экране обычных часов (даже несмотря на то, что JavaScript управляет време- нем в миллисекундах соответственно времени Гринвичского меридиана). Тем не менее, в ре- зультате применения некоторых методов к экземпляру объекта даты из него можно извлечь отдельные компоненты даты. В табл. 10.1 приведен краткий список соответствующих свойств и их описания. Л 1 Метод Диапазон значений Описание объектДаты.getTime() о-... Количество миллисекунд, начиная с 1 января 1970 года 00:00:00, по Гринвичскому времени объектДаты.getYear() 70-... Заданный год минус 1900. Четырехзначное число для года, начиная с 2000 и позже объектДаты.getFullYear() 1970-... Четырехзначное число, определяющее год. Поддерживается браузерами, начиная с четвертой версии объектДаты.getMonth () 0-11 Месяц года (Январь=о) объектДаты.getDate() 1-31 Число месяца объектДаты.getDay() 0-6 День недели (Воскресенье=о) объектДаты.getHours() 0-23 Время суток в часах объектДаты.getMinutes() 0-59 Минуты объектДаты.getSeconds() 0-59 Секунды объектДаты.setTime (значение) 0- . . . Задает количество миллисекунд, начиная с 1 января 1970 года 00:00:00 по Гринвичскому времени объектДаты.setYear (значение) 70- . . . Задает год минус 1900. Четырехзначное число для года, начиная с 2000 и позже объектДаты.setMonth (значение) 0-11 Задает месяц года (Январь=о) Глава 10. Строки, математические выражения и даты 151
Окончание табл. 10.1 Метод Диапазон значений Описание объектДаты.setDate(значение) 1-31 Задает число месяца объектДаты.setDay(зна чение) 0-6 Задает день недели (Воскресенье-о ) объектДаты.setHours(значение) 0-23 Задает время суток в часах объектДаты.setMinutes(значение) 0-59 Задает минуты объектДаты.setSeconds(значение] 0-59 Задает секунды Будьте внимательны, работая со значениями, диапазон возможных изменений Внимание! которых начинается с нуля. Особенно это касается месяцев. Методы getMonthO и setMonthO могут возвращать в качестве значения нуль. Таким образом соответствующее число на единицу меньше, чем номер месяца (например, январю соответствует о, декабрю—11). В методах, используемых для задания даты (те, что содержат в имени set), можно заме- тить одну интересную особенность. Вместо того чтобы возвращать новое значение, эти мето- ды, фактически, изменяют значение экземпляра объекта даты, на который сделана ссылка при вызове метода. Определение даты Работа с датой подразумевает использование значений объектов. Значения эти, как уже от- мечалось, указаны в миллисекундах. Это позволяет легко складывать, вычитать и сравнивать да- ты. В целях демонстрации методов управления датой и временем приведен листинг 10.1. В нем на загружаемой странице отображаются текущие дата и время. В другом сценарии произво- дится расчет даты и времени на семь дней вперед по сравнению с текущей датой и временем. Листинг 10.1. Вычисг.»н« дты и времени <html> <head> <title>Date Calculation</title> «script type="text/javascript"> function nextWeek() { var todaylnMS = today.getTime(); var nextWeeklnMS = todaylnMS +'(60 * 60 * 24 * 7 * 1000); return new Date(nextWeeklnMS); } «/script> </head> «body> Today is: <script type="text/javascript"> var today = new Date(); document.write(today); </script> <br> Next week will be: «script type="text/javascript"> 152 Часть II. Руководство no JavaScript
document.write(nextWeek()); </script> </body> </html> В теле документа первый сценарий запускается при загрузке страницы, определяя гло- бальную переменную (today), значение которой равно текущей дате и времени. Строковый ее эквивалент отображается на странице. Во втором сценарии упомянутого раздела метод document .write () вызывает функцию nextWeek (), определяющую значение, которое впоследствии будет отображено на странице. Эта функция использует глобальную перемен- ную today и копирует ее значение в миллисекундах в новую переменную todaylnMS. Для вычисления даты через семь дней после текущей в следующем операторе к текущей дате (в миллисекундах) добавляется число миллисекунд в семи днях (60 секунд умножить на 60 ми- нут, умножить на 24 часа, умножить на 7 дней и умножить на 1000 миллисекунд). Далее в сценарии задается новый экземпляр объекта с рассчитанным суммарным числом миллисе- кунд. С этой целью вызывается конструктор объекта Date с данным числом миллисекунд в качестве параметра. Возвращаемым значением является объект даты, который автоматиче- ски преобразуется к строковому типу для отображения на странице. При создании с помощью JavaScript нового объекта даты вы можете воспользоваться од- ной хитростью, которая избавляет вакс от необходимости подсчета количества миллисекунд. Удачно комбинируя методы setDate () и getDate (), вы получите объект даты, в котором не выполняются дополнительные временные преобразования. today.setDate(today.getDate() + 7); document.write(today); Тех, кто и в дальнейшем будет использовать в своих сценариях даты, ждет много откровен- ных неожиданностей в поведении дат. Однако конечный результат стоит затраченных усилий. Упражнения 1. Создайте Web-страницу, которая содержит одно поле формы для введения в него почтового адреса пользователя и кнопку Submit. Используйте программу предвари- тельной проверки правильности введенных данных. Отправка формы должна выпол- няться только в том случае, если в текстовом поле обнаружен используемый в поч- товых адресах символ @. 2. У вас ест^ текстовая строка "Internet Explorer". Ниже приведен оператор myString. substring () с пропущенными параметрами. Расставьте эти параметры так, чтобы получить нужный результат. var myString = "Internet Explorer" myString. substring (__,______) //Результат = "Intt" myString. substring (__,______) //Результат = "plorer" myString. substring (__,) //Результат = "net Exp" 3. Введите недостающий код функции, приведенной ниже, так, чтобы она просматривала каждый символ текстового поля ввода и определяла, сколько раз в этом поле использо- вана буква " е ". Подсказка: в представленном коде отсутствует цикл повторения for. <html> <head> <title>Wheel o' Fortuna</title> <script type="text/javascript"> function countE(form) { Глава 10. Строки, математические выражения и даты 153
var count = 0; var inputstring = form.mainstring.value.toLowerCaseO; missing code var msg = "The string has " + count; msg += " instances of the letter e."; alert(msg); } </script> </head> <body> <form> Enter any string: <input type="text" name="mainstring" size="3 0"><br> <input type="button” value="Count the Es" one1i ck="countE(thi s.form)"> 1 </form> </body> </html> 4. Создайте страницу, имеющую два поля и одну кнопку. Кнопка должна запустить функцию, генерирующую два случайных числа в диапазоне от 1 до 6, разместить эти числа по одному в каждом поле. Результат напоминает подбрасывание двух кубиков при игре в кости. 5. Создайте страницу, которая бы отображала число дней, оставшихся до Рождества. 154 Часть II. Руководство по JavaScript
Работа с окнами и фреймами Одним из главных преимуществ JavaScript с точки зрения клиента является управление в одном окне или фрейме содержимым других окон и фреймов, реализуе- мое с помощью родительско-дочерних отношений. В этом разделе вы расширите свои знания о ссылках на объекты мно- гофреймовых документов. Окна: отцы и дети Вероятно, вы уже заметили, что расположенный в верх- ней части иерархической структуры упрощенной объектной модели документа (рис. 4.1) объект window связан с некото- рыми другими объектами. В главе 8 вы узнали, что ключевое слово self — синоним понятия window, когда ссылка зада- ется на то же окно, которое содержит документ со сценари- ем. В этой главе рассказывается о том, какую роль играют три других целевых объекта — frame, top и parent. Загрузка в браузер самого обычного документа HTML приводит к тому, что в браузере создается модель, которая на- чинается с единого объекта окна window, содержащего доку- мент. Документ, скорее всего, будет содержать другие элемен- ты, но пока этот вопрос мы затрагивать не будем. Верхняя часть иерархической структуры настолько проста, насколько это вообще возможно. Ее можно увидеть на рис. 11.1. Именно в этой части начинаются ссылки, в начале которых задано window или self (они также могут на- чинаться с document, поскольку теку- щее окно задано по умолчанию). В случае, если в браузер загружает документ с несколькими фреймами, то он создает несколько иную иерархиче- скую структуру. Точный вид структуры полностью зависит от вставленных в документ фреймов, определяемых Рис. 11.1. Простое ок- в загружаемом документе. Далее мы рас- но и иерархия объек- смотрим одно из представлений много- тов документа фреймового документа. ОИГСЯЦУМЙв* А
<html> <frameset cols="50%,50%"> <frame name="leitFrame" src="somedocl.htnil"> <frame name="rightFrame" src="somedoc2.html"> </frameset> </html> Этот HTML-код разбивает окно на два фрейма (подокна), расположенных рядом. В каж- дом фрейме загружается отдельный документ. Модель отображает только структуру — в этом случае относительный размер фреймов не столь важен, как их расположение (по вер- тикали или по горизонтали). Настройки фреймов задают взаимоотношения между всеми объектами. Используя терми- нологию объектно-ориентированной концепции, многофреймовые документы загружаются в родительское окно. Каждый фрейм в этом родительском окне является дочерним фреймом. На рис. 11.2 показана иерархическая структура двухфреймовой среды. Эта иллюстрация по- могает выяснить многие тонкости взаимоотношений фреймов в одном документе. <frame> Рис. 11.2. Окно, разделенное на два фрейма, и иерархия многофреймового документа Иногда довольно сложно сразу представить многофреймовую структуру в качестве объекта окна в иерархической структуре. Если не считать отображаемого в поле Location или Address адреса URL, никакие другие признаки фреймовой структуры в браузере обнаружить невозмож- но. Однако сам объект многофреймового документа в модели все же представлен. Возьмите на заметку, что родительское окно на диаграмме многофреймовой структуры не содержит никаких документов. Это может показаться странным, поскольку окно, по всей видимости, должно со- держать HTML-файл с приведенными в нем параметрами всех фреймов. На самом деле роди- тельское окно представлено объектом документа, но он специально опущен в структуре (мы уп- ростили описание принципа взаимодействия между родительским и дочерними окнами). Родительский документ многофреймовой структуры содержит лишь часть объектов обычных HTML-документов (в эту часть формы и элементы управления не входят). Таким образом, ссылки на родительский документ используются крайне редко, если вообще когда-нибудь используются. Если в многофреймовый документ добавить сценарий, в котором требуется получить дос- туп к свойству или методу объекта исходного окна, структура ссылок останется абсолютно такой же, как и в случае использования простого окна. Ситуация полностью идентична рас- положению сценария в этом окне. Ситуация станет намного интереснее, если нужно обратиться к дочерним фреймам. Каждый такой фрейм содержит объект документа (его содержимое отображается в окне браузера). 156 Часть II. Руководство по JavaScript
Структура всей этой модели такова, что каждый фрейм является независимым друг от друга. Создается впечатление, что каждый документ существует в отдельном окне браузера. Именно поэтому дочерние фреймы могут рассматриваться как объекты окна. Фреймы имеют тот же набор свойств и методов объекта окна, что и большое окно, расширенное до максимального размера. С точки зрения любого дочернего фрейма (рис. 11.2) его непосредственным контейнером является родительское окно. Если родительское окно находится в верхней части иерархиче- ской модели, загружаемой в браузер, то на это окно ссылка задается так же, как на объект высшего уровня. Ссылки на другие объекты Далее мы выясним, как сценарии, размещенные во всех окнах многофреймовой структуры (рис. 11.2), получают доступ к объектам, функциям или переменным в других окнах. Таким образом, если сценарий получает доступ к объектам, функциям или глобальным переменным в текущем окне, то он может получить доступ к таким же элементам и в других окнах струк- туры (подразумевается, что всеми документами управляет один и тот же Web-сервер). В сценарии, который управляет двухуровневой иерархической структурой (описываемой в даннсй главе), вам понадобятся ссылки трех типов: из родительского фрейма на дочерний; из дочернего фрейма на родительский; из одного дочернего фрейма на другой дочерний фрейм. Каждый из этих типов ссылок подразумевает использование разных вариантов введения кода. Ссылки из родительского фрейма на дочерний Наиболее редко используют такой тип ссылок, при котором сценарий из родительского окна получает доступ к элементу в одном из его фреймов. Родительское окно содержит два или более фреймов. Это подразумевает, что родительское окно содержит массив объектов дочерних фреймов. Доступ к фрейму из этого массива можно получить с помощью индекса массива или его имени, которое присваивается фреймам в атрибуте name дескриптора <frame>. В приведенных ниже примерах ссылок в качестве заполнителя объектов, функций или глобальных переменных окон или фреймов, доступ к которым нужно получить, исполь- зуется ИмяПеременнойОбъектаФункции. Не следует забывать, что каждый отображаемый фрейм содержит объект документа, который обычно выступает контейнером для элементов, задействованных в сценарии, — поэтому в соответствующих ссылках нужно использовать указание на document. Учтя все это, можем организовать ссылку из родительского окна на один из его фреймов, используя любой из приведенных двух способов. [window.]frames[n]. ИмяПеременнойОбъектаФункции [window.]имяФрейма.ИмяПеременнойОбъектаФункции Индексы фреймов определяются в той же очередности, в которой они описаны в дескрип- торах <f rame> многофреймового документа. Чтобы упростить задачу, каждому фрейму при- свойте легкоузнаваемое имя, а затем эти имена используйте в ссылках. Отметьте также, что в ранних версиях браузеров часто возникают проблемы с обработкой ссылок, начинающихся с window. Поэтому я бы порекомендовал отказаться от использования window в таких ссылках. Ссылки из дочернего фрейма на родительское окно Достаточно распространена ситуация, когда сценарии размещаются в родительском окне (в разделе заголовка), а потом используются несколькими фреймами или документами в каче- стве библиотеки. При таком способе загрузки сценарии загружаются только один раз, когда Глава 11. Работа с окнами и фреймами 157
отображается окно многофреймового документа. Если спустя некоторое время во фреймы за- гружаются другие документы, то вы сможете воспользоваться всеми преимуществами, пре- доставляемыми при этом родительскими сценариями (дополнительно не дозагружая собст- венные сценарии в браузер). В дочернем фрейме следующий уровень вверх в иерархической структуре будет представ- лен объектом parent. Поэтому ссылка из дочернего фрейма на элемент родительского окна выглядит следующим образом. parent.ИмяПеременнойОбъектаФункции Если ссылка задается иа функцию родительского окна, которая возвращает значение, то это значение будет отправлено из родительского в дочерний фрейм без дополнительного вмешательства. Если родительское окно находится на вершине иерархической структуры, загруженной в текущий момент в браузер, то по желанию ссылку на него можно задать как на окно наи- высшего уровня. top.ИмяПеременнойОбъектаФункции Использовать в ссылках ключевое слово top достаточно опасно, если по каким-то причи- нам используемая страница отображается во фрейме другого Web-узла. В этом случае окно наивысшего уровня (если можно так сказать) располагается не на самом высоком уровне. По- этому, где это только возможно, используйте в ссылках термин parent (если только предыду- щий метод ие используется для очистки узла от нежелательных фреймов). Ссылка из дочернего фрейма на дочерний фрейм Если требуется организовать взаимодействие одного фрейма с одноуровневым объектом, затрагиваются все высшие уровни структуры объектной модели браузера. Одно из свойств любого окна или фрейма — это его родитель parent (данное значение для обычного окна имеет значение null). В ссылке на одноуровневый объект обязательно используется это свойство, что обеспечивает переход к общей исходной точке обоих дочерних фреймов (в данном случае — к их родительскому окну). Теперь, когда ссылка начинается на родитель- ском уровне, остальная ее часть организована точно так, как если бы о(на задавалась из роди- тельского окна на дочернее. Таким образом, ссылка из одного дочернего фрейма на другой задается любым из приведенных ниже двух способов. parent.frames[n]. ИмяПеременнойОбъектаФункции parent.frames["имяФрейма"].ИмяПеременнойОбъектаФункции parent.имяФрейма. ИмяПеременнойОбъектаФункции Обратная ссылка из второго фрейма на первый реализуется так же, за исключением дру- гого индекса или значения имяФрейма в массиве frames. Конечно же, в HTML можно ис- пользовать более сложные иерархические структуры ссылок. Как бы сложна ни была объект- ная модель документа, правила задания ссылок позволяют найти решение при использовании самых запутанных структур и глубоко вложенных фреймов. Полезные советы Одна из наиболее распространенных ошибок, которые допускают начинающие пользова- тели при составлении сценариев в многофреймовых средах, заключается в следующем: сразу создаются сценарии, в которых другие фреймы вызываются еще при загрузке стра- ницы. Проблема состоит в том, что нельзя предусмотреть последовательность загрузки объектов документа исходя из того, как расположены соответствующие операторы много- фреймовой страницы. Вы должны знать, что родительский документ начинает загружаться 158 Часть II. Руководство no JavaScript
первым. Независимо от последовательности дескрипторов <frame>, загрузка дочерних фреймов начинается в любое время. Более того, время загрузки фреймов зависит от других элементов документа — изображений или аплетов Java. Настроить загрузку сценария можно только после успешной загрузки всех документов фреймов. Точно так же, как при полной загрузке документа запускается обработчик события onload, в многофреймовой структуре выполнение обработчика события onload в дочернем окне определяет его готовность к использованию в родительском окне. Задать настройки об- работчика onload можно в дескрипторе <f rameset>. Этот обработчик вызывает функцию в многофреймовом документе, после чего можно использовать объекты, функции или пере- менные во всех фреймах иерархической структуры объектов. Обратите внимание, что ссылка на фрейм как на специальный тип объекта окна сущест- венно отличается от ссылки на объект элемента frame. Элемент объекта представляет собой отдельный узел в объектной модели документа (глава 4). Свойства и методы этого узла отли- чаются от свойств и методов объекта окна (указанной разницей весьма удобно пользоваться при решении сложных задач программирования). Способ обращения к фрейму — объект ок- на или узел — определяет используемые в сценарии свойства и методы. В главе 15 приведено более полное описание характеристик объектов и узлов. Если вы решили использовать объект frame, то вполне можете обратиться к объекту document, в который загружен фрейм. При этом синтаксис ссылки будет значительно отли- чаться — в IE4+ и Safari объект document представляет окно; в Mozilla-совместимых брау- зерах поддерживаются стандарты W3C DOM, которые обуславливают использование свойст- ва contentDocument. Чтобы обеспечить поддержку обоих вариантов синтаксиса, применяется следующий код. var docObj; var frameObj = document.getElementByld("myFrame”); if (frameObj.contentDocument) { docObj = frameObj.contentDocument; } else { docObj = frameObj.document; } Элемент iframe Элемент iframe поддерживается в браузерах IE4+, Safari и Mozilla в виде отдельного объекта. Обычно он используется для загрузки HTML- или XML-документа в отдельном ок- не, которое отображается в пределах текущей страницы. Тем не менее, часто объект iframe умышленно не отображают, чтобы скрыть от пользователя сценарий. Элемент iframe включается в коллекцию frames окна текущего документа. Но вы мо- жете обратиться к нему как к отдельному элементу объекта, воспользовавшись методом document.getElementByld() в W3C DOM. В отличие от стандартной иерархической структуры типа кадр-окно, объект элемента требует использования специального кода для обращения к документу, расположенному в объекте iframe (см. главу 16). Способы управления многофреймовыми документами Если с помощью фреймов вы организуете сложные Web-страницы, то вам понадобится постоянная навигационная панель (чтобы совершать переходы от одних фреймов к другим). Ниже представлена концепция такого средства управления, реализуемая с помощью приложения Глава 11. Работа с окнами и фреймами 159
Decision Helper (Помощник принятия решений) (его вы найдете на компакт-диске, прилагае- мом к книге; см. также главу 55). Приложение состоит из трех фреймов (рис. 11.3). Фрейм в верхней левой части состоит из одного изображения, на котором расположены четыре гра- фические кнопки. Вы должны включить это изображение в карту изображения клиента и соз- дать такой сценарий, который в правом и нижнем фреймах изменял бы соответствующие страницы. В правом верхнем фрейме сценарий загружает полностью произвольный документ из набора пяти разных используемых документов. В нижнем фрейме сценарий переходит к одному из пяти анкеров для отображения фрагмента инструкций, которые применяются к документу, загруженному в правом верхнем фрейме. Results are calculated based on the various weights and rankings you entered in previous screens The specific numbers are not particularly important their relative positions, however, are what you’re looking for. The highest number represents the alternative rating the highest based on your input Values are shown to four decimal places in case of close races. Unfortunately, this results screen cannot be printed or ssy®d If you want to preserve this information take a screen shot using your operating system’s screen capture utility (e.g., Windows 96 Press PrtSc. MacOS. Press Cmd-Shift-3) |Done .................. , ~ ^loctfintrar# Puc. 11.3. Так выглядит приложение Decision Helper В листинге 11.1 приведена несколько измененная версия настоящего файла навигацион- ного фрейма приложения Decision Helper. В данном листинге были использованы новые объ- екты и концепции, с которыми мы еще не знакомились. Для того чтобы облегчить процесс восприятия нового материала, код сценария и HTML для верхней и нижней кнопок мы реши- ли не приводить. Опишем только навигационные кнопки со стрелками. Листинг 11.1. Графическая навигационная панель <html> <head> <title>Navigation Bar</title> <script type="text/javascript"> <!-- start function goNextO { var currOffset - parselnt(parent.currTitle); if (currOffset < 5) { currOffset += 1; 160 Часть II. Руководство no JavaScript
parent.entryForms.location.href = "dh" + currOffset + ".htm"; parent.instructions.location.hash = "help" + currOffset; } else { alert("This is the last form."); } } function goPrev () { var currOffset = parselnt(parent.currTitle); if (currOffset >1) { currOffset -= 1; parent.entryForms.location.href = "dh" + currOffset + ".htm"; parent.instructions.location.hash = "help" + currOffset; } else’ { alert("This is the first form."); } } // end --> </script> </head> <body bgColor="white"> <map name="navigation"> «area shape="rect" coords="25,80,66,116" href =" javascript .-goNext () "> «area shape="rect" coords="24,125,67,161" href="javascript:goPrev()"> </map> <img src="dhNav.gif" height="240" width="96" border="0" usemap="ttnavigat ion"> </body> </html> Начать лучше с первого раздела HTML — с раздела body. Практически весь приведен- ный выше код предназначается для объявления стандартных карт изображений. Применен- ные координаты определяют рамки вокруг каждой стрелки большего изображения. Исполь- зованный для двух областей атрибут href указывает на функцию JavaScript, определяемую в разделе head документа. В настройках приложения Decision Helper каждому фрейму присваивается имя. Верхний правый фрейм называется entryForms,-. Нижнее окно называется instructions. Для того чтобы совершить переход от определенной страницы к той, что загружена в верхнем правом фрейме, нужно знать, какая страница загружена там в текущее время. С этой целью как в родительский документ, так и в дочерние, встроен специальный сценарий, кото- рый загружается в указанный фрейм. В родительском документе определена глобальная пе- ременная— currTitle. Ее значением является число в диапазоне от 1 до 5, которое и оп- ределяет, какая из набора страниц загружена на текущий момент в фрейме. Обработчик события onLoad каждого из пяти документов (dhl. htm, dh2 . htm, dh3 . htm, dh4 . htm и dh5. htm) присваивает номер своей страницы этой глобальной переменной. Такая органи- зация позволяет легко использовать значение переменной для всех фреймов. Когда пользователь щелкает на кнопке со стрелкой “вправо” для перехода на другую страницу, вызывается функция goNext (). Первое выражение используется для получения значения переменной currTitle из родительского окна и с целью присвоения этого значе- ния локальной переменной currOffset. Конструкция if. . .else используется для про- верки того, является ли номер страницы числом, меньшим 5. Если это так, оператор прира- щения добавляет единицу к локальной переменной, которая потом может использоваться в следующих двух командах. Глава 11. Работа с окнами и фреймами 161
В следующих двух выражениях обрабатывается содержимое двух правых фреймов. Исполь- зуя parent, можно получить доступ к обоим фреймам. Свойству location.href правого верхнего фрейма назначается имя следующего по порядку файла (благодаря вставке соответст- вующего номера в имени файла). В следующем выражении свойство location.hash (которое управляет анкером начала перехода) сохраняет анкер в фрейме instructions (имена анкеров helpl, help2, help3, help4 и help5). Щелчок на кнопке со стрелкой “влево” приведет к противоположному результату. От но- мера текущей страницы единица уже отнимается (с использованием оператора понижения) с соответствующей заменой страниц. Пример, приведенный в листинге 11.1, является только одним из многих способов создания сценариев для навигации по окнам в JavaScript. Независимо от того, какой подход использу- ется, взаимодействие между фреймами в сложном документе будет весьма значительным. Дополнительные сведения о ссылках В главе 8 показано, как можно создать новое окно и затем обратиться к нему с использо- ванием ссылки на объект window, возвращаемой методом window. open (). В этом разделе вы узнаете о том, как подокна взаимодействуют с объектами, функциями и переменными ок- на или фрейма, создающими это подокно. В сценарных браузерах (кроме NN2) каждое окно имеет свойство, которое называется opener. Это свойство содержит ссылку на окно или фрейм, которые вмещают в себя сцена- рий, оператор window, open () которого использован для генерирования подокна. Для глав- ного окна браузера и расположенных в нем подокон значение этого свойства равно null. Поскольку свойство opener является допустимым в данном контексте, то его можно исполь- зовать в начале ссылки на элемент исходного окна — точно так же, как сценарий в дочернем окне использовал parent для получения доступа к элементам в родительском документе. Терминология родительских и дочерних окон, тем не менее, к подокнам не применима. В листингах 11.2 и 11.3 приведены документы, которые взаимодействуют в разных окнах. Листинг 11.2 отображает кнопку, открывающую меньшее окно и загружающую в него доку- мент с листингом 11.3. В документе основного окна также есть текстовое поле, которое за- полняется при введении соответствующего текста в поле подокна. В документе основного окна функция newWindow () генерирует новое окно. Поскольку больше ни в одном операторе в документе не используется ссылка на только что открытое окно, то возвращаемое значение ни одной переменной не присваивается. Подобная ситуация в JavaScript крайне редкая — возвращаемое функцией или методом значение никому не нужно. <html> <head> <title>Main Document</title> <script type="text/javascript"> function newWindow() { window.open("subwind.htm","sub","height=200,width=200"); } </script> </heads <body> <forms <input type="button" value="New Window" onclick="newWindow() "s 162 Часть II. Руководство no JavaScript
<br> Text incoming from subwindow: «input type="text" name="entry" </form> </body> </html> Все, что происходит в документе подокна, относится к обработчику события onchange текстового поля. Значению поля окна документа opener присваивается значение текстового поля подокна. При этом ие следует забывать, что содержимое каждого окна и подокна отно- сится к документу. Поэтому, даже если ссылка на какое-то конкретное окно или подокно бы- ла успешной, этого недостаточно. Нужно, чтобы она точно указывала браузеру, что именно нужно найти. Как правило, это один из элементов документа. <html> <head> <title>A SubDocument«/title> • </head> <body> «form onsubmit="return false"> - Enter text to be copied to the main window: «input type="text" onchange="opener.document.forms[0].entry.value = this.value"> «/form> </body> </html> Осталось осилить еще одну главу, и уже после этого можно смело браться за изучение любого материала. В следующей главе вы узнаете о том, как изменить изображение, когда пользователь наводит на него указатель мыши. Упражнения Перед тем как ответить на первые три вопроса, следует внимательно изучить структуру приведенного ниже многофреймового документа Web-страницы, в котором отображается список читаемых в колледже предметов. «frameset rows="85%,15%"> «frameset cols="20%,80%"> «frame name="mechanics" src="historyl01M.html"> «frame name="description" src="historyl01D.html"> </frameset> «frameset cols="100%"> «frame name="navigation" src="navigator.html"> «/frameset> </frameset> </html> 1. Когда бы документ ни загружался в описываемый фрейм, в нем задается обработчик события onload, содержащий в глобальной переменной currCourse многофреймо- вого документа идентификатор курса. Напишите обработчик события onload, кото- рый устанавливает это значение равным "hist oryl 01". Глава 11. Работа с окнами и фреймами 163
2. Нарисуйте блочную структуру, которая описывает иерархию окон и фреймов, опреде- ляемую приведенным выше многофреймовым документом. 3. Напишите операторы JavaScript, которые будут размещаться в навигационном фрейме, выполняющем загрузку файла "french201M.httnl" в фрейм для курса механики (mechanics), а файла "f rench201D. html" — в фрейм описания (description). 4. Пока загружается многофреймовый документ, неожиданно появляется сообщение JavaScript об ошибке: window, document, navigation, form, selector is undefined (не определен объект window.document.navigation.form.selector). Что могло произойти в сценарии приложения и как устранить эту проблему? 5. Сценарий в дочернем подокне главного окна использует метод window. open () для создания другого окна. Как сценарий в этом втором окне может получить доступ к объекту location родительского окна в главном окне браузера? 164 Часть II. Руководство по JavaScript
Изображениям динамический HTML Предыдущие восемь глав были весьма насыщенными; в них были рассмотрены как основные принципы программирования, так и особенности JavaScript. Теперь на- стало время применить эти фундаментальные познания для изучения более совершенных методов. В данной главе мы уделим внимание особенностям использования ролловеров для создания динамических изменений изображения при на- ведении на него указателя мыши. Также речь пойдет об ос- новных принципах динамического управления кодом. Объект изображения Одним из объектов, которые содержатся в документе, яв- ляется объект изображения. К сожалению, этот объект под- держивается не всеми браузерами, управляющими сценария- ми. Самыми старыми версиями браузеров, которые еще работают с такими объектами, являются NN3 и IE4. По- скольку документ может содержать больше одного изобра- жения, то ссылки на объект изображения для документа в объектной модели представлены в виде массива, включен- ного в объект document. Поэтому ссылаться на изображе- ния можно лцбо по индексу в массиве, либо по имени. Более того, индекс массива может быть строковой версией имени изображения. Поэтому все, что написано ниже, является вполне приемлемым способом задания ссылок. document.images[n] document.images["имяИзображения”] document.имяИзображения Если вашей целью является управление в сценариях изо- бражениями, то будьте готовы к тому, что браузеры NN3 hNN4 весьма ограничены в соответствующих средствах. В частности, диапазон свойств изображений, которые под- держиваются в этих браузерах, ограничен — абсолютно дос- тупным считается только стандартное свойство src. К тому же, до появления IE4+ и NN6+ объекты изображений не
имели собственных обработчиков событий. Чтобы сделать изображение интерактивным в ранних версиях браузеров нужно было добавить к ним гиперссылки, удалить рамки или создать карты изображения. Сейчас связь типа изображение-гиперссылка используется толь- ко для добавления на страницы графических кнопок. Изменяемые изображения Преимущество использования управляемых в сценариях объектов изображений заключа- ется в том, что сценарий может изменять изображения, уже занимающие прямоугольную об- ласть на странице. В браузерах IE4+ и NN6+ можно даже изменить размер таких изображе- ний с выполнением соответствующего обтекания остального содержимого страницы. Сценарий таких изменений изображения достаточно прост. Он лишь присваивает свойст- ву src объекта изображения новый адрес URL. Размер изображения на странице регулирует- ся с помощью атрибутов height и width, которые устанавливаются в дескрипторе <img> при загрузке страницы. В самом простом случае для каждого изображения используются одинаковые размеры. В браузерах NN3 и NN4 размер изображения на странице изменить нельзя, что приводит к масштабированию изображений, когда они имеют разные размеры. Предварительная загрузка изображений Загрузка изображений с Web-сервера может занять некоторое время. Если страница орга- низована так, что в ответ на действия пользователя изображения на странице изменяются, желательно, чтобы скорость выполнения этих операций была не ниже, чем в остальных муль- тимедийных программах. Если пользователю придется подолгу ждать, пока будет изменено изображение, он вряд ли получит от этого удовольствие. JavaScript приходит в этом случае на выручку. С его помощью можно предварительно за- грузить изображения в кэш-память браузера без их отображения на странице. Такой подход называют предварительным кэшированием изображений. Наилучшей тактикой при этом яв- ляется предварительная загрузка изображений в используемую для этих целей кэш-память браузера в момент первоначальной загрузки страницы. В таких случаях пользователи не очень нервничают по поводу нескольких лишних секунд, затрачиваемых при загрузке глав- ной страницы на то, чтобы загрузить все изображения. Наряду с этим “накал страстей”, кото- рый возникает при загрузке тех же самых изображений в режиме реального времени в про- цессе выполнения сценария, несравненно больше. Для того чтобы загрузить изображения, нужно создать в памяти объект этого изображе- ния. Объект изображения, создаваемый в памяти, в некотором отношении отличается от объек- та изображения документа, создаваемого с помощью дескрипторов <img>. Те объекты, кото- рые создаются сценариями и размещаются только в памяти, на странице не отображаются вообще. Но их присутствие в коде документа приводит к тому, что при загрузке страницы эти изображения также будут загружаться. В объектной модели есть функция-конструктор объек- та Image, с помощью которой можно в памяти создать объекты изображений. var mylmage = new Image(ширина, высота); Параметрами функции-конструктора является ширина и высота изображения в пикселях. Эти размеры должны соответствовать настройкам атрибутов width и height в дескрипторе <img>. Если только объект изображения существует в памяти, свойству src этого объекта можно присвоить имя файла или адреса URL. myImage.src = "someArt.gi f"; Если браузер обнаруживает указание Присвоить свойству src объекта URL-адрес, то браузер загружает соответствующее изображение в кэш-память. Все, что при этом видит 166 Часть II. Руководство no JavaScript
пользователь, — это дополнительная информация о загрузке в строке состояния (как если бы изображение отображалось на странице). К тому времени, когда будет загружена вся страница, сгенерированные таким способом изображения будут занесены в кэш-память. После этого свойству src изображения документа, созданного с помощью дескрипторов <img>, можно присвоить значения кэшированных в памяти изображений или реальных изображений с предопределенным URL. document.images[0].src = mylmage.src,- Изменяются изображения в документе таким же способом. Код в листинге 12.1 является достаточно простым примером описания страницы. В нем используется дескриптор «img» и список выбора, позволяющий перемещать изображение в документе на место одного из четырех, загруженных в кэш браузера (включая и исходное изображение, описанное в дескрипторе). После того как этот листинг будет вами введен (вдумчиво и аккуратно), в папке с листингами главы 12 на компакт-диске следует найти че- тыре файла с используемыми в данном документе изображениями (однако сам код, включая и HTML-дескрипторы, придется ввести вручную). «htrnl» <head> <title>Image Object</title> «script type="text/javascript"» // инициализация пустого массива var imageLibrary = new Array(); // предварительной загрузка изображений imageLibrary["imagel"] = new Image (120, 90) ,• imageLibrary["imagel"].src = "deskl.gif"; imageLibrary["image2"] = new Image(120,90); imageLibrary [" image2 " ] . src = "desk.2 .gif " ; imageLibrary ["image3"] = new Image (120,90) ; imageLibrary["image3"].src = "desk3.gif"; imageLibrary["image4"] = new Image(120,90); imageLibrary("image4"].src = "desk4.gif",- // загрузка выбранного в списке изображения function loadCached(list) { var img = list .options [list .selectedlndex] .value,- document.thumbnail.src = imageLibrary[img].src; } «/script» «/head» «body» <h2»Image Object«/h2» <img src="deskl.gif" name="thumbnail" height="90" width="120"> «form» «select name="cached" onchange="loadCached(this)"» «option value="imagel"»Bands «option value="image2"»Clips «option value="image3"»Lamp «option value="image4"»Erasers «/select» «/form» «/body» «/htrnl» Глава 12. Изображения и динамический HTML
Как только страница загружается, сразу начинают выполняться всевозможные операторы. Эти операторы создают в памяти четыре новых объекта изображения и присваивают свойст- вам src этих объектов имена соответствующих файлов. Изображения будут загружены в кэш-память при загрузке страницы. Дальше в теле документа с использованием дескриптора <img> реализуется представление на странице одного из изображений в качестве начального. Элемент select используется для задания списка с понятными для пользователя имена- ми рисунков, которые уже загружены в кэш-память. Когда пользователь выбирает один рису- нок из предложенного списка, функция loadCached () находит значение выбранного эле- мента, которое является строковой версией имени объекта изображения в массиве imageLibrary. Свойство src выбранного объекта изображения присваивается свойству src отображаемого изображения на странице, в результате чего на странице незамедлитель- но будет представлен сохраненный в памяти рисунок. Создание ролловеров Самым простым способом повышения привлекательности страницы является использова- ние ролловеров, изменяющих свой внешний вид при наведении на них указателя мыши. Вно- сить изменения в изображение вы можете в соответствии с вашим вкусом. Эффект может быть едва заметным — легкая подсветка или выделение границ исходного изображения, или крайне радикальным — полное изменение цветовой гаммы. Какой бы вариант ни был избран, писать сценарий придется все равно один и тот же. Если несколько подобных кнопок объединены в группу, то удобно организовать такую структуру в памяти в виде массива объектов изображений с соответствующими вариантами их нумерации и именования, необходимыми при управлении массивами. В листинге 12.2 приве- ден пример упорядочения массива для четырех управляющих кнопок. Приведенный в листинге код используется в рамках приложения, выполняющего подкачку изображений. Это один из наиболее сложных и длинных листингов в руководстве, поэтому он требует некоторых поясне- ний. Такие пояснения будут приведены непосредственно по ходу отображения листинга. <html> <head> <titlesJukebox/Image Rollovers</title> «script type="text/javascript"> Только браузеры, работающие с объектами изображений, могут выполнять загрузку изо- бражений в кэш. Поэтому вся соответствующая последовательность находится внутри конст- рукции if, в условном операторе которой проверяется наличие массива document. images. В браузерах старых версий это значение не может быть определено, что соответствует значе- нию false при проверке условия в блоке if. if (document.images) { Загрузка изображений в память начинается с создания двух массивов объектов изображе- ний. В одном массиве хранится информация об изображениях, которые используются для кнопок в неактивном состоянии (off). В другом содержатся изображения активных кнопок (в состоянии on). В этих массивах в качестве индексов вместо целых чисел используются строки. Строковые названия соответствуют тем именам, которые присвоены видимым гра- фическим объектам (их дескрипторы приведены в исходном коде ниже). В этом случае код более прост для восприятия. Например, запись of f ImgArray ["play"] вполне определен- но дает понять, для чего нужен данный элемент. Как можно будет в дальнейшем увидеть из 168 Часть II. Руководство по JavaScript
листинга, подкачиваемые изображения не конфликтуют с прочими отображаемыми на стра- нице рисунками (такое возможно, если в ссылке на отображаемые изображения при подкачке используются исключительно числовые индексы). После создания массива и присвоения первым его четырем элементам новых пустых объ- ектов изображений, элементы этого массива просматриваются заново, чтобы указать в свой- стве src каждого объекта, записанного в массив, путей к графическим файлам. Соответст- вующие строки кода выполняются при загрузке страницы, поэтому сразу производится загрузка изображений в соответствующую область кэш-памяти. // Запись в кэш всех неактивных кнопок var offlmgArray = new.ArrayO; OfflmgArray["play"] = new Image(75,33); offlmgArray["stop"] = new Image(75,33); pfflmgArray["pause"] = new Image(75,33); offlmgArray ["rewind"] = new Image (86,33) ,- // Массив изображений - указывается путь к неактивному изображению для каждой кнопки offlmgArray["play"].src = "images/playoff.jpg"; offlmgArray["stop"].src = "images/stopoff.jpg"; offImgArray["pause"].src = "images/pauseoff.jpg"; offlmgArray["rewind"].src = "images/rewindoff.jpg"; // Запись в кэш всех активных кнопок var onlmgArray = new Array () ,- onlmgArray["play"] = new Image(75,33); onlmgArray ["stop"] =; new Image (75,33) ; onlmgArray["pause"] = new Image(75,33) ; onlmgArray["rewind"] = new Image(86,33); // Массив изображений - указывается путь к активному изображению для каждой кнопки onlmgArray["play"].src = "images/playon.jpg"; onlmgArray["stop"].src = "images/stopon.jpg"; onlmgArray["pause"].src = "images/pauseon.jpg"; onlmgArray["rewind"].src = "images/rewindon.jpg"; } Как можно увидеть из следующего фрагмента HTML-кода, при наведении пользователем указателя мыши на любой из отображаемых графических объектов документа, обработчик события onmouseover (в объекте документа) вызывает функцию. imageOn (), передавая ей имя конкретного изображения. Функция imageOn () использует это имя для синхронизации записей массива document. images (отображаемые изображения) и массива размещенных в памяти изображений активных кнопок onlmgArray. Свойство src элементов этого мас- сива присваивается соответствующим свойствам src изображений документа. // Функция, которая выполняет подкачку изображений function imageOn(imgName) { if (document.images) { document.images[imgName].src = onlmgArray[imgName].src; } } To же происходит при использовании обработчика события onmouseout, который пере- водит изображение в “выключенное” состояние, для чего использует функцию imageOf f () с тем же индексным значением в качестве параметра. Глава 12. Изображения и динамический HTML 169
function imageOff(imgName) { if (document.images) { document.images[imgName].src = offlmgArray[imgName].src; } } Оба обработчика событий onmouseover и onmouseout настраивают строку состояния так, чтобы там не отображались инструкции javascript: URL при наведении пользовате- лем указателя мыши на изображение. В обработчике события onmouseout сообщение, ото- бражаемое в строке состояния, выставляется равным пустой строке. function setMsg(msg) { window, status = msg.- return true; } В данном примере функции управления, приведенные ниже, не задействованы, но все же они содержат пустые операторы. Это сделано для того, чтобы функции отлавливали все вы- зовы, которые выполняются при активизации ссылок, указывающих на изображения. // Функции управления (не задействованы) function playltO { function stoplt() { } function pauseltO { function rewindltO { } «/scripts «/heads «bodys «centers <forms Jukebox Controlscbrs Каждое изображение заключается в объект ссылки. Подобная конструкция необходима, поскольку в объекты ссылки включены обработчики события, применяемые для задания от- ветной реакции сценария на манипуляции пользователя с мышью (а это позволяет поддержи- вать совместимость документа с NN3). Каждый обработчик события onmouseover вызыва- ет функцию imageOn (), передавая при этом имя подкачиваемого объекта изображения. Поскольку в обоих обработчиках (onmouseover и onmouseout) необходимо использовать выражение return true, для запуска процесса, вызов второй функции setMsg () необхо- димо объединить с требованием return true. Функция setMsg () всегда возвращает зна- чение true, а наличие ключевого слова return перед вызовом этой функции обеспечивает нужный результат. В результате вы сможете уменьшить объем используемого кода. / При введении этого листинга с последующим его использованием следует вни- /н» заметку мательно следить за тем, чтобы каждый дескриптор «as вместе с его атрибута- ♦ ми располагался в одной строке. Либо следует вставить символ возврата карет- ки перед именем любого обработчика событий. <а href="javascript:playlt()" onmouseover= " imageOn (' play ’),- return setMsg (' Play the selected tune1)" onmouseout="imageOff('play1); return setMsg('')"s <img src="images/playoff.jpg" name="play" height="33" width="75" border="0"s «/as 170 Часть II. Руководство no JavaScript
<a href="javascript:stoplt()" onmouseover="imageOn(’stop’); return setMsg(’Stop the playing tune')" onmouseout="imageOf f('stop'); return setMsg('') " > <img src="images/stopoff.jpg" name="stop" height="33" width="75" border="0"> </a> <a href="javascript:pauselt()" onmouseover="imageOn('pause1); return setMsg(1 Pause the playing tune')" onmouseout="imageOff('pause'); return setMsg('')"> cimg src="images/pauseoff.jpg" name="pause" height="33" width="75" border="0"> </a> <a href="javascript:rewindlt()" onmouseover="imageOn('rewind'); return setMsg(’Rewind back to the beginning')" onmouseout="imageOff('rewind'); return setMsg('')"> <img src="images/rewindoff.jpg" name="rew5nd" height="33" width="86" border="0"> </a> </form> </centers </body> </html> На рис. 12.1 приведен пример выполнения этого длиннющего сценария. Когда пользова- тель наводит указатель мыши на одно из изображений (изображениями являются кнопки му- зыкального проигрывателя), оно изменяет свой цвет на более темный, что выполняется путем подкачки нового изображения. Файлы с изображениями можно найти на прилагаемом к книге компакт-диске. Листинг же лучше ввести самостоятельно. Только тогда можно будет ощу- тйть всю прелесть создания сценария. Рис. 12.1. Так выглядят кнопки музыкального проигрывателя на странице Оператор javascript: псевдо-URL В предыдущих главах было приведено несколько примеров использования оператора javascript: в атрибуте href таких дескрипторов, как <а> и <агеа>. Это весьма удобный элемент языка, поскольку он поддерживается даже теми браузерами, которые не могут управлять сценариями. Указанный оператор обычно используется для задания обработчика события щелчка в та- ких объектах, которые выступают на странице в качестве гиперссылок. На ранних этапах раз- вития языка и браузеров объекты изображения вообще не поддерживали обработчики событий, Глава 12. Изображения и динамический HTML 171
хотя их всегда можно было включить в интерактивные элементы. Если разработчику нужно было назначить для изображения определенное динамическое действие (попросту выполнить какую-либо функцию, вместо перехода по указанному URL), то он заменял в операторе j avascript: URL-адрес на имя функции. В результате в атрибуте href можно было указать действие, выполняемое при щелчке на текущем элементе даже в браузерах, которые не обеспечивают обработку событий для объек- тов этого типа. Например, в конце листинга 12.2 все четыре дескриптора <а> содержат опе- ратор j avascript:, который вызывает функцию, созданную в сценарии. <а href="javascriptzplaylt()" ...> Обратите внимание на следующую особенность описанной выше методики. Несмотря на явное указание в сценарии текста, отображаемого в строке состояния, в ней всегда будет представлен псевдо-URL, заданный в операторе j avascript: (что не может не удивлять пользователей). Поэтому старайтесь не использовать текущую методику в случае работы с браузерами, поддерживающими обработчики событий для объектов. Больше динамизма в HTML Поскольку современные браузеры предоставляют в сценарии доступ к любому элементу документа и позволяют обновлять содержимое страницы даже при малейших его изменениях, разрабатываемые приложения получают весьма широкие возможности по динамическому управлению. Тем не менее, технология Dynamic HTML не столь проста в использовании, как кажется, так как требует использования огромного количества специфических для каждого типа браузеров элементов. В последнем разделе этого занятия вы изучите некоторые специ- альные методики, поддерживаемые только W3C DOM-совместимыми браузерами. Следует обратить ваше внимание на две самые распространенные задачи, решаемые в помощью DHTML, — изменение стиля элементов и изменение содержимого тела документа. Изменение настроек таблицы стилей Каждый отображаемый на странице элемент (и даже некоторые скрытые элементы) имеют свойство style. Оно предоставляет в сценарии доступ ко всем свойствам каскадных таблиц стилей (CSS) элемента, поддерживаемым текущим браузером. Значения этих свойств те же, что указываются в спецификации таблиц стилей — обычно они задаются с помощью специальных дескрипторов, атрибуты которых отличаются в разных браузерах. Например, для изменения цвета текста элемента с идентификатором Frankl inQuote используется следующий синтаксис. document.getElementByld("FranklinQuote").style.color = "rgb(255, 255, 0)"; Поскольку свойство color таблицы стилей позволяет применять другие методы опреде- ления цветов (например, с помощью гексагонального триплетного значения #ffffOO), то в вашем конкретном случае указанное выражение может несколько отличаться. Имена отдельных свойств CSS-стилей, тем не менее, не соответствуют именам, принятым в JavaScript. В частности, некоторые свойства CSS-стилей содержат в именах дефисы. В та- ком случае в сценарии используется имена без дефисов (имена вводятся слитно), а отдельные слова начинаются с большой буквы. Например, свойство font-weight в сценарии реализу- ется следующим образом. document.getElementByld("highlight").style.fontweight = "bold"; Подобное поведение сценариев накладывает серьезное ограничение на код, задающий спецификации CSS-стилей. Например, если вы определили CSS-правила для двух различных 172 Часть II. Руководство по JavaScript
классов, то можете легко изменить определение класса, примененного к элементу, воспользо- вавшись свойством className объекта этого элемента. Далее мы рассмотрим ситуацию оп- ределения двух CSS-классов для различных фоновых цветов. .normal {background-color: #ffffff} .highlighted {background-color: WffOOOO} В HTML-документе элементу сначала назначается класс по умолчанию. <р id="news" class="normal">...</?> В сценарии можно легко изменить назначенный элементу CSS-класс на highlighted, document.getElementByld("news").className - "highlighted"; Изменив CSS-класс, назначенный элементу, вы изменяете его внешний вид и поведение. Этот метод удобно использовать для быстрого изменения сразу нескольких свойств элемента. Динамическое содержимое узлов W3C DOM В главе 8 вы ознакомились с методами document. createElement () и document. createTextNode О. Они используются для создания новых объектов, которые впоследствии будут настраиваться с помощью свойств (атрибутов) перед добавлением в целевой документ. В качестве введения в рассматриваемую методику я предлагаю вам ознакомиться с при- мером добавления элемента span, содержащего текст, на Web-страницу, В данном случае элементу абзаца с идентификатором placeholder назначен класс centered. Часть текста абзаца (имя посетителя страницы) заимствует из текстового поля, содержащегося в форме. var newElem = document.createElement("р"); newElem.className = "centered"; var newText = document.createTextNode("Thanks for visiting, " + document.forms[0] .f irstName.value); // вставка в абзац текстового узла newElem.appendChild(newText); // вставка абзаца в заполнитель document.getElementByld("placeholder").appendChild(newElem) Подход к программированию подобного поведения страницы в спецификации W3C DOM весьма сложен. Он требует выполнения несравненно большого количества действий, которые не всегда очевидны. После создания элемента и текстового узла последний требуется вста- вить в узел элемента. Поскольку новый узел элемента при создании не содержит данных, для вставки текстового узла в элемент необходимо выполнить метод appendChild() (между открывающим и закрывающим дескрипторами). После создания элемент абзаца располагает- ся в конце исходно пустого элемента span. Специальные методы в W3C DOM (описанные в главах 15 и 16) позволяют быстро вставлять, удалять и заменять узлы. Свойство innerHTML До разработки спецификации W3C DOM компания Microsoft снабжала каждый объект свой- ством HTML. Впервые это свойство стало поддерживаться в браузере IE4 и вскоре приобрело большую популярность благодаря свой высокой практичности. Это свойство принимает в каче- стве значений дескрипторы и другое содержимое, расположенное в HTML-документе и пред- ставляющее текущий элемент. Хотя в W3C DOM этому свойству не уделено должного внима- ния, оно до сих пор настолько популярно, что его поддержка реализована во всех современных браузерах. Вы даже сможете воспользоваться им в Mozilla-совместимых браузерах и Safari. Глава 12. Изображения и динамический HTML 173
Чтобы продемонстрировать преимущества этого свойства, рассмотрим два примера кода, выполняющих одну и ту же задачу. var newHTML = "<р class='centered'>Thanks for visiting, "; newHTML += document.forms[0].firstName.value; newHTML += "</p>"; document.getElementByld("placeholder").innerHTML = newHTML; Второй вариант несколько проще для понимания, да и его синтаксис значительно легче для ввода. Первый подход, заключающийся в управлении узлами, требует более вниматель- ного изучения, хотя его код выполняется намного дольше. Зачастую самый простой код не всегда самый эффективный с точки зрения выполнения его компьютером. Итак, будем считать, что вы успешно изучили основы языка, выполнили все упражнения и прекрасно подготовились к дальнейшему знакомству с возможностями объектной модели и специальными методами программирования на JavaScript. Можете смело приступать к изу- чению материала частей Ш и IV, но перед этим ознакомьтесь с главой 45 на прилагаемом к книге компакт-диске, в которой рассказывается об отладке программного кода. Упражнения 1. Объясните различия между объектом изображения документа и объектом изображения в памяти. 2. Введите команды JavaScript, необходимые для предварительной загрузки в кэш-пдмять изображения jane.jpg, которое потом будет использовано для замещения объекта изображения документа, определяемого следующим кодом HTML. <img name="people" src="john.jpg" height=120 width=100 alt="people"> 3. С помощью кода, созданного для ответа на второй вопрос, нужно определить JavaScript- операторы, используемые для замены изображения документа на изображение в памяти. 4. Совместимые со старыми версиями браузеров объекты изображений не имеют своих обработчиков событий. Как в этом случае реализуется процесс подкачки изображений в ответ на действия мышью? 5. Предположим, что элемент table содержит пустой элемент ячейки (td), имеющей идентификатор forwardLink. Воспользовавшись спецификацией W3C DOM, напи- шите операторы, которые добавляют в ячейку таблицы следующую гиперссылку. <а href="page4.html">Next Page</a> 174 Часть II. Руководство no JavaScript
Объекты документа
Основы JavaScript Перед разработчиками часто возникает проблема, свя- занная с четким разграничением базового языка соз- дания сценариев JavaScript и теми объектами, которые должны управляться с помощью этого языка. Поэтому имеет смысл сразу провести разделительную черту между языком програм- мирования и объектной моделью. В дальнейшем это будет способствовать облегчению процесса принятия решений при оформлении страниц с использованием JavaScript. Если когда- нибудь придется использовать JavaScript с другими объектны- ми моделями (как, например, при программировании задач для серверов), четкое разграничение вам тоже пригодится. Основы языка при этом неизменны — изменяются только объекты. В этой главе рассматриваются многие вопросы использо- вания базового языка JavaScript, о которых речь уже шла в предыдущей части (например, создание страниц, рассчи- танных на широкий круг пользователей и всевозможные ти- пы используемых ими браузеров). Кроме того, будуг описаны новые возможности самого языка программирования. Де- тальную информацию о синтаксисе базового языка JavaScript можно найти в следующей части. Версии JavaScript Язык JavaScript имеет собственную систему нумерации версий, которая абсолютно независима от нумерации поко- лений браузеров. Компания Netscape, создавшая этот язык, во многом и определила принцип нумерации версий. Первой версией, логически завершенной, была 1.0 (она встроена в Navigator 2 и в первое издание Internet Explorer 3). По мере развития языка и разработки новых версий браузе- ров номера версий JavaScript увеличивались весьма умерен- ными темпами. Например, в Internet Explorer 6 и Mozilla- совместимых браузерах используется JavaScript версии 1.5. Каждое успешное поколение браузеров применяло новые возможности языка. Например, в JavaScript 1.0 концепция мас- сивов не была доработана полностью, что привело к невозмож- ности отслеживания всех элементов в массиве. В JavaScript 1.1 этот промах был устранен путем введения функции-конструк- тора для генерации массивов и свойства length для каждо- го созданного массива.
На практике, тем не менее, встроенная в браузер версия JavaScript далеко не всегда может реализовать весь набор своих возможностей, поскольку не все ее средства доступны для управления в данной версии браузера. Например, JavaScript 1.2 (который используется в NN4) включает широкую поддержку регулярных выражений, однако не все они доступны для использования в Microsoft JavaScript 1.2, поддерживаемом в IE4. Кроме того, Microsoft включила в JScript (IE5) систему отслеживания ошибок try-catch, в то время как Netscape не использовала эту возможность вплоть до JavaScript версии 1.5 в NN6. Поэтому при опре- делении тех средств, которые допускается использовать, определяющей является не версия самого языка, а, скорее, используемого браузера. Стандарт базового языка - ECMAScript Несмотря на то, что компания Netscape и разработала язык JavaScript первой, Microsoft включила этот язык в Internet Explorer 3. Поскольку Microsoft не имела желания лицензиро- вать название “Java” у владельца этой торговой марки — компании Sun Microsystems, язык в среде IE стал использоваться под названием JScript. За исключением специфических харак- теристик и некоторых нововведений, оба языка практически идентичны. Если сравнивать степень совместимости базовых языков и соответствующих типов браузеров, то для языков уровень совместимости намного выше (в отличие от ряда несогласованностей в реализации объектных моделей, обсуждаемых в следующей главе). Как уже отмечалось в главе 2, были предприняты серьезные попытки по созданию общих стандартов для разработчиков браузеров. Последние разработки призваны облегчить.жизнь разработчикам программных продуктов для Web. Новые веяния в первую очередь привели к изменению базовых принципов языка. При содействии европейской организации по стан- .дартизации — ЕСМА, формальный стандарт для языка был согласован и представлен обще- ственности. Первая версия стандарта языка, названная группой разработчиков ECMAScript, была, фактически, точной копией версии JavaScript 1.1, использованной в Netscape Navigator 3. В стандарте определялись способы трактовки различных типов данных, принципы работы операторов, особенности синтаксиса и ряд других характеристик. В более новой (третьей) версии базового языка многое было усовершенствовано (вторая версия представляла собой первую, с исправленными ошибками). Описание текущей спецификации ЕСМА-262 можно найти по адресу http://www.ecma-international .огд. Студенты, изучающие языки программирования, найдут для себя этот документ весьма занимательным. Те же, кто просто решил научиться писать сценарии для страниц, могут испытать легкое замешательство. Как Netscape, так и Microsoft, обязались придерживаться при разработке своих браузеров стандарта ЕСМА. Вся широта возможностей стандарта ECMAScript была реализована уже в Netscape Navigator 3 н Internet Explorer 4. По мере того, как в стандарт ЕСМА добавляются новые характеристики, они сразу же находят себе применение в новых версиях браузеров. На данный момент ECMAScript имеет версию 3, которая поддерживается в JavaScript 1.5 (Mozilla) и JScript (IE6). Встроенные в HTML-документы сценарии В браузерах, поддерживающих JavaScript, существуют различные способы включения сценариев или элементов сценариев в документы HTML. Не каждый из таких методов может быть использован в любой версии браузера, но в этом плане, начиная с браузеров Navigator версии 3 и Internet Explorer версии 3, поддерживается достаточная степень гибкости. На дан- ный момент достаточно предположить, что большинство пользователей работают в браузерах Глава 13. Основы JavaScript 177
не старше IE4. В результате вы автоматически исключаете поддержку ваших сценариев в весьма небольшом кругу старых браузеров. Редкое исключение составляют пользователи, которые работают в браузерах с отключенной функцией выполнения сценариев. Дескриптор сценария <script> Самый простой способ использования операторов сценария в документе HTML состоит в том, чтобы заключить их в дескрипторы < script >. . .</script >. Язык сценария при этом указывается с помощью атрибута language. В документе можно использовать произвольное количество таких пар дескрипторов. Например, в разделе заголовка можно определить несколь- ко функций, которые потом будут вызываться обработчиками событий в теле документа HTML. Другие дескрипторы могут использоваться в блоке тела документа для выполнения той части сценария, которая активизируется при загрузке страницы. Все операторы и комментарии сцена- рия следует размещать между открывающими и закрывающими дескрипторами. В них не стоит использовать дескрипторы HTML, если только они не являются частью параметра оператора document. write (), который используется для отображения содержимого страницы. В каждом открывающем дескрипторе сценария «script> должен быть указан используе- мый язык (для этого используется атрибут language). Дескриптор <script> применяют для указания браузеру того, что содержащиеся внутри дескрипторов операторы являются частью выполняемого сценария и не должны интерпретироваться как обычный код HTML. В этом де- скрипторе также можно указать любой язык, который доступен для интерпретации браузером. Задание версии языка Начиная с IE5 и Mozilla-совместимых браузеров, дескриптор «script> поддерживает атрибут type. Например, для определения MIME-типа содержимого дескрипторов использу- ется следующее выражение type="text/javascript". Таким образом, дескриптор <script> для языка JavaScript будет иметь следующий вид. «script type="text/javascript">...«/script> Атрибут type стал знаком разработчикам, начиная с IE4. Старые браузеры, позволяющие использовать сценарии (в Netscape Navigator 2 и Internet Explorer 3), признают атрибут указа- ния языка language="JavaScript". Вместе с тем, более современные версии браузеров обычно распознают еще и версию языка, а в случае Internet Explorer, и другие языки (например, VBScript). Встроенный в Navigator 3 интерпретатор языка JavaScript знает версию языка JavaScript 1.1, a Navigator 4 и Internet Explorer 4 определяют версию JavaScript 1.2. При указании версий языка, отличных от исходного JavaScript, номер версии указывается после названия языка без пробела, как показано ниже. «script language=“JavaScriptl.l">...«/script> «script language="JavaScriptl.2">..,«/script> Обратите внимание на то, что атрибут language стал неактуальным в HTML 4 с появле- нием атрибута type, который точнее определяет используемый язык написания сценариев. Тем не менее, в IE5+ и браузерах Mozilla первый все еще поддерживается, хотя версии языка в расчет не принимаются. Для того чтобы обеспечить совместимость со старыми браузерами и, в то же время, не отставать от последних разработок в этой области, можно использовать в дескрипторах сценария «script > оба атрибута: language и type. При использовании браузеров старых версий атрибут type будет игнорироваться. 178 Часть III. Объекты документа
Дескриптор <script for> В Internet Explorer 4 и более поздних версиях операторы, размещенные внутри дескрипторов сценария < script >, можно связать с конкретным объектом и событием, им генерируемым. В соответствии со спецификацией языка, набор атрибутов этого дескриптора должен дополни- тельно включать элементы for и event (которые не являются частью стандартного HTML). Значение, присваиваемое атрибуту event, является ссылкой на нужный объект. Как правило, это обычный идентификатор, присоединяемый к объекту (в IE4+ ссылку на объект можно задать либо в формате document .all. object ID, либо просто указав идентификатор object ID). Ат- рибут event используется для определения имени обработчика события, на которое будет реаги- ровать сценарий. Например, если сценарий должен выполнять определенные действия в ответ на перемещение указателя мыши вниз на странице (событие mouse down) в разделе с идентифика- тором myParagraph, соответствующий фрагмент сценария должен будет выглядеть так. «script for="myParagraph" event="onmousedown" type="textIj avas cript"> «/script» Операторы внутри дескрипторов будут выполняться только при наступлении нужного со- бытия. Для этого не следует описывать никакие дополнительные функции. Использование такого способа привязки событий объектов к сценарию означает, что можно отказаться от описания обработчиков событий в дескрипторах отдельных элементов. Эта техника доступна только в IE4 и более поздних версиях браузеров. Ее можно быть с ус- пехом использовано при обработке определенного типа событий. С другой стороны, сущест- вует серьезное ограничение, когда большая часть кода размещается в сценариях отдельных объектов. Такой подход вряд ли удастся использовать при задании операторов, которые вы- зываются несколькими объектами. Еще одним недостатком является то, что в браузерах, отличных от IE или более ранних, чем IE4, описанные дескрипторы не могут использоваться при загрузке изображений. В таких брау- зерах операторы сценария выполняются при загрузке страницы, а это будет приводить к ошибкам. Особенности написания кода при работе со старыми типами браузеров Среди пользователей увеличивается количество новых версий браузеров, поддерживаю- щих сценарии, количество устаревших их версий, соответственно, неуклонно уменьшается. Однако факт остается фактом: достаточно много посетителей Web-узлов используют браузе- ры, которые не имеют встроенных интерпретаторов JavaScript. К ним относятся, например, браузеры, работающие в мобильных телефонах и карманных компьютерах. Не управляющие сценариями браузеры не распознают дескриптор «script», а потому не умеют его обрабатывать. Как правило, браузеры просто игнорируют незнакомые дескрип- торы. С этим не возникает проблем, если весь код HTML помещается в одну строку. Но в де- скрипторах «script» может содержаться достаточно большое количество таких строк. Браузеры старых версий не реагируют также и на добавление дескриптора завершения сцена- рия «/script». Поэтому такие браузеры пытаются интерпретировать сценарии как обыч- ный для них код HTML. К сожалению, операторы сценария располагаются непосредственно в документе. В результате на странице будет отображаться всякая ерунда, что может вызвать у пользователей вполне понятное недоумение. Однако существуют способы, позволяющие “перехитрить” многие браузеры старых типов и скрыть от них операторы сценария. Например, заключите команды сценария вместе с дескрип- Глава 13. Основы JavaScript 179
торами < script > внутрь дескрипторов комментария HTML. Комментарий HTML начинает- ся с последовательности символов < ! - - и заканчивается последовательностью - - >. «script type="text/javascript"> <! -- Здесь размещаются операторы сценария // -> «/script» Интерпретатор JavaScript будет игнорировать строку, которая начинается с символов комментария HTML. Сложнее дела обстоят с интерпретацией последовательности окончания такого комментария. Последовательность, закрывающая комментарий HTML, начинается с символа комментария JavaScript (//) — JavaScript должен проигнорировать данную строку. Однако не поддерживающие сценарии браузеры распознают последовательность окончания комментария HTML и поэтому начинают обрабатывать код HTML уже со следующего деск- риптора или текстового фрагмента в документе. Поскольку этим браузерам дескриптор «/script» не знаком, то они его просто игнорируют. Однако зачастую даже такие замысловатые приемы не всегда эффективны. Некоторые со- всем старые браузеры (America Online) будут отображать на странице фрагменты кода сцена- рия, несмотря на все попытки разработчиков страницы помешать этому. К счастью, такого типа браузеры встречаются крайне редко. Если разрабатываемая страница предназначена для широкого круга пользователей, в ком- ментарий HTML всегда следует заключать весь код сценария, размещенный между дескрип- торами <script» (см. выше). Указанные дескрипторы также должны заключаться в ком- ментарий— ни в коем случае не наоборот. В данной книге в большинстве приведенных примеров такого рода методология не используется, однако мы делаем это исключительно в целях экономии места. Что значит “спрятать” сценарий Было бы не совсем правильным утверждать, что описанная выше процедура использова- ния комментариев HTML помогает “спрятать” сценарий от старых браузеров. На самом деле таким образом сценарий можно предохранить только от обработки его браузером. Дескрип- торы и операторы сценария при этом загружаются в браузер, и если пользователь захочет просмотреть исходный код страницы, он увидит и этот сценарий. Разработчики страниц всегда мечтали “по-настоящему” скрыть сценарии от посторонних глаз. Рассчитанный на управление на стороне клиента, код JavaScript должен загружаться на страницу. Как результат, он будет отображаться при просмотре пользователем исходного ко- да. Существуют, конечно, хитрости, позволяющие скрыть этот код от любопытных глаз. Са- мое простое, что можно сделать в такой ситуации, -—загружаемая страница не должна содер- жать отображаемых элементов, а только сценарии, вызывающие отображаемую страницу. В этом случае код отображаемой страницы содержит только дескрипторы HTML, но никак не операторы сценария. Такая страница не будет интерактивной, поскольку в ней нет ни одной строки сценария. Это само по себе лишает смысла “скрытие” кода сценария. Все попытки скрыть исходный код с помощью сценариев могут быть сведены на нет, если пользователь при загрузке страницы временно отменит выполнение сценариев. И тогда абсолютно весь ис- ходный код снова будет виден, как на ладони. Если кто-то беспокоится о том, что другие разработчики смогут “украсть” его сценарии, то советуем разместить предупреждение о соблюдении авторских прав прямо в исходный код страницы. Ведь не только злоумышленники могут просматривать чужие сценарии. С таким же успехом их собственные сценарии также могут быть просмотрены. Так можно отлавли- вать тех, кто использует чужие разработки. 180 Часть III. Объекты документа
i ч Одним из способов предотвращения использования чужими людьми созданного вами JavaScript-кода является использование специальной программы шифро- f вания кода, что делает его значительно сложнее для понимания. На первый взгляд, код выглядит абсолютно правильным, но при анализе он оказывается весьма сложным для изменения. Шифрованный файл можно смело размещать в Web, но при этом не забывайте хранить исходную версию кода в своем компью- тере на случай, если вам понадобится когда-либо его изменить. Одну из условно- бесплатных программ шифрования кода сценариев (JavaScript Scrambler) вы найдете на узле www. quadhead. de. Библиотеки сценариев (файлы .js) Тем, кто уже работал со сценариями или в свое время трудился над разработкой страниц для сложных Web-приложений, должно быть известно, что можно разработать набор функ- ций н фрагментов сценариев, которые впоследствии будут использоваться в разных приложе- ниях. Вместо того чтобы каждый раз копировать такой код в соответствующие документы (а потом пройти через кошмар внесения изменений в каждую отдельную версию при добав- лении новых средств или при отладке ошибок), можно создать специальную библиотеку фай- лов, которую впоследствии следует подключить к нужной странице. Такого рода внешние файлы не содержат ничего, кроме кода JavaScript, — никаких деск- рипторов < script >, никаких HTML-элементов. Создаваемый файл с фрагментом кода сце- нария должен быть текстовым, но его имя должно иметь расширение . j а. Чтобы браузер за- грузил его в определенном месте структуры HTML, в дескриптор <script> добавьте атрибут src, как показано ниже. «script type="text/Javascript" src="hostscript. js"x/script> Такие дескрипторы должны размещаться в самом начале документа перед всеми осталь- ными дескрипторами « script >, поэтому они загружаются в первую очередь. Если загружа- ется несколько внешних библиотечных файлов, то все соответствующие дескрипторы долж- ны размещаться в начале документа. Работая с внешними файлами, помните о следующем. Во-первых, нужно в любом случае использовать пару дескрипторов «script>. . . </script>, даже если между ними ничего нет. При этом используются как внешние сценарии, так и сценарии в самом документе. Во- вторых, если дескриптор начала сценария содержит атрибут src, то между дескриптором на- чала н завершения сценария другие команды размещать нельзя. Способ ссылки на внешний файл в атрибуте src зависит от размещения этого файла и стиля работы автора сценария. В предыдущем примере предполагалось, что внешний файл находится в той же папке, что и файл HTML, содержащий данный дескриптор. Но если нуж- но сослаться на адрес URL, то сделать это можно с помощью записи протокола http// (по аналогии с файлами HTML). «script language="JavaScript" src="http://www.cool.com/hostscript.j s"> </script> Важным условием для управления документами из внешних библиотек сценариев является возможность программного обеспечения используемого Web-сервера сортировать файлы срасширением . js для обработки их с помощью приложения application/x- javascript. Поэтому перед тем, как применить с помощью JavaScript внешние библиотеки, следует прове- рить, как на это среагирует сервер, затем внесите, если нужно, коррективы в его настройки. Если пользователь захочет просмотреть исходный код загруженной страницы, в которой использованы внешние библиотеки, то код, содержащийся в j s-файле, отображен не будет (однако браузер трактует его как составную часть текущего документа). При этом имя или Глава 13. Основы JavaScript 181
'На заметку URL использованного j s-файла будут видны (именно в том месте, где они расположены в исходном коде). Таким образом, любой желающий сможет отключить в браузере JavaScript, открыть соответствующий j s-файл (используя протокол http: //) и просмотреть исходный код. Другими словами, код JavaScript, содержащийся во внешнем файле, не более защищен от нежелательного просмотра, чем тот, который находится непосредственно в HTML-файле. Определение версии браузера Вне всяких сомнений, наибольшие трудности у разработчиков сценариев связаны с созда- нием таких приложений, которые бы работали с достаточно большим набором браузеров разных типов и версий. Каждый такой браузер имеет свои особенности. В этом отношении счастливчиками являются разработчики, работающие в локальных сетях компаний, в которых все компьютеры используют один стандартный тип и версию браузера. Но это, скорее, ис- ключение из правил, когда получают широкое развитие частные корпоративные сети, где приложения используются как компаниями, так и клиентами. Описываемая проблема возникла после выхода версии браузера NN2, который был на то время единственным браузером, работающим со сценариями. Решать ее можно по-разному. Можно либо строго определиться с типом используемого браузера, либо пойти на компромисс. Можно уменьшить требования к функциональности страницы. Вы также можете использовать на Web- узле разные страницы для браузеров разных типов. В этом разделе будет рассказано о некото- рых приемах, позволяющих решать проблемы, связанные с фрагментацией рынка браузеров. Как только популярность языка JavaScript достигла определенного уровня, его поддержка стала считаться неотъемлемым атрибутом не только браузеров для настольных компьютеров, но и для мобильных устройств. Уже сегодня отдель- ные версии браузеров для мобильных устройств поддерживают JavaScript. Проверка поддержки JavaScript Часто наиболее важным условием в работе приложения является определение доступно- сти JavaScript для клиента, посещающего узел. Все браузеры, не поддерживающие JavaScript, можно разделить на две категории: а) браузеры, которые JavaScript поддерживает (просто у них в соответствующих установках выключен режим поддержки JavaScript); б) браузеры, в которых поддержка JavaScript не предусмотрена вообще. Использование дескриптора <noscript> За исключением некоторых ранних выпусков NN2, все поддерживающие JavaScript браузе- ры в настройках (Preferences) имеют опцию, позволяющую отключать режим поддержки JavaScript (и аналогичную опцию для Java). Как правило, по умолчанию такой режим включен, од- нако при установке в компьютер клиента браузера этот режим иногда не работает. Причиной могут стать меры безопасности, предпринимаемые для исключения возможных конфликтов с Java, или попытки некоторых брандмауэров отследить код JavaScript во входящих HTML-потоках. Все совместимые с JavaScript браузеры поддерживают пару дескрипторов <noscript>. . . </noscript>, которые полностью противоположны дескрипторам <script>. . . </script>. Если в таком браузере режим поддержки JavaScript отключен, то' дескрипторы <script>, в отличие от <noscript>, игнорируются. Как это происходит с дескрипторами <noframes>, дескрипторы <noscript> можно использовать для того, чтобы с помощью HTML вывести сообщение, что JavaScript отключен (поэтому все возмож- ности страницы не могут быть задействованы, если JavaScript не подключить). В листин- ге 13.1 приведен пример такого кода HTML. 182 Часть III. Объекты документа
<html> <head> <title>Some Document</title> <script type="text/javascript"> // операторы сценария </script> </head> <body> <noscriptxb>Your browser has JavaScript turned off.c/bxbr /> You will experience a more enjoyable time at this Web site if you turn JavaScript on <hr /></noscript> <h2>The body of your document.</h2> </body> </html> В дескрипторе <noscript> можно использовать любой стандартный код HTML. Чтобы йривлечь внимание пользователя к советам в верхней части страницы, используйте цветные значки. Если в определенных местах документа содержимое управляется динамически, то можно сразу после соответствующих дескрипторов <script> использовать дескрипторы <noscript>. Тогда пользователь сразу увидит, где и что пропущено. При этом комментарии HTML, которые использовались ранее с целью скрыть сценарий от браузеров старых версий, в данном случае использовать не нужно. Их наличие в дескрипторе <noscript> не позво- лит нормально обработать код HTML. Браузеры других типов Приступая к изучению принципов создания сценариев, необходимо знать, как написать та- кой сценарий, который бы определял, включен или выключен в браузере режим поддержки JavaScript. Разработчики пытаются составлять такие сценарии, которые могли бы работать в са- мых разных ситуациях и программных средах. Поэтому сложно представить, что поддержи- вающий JavaScript браузер не может выполнить сценарий: если в браузере нет интерпретатора JavaScript (или он отключен), то сценарий игнорируется. Существуют, тем не менее, методы оп- ределения поддержки Java в JavaScript (например, метод navigator. j avaEnabled ()), ко- торые вселяют определенную надежду. Однако логически представить такое довольно сложно. Зачастую пользователям требуется заменить содержимое документа кодом JavaScript при включенном в браузере режиме поддержки JavaScript. Однако только в IE4+ и NN6+ сцена- рий может заменять стандартный код HTML своим содержимым. Если разрабатываемый про- граммный продукт должен быть совместимым с ранними версиями браузеров, то помните, что весь код HTML в документе используется для отображения страницы, в то время как сце- нарий является лишь дополнительным средством управления. Сценарии могут использоваться для того, чтобы создавать необычные эффекты при отобра- жении различных ссылок и (будьте осторожны) основного текста. Этот метод применим как при управлении браузерами, поддерживающими сценарии, так и теми, которые сценарии не выпол- няют. В листинге 13.2 показан небольшой документ, в котором символы комментария HTML использованы для предоставления возможности не поддерживающим сценарии браузерам ото- бражать ссылку на Web-узел Netscape и две строки текста. Если браузер знает, как работать со сценариями, то он узнает дескрипторы <а> и </а> и выполнит операторы, включенные в них. В последнем случае ссылка на узел Netscape на странице не появится, но зато отобразится ссылка на другой Web-узел. Что касается фрагмента основного текста HTML, то сценарий Глава 13. Основы JavaScript 183
окрашивает его в тот же цвет, что и фон документа. Пока цветной текст скрыт в браузере, выполняющем сценарии (равно как и другой текст, сохраненный в документе), пользователь его не увидит. Многим приверженцам HTML такое поведение может не понравиться, по- скольку оно противоречит самим принципам HTML. Однако выглядит это довольно забавно. <html> <head> > <title>«/title> </head> <body bgcolor="#FFFFFF"> <a href="http://www.microsoft.com"> «script type="text/javascript"> document.writein("<a href=1 http://www.dannyg.com>") //--> </script> Where?«/a> <hr /> «script type="text/javascript"> < 1 - - document.write("Howdy from the script!<font color='#FFFFFF'>") //-> </script>If you can read this, JavaScript is not available. «script type="text/javascript"> <! - - document.write("«\/font>") //--> «/scriptxbr /> Другие операторы «/body> </html> Написание сценариев для разных браузеров Проблему совместимости с разными типами браузеров можно решать по-разному. Все зави- сит от конкретных целей и используемых типов браузеров. Можно использовать специальные ссылки на страницы со сценариями для поддерживающих сценарии браузеров. Также вы вправе применять для разных классов браузеров различные части приложения. При желании можно реализовать промежуточный вариант. Первым шагом в решении этой проблемы всегда является определение приоритетности браузеров, которыми пользуются посетители ваших Web-страниц. Определение приоритетов Если общая схема разрабатываемого приложения уже вырисовывается, можно заняться определением, браузеры каких классов мотуг полностью реализовать все основные возмож- ности этого приложения. Например, если на странице проводится предварительная загрузка изображений для ролловеров, то последние доступны только в браузерах NN3+ и IE4+. При использовании возможностей динамического HTML (например, перемещении элементов или динамическом изменении содержимого) по причине различий в объектных моделях докумен- тов в NN4, IE4+ и поддерживающих стандарт W3C DOM браузерах Mozilla, ГЕ5+ и Safari об- ращайтесь к разным принципам организации сценариев. 184 Часть III. Объекты документа
В идеальном сценарии рекомендуется сделать оценку особенностей всех тех браузеров, ко- торые используются посетителями страницы. Например, если нужно задействовать возможно- сти DHTML, а пользователи с браузерами NN4 составляют только незначительную часть всей аудитории, то можно создавать сценарий, ориентируясь на объектные модели документов W3C DOM и IE4+. Советуем просто “махнуть рукой” на остальную аудиторию и использовать DHTML, ориентируясь исключительно на пользователей с браузерами, поддерживающими стандарт W3C DOM. Если задействованные Web-службы регистрируют посетителей страницы, то с помощью такой статистики легко узнать, браузеры каких типов используют посетители узла. Когда основной класс используемых браузеров будет определен, решите, что же делать с теми пользователями, браузеры которых не соответствуют минимальным требованиям для посещения страницы. Например, если узел или страница полностью рассчитаны на использование совмести- мых со стандартом W3C DOM браузеров, то можно предусмотреть специальный способ выхода со страницы для пользователей с более старыми браузерами. Для этих целей используется наибо- лее простой формат представления данных, который поддерживает любой браузер от Lynx до IE4 и NN4. Специально для пользователей с браузерами старых типов можно предложить аль- тернативный упрощенный вариант страницы, управлять которой можно и в этих браузерах. Создание сценария или узла, в котором будет использоваться несколько способов отображе- ния одного и того же содержимого, кажется достаточно простой задачей. На самом деле она требует серьезной и кропотливой работы. Чтобы реализовать подобную задачу и потом под- держивать функциональность такого узла, потребуется время и средства. Опыт подсказывает: какими бы благими ни были намерения дизайнера нового Web-узла, ему все же следует знать, что поддерживать ; функциональность этого узла намного сложнее, чем создавать его. Использование страниц ветвления Если принято решение использовать для просмотра страницы несколько путей (в зависи- мости от типа используемого пользователем браузера), то разумнее всего в этом случае соз- дать загружаемую по умолчанию страницу ветвления. Для того чтобы направить посетителя по нужному пути, существуют различные приемы. Проще всего переложить ответственность за выбор правильного маршрута просмотра со- держимого узла непосредственно на пользователя. В этом случае используются специальные кнопки или ссылки с указанием того, какие требования предъявляются к браузерам для каж- дого конкретного случая. Такой вариант приемлем для опытных пользователей, разбираю- щихся в HTML и современных типах браузеров. Проблема, однако, состоит в том, что на се- годня большинство пользователей, работающих с Web, понятия не имеют об уровне поддержки их браузерами HTML и о том, поддерживают ли их браузеры JavaScript. Поэтому для разработчика такой страницы важно автоматизировать процесс выбора пути следования посетителя, насколько это возможно. В индексных страницах ветвления ничего особенного нет. Это не начальная страница, ко- торую можно просматривать, а, скорее, шлюз к нужному Web-узлу. В задачи такой страницы входит перераспределение потока пользователей — все они должна иметь возможность ока- заться на начальной странице узла. В листинге 13.3 показано, как выглядит код для такой ин- дексной страницы ветвления. Чтйнг 13.3. Индексная страница ветвления <html> <head> <title>GiantCo On The Web</title> «script type="text/javascript"> window.location = "homel.html" Глава 13. Основы JavaScript 185
п-> </script> <meta http-equiv="REFRESH" content= URL=http://www.giantco.com/home2.html"> </head> <body> <center> <a href="home2.html"ximg src="images/giantcoLogo.gif" height="60" width="120" border="0" alt="Go To GiantCo Home Page" /></a> </center> </body> </html> Обратите внимание, что отображаться на странице будет только рисунок, который в лис- тинге заключен в дескриптор стандартной ссылки. В дескрипторе <body> тоже не содержит- ся ничего специфического. Единственный оператор сценария размещается в блоке заголовка. Дескриптор <meta> в этом же блоке используется для того, чтобы автоматизировать процесс навигации для пользователей. Чтобы выяснить, что же будет происходить при использовании этой страницы различными типами браузеров, последние следует разделить на три группы. 1. Браузеры, поддерживающие JavaScript. Несмотря на то, что вся страница целиком может загружаться за считанные секунды (может промелькнуть отображение логотипа компании), это еще не значит, что у браузера при этом мало работы. Он выполняет операторы сценария и загружает в окно документ homel. html. В то же самое время в кэш-память браузера загружается изображение. Это изображение впоследствии бу- дет неоднократно использоваться в документе homel .html, поэтому, с точки зрения оптимизации процесса, все выполняется нормально. Если для управления страницей нужны браузеры только определенных типов или версий, то следует отфильтровать те из них, которые не соответствуют таким требованиям (в которые может потребоваться установка некоторых специальных компонентов). Для того чтобы написать сценарий проверки браузеров, можно воспользоваться соответствующими свойствами объекта navigator (глава 38 на прилагаемом к книге компакт-диске). Тогда те браузеры, ко- торые удовлетворяют минимальным необходимым характеристикам для работы со страницей, смогут перейти к ней, а работа с остальными браузерами будет продолжена на следующем этапе выполнения сценария. 2. Современные браузеры с отключенным или отсутствующим режимом поддержки JavaScript. Некоторые современные браузеры распознают специальный формат деск- риптора <meta> как такой, который используется для загрузки URL в текущее окно через указанный интервал времени (в секундах). В приведенном выше листинге 13.3 такой интервал равен нулю. Операторы дескрипторов <meta> выполняются только в том случае, если будут проигнорированы дескрипторы сценария <script>. Поэто- му любой браузер, у которого отключен режим поддержки JavaScript, или браузер, распознающий дескрипторы <meta>, последует инструкциям команды обновления, размещенной в этом дескрипторе. Если такой дескриптор на странице используется, следует быть предельно аккуратным с настройками атрибута contents После указа- ния длительности интервала в секундах вводится точка с запятой и дополнительный атрибут URL. В этом атрибуте задается полная ссыпка на адрес URL начальной стра- ницы, в которой сценарии не используются. Помните также, что значение атрибута content должно быть заключено в кавычки. 186 Часть III. Объекты документа
3. Старые графические браузеры, браузеры PDA и Lynx. В последнюю группу входят графические браузеры, которые еще иногда называют “примитивными”, а также ряд устаревших браузеров. Lynx, например, рассчитан на работу только с текстовым тер- миналом VT-100. Такие средства персональной цифровой поддержки PDA (Personal Digital Assistant), как компьютеры серии Palm, оснащены браузерами, рассчитанными на работу с низкоскоростными модемами и небольшими экранами. Если такой браузер не распознает дескриптор <meta> и поэтому не обновляет содержимое страницы, то в этом месте процесс получения доступа к странице для такого браузера будет остановлен. Но поскольку на странице есть изображение, которое используется в качестве ссылки, то пользователь, скорее всего, щелкнет на нем. Таким образом можно перейти к начальной странице, в которой сценарии не используются. Кроме того, следует учесть, что изобра- жение имеет атрибут alt. Браузеры Lynx и PDA (изображения не загружают) отобра- жают текст из описания атрибута alt вместо самого изображения. Пользователи мо- гут, щелкнув на этом тексте, перейти к адресу, указанному в ссылке URL дескриптора. Цвет фона страницы ветвления выставлен по умолчанию не случайно. Если маршрутиза- ция выполняется автоматически и пользователь сразу переходит к начальной странице, то фон страницы меняется от используемого по умолчанию в браузере на фон начальной стра- ницы. Это приводит к неприятному мерцанию экрана. Оставив же на странице ветвления только логотип компании, можно частично решить эту проблему. Одна ссылка - разные страницы Еще один способ фильтрации может быть реализован непосредственно с помощью ссы- лок. Во всех браузерах, за исключением NN2 и ГЕЗ, задание ссылки на другой ресурс (если брау- зер поддерживает сценарии) может выполняться в обработчике события one lick или (если браузер не выполняет сценарии) проводиться в атрибуте href. • Особенность заключается в том, чтобы использовать в обработчике события one lick еще один дополнительный оператор return false. Этот оператор отменяет действие ат- рибута href. Например, если процесс нужно организовать так, чтобы не поддерживающий сценарии браузер при использовании ссылки переходил к одному варианту страницы, а под- держивающий сценарии — к другому, то соответствующий дескриптор ссылки будет выгля- деть следующим образом. <а href="nonJSCatalog.html" onclick="location.href= 1JSCatalog.htmlreturn false">Product Catalog</a> Теперь только те браузеры, которые не поддерживают сценарии, а также NN2 и ГЕЗ, будут переходить к странице nonJSCatalog.html, в то время как остальные— к странице JSCatalog. html. Определение объектов Последний способ перенаправления посетителя в зависимости от типа используемого брау- зера известен под названием детектирование объектов. Принцип прост: если данный тип объекта существует в объектной модели браузера, то сценарий для этого объекта можно выполнять. Возможно, самым удачным примером такого детектирования является сценарий, который выполняет предварительную загрузку изображений на странице при работе с новыми браузе- рами и не делает этого при использовании старых браузеров, которые не интерпретируют изображения как объекты. В этих случаях обычно обработчики событий onmouseover и onmouseout (для обеспечения совместимости), задаваемые в ссылке, вызывают функцию, которая изменяет у соответствующего изображения значение свойства src. Все такие функции могут вызываться любым поддерживающим сценарии браузером. В данном случае нужно, что- бы операторы функции выполнялись только тогда, когда изображения трактуются как объекты. Глава 13. Основы JavaScript 187
В объектных моделях, которые представляют изображения в качестве объектов, эти изо- бражения упорядочены в виде массива, который включен в объект документа document. Массив document. images существует всегда, даже когда у него нулевая длина, что соот- ветствует случаю, когда на странице рисунки не используются. Поэтому, если операторы для предварительной загрузки изображений вставить в условную конструкцию if, которая по- зволит их выполнять только при наличии массива document. images, то браузеры старых версий просто пропустят эту последовательность команд. function imageSwap(imgName, url) { if (document.images) { document.images[imgName].src = url; } Детектирование объектов рекомендуется проводить в тех случаях, когда наперед извест- но, как данный объект трактуется браузерами разных типов. В сйучае с document. images трактовка объектов изображений в разных браузерах практически идентична. Поэтому в дан- ном примере можно уверенно использовать метод детектирования объектов в качестве усло- вия ветвления. Однако такая ситуация имеет место далеко не всегда, и описанный метод сле- дует использовать с большой осторожностью. Например, в IE4 существует массив объекта документа document, который называется document. all. Он часто используется в ссыл- ках на элементы объектов HTML. Но в NN4 этот массив не используется, а вместо него за- действован массив слоев документа в иерархической структуре объектов — layers. Этот массив, в свою очередь, не используется в П34. К сожалению, многие авторы сценариев вы- полняют проверку наличия этих массивов для определения типа браузера. В данном случае тип браузера определяется по достаточно нестабильной характеристике. Это очень нежела- тельно, поскольку неизвестно, будут ли будущие версии браузеров разных типов иметь по- добные различия, или эти различия в них будут нивелированы. К примеру, Opera полностью поддерживает массив document.all. В результате при загрузке старых страниц браузер будет трактоваться как Internet Explorer, а это ни к чему хорошему привести не может. Поэтому детектирование объектов лучше проводить не с целью определения версий брау- зеров, а, скорее, для определения методов обработки тех или иных объектов, как это делалось в примере с изображениями. Более того, безопасным применение метода детектирования объектов будет только в том случае, когда браузеры всех основных типов (а также стандарт W3C DOM) поддерживают используемый объект. В этом случае можно не опасаться, что в будущем страница не будет работать с браузерами новых версий. К детектированию объектов относят и проверку доступности методов объектов. Ссылка на метод объекта возвращает значение, поэтому такая ссылка может быть использована в условном операторе. Например, приведенный ниже фрагмент кода показывает, как функции передается аргумент, состоящий из строчного идентификатора элемента, который она преобразует в ссылку на объект (в зависимости от использования одного из трех типов объектных моделей документа). function myFunc(elemlD) { var obj; if (document.getElementByld) { obj = document.getElementByld(elemlD); } else if (document.all) { obj = document.all(elemlD); } else if (document.layers) { obj = document.layers[elemlD]; } if (obj) { // операторы управления объектом } 1 188 Часть III. Объекты документа
В данном случае не имеет значения, какой способ преобразования идентификатора эле- мента в ссылку на объект используется в определенной версии браузера и операционной сис- теме. Для выполнения преобразования будет использован тот метод или свойство объекта document, который поддерживается браузером. Если браузер поддерживает больше одного свойства, то использовано будет первое доступное из приведенного выше перечня. Если браузер не поддерживает вообще ни одного свойства, то и выполняться ничего не будет. Если в сценарии выполняется проверка наличия того или иного свойства объекта, то разум- но предварительно проверить, используется ли в браузере такой объект вообще. Подобная про- верка выполняется в том случае, если заранее известно, что данный объект используется не во всех объектных моделях браузеров. Если в условном операторе будет сделана попытка со- слаться на свойство или метод несуществующего объекта, это приведет к ошибке выполнения сценария. Чтобы избежать этого, можно каскадно объединить операторы проверки несколь- ких условий, для чего используется оператор &&. В приведенном ниже фрагменте кода проверя- ется наличие как объекта document. body, так и его свойства document. body. style. if (document.body && document.body.style) { // Операторы для работы co свойством style объекта body } В данном случае если объект document. body не существует, то JavaScript второе усло- вие проверять не станет. При использовании условных операторов для проверки существования свойства объекта вы столкнетесь с одним “но”. Проблема заключается в следующем: если свойство существу- ет, но его значение равно нулю или пустой строке, то это будет интерпретироваться в услов- ном операторе как отсутствие свойства. Чтобы избавиться от этой неприятности, в условном операторе нужно проверить еще и тип возвращаемых данных. В том случае, если такого свойства не существует, типом возвращаемых данных является undefined (неопределенный). Для проверки типа данных используется оператор typeof (глава 32). if (document.doby && typeof document.body.scroll != "undefined") { // Операторы для работы co свойством style объекта body } За детектированием объектов — будущее программирования, поэтому этот прием можно с успехом использовать в сценариях. Методы использования программируемых характери- стик в браузерах постоянно расширяются и используется в разных вычислительных приложе- ниях. Нет уверенности в том, что в будущем новые классы и версии браузеров будут так же успешно работать со сценариями, как это делают современные браузеры. Если в сценарии процессы обработки данных организованы на основе проверки функциональных возможно- стей используемого браузера, то в будущем это избавит от серьезных проблем с совместимо- стью. В главах 47 и 56, приведенных на прилагаемом к книге компакт-диске, вопросы детек- тирования объектов рассмотрены более детально. Обеспечение совместимости Каждое новое поколение браузеров имеет новые проблемы совместимости. Старые сцена- рии будут работать в браузерах новых типов. Хорошо написанный сценарий редко дает сбои при переходе на новую версию браузера. Исключением является, пожалуй, только ситуация с переходом от NN4 к новому программному ядру Mozilla. Но проблемы начинаются не здесь. Все дело в том, что разработчиков быстро привлекают новые возможности браузеров последних версий. При этом они не всегда принимают во внимание, что пользователи далеко не сразу пе- реходят к использованию браузеров новых версий и типов, а продолжают пользоваться стары- ми. В этих старых браузерах такие дополнительные свойства не доступны. Это нужно помнить. Также следует напомнить о всевозможных недоработках в браузерах “первой волны”. Глава 13. Основы JavaScript 189
Можно, конечно, ориентироваться на использование только тех характеристик, которые будут доступны самому широкому кругу пользователей. Однако для этого придется удвоить свои усилия и погрязнуть в море рутинной работы. Поэтому придется выбирать между функ- циональностью страницы и ее общедоступностью. Если есть желание задействовать какие-то свойства, которые доступны только в браузерах последних версий, значит, пользователей с браузерами более старого образца придется отсеивать и направлять к более простой версии страницы, с которой они смогут работать. Еще один подход состоит в том, чтобы сделать часть страницы доступной для многих (если не для всех типов браузеров), а затем, по мере дальнейшего перемещения “в дебри” страницы, отсеивать тех пользователей, которые работают с более старыми типами браузе- ров. В этом случае положительным моментом является то, что практически все пользователи смогут в определенных рамках работать со страницей, а для тех из них, кто использует брау- зеры, скажем, стандарта W3C DOM, она засияет новыми красками. Идеальной страницей считается такая, которая содержит полезную информацию и ото- бражается всеми без исключения браузерами, а также предлагает наиболее совершенные средства навигации и интерактивное содержимое. Сделать подобную страницу весьма сложно. Но даже если это удастся в каком-то конкретном случае, следует продумать способы сортировки пользователей по типам используемых браузеров и заняться поддержкой путей ветвления. Независимо от того, насколько разные технологи используются в браузерах, со временем количество потенциально возможных проблем постепенно уменьшится. Выработанные за про- шедшие годы стандарты прошли успешную “обкатку”, а потому разработчики окончательно опре- делились с теми спецификациями, которые стоит включать в свои программы или которые лучше избегать. Более того, большинство пользователей спешит воспользоваться последними версиями браузеров, а потому поддержка старых программ становится не столь актуальным занятием. Использование экспериментальных версий браузеров Иногда так случается, что при использовании экспериментальных версий браузеров (так называемых бета-версий) в работе с уже опробованными Web-страницами или узлами возни- кают ошибки при выполнении сценариев или другие проблемы, связанные с совместимостью. Скорее всего, это является следствием недоработок в браузере. Если сценарий написан ipa- мотно, он должен работать и с последующими поколениями браузеров. Если код не работает корректно, следует что-то делать с браузером. Разработчику данного браузера нужно сооб- щить об имеющихся недостатках, при этом желательно привести в качестве примера упро- щенный код, при управлении которым возникает ошибка. Исключением из правила, когда причиной несовместимости являются не недоделки брау- зера, а сценарий, может быть конфликт версий NN4 и NN6. Как отмечается в главе 14, созна- тельные попытки убрать одно из средств NN4 (объект, соответствующий дескриптору < layer >) привели к тому, что в бета-версии NN6 (и в конечной версии тоже) многие сцена- рии, написанные для NN4, перестали выполняться. Взаимодействие авторов страниц с разра- ботчиками браузеров (особенно новых, вроде Mozilla) является взаимовыгодным; оно позво- ляет изучить политику компании-производителя и учесть возможные ее изменения. Ситуация, при которой в новых браузерах резко отбрасываются какие-то часто используемые средства, крайне маловероятна, но все же возможна. И это следует учесть. Зачастую сложно бывает удержать себя от соблазна идти в ногу с разработчиками новых версий браузеров. Только не следует при этом забывать, что бета-версия — это еще не конечная версия браузера. Если пользователи бета-версий браузеров при посещении страницы получают сообщения об ошибках, то их причиной, скорее всего, являются недоделки в программе браузера. 190 Часть III. Объекты документа1
Это не вина разработчика страницы. Однако и закрывать на это глаза не стоит. В такой ситуа- ции следует связаться с компанией-разработчиком и выяснить, будет ли конечная версия браузера выдавать ту же ошибку, или эта недоработка в бета-версии будет устранена. Проблемы с браузерами Internet Explorer Как будет подробно рассказано в главе 38 при описании объекта navigator, в сценарии до- ‘ вольно просто определить тип используемого браузера. Но, несмотря на это, реальная кар- [ тинв положения дел с Internet Explorer далеко не ограничивается различием версий. В главе 38 показано, что при использовании свойства navigator .appversion в IE5 для j Windows возвращаемое значение соответствует четвертой версии (т.е. точно то же, что ив1Е4). До истины, тем не менее, можно докопаться (свойством navigator.userAgent возвращается значение msie 5), но сам этот процесс далеко не так прост, как должен быть, — особенно если требуется определить последующие версии, а не только пятую. Советуем не терять бдительность, следить за появлением новых версий браузеров и использовать мето- ды детектирования объектов. Приложение The Evaluator Sr. В главе 6 в несколько упрощенном варианте было описано приложение The Evaluator Jr., которое позволяет в интерактивном режиме проводить вычисление выражений и проверку объектов. В дальнейшем при изучении базового языка JavaScript и терминологии DOM это приложение будет использоваться часто, поэтому с ним стоит познакомиться поближе. По сравнению с версией, которая описывалась в главе 6, полная версия имеет два важных отличия (рис. 13.1). Рис. 13.1. Приложение The Evaluator St. Глава 13. Основы JavaScript 191
Во-первых, если в браузере включен режим Code Base Principles и выбрана опция (только в NN4+) Use Code Base Security, то можно проверить некоторые свойства безопасно- сти Netscape. Во-вторых, на странице установлено несколько элементов HTML, которые ис- пользуются для исследования свойств и методов модели DOM. Как и в упрощенной версии при- ложения, в данном случае инициализировано 26 глобальных переменных (символы от а до z), которым можно присваивать значения и использовать во всевозможных выражениях. Для использования этого приложения нужно скопировать файл evaluator. html с компакт- диска на жесткий диск и добавить на него соответствующую закладку во всех используемых брау- зерах. Если необходимо, на странице приложения добавьте дополнительные элементы. Принци- пы использования приложения The Evaluator в качестве средства отладки описаны в главе 45. Принципы совместимости При создании программного продукта важно знать, какие особенности языка, объектной модели, свойства, методы и обработчики событий доступны в той или иной версии браузеров. В дальнейшем для указания совместимости (или несовместимости) будут использоваться специальные обозначения. Совместимость: WinIE5+, MacIE5+, NN4, Mozl.01+, Safari Знак “плюс” после названия браузера указывает на то, что данный элемент языка впервые был реализован в указанной версии и продолжает поддерживаться в последующих версиях. Знак “минус”, наоборот, указывает на отсутствие под держки в браузере текущей возможно- сти. Мы тестировали сценарии в таких браузерах, как Internet Explorer (для Windows и Мас), Netscape Navigator, Mozilla (включая браузеры на его основе) и Apple Safari. Хорошо было бы, распечатать справочное руководство по JavaScript и объектам браузеров. Соответствующий файл в формате Adobe Acrobat находится в папке приложения А на компакт-диске. В этом руководстве четко указаны все свойства объектов, их методы, обработчики событий и ключи с указанием того, какие свойства в каких типах браузеров поддерживаются. Данное пособие может стать отличным настольным справочником. Особеннрсти языка JavaScript Этот раздел адресован опытным JavaScript-программистам. Новичкам и тем, кто не рабо- тал со сценариями, многое может быть непонятно. Данные раздел также предназначен тем, кому часть II показалась слишком легкой. Ниже кратко описаны наиболее современные сред- ства языка JavaScript. Язык написания сценариев JavaScript. Язык используется в среде поддержки узлов (пример — Web-браузер), отображающей объекты, свойства и поведение которых мо- гут управляться с помощью операторов, написанных на этом языке. Сценарии выпол- няются в контексте среды. Среда поддержки узлов управляет тем, как задаются ссылки на внешние объекты (в результате выполнения операторов языка). В целях соблюде- ния прав интеллектуальной собственности и для поддержки необходимого уровня безопасности Web-браузеры, как правило, не предоставляют прямой (или обеспечива- ют ограниченный) доступ JavaScript к настройкам браузера, операционной системы- или внешних программ, запускаемых вне браузера. Исключением из этого правила яв-1 ляются самые последние браузеры, предоставляющие клиенту более полный доступ (с разрешения пользователя) с помощью механизма доверительных отношений— защи-, щенных сценариев (Netscape Navigator) или элементов управления ActiveX (Windows). 192 Часть III. Объекты документа
JavaScript — язык объектный. Хотя между JavaScript и Java с точки зрения синтак- сиса много общего, JavaScript не настолько объектно-ориентирован, как Java. Базовый язык включает в себя несколько встроенных статических объектов, с помощью кото- рых генерируются все рабочие объекты. Объекты создаются путем вызова функции- конструктора встроенного объекта и оператора new. Например, чтобы сгенерировать объект String и получить ссылку на этот объект, нужно сделать следующее. new String("Hello") В табл. 13.1 приведен список встроенных объектов, с которыми взаимодействуют сценарии. lr ЖВГ . ЙИн» . йЦГкД, leW-Vrt -те— н—------------------ . -........... - • Е Array1 Boolean Date Error2 Eval Error2 Function1 Math Number1 Ob j ect1 RangeError2 ReferenceError2 RegExp3 String1 SyntaxError2 TypeError2 URIError2 1 — несмотря на то, что объекты и определены в первом стандарте ЕСМА, они стали доступны, только начиная с NN3 и IE3/J2; 2 — определяются в ЕСМА 3, реализованы в Mozl; 3 — определяются в ЕСМА 3, полностью реализованы в NN4 и IE6. Свободное определение типов. Тип данных, которые возвращают переменные, мас- сивы и функции, в JavaScript не предопределяются. Фактически, одна и та же инициа- лизированная переменная может в разных операторах сценария содержать данные са- мых разных типов (не всегда это хорошо, но всегда возможно). Аналогично массив может содержать значения разных типов. Диапазон встроенных типов данных перво- начально ограничен таким набором: • Boolean (значения true или false); • Null; • Number (64-битовые значения двойной точности в формате IEEE 734); • Ob j ect (включая и объект Array); • String; • Undefined. Среда определяет глобальную область. Традиционно браузеры трактуют окно брау- зера или фрейм как глобальную область задания операторов сценария. При выгрузке документа все глобальные переменные, определяемые в документе, уничтожаются. Глобальные и локальные переменные. Глобальные переменные в Web-браузере обычно декларируются с использованием оператора var, выполняемого при загрузке документа. Такие глобальные переменные доступны для чтения и использования в лю- бом месте документа. Локальные переменные определяются внутри функций (также с использованием оператора var). Однако доступ к этим переменным можно получить только в рамках данной функции. Доступ к свойствам и методам статических объектов JavaScript. Некоторые стати- ческие объекты позволяют получать прямой доступ к их свойствам и методам. Например, Глава 13. Основы JavaScript 193
все свойства объекта Math используются как математические константы (число п оп- ределяется так: Math. PI). Добавление свойств и методов. Д ля того чтобы добавить объекту свойство, ему сле- дует присвоить значение любого типа. Например, чтобы добавить свойство author строчному объекту myText, можно использовать такую команду. myText.author = "Jane"; Если свойству объекта присвоить ссылку на функцию, то таким образом будет опреде- лен новый метод этого объекта. // Описание функции function doSpecial(argl) { // Операторы } / / Задание ссылки на функцию по названию метода myObj.handlespecial = doSpecial; // Вызов метода myObj.handlespecial(argValUe); Внутри самой функции ключевое слово this используется для ссылки на объект, ко- торому принадлежит метод. Объекты наследуют прототипы. Все конструкторы объектов создают рабочие объек- ты, свойства и методы которых наследуют свойства и методы, определенные в про- тотипе этого объекта. Начиная с NN3 и IE3, в сценариях можно добавлять и удалять некоторые свойства и/или методы, связанные с прототипом статического объекта. Но- вый рабочий объект наследует свойства текущего прототипа. В сценариях можно сво- бодно переопределять значения свойств прототипа или присваивать различные функ- ции в качестве методов прототипа. Если даже наследованное свойство или метод в текущем рабочем объекте не меняются, то изменения, внесенные в прототип стати- ческого объекта, отразятся и на рабочем объекте. (Принцип, согласно которому реали- зуются ссылки на свойства объекта, состоит в том, что путь к свойству определяется через совпадение имен свойств в наследованном прототипе.) Большое количество операторов. В JavaScript представлены практически все опера- торы, которые есть в других языках. Управляющие структуры. Во всех версиях JavaScript есть такие конструкции, как if, if-else, for и while. В JavaScript 1.3 (NN4+ и IE4+), кроме прочего, использу- ется еще и конструкции do-while и switch. В таких итерационных структурах управления процессом выполнения операторов предусмотрено использование опера- торов break и continue. Функции могут возвращать, а могут и не возвращать значение. В JavaScript есть толь- ко один тип функций. Значение функцией возвращается только в том случае, если в ее со- ставе есть ключевое слово return, после которого следует значение, которое должно быть возвращено в качестве результата. Возвращаемые значения могут быть любого типа. Функции нельзя перезагружать. Функции JavaScript, в зависимости от числа опре- деленных переменных-параметров, могут или использовать аргументы, или не исполь- зовать их вообще. Все аргументы автоматически записываются в массив arguments, который является свойством объекта функции. Данные переменных-параметров не предопределяются. Значения присваиваются “по ссылке” и “по значению”. Функции может передавать- ся ссылка на объект, предоставляя при этом полный доступ к свойствам и методам 194 Часть III. Объекты документа
объекта, для чтения и записи. Но значения других типов (включая и свойства объекта) могут передаваться по значению, не используя никаких ссылок на объекты. В приведенном ни- же примере выполняется очистка текстового поля при обработке события onchange. function ernptyMe (argl) { argl.value = ""; } cinput type="text" value="Howdy" onchange="ernptyMe(this)"> В следующем примере ничего не происходит. function ernptyMe (argl) { argl = ""; } cinput type="text" value="Howdy" onchange="ernptyMe(this.value)"> Локальная переменная (argl) просто заменяет значение с "Howdy" на пустую строку. Способ обработки ошибок зависит от используемой версии JavaScript В браузерах NN2 и ТЕЗ способы отслеживания ошибок не предусмотрены. Отслеживание ошибок в NN3, NN4 и IE4 выполняется в рамках объектной модели Web-браузера. JavaScript, ис- пользуемый в IE5, Mozl и Safari имеет операторы try-catch и throw, а также встро- енные объекты для обработки ошибок, которые являются независимыми от среды. Управлять памятью с помощью сценариев нельзя. Среда управляет распределени- ем памяти. Разные браузеры делают это по-разному. Пробелы во внимание не принимаются. Пробелы и символы табуляции можно ис- пользовать для разделения лексических единиц (ключевых слов, идентификаторов и т.д.). Символ окончания строки обычно трактуется как разделитель операторов. За очень редким исключением, JavaScript автоматически при синтаксическом анализе вставляет точку с запятой (используется для разделения операторов) в местах с символа- ми окончания строки (например, символы возврата каретки и разрыва строк). Раздели- тель в виде точки с запятой используют между двумя операторами в одной строке исход- ного кода. Далее символы, используемые в строках, не должны содержать символов возврата каретки (но символ перехода на новую строку (\п) использоваться может). Вперед, к объектным моделям. документов! При работе с Web-страницами базовый язык является только маленькой частью того, что нужно знать. Также вы должны знать и понимать принципы организации объектных моделей документа в браузерах разных типов. Этому будет посвящена следующая глава. Глава 13. Основы JavaScript 195
Основы объектной модели документа не всяких сомнений, в короткой истории развития браузеров, поддерживающих сценарии, самым захва- тывающим-и запутанным процессом является эволюция объект- ных моделей документов. Первая такая модель была предло- жена в браузере NN2. С того времени и вплоть до разработки четвертого поколения браузеров исходная объектная модель приобрела много новых характеристик, общих для браузеров разных типов, а также ряд средств, которые являются просто уникальными с точки зрения первых браузеров как Netscape Navigator, так и Internet Explorer. По сравнению с исходными объектными моделями, в последующие их версии постоянно вносились новые изменения, что добавило головной боли разработчикам страниц— ведь сценарии нужно составлять так, чтобы они могли использоваться в самых разных типах браузеров. Свет в конце туннеля появился, когда консорциум World Wide Web Consortium (W3C) приступил к разработке стандарта объектной модели документа (DOM— Document Object Model). Новые подходы позволили по-новому взгля- нуть на проблему. В стандарте предусмотрены альтернатив- ные способы адресации к объектам документа. В этой главе описываются различные объектные модели. Бу- дут проанализированы перспективы их использования, а также преимущества и недостатки их использования для создания Web-приложений. Но перед тем, как приступить к изучению специфических аспектов объектных моделей, рассмотрим ту роль, которую объектные модели играют при создании сце- нариев и приложений. Иерархическая структура объектной модели В руководстве по основам программирования в части П из- ложены основные идеи, определяющие в поддерживающих сце- нарии браузерах иерархию объектов документа. В других про- граммных средах, по сравнению с использующими JavaScript
браузерами, такая иерархия имеет более важное значение. В JavaScript, например, нет ника- кой необходимости при написании сценария знать, что такое классы, наследование и экземп- ляры объектов. Тем не менее, полностью игнорировать иерархическую организацию элемен- тов ие получится, поскольку в сценарии как минимум нужно будет использовать ссылки на объекты. А для этого необходимо знать, как они соотносятся друг с другом. Упомянутые объекты не являются объектами JavaScript в полном смысле этого слова. Это са- мые настоящие объекты браузера: для того, чтобы их запрограммировать, используется JavaScript. Однако те создатели сценариев, которые для решения тех же задач и программирования объек- тов документа привлекает браузеры Microsoft Internet Explorer, могут также использовать и язык VBScript. Формально JavaScript по отношению к документу является внешним средст- вом, используемым для обработки данных разных типов и прочих объектов. Поэтому следует четко понимать, что между документом и базовым языком есть принципиальная разница. Это важно для анализа задач, связанных с совместимостью разных типов браузеров. Иерархия и структурная схема объектов Программист должен знать иерархическую структуру организации объектов в первую очередь потому, что она применяется в сценарии при задании ссылок на объекты, содержа- щиеся в окне браузера. Такая иерархическая структура играет роль схемы, следуя которой сценарий точно определяет нужный объект. Рассмотрим такой пример. Два друга — Петров и Васечкин — находятся в классной ком- нате. Полуденное солнце уже находится с западной стороны, и в комнате начинает припекать. Петров просит Васечкина: “Открой, пожалуйста, окно”, — указывая при этом на то окно, ко- торое нужно открыть. Если провести параллель с программированием, то это будет анало- гично команде объекту (независимо от того, откроет Васечкин окно или нет). По сравнению с программированием, такой пример человеческого общения имеет много преимуществ. Во- первых, еще до того, как Петров высказал свою просьбу, уже по его взгляду Васечкин смог бы догадаться, что его о чем-то попросят. Во-вторых, язык жестов является достаточно крас- норечивым для того, чтобы безошибочно и однозначно указать на нужное окно. Если теперь представить, что директор школы из своего кабинета по общешкольной сис- теме оповещения попросит: “Пожалуйста, откройте окно”, то каждый будет думать, что об- ращение направлено не к нему, и окно так и не будет открыто. Если же директор скажет: “Петя Васечкин из 312 комнаты, открой, пожалуйста, среднее окно с западной стороны”, то Васечкин вряд ли посмеет ослушаться. Теперь посмотрим, как описанная процедура выглядела бы в JavaScript (с использованием уже знакомого точечного синтаксиса, описанного в главе 4). Вызов нужного объекта через систему ссылок начинается с самого высокого уровня и затем, проходя последующие уровни в иерархии объектов, производится все более точная локализация объекта. Высшим уровнем является кабинет директора. класс312.Васечкин.Петя Можно также, продолжая аналогию, сказать, что тот запас знаний и навыков, которые по- зволяют Пете открыть окно, является методом Пети. Поэтому полная ссылка на Петю и его метод выглядит так. класс312.Васечкин.Петя.открытьОкно() На этом работа по составлению ссылки еще не завершена. Чтобы использовать метод, ему нужно указать параметры. Эти параметры определяют, какое именно окно следует открыть. В данном случае речь идет о среднем окне с западной стороны класса 312. На языке объект- ных ссылок получим. класс312.западнаяСторона.среднееОкно Глава 14. Основы объектной модели документа 197
Эта ссылка является параметром для метода Пети открытьОкно (). Вся команда цели- ком выглядит так. класс312.Васечкин.Петя.открытьОкно(класс312. западнаяСторона.среднееОкно) Теперь представьте, что нужно отдать такое распоряжение не из кабинета директора, а из резиденции Президента страны. Представляете, какими длиннющими при этом будут ссыл- ки? Полная ссылка на метод Пети открытьОкно О с указанием окна, которое нужно от- крыть, составит не один десяток уровней. Мораль сей басни такова — чем меньше объектов, которыми управляют программы, тем легче задавать на них ссылки. Для клиента JavaScript диапазон возможного расширения про- граммной среды ограничен браузером. Другими словами, любой объект в JavaScript может быть задействован в рамках приложения браузера. За некоторым исключением, в сценариях доступ к аппаратному обеспечению компьютера, операционной системе, другим приложениям, рабочему столу и всем прочим программным средствам за пределами браузера не предоставляется. Структура объектной модели документа На рис. 14.1 показана упрощенная иерархическая структура объектов документа, которая лежит в основе всех поддерживающих сценарии браузеров. Вершиной всей структуры явля- ется объект окна window. Все объекты, которыми можно управлять в JavaScript, располага- ются в окне браузера. В показанной иерархической структуре каждый объект принадлежит определенному ие- рархическому уровню. Объекты, отображенные в одной строке, принадлежат одному иерар- хическому уровню по отношению к объекту window. Связи между объектами показаны в ви- де соединяющих их линий. Объекты на более высоком уровне содержат в себе те объекты, которые расположены ниже и соединены с первыми линиями. Так, объект окна window со- держит в себе объект документа document. В свою очередь, объект документа document содержит объект формы form. Объект формы содержит в себе много различных элементов управления формы, которые также являются объектами. window frame| self top | parent | history | | document"] | location | ] | form | [ anchor | link | text гагатам | password I | submit | Puc. 14.1. Общая схема иерархической структуры объектов Модель, изображенная на рис. 14.1, продемонстрирована с целью обрисовать в общих чертах базовые элементы Web-страницы, для которых пишутся сценарии. В современных типах 198 Часть III. Объекты документа
браузеров используются более сложные иерархические структуры. Однако “фундамент” оста- ется неизменным. Чтобы такая иерархическая объектная модель не казалась чем-то ужасным, следует написать с ее использованием несколько сценариев (в процессе работы с такими мо- делями они станут вполне привычными и понятными). Совсем не обязательно помнить кон- кретные детали (свойства, методы или обработчики событий) каждого объекта. В конце кон- цов, под рукой всегда найдется справочник. Создание объектов в документе Большинство объектов, создаваемых браузером, генерируются, когда документ с кодом HTML загружается в браузер. Похожий код HTML используется для создания в памяти поддер- живающих JavaScript браузеров объектов ссылок, анкеров и элементов ввода данных. Эти объекты размещаются в памяти независимо от того, будут они использоваться в дальнейшем или нет. Единственное отличие в таком коде HTML состоит в том, что дополнительно задействуются некоторые специфические для JavaScript атрибуты. В основном, такие атрибуты используются для организации ответной реакции элементов страницы на действия пользователя. С помощью JavaScript программируется последовательность операций, выполняемых при этом сценарием. Создание объектов также выполняется с помощью специального кода документа HTML. Кроме того, здесь же определяется поведение создаваемых объектов и выполняемые ими задачи. Следует иметь в виду, что объекты создаются согласно очередности их загрузки. Если ис- пользуется многооконная среда, то объекты одного подокна не взаимодействуют с объектами другого подокна до тех пор, пока оба эти подокна не загружены. На этой почве у многих про- граммистов и создателей сценариев для многооконных сред возникают серьезные проблемы (детальнее об этом — в главе 16). Свойства объектов Обычно свойства определяют текущие настройки объекта. Зачастую эти настройки впол- не понятны — например, описывающие состояние элемента управления (активен или нет). Но иногда в них содержится информация более абстрактного характера, например, сведения о действиях или методах предоставляемой формы. Большинство свойств объектов устанавливаются с помощью атрибутов дескрипторов HTML при создании этих объектов. Свойством может быть слово (например имя) или число (например размер). Если в документе HTML некоторые атрибуты не определяются, то брау- зер присваивает этим атрибутам и соответствующим свойствам JavaScript значения, исполь- зуемые по умолчанию. При использовании имен свойств в операторе сценариев следует иметь в виду, что они чув- ствительны к состоянию регистра. Другими словами, имеет значение, строчные или прописные буквы использованы в имени. Таким образом, если в сценарии определено имя bgColor, то вводить его нужно именно так, как оно задано вначале — с учетом прописных и строчных букв. Но при начальной установке свойств атрибутов HTML состояние регистра в имени атрибута во внимание не принимается. С этой точки зрения, описания <body bgColor="white" > H<body bgcolor="white">, устанавливающие значение свойства bgColor, являются эк- вивалентными. Хотя XHTML не выдвигает жестких требований к регистру символов, которыми вводятся дескрипторы и имена переменных, большинство браузеров чувствительны к регистру символов, независимо от того, назначено атрибуту doctype значение HTML или XHTML. У каждого свойства есть свой статус чтения/записи. Некоторые свойства могут только считываться. Другим свойствам можно присваивать еще и новые значения. Например, чтобы Глава 14. Основы объектной модели документа 199
текстовому объекту в качестве значения присвоить новый текст, свойству объекта value присваивается такая строка. document.forms[0]phone.value = "555-1212" Если объект размещен в существующем документе (это значит, что код HTML загружен в документ), то этому объекту можно добавить несколько новых свойств. Поступают так в тех случаях, когда с объектом нужно связать определенные данные, которые будут исполь- зоваться в дальнейшем в сценарии. Для того чтобы добавить объекту новое свойство, доста- точно просто указать его при присвоении значения этому свойству. document.forms[0]phone.delimiter = "-" Каждое такое свойство, добавленное к объекту, будет доступно до тех пор, пока документ загружен в окно, а сценарий не переопределит данный объект. Тем не менее, следует иметь в виду, что при перезагрузке страницы все добавленные к объекту свойства обычно удаляются. Специально для тех, кто имеет опыт в объектно-ориентированном программировании Несмотря на то, что в иерархии приведенной объектной модели прослеживается принцип клас- совой организации, многие традиционные для такого объектно-ориентированного подхода ас- пекты к данной модели неприменимы. Исходная иерархия объектов документа JavaScript является иерархией структуры, а не иерархией наследования. Ни один из объектов, расположенных на более низких ступенях иерархической структуры, не наследует свойства объектов, расположенных на более высоких уровнях. Между объектами в данном случае, в отличие от структур с иерархиче- ским наследованием, сообщения автоматически не передаются. Поэтому задействовать ме- тод объекта окна, отправив последнему сообщение с помощью объекта документа document или формы, не удастся. Все ссылки на объекты придется делать в явном виде. Предопределенные объекты документа генерируются при загрузке кода HTML, содержащего описания этих элементов, в браузер. В браузерах самых первых версий после загрузки доку- мента, изменять многие свойства, методы и обработчики событий не представляется воз- можным. В главе 33 речь пойдет о том, как создать собственные объекты. Однако такие объ- екты на странице определяют только те отображаемые элементы, которые задаются средствами HTML, аплетами Java или другими программными методами. Наследование становится актуальными, как показано далее в этой главе, при использовании 'объектной модели стандарта W3C. В этом стандарте иерархия имеет более общий характер. Такая система взаимосвязи объектов позволяет наряду с HTML использовать и XML. Тем не менее, иерархические структуры объектов HTML, описываемые в данном разделе, могут быть успешно задействованы и в браузерах стандарта W3C DOM. Методы объекта Методом объекта называется команда, которую сценарий дает объекту. Некоторые мето- ды возвращают значение, хотя это и не обязательно. Более того, некоторые объекты вообще не имеют методов. В большинстве случаев вызов в сценарии метода объекта подразумевает выполнение некоторых действий. Иногда такие действия являются вполне конкретными и понятными (например, если изменяется размер окна). Бывает, что выполняются и более за- мысловатые процедуры (как при сортировке в памяти массива). Все методы при указании ссылки на них после своего имени требуют введения скобок; в ссылках они всегда задаются в конце выражения. Если метод используется вместе с пара- метрами, эти параметры указываются в скобках после имени метода. Если параметров не- сколько, они друг от друга отделяются запятой. 200 Часть III. Объекты документа
Методы для каждого объекта предопределяются в используемой объектной модели. Уже существующим объектам после загрузки их кода HTML в документ можно присваивать но- вые методы. Для этого в сценарии документа (другого окна или подокна, доступного доку- менту) следует описать функцию JavaScript, а потом присвоить эту функцию в качестве име- ни нового метода объекта. В приведенном ниже примере функция fullscreen () вызывает один из методов объекта window. При этом задействовано два метода объекта window. Функция maximize () объекта window определяется в результате задания ссылки на функ- цию новому методу window.maximize () объекта окна. После этого обработчик события кнопки сможет напрямую вызвать этот метод. Сценарий рассчитан на использование браузе- ров, начиная с четвертой версии и выше. // Определение функции function fullscreen() { this.moveTo(0,0); this.outerwidth = screen.availwidth; this.outerHeight = screen.availHeight; } // Присвоение функции свойству window.maximize = fullscreen; < I -- Вызов нового метода --> «input type=”button" value="Maximize Window" onclick="window.maximize()" /> Обработчики событий объектов В обработчике события объекта определяется, как должен реагировать объект на соот- ветствующее событие, инициированное пользователем (например, щелчок на кнопке) или браузером (например, окончание загрузки документа). В самых первых версиях браузеров, поддерживающих JavaScript, обработчики событий определялись как дополнительные атри- буты в дескрипторах HTML. Они состоят из имени атрибута, после которого следует знак ра- венства (используемый в качестве оператора присвоения) и строки, содержащей оператор сценария или имена функций, которые следует выполнить при наступлении события (глава 5). Обработчики событий могут иметь и другой вид. В браузерах NN3+ и IE4+ обра- ботчики событий используют соответствующие методы своих объектов, и каждый такой об- работчик события является свойством этого объекта. Обработчики событий как методы Рассмотрим объект кнопки. У этого объекта есть очень важный обработчик события onclick. При щелчке объект кнопки запускает этот обработчик события. В результате будут выполнены те команды и функции JavaScript, которые присвоены обработчику события при его описании в документе HTML. «input type="button" name="clicker" value="Click Me" onclick="dolt()" />- Как правило, под событием “щелчок ” подразумевается ситуация, когда пользователь щелкает мышью на кнопке страницы. В браузерах NN3+ и IE4+ обработчик события можно вызывать из сценария так, как если бы это был самый обычный метод объекта. document.formName.clicker.onclick(); Глава 14. Основы объектной модели документа 201
Следует обратить внимание на следующий факт: если обработчик события вызывается в качестве метода объекта, то имя этого обработчика события состоит исключительно из строчных букв независимо от способа определения атрибута этого обработчика события в де- скрипторе HTML. Это обязательное условие. Такое использование обработчика события принципиально отличается от использования ме- тода для эмулирования действия для события. Например, представим, что страница содержит три текстовых поля, одно из которых имеет обработчик события onf ocus, который отвечает за активизацию поля. Если в этом поле щелкнуть мышью или перейти к нему с использованием клавиатуры, то поле активизируется и будет задействован обработчик события onfocus. Но даже если поле неактивно, обработчик события onfocus можно вызвать, щелкнув на кнопке, которая и вызовет обработчик события в качестве метода объекта текстового поля. document.formName.fieldName.onfocus(); В данном случае поле не активизируется. Но с помощью сценария метод поля onfocus () все же будет вызван. В результате использования обработчика события в качестве метода появляется возмож- ность задания последовательности действий, выполняемых обработчиком события, в функции, имеющей имя обработчика события. Например, вместо того чтобы описывать обработчик собы- тия onload в дескрипторе документа <body>, достаточно описать следующую функцию. function onload() { Команды функции } Это очень полезная возможность, особенно если нужно задействовать обработчики собы- тий в сценариях для браузеров NN3, IE4 или более поздних версий. В случае использования Netscape Navigator 2 или Internet Explorer 3 в сценарии изменения вносить не придется. Обработчики событий как свойства Несмотря на то, что обработчики событий обычно определяются в дескрипторах объектов HTML, при использовании браузеров NN3+ и IE4+ существует возможность изменять или присваивать обработчики событий объектам в полной аналогии со свойствами, которые так- же могут изменяться и присваиваться. Значение свойства обработчика события внешне по- хоже на описание функции. Например, рассмотрим следующее описание в HTML. cinput type="text" name="entry" onfocus="doltО" /> Значением свойства объекта onfocus () (все буквы строчные) является function onfocus() { dolt О ; } Существует возможность присвоить обработчику события совершенно другую функцию; при этом свойству присваивается ссылка на данную функцию. Скобки, являющиеся частью определения функции, в ссылке не используются. Более подробно метод присвоения объек- там свойств в качестве значений функций рассматривается в главе 33. Если у вас возникает ситуация, когда в зависимости от отображаемых данных текстовое поле при активизации ведет себя иначе, то обработчику события поля можно присвоить дру- гую функцию. Выполняется эта задача с помощью оператора определения функции. function doSomethingElse() { Команды функции } Вы можете присвоить эту функцию полю с помощью оператора присвоения. document.formName.entry.onfocus = doSomethingElse; 202 Часть III. Объекты документа
Поскольку используется функция JavaScript, в ее имени следует строго соблюдать строч- ные и прописные буквы. В версии NN4 имена обработчиков событий вводятся в так называе- мом слитном формате (interCap). Тем не менее, во избежание проблем при использовании браузеров других версий в именах обработчиков событий, используемых в качестве свойств объектов, рекомендуется использовать только строчные буквы. Помните: как и для многих настраиваемых свойств объектов, которые в явном виде на странице не проявляются, изменения, вносимые в свойства обработчиков собы- тий, при перезагрузке документа не восстанавливвются. Поэтому подобной практи- ки лучше избегать и вносить описанные изменения только в крайних случаях: на- пример, когда обрвботчики событий вызываются в сценарии в качестве методов. Если в вашем сценарии новые объекты элементов создаются динамически, то вы можете назначить этим объектам обработчики событий с помощью свойств. Например, следующий код написан в соответствии со спецификацией W3C DOM — он создает новую кнопку и на- значает в качестве обработчика событий one lick этой кнопки некую функцию, определен- ную далее в сценарии. var newElem = document.createElement("input"); newElem.type = "button"; newElem.value = "Click Here"; newElem.onclick = dolt; document.forms[0].appendChild(newElem); Таким образом, обработчики событий могут использоваться и в качестве методов, и в ка- честве свойств объектов. В следующих главах при описании свойств и методов различных объектов этот факт специально подчеркиваться не будет. Тем не менее, можно быть уверен- ным, что такая техника успешно применяется ко всеми объектами JavaScript, имеющим обра- ботчики событий, начиная с браузеров Netscape Navigator 3 и Internet Explorer 4. Разнообразие объектных моделей В процессе эволюции браузеров, поддерживающих сценарии, начиная с NN2 и IE3 и за- канчивая IE5.5 и Mozilla, было разработано шесть (именно шесть!) различных типов объект- ных моделей. Даже в самом простом случае, когда создаваемая страница рассчитана на ис- пользование только одного типа браузеров, будут задействованы, скорее всего, элементы и объекты разных объектных моделей. Изучение различных объектных моделей — занятие весьма поучительное для начинаю- щих программистов. Освоение объектной модели последней версии браузера не займет много времени. Это простой путь. Однако потом, как правило, при использовании браузеров более старых версий, возникают серьезные проблемы с использованием программных продуктов, написанных в расчете на эту объектную модель. Поэтому стоит потратить время на то, чтобы ознакомиться с историей развития объектных моделей, начиная с самой первой версии, и по- нять главные их особенности. В табл. 14.1 перечислены разные типы (или семейства) объект- ных моделей (в хронологическом порядке их появления) вместе с указанием типа браузеров, в которых эти модели используются. Позже в этой главе будут описаны критерии, по кото- рым выбирается оптимальная для того или иного случая объектная модель. Базовая объектная модель В первом поддерживающем сценарии браузере Netscape Navigator 2 использовалась дос- таточно простая объектная модель. На рис. 14.1 представлены объекты этой модели, которыми управляли сценарии. Иерархическая структура начинается с объекта окна, ниже расположены Глава 14. Основы объектной модели документа 203
документ, формы и их элементы. При этом документ, определяющий основное содержимое страницы, практически не программируется. Объектами (с их свойствами, методами и обра- ботчиками событий) являются только такие интерактивные по своей природе элементы, как ссылки, текстовые поля, кнопки и т.д. Тип объектной модели Версия браузера Базовая объектная модель NN2, NN3, IE3/J1,1E3/J2, NN4,1Е4,1Е5,1Е5.5,1Е6, Moz1, Safari! Основная модель, поддерживающая изображения NN3, IE3.01 (только для Mac), NN4, IE4, IE5, IE5.5, IE6, Moz1, Safari! Расширенная модель NN4 NN4 Расширенная модель IE4 IE4, IE5, IE5.5, IE6 (для использования некоторых характеристик во всех версиях нужна огерационная система Win32) Расширенная модель IE5 IE5, IE5.5, IE6 (для использования некоторых характеристик во всех версиях нужна операционная система Win32) W3C DOM (уровней 1 и 11) IE5 (частично), IE5.5 (частично), IE6 (частично) Moz1 (практически полностью), Safari (частично) Использование объектной модели открыло широкие возможности, которые были не дос- тупны ранее и на то время казались чем-то исключительным. Поскольку сценарии могли управлять значениями элементов форм, последние предварительно проверялись клиентом на корректность введенных пользователем данных. Если страница содержит сценарии, выпол- няющие определенные расчеты, то результаты таких вычислений и другие данные можно отображать в редактируемых текстовых полях. Дополнительные объекты (window, history и location), которые выведены за рамки документа, позволяет получить доступ к некоторым достаточно простым свойствам браузе- ра, выполняющего загрузку страницы. Наиболее общим с этой точки зрения является объект navigator, свойства которого позволяют узнать тип и версию браузера. Когда появился Internet Explorer 3, Netscape Navigator 2 отошел на второй план. Несмотря на то, что уже достаточно широко использовалась экспериментальная версия Netscape Navi- gator 3, в IE3 применялась базовая модель из NN2 (и еще одно свойство объекта window, представленное в NN3). Поэтому если судить по объектной модели, то NN2 и ТЕЗ находятся на одном уровне, хотя и имеют разную нумерацию версий. На этом непродолжительном эта- пе развития браузеров между Microsoft и Netscape существовала практически полная гармо- ния — хотя и на уровне достаточно простых объектных моделей. Базовая объектная модель, поддерживающая изображения Практически сразу после выхода в свет IE3 компания Netscape представила завершенную версию Netscape Navigator 3. Объектная модель этого браузера базировалась на объектной модели предыдущей версии. В старые объекты были добавлены новые свойства, методы и обработчики событий. Это относится в первую очередь к объекту window. В сценариях стало возможно обращаться к аплетам Java как к объектам. Но самым важным усовершенст- вованием стало создание объекта изображения Image и поддержка массивов объектов изо- бражений, размещенных в объекте документа document. 204 Часть III. Объекты документа
В NN3 большинство свойств объектов изображений были доступны только для чтения. Как правило, значения этих свойств устанавливались в атрибутах дескриптора <img>. Одно свойство объекта изображения можно было изменять и после загрузки страницы — речь идет о свойстве src. Теперь сценарии в области фиксированных размеров могли выполнять пред- варительную загрузку изображений. Хотя эти новые объекты изображений не имели своих собственных обработчиков событий, их можно было размещать внутри ссылки (для которой задается обработчик события onmouseover и новый обработчик onmouseout). Последнее позволяет изменять изображения на другие объекты при наведении на них указателя мыши. Таким образом, страница становилась более интересной с точки зрения ее оформления. По мере того, как разработчики страниц знакомились с возможностями JavaScript, попу- лярность последнего росла. Однако возникала серьезная проблема, связанная с тем, что пред- варительная загрузка изображений, описанная выше и успешно используемая в NN3, не сра- батывала в браузере IE3. Разумеется, несложно написать такой сценарий, который при использовании IE3 не будет вызывать ошибки (глава 12). Однако при этом не будут задейст- вованы и новые возможности по изменению изображений, доступные в NN3. Последнее мно- гих разочаровало. Также следует учесть и то, что достаточно большое количество пользова- телей еще не перешли с NN2 на NN3. Если, к тому же, принять во внимание тот факт, что в IE3.01 (второй выпуск браузера IE3 для Мас) использовались управляемые сценариями объек- ты изображений, то можно было легко запутаться во всем этом. Несмотря на такие серьезные проблемы с совместимостью, объектная модель, использо- ванная в NN3, стала основой для разработки последующих объектных моделей документа. За редким исключением, любой код, написанный для этой модели, будет выполняться во всех браузерах, начиная с NN3 и IE4 вплоть до самых последних версий браузеров обоих произво- дителей. Упомянутые редкие исключения касаются, в основном, объектной поддержки апле- тов Java в версиях IE4+, рассчитанных на отличные от Windows операционные системы. Расширенная модель NN4 Следующим браузером, представленным на суд общественности, стал NN4. Внесенные из- менения в уже существующие объекты добавили больше свободы для разработчиков сценариев. Была предусмотрена возможность с помощью свойств объекта screen перемещать и изменять размеры окна браузера (хоть на весь экран). Две новые концепции существенно расширили представление об объектной модели — это расширенная модель событий и объект layer. Модель перехвата событий В NN4 был существенно расширен диапазон обрабатываемых событий. События, связан- ные с действиями пользователя на клавиатуре, и новые добавленные события, относящиеся к мыши (onmousedown и onmouseup), значительно расширили возможности сценариев. Все эти события обрабатывались так же, как в предыдущих объектных моделях, где обработ- чики событий, как правило, присваивались в виде атрибутов дескрипторов соответствующих элементов (хотя обработчики событий можно использовать в операторах сценария в качестве свойств). Для того чтобы в полной мере реализовать потенциал динамического HTML в объект- ной модели NN4, модель событий была существенно доработана. Главная идея, положенная в основу обработки событий, выглядит так: когда пользователь выполняет действия над объектом (например, щелкает на кнопке формы), то текущее событие передается этому объекту (кнопке) в соответствии с иерархической структурой документа (начиная с самого высшего ее уровня). Если используется несколько объектов и один и тот же общий обработчик события, то вместо присвоения этого обработчика события каждому элементу Глава 14. Основы объектной модели документа 205
в отдельности, удобно было бы перехватить событие заранее, на самом высшем уровне иерар- хической структуры документа — на уровне window или document. По умолчанию в Netscape Navigator 4, как и во всех предыдущих версиях браузеров, события из вершины иерархиче- ской структуры отправлялись непосредственно к объекту назначения. Однако в объектах window, document и layer была предусмотрена возможность использования режима перехвата событий. После перехвата событие может использоваться на высшем уровне, об- работано перед отправкой объекту назначения или перенаправлено к другому целевому объекту. Независимо от того, используется или нет режим перехвата событий, в NN4 для каждого со- бытия создается объект event (в данном случае первая буква "е " — строчная, чтобы отличить этот объект от статичного объекта Event). В этом объекте хранятся свойства, которые подроб- но описывают каждое конкретное событие (как, например, символ клавиши, нажатой на клавиа- туре, или расположение на странице указателя мыши при щелчке). Поэтому каждый обработчик события перед началом обработки внимательно исследует свойства объекта event. Объект Layer Самым существенным новшеством в объектной модели NN4 стало, пожалуй, использова- ние принципиально нового объекта, отвечающего абсолютно новому в HTML элементу — элементу слоя layer. Объект слоя layer является контейнером, в котором может содер- жаться собственный документ HTML, располагающийся на фоне главного документа. С по- мощью сценария его можно перемещать, изменять размеры и скрывать. Этот новый элемент на первых этапах позволял выполнять наложение элементов HTML на странице. Для того чтобы в иерархической структуре документа для объекта layer нашлось место, он был помещен в объект документа. В результате объект document приобрел новое свойст- во document. layers. Данное свойство является массивом объектов layer документа. В мас- сиве отображаются только объекты layer первого уровня текущего объекта document. Для ссылки на объект слоя layer в основном документе подойдет любая из следующих команд. document.имяСлоя document.layers[n] document.layers[имяСлоя] У каждого Объекта слоя layer есть собственный объект документа document, посколь- ку каждый объект layer в случае необходимости может выполнять загрузку внешнего доку- мента HTML. Таким образом, если сценарию нужен доступ, скажем, к элементу формы внут- ри объекта layer, ссылка будет выглядеть так. document.имяСлоя.document.forms[0]... Если объект layer содержит внутри себя очередной слой, ссылка станет длиннее. document. имяВнешнегоСлоя. document. имяВнутреннегоСлоя. document. forms[0]... Как позиционируемый элемент, объект слоя layer имеет целый ряд свойств и методов, позволяющих сценариям перемещать его, скрывать и снова отображать, а также изменять по- рядок расположения в стеке. Недостатком для Netscape Navigator является то, что дескриптор <1ауег> в стандарт HTML 4.0 включен не был; потому используется он только в NN версии 4 (в NN6 и более поздних версиях от его использования отказались). Это же замечание относится и к сценари- ям, использующим объект слоя и ссылки на него. В NN4, с другой стороны, для позициони- руемых элементов в незначительной степени была реализована поддержка спецификации HTML 4.0 и таблиц стилей CSS. Причина состоит в том, что таблицы стилей можно задавать (вместе с указанием расположения на странице и прочими атрибутами) элементам div 206 Часть III. Объекты документа
и span, также используемым в NN4. Позиционируемый элемент div или span трактуется Netscape Navigator, с точки зрения сценария, практически эквивалентно объектам layer. Та- ким образом, даже если с помощью HTML можно заставить браузер выполнить поставлен- ную задачу с использованием элементов div и span (не всегда успешно, поскольку в NN4 и IE4 существуют различия в настройках позиционирования элементов), написание сценариев для NN4 подразумевает использование синтаксиса, аналогичного тому, который используется для объектов слоев. Этот синтаксис отличается от используемого в IE4 для CSS. Расширенная модель IE4+ Браузером IE4, выпущенном через несколько месяцев после NN4, компания Microsoft на- чала новый этап в развитии браузеров. Основные изменения касались способа отображения элементов HTML, поддержки в сценариях CSS-стилей и новой модели событий. Некоторые другие усовершенствования были доступны только при использовании 32-разрйдной опера- ционной системы Windows. Объекты элементов HTML Самое серьезное новшество объектной модели состоит в том, что теперь все элементы HTML стали объектами, которыми можно управлять из сценария. Microsoft предложила массив document. all (так называемую библиотеку объектов). Этот массив содержит ссылки на все элементы в документе, независимо от места размещения этого элемента в иерархии объектов. Если атрибуту ID элемента присвоен идентификатор (имя), то ссылку на этот элемент можно делать по его значению (в данном случае идентификатор — ИдентификаторЭлемента). document.all.ИдентификаторЭлемеита В большинстве случаев полную ссылку из массива document.all можно упростить и использовать только идентификатор элемента. Каждый объект элемента имеет совершенно новый набор свойств и методов, предостав- ляющих создателям сценариев такие полномочия по управлению содержимым документа, ко- торые им и не снились. В табл. 14.2 приведен список свойств и методов, которыми в сово- купности обладают элементы HTML в IE4 (свойства, после имен которых идут квадратные скобки, являются массивами). ь Г4.2„ XapaKrepMCTMKM3neMeHTOBHTMLBlE4 Свойства. Методы all I] children [] click() contains() className getAttribute() document insertAdj acentHTML() filters [] insertAdj acentText() id removeAttribute() innerHTML scrol1IntoVeiw() innerText isTexEdit setAttribute() Глава 14. Основы объектной модели документа 207
Окончание табл. 14.2 Свойства Методы lang language offsetHeight offsetLeft offsetParent offsetTop offsetwidth outerHTML outerText parentElement parentTextEdit sourceindex style tagName title Детальное описание приведенных в табл. 14.2 свойств и методов можно найти в главе 15. Однако некоторые важные характеристики, будут описаны в этой главе. Получить доступ к содержимому документа для чтения и записи можно с помощью четы- рех свойств: innerHTML, innerText, outerHTML и outerText. В результате отпадает необходимость в использовании текстовых полей для отображения результатов вычислений в сценариях. Стало возможно редактировать содержимое абзацев и таблиц непосредственно в процессе работы. Браузер автоматически изменяет содержимое документа при изменении содержимого элементов. Это свойство добавило больше “динамизма” в и без того “динами- ческий” HTML. Для тех, кто начинал с создания статичных страниц для браузеров первых версий, такие широкие возможности казались просто фантастическими. Группа свойств с префиксом offset предназначена для изменения размещения элемен- тов на странице. Эти свойства отличаются от тех, которые используются при позиционирова- нии с использованием CSS-стилей. Возможность определения места расположения элементов на странице весьма полезна. В зависимости от размера окна браузера, позиционируемые эле- менты на странице могут отображаться в разных местах. Зная размеры и расположение таких элементов, их легче перемещать по странице. Наконец, свойство style используется для получения доступа к спецификации CSS-элемеи- тов. Важно также то, что в сценарии можно изменять многочисленные свойства объекта style. Поэтому после загрузки страницы существует возможность изменить характеристики шрифтов, цветов, границ и расположение элементов на странице. Все изменения выполняют-' ся динамически в процессе работы (например, изменение размера шрифта). Иерархия содержимого элементов Несмотря на то, что IE4 поддерживает исходную объектную модель (см. рис. 14.1), собст- венная объектная модель IE4 несколько отличается от базовой. Речь идет, в основном, об ор- ганизационной структуре элементов модели. Если бы это было так, то, скажем, адресация на 208 Часть III. Объекты документа
элементы таблицы td выполнялась бы через внешний для них элемент tr или table. Точно так же сослаться на элемент управления формы можно, если указать в ссылке форму form. На рис. 14.2 показана схема организации элементов HTML в объекте документа document. В массиве document.all содержатся ссылки на каждый из элементов иерархической структуры (рис. 14.2). Ссылка даже на самый “глубоко спрятанный” в иерархической струк- туре элемент td будет выглядеть как document. all. ИдентификаторЯчейки. Последний способ задания ссылок на объекты в П34 является преобладающим. window frame | self top | parent | navigator ~| | scraen~j | history | | document] | location"^] | event"] | link | ["styleSheets ~| | applets"] | form] [ images'] | plugins [ | embedj | anchor | ГТТ" III II __________ | [elements] | | text | I radio [ | buttori| | select [ | , | selection | II I I .. ‘ I .. I | style | textarea checkbox reset option I | password"] | submit | Puc. 14.2. Иерархия объектов документа в IE4 Система организации элементов в IE4 важна и с другой точки зрения. Элементы могут на- следовать некоторые атрибуты таблиц стилей тех объектов, которые содержат в себе данные элементы. Поэтому в коде документа HTML содержимое страницы рекомендуется разбить на фрагменты и заключить в контейнеры. Это значит, что абзацы являются контейнерами для текста (используются дескрипторы начала и конца абзаца), а не фрагментами текста на стра- нице. В IE4 вводится понятие о взаимодействии объектов на уровне родительско-дочерних отношений. Такого типа взаимодействие осуществляется между контейнерами и содержащи- мися в них элементами. Таким образом, расположение элемента можно вычислить по отно- шению к расположению содержащего его объекта. Вывод из всего выше сказанного следующий: в отличие от исходной объектной модели, в данном случае иерархическая структура определяется путем установки системы отношений одного объекта относительно другого. Каскадные таблицы стилей На рынке программных продуктов четвертая версия браузера Microsoft появилась не- сколько позже, чем Netscape Navigator 4. Поэтому Microsoft получила преимущество в том смысле, что смогла использовать в своем браузере более совершенную первую версию таб- лиц стилей CSS. Отсюда и более полная совместимость со стандартом CSS по сравнению с NN4 (хотя и не абсолютная). Следует отметить, что в первом поколении CSS-стилей попытки использования сценариев для программирования свойств стилей осуществлялись с некоторой несогласованностью. В результате разработчикам не удалось реализовать весь потенциал JavaScript. Многие имена атрибутов CSS содержат дефисы (например, text-align или z-index). Но дефис в именах объектов JavaScript использовать запрещено. Имена атрибутов CSS, состоящие из нескольких Глава 14. Основы объектной модели документа 209
слов, необходимо преобразовывать к именам свойств JavaScript в слитном виде (interCap). Поэтому text-align превратится в textAlign, a z-index станет zlndex. Доступ к этим свойствам осуществляется с помощью свойства style элемента. document.all.ИдентификаторЭлемента.style. ИмяСвойстваСтиля Побочным эффектом использования таблиц стилей в сценариях, выполняемых в IE4 и бо- лее поздних версиях браузеров, является так называемый синдром блуждающего элемента. Такая ситуация имеет место при изменении формата страницы после загрузки ее исходного кода HTML в браузер. При загрузке страницы не все элементы отображаются (или они отображаются не в очередности загрузки). После загрузки страницы обработчик события onload запускает сценарий, изменяющий стиль или содержимое страницы. В результате элементы на странице меняют свое расположение. Нетрудно представить удивление пользователя, который собрался щелкнуть мышкой на ссылке, а эта ссылка начала перемещаться по странице в другое место. / Специально для пользователей 32-разрядных операционных систем Windows /назмюпу в объектной модели IE4 был предложен ряд дополнительных расширений. Целый • ряд интересных визуальных эффектов стал доступен с использованием фильтров. Фильтры — это такие дополнительные таблицы стилей, которые предназначены для управления основным текстом страницы. Например, эффект тени или подсветки текста достигается применением к этому тексту фильтра стилей. Поскольку синтаксис фильтров выдержан в духе CSS, то они не являются частью стандарта W3C. При переходе от скрытого к видимому содержимому страницы используются два анимационных фильтра. Например, нужно создать слайдовую презентацию. Ка- ждый слайд содержится в позиционируемом элементе div. При отображе- нии (с помощью сценария) следующего слайда (т.е. элемента div) анимацион- ные фильтры могут просто удалять предыдущий слайд или заменять один слайд на другой с эффектом кругового вытеснения одного другим. И еще о событиях Точно так же, как компания Netscape разработала модель событий для своего браузера NN4, Microsoft сделала то же самое для IE4. К огромному сожалению тех создателей сцена- риев, кто разрабатывает свои продукты в расчете на использование браузеров обоих типов, модели эти совершенно разные. Вместо того чтобы отправлять события вниз по иерархиче- ской структуре к элементу назначения, в IE событие “начинает свой путь” с элемента назначе- ния, и (если явно не указана ссылка в обратном направлении) “всплывает” вверх по иерархиче- ской структуре, вплоть до объекта window. При перемещении события по объектам в иерархии объектной модели обработчики события текущего объекта могут выполнять определенные дей- ствия. Поэтому, чтобы назначить для обработки всех щелчков мыши на странице один обра- ботчик события, достаточно присвоить этот обработчик объекту body или window. Если при всплывании событие не будет перехвачено другим объектом, оно достигнет вершины иерар- хической структуры, что приведет к выполнению сценарием нужного обработчика. В IE включен объект event (свойство объекта window). В нем содержится детальная ин- формация о конкретном событии. В частности, для события нажатия клавиши в нем предусмот- рен символ нажатой клавиши. При щелчке кнопки мыши в нем записываются координаты указате- ля. Имена этих свойств полностью отличаются от аналогичных свойств объекта event в NN4. Вопреки складывающемуся впечатлению о невозможности совместить несовместимое (речь идет об отличии моделей событий в NN4 и IE4), выход можно найти в использовании специального набора сценариев для обработчиков событий (примеры таких сценариев приве- дены в главах 25 и 56). Фактически, две описанные модели событий объединены в одну во второй версии стандарта W3C DOM (об этом речь пойдет несколько позже). 210 Часть III. Объекты документа
События и сценарии В IE предложен дополнительный способ привязки событий к объектам. Он выполняется по- средством дескриптора <script> и двух дополнительных, ие поддерживаемых в стандарте W3C, атрибутов — for и event (примеры их использования можно найти в главе 13). В каче- стве значения атрибуту for присваивается идентификатор id объекта элемента, для которого вызывается сценарий. Значение атрибута event — это имя обработчика события (например onclick), с помощью которого запускаются операторы сценария указанного выше дескриптора. Внутри дескрипторов находятся операторы сценария. Однако, когда браузер обнаружива- ет там специальные атрибуты, выполнение операторов отменяется до того момента, пока не будет сгенерировано нужное для данного объекта событие. Объекту передается экземпляр события, после чего выполняются операторы сценария, размещенные в дескрипторе. Обра- ботчику события можно присвоить и определение функции. Иногда это целесообразно де- лать; в таком случае используется специальная форма записи дескриптора. Эта так называе- мая, концепция “строгого запуска” получила применение в DHTML в браузерах IE5 для Windows (см. следующий раздел). Такой специальный способ привязки событий к объектам можно использовать только в браузере IE4+. Все прочие браузеры, включая и IE3, игнорируют специальные атрибуты и трактуют операторы сценария, размещенные в дескрипторе, как такие, которые должны выполняться при загрузке страницы. Расширенная модель IE5+ Начиная с IE5, компания Microsoft доработала объектную модель, использованную в IE4. Хотя основной набор объектов остался практически тем же, что и в предыдущей модели, однако количество свойств, методов и обработчиков событий этих объектов возросло невероятным обра- зом. Некоторые новшества были направлены на то, чтобы обеспечить совместимость со стан- дартом W3C DOM (см. следующий раздел). В результате возникли некоторые проблемы совмес- тимости с IE4. Была также усилена тенденция по предоставлению пользователям операционной системы Windows особых привилегий. Последние, однако, совсем не обязательно должны стать стандартом для всей индустрии — речь идет о поведениях DHTML и приложениях HTML. Поведения DHTML — это фрагменты сценариев, которые сохраняются как внешние фай- лы и определяют разного рода последовательность действий. Обычно эти действия направле- ны на изменение одного или более свойств стиля. Такие фрагменты сценария могут приме- няться к самым разнообразным элементам. Соответствующий файл сценария называется компонентом HTML и имеет расширение . htc. Идея состоит в том, чтобы создать много- кратно используемый компонент, который потом можно будет загружать в документ каждый раз, когда элемент этого документа должен выполнять предопределенную в компоненте по- следовательность действий. Компоненты являются документами XML, в дескрипторах XML которых определены события и программы обработки этих событий, выполняемые независи- мо от типа используемого элемента. Операторы сценария в htc-документах размещаются, как и в обычном документе HTML, — внутри дескрипторов < script >. В качестве примера использования поведений DHTML можно привести ситуацию, когда текст элемента страницы при наведении на этот элемент указателя мыши становится красного цвета, а когда сводится с элемента— восстанавливается до исходного варианта. Если такой тип поведения задать элементу документа с помощью синтаксических правил CSS, то этот элемент будет вести се- бя, как описано, — и не иначе. Причем такой стиль поведения можно использовать буквально для всех элементов документа. (Компания Microsoft для обеспечения совместимости с W3C предложила использовать этот метод в третьем поколении CSS.) Примеры использования Глава 14. Основы объектной модели документа 211
поведений DHTML можно найти в главе 15 при описании метода addBehavior (), а также в главе 47, где подробно проанализирован данный подход. Приложения HTML (на языке Microsoft такое приложение сокращенно называется НТА) представляют собой файлы HTML с элементами XML, известными также под именем элемента hta: application. Приложения НТА можно загрузить в IE5 с сервера подобно тому, как за- гружают самые обычные Web-страницы (хотя расширение этих файлов — . htc, а не . htm или . html). Пользователь может установить приложение НТА в системе клиента так, что на рабо- чем столе отобразится пиктограмма этого приложения, а внешний вид окна приложения можно будет настроить по своему усмотрению. Вопрос с защитой данных в НТА решен в пользу кли- ента, поэтому такое приложение напоминает обычную программу. Фактически, можно отклю- чить стандартную строку меню и, используя методы DHTML, создать собственную строку меню для приложения. Особенностей использования приложений НТА не будут рассмотрены в этой книге. Но о том, что подобные возможности существуют, нужно знать. Более подробную информацию по этому вопросу вы найдете по адресу: http: //msdn. microsof t. com. Модель W3C DOM Конфликт различных версий объектных моделей от Netscape и Microsoft усложнил жизнь разработчикам Web-страниц. Необходимость создания единого стандарта для разработчиков объектных моделей (когда стандартом для содержимого и стилей стали HTML и CSS соот- ветственно), оказалась очевидной. Обязательства по разработке такого стандарта взяла на се- бя организация W3C, а разрабатываемая объектная модель получила название W3C DOM. Группа разработчиков W3C DOM имела целью создание такой объектной модели докумен- та, которая была бы применима как к документам HTML, так и к XML. Поскольку в документах XML, фактически, могут использоваться дескрипторы с любыми названиями (это определяется в Document Type Definition — Описание типов документов), то строгой структуры или фикси- рованного словаря для элементов, в отличие от документов HTML, в данном случае нет. Как ре- зультат— стандарт DOM должен соответствовать и предопределенной структуре HTML (определяемой в спецификации HTML 4.0), и наперед неизвестной структуре документа XML. Для того чтобы выполнить задание качественно, рабочая группа по созданию D0M разде- лила саму модель на две части. Первая, базовая модель Core DOM, определяет спецификацию для оболочки и структуры документов XML и HTML. В нее входят способы включения в до- кумент элементов, имеющих дескрипторы и атрибуты. В таких элементах могут содержаться другие элементы. Вторая часть модели DOM имеет отношение исключительно к элементам и другим характеристикам документов HTML. Эта HTML-часть “наследовала” все характеру стики базовой модели DOM. Кроме того, в ней предусматривались меры по обеспечению со- вместимости с объектными моделями, уже использованными в браузерах, и осуществлялись наработки для дальнейших усовершенствований. Важным все же является тот факт, что не все свойства объектных моделей существующих на то время браузеров были включены в модель стандарта W3C DOM. Многие характеристики объектной модели Inte.net Explorer 4 (и более поздних версий) так в стандарт W3C DOM и не вошли. Таким образом, если кто-то достаточно хорошо освоился со средой IE и решил пере- ключиться на создание программных продуктов в стандарте W3C DOM, то ему в свой стиль ра- боты придется внести некоторые изменения (подробнее об этом рассказывается далее). К поте- рям следует отнести и дескриптор <1ауёг> из Netscape Navigator 4 (поскольку он не используется в HTML 4.0, то и в стандарт вряд ли когда-нибудь будет включен), а также и соот- ветствующий ему объект слоя layer. Во многих отношениях, особенно принимая во внимание приложения DHTML, стандарт W3C D0M является полностью новой моделью DOM со своей концепцией, которую обязательно нужно изучить перед началом работы в среде JavaScript. 212 Часть III. Объекты документа
ч Помните: если NN6 практически полностью поддерживает стандарт W3C DOM первого поколения и в значительной степени второго, то Microsoft (по разными причинам) вплоть до IE5.5 только частично реализовала в своих браузерах средства W3C DOM. Хотя в IE6 под- держка W3C DOM реализована на более высоком уровне, отдельные ее части, особенно ка- сающиеся событий, браузером этой версии проигнорированы. Другие современные браузера, например Safari, поддерживают базовую модель W3C DOM, хотя все еще “не дотягивают” до уровня ее реализации в Mozilla. Поколения DOM Как и большинство программных продуктов, которые редко имеют только одну версию, существует несколько поколений DOM. Задача по разработке DOM была слишком объемной, чтобы выполнить ее за один раз. Поэтому спецификация DOM постоянно развивается. Про- цесс выхода в свет новых поколений DOM редко совпадает с разработкой новых версий брау- зеров. Поэтому нередки случаи, когда браузеры поддерживают стандарт W3C последнего по- коления только частично. Формально первая версия модели DOM увидела свет уже после выпуска браузеров NN4 и IE4. В HTML-часть первого поколения модели DOM была включена нулевая версия DOM. Это, по большому счету, не что иное, как объектная модель, использованная в NN3 (и во мно- гом в Internet Explorer 3, а также объекты изображений). Пожалуй, самым существенным не- достатком модели DOM первого поколения стала модель событий, в которой игнорировались даже самые элементарные события из NN2 и ВЕЗ. Основой для второй версии DOM стала первая. Кроме существенных усовершенствова- ний, внесенных в обе части (базовую и HTML) модели, во второй версии значительно расши- рена модель событий, добавлены методы отслеживания иерархической структуры документа, расширены возможности использования XML, текстов, таблиц стилей и свойств стилей. В настоящий момент не прекращается работа над третьей версией модели, хотя о реализации ее в браузерах говорить еще рано. Неизменная часть Как уже отмечалось, исходной точкой развития HTML-части модели следует считать ну- левую версию DOM. Последнее в стандарте W3C сделано для того, чтобы обеспечить воз- можность большинству сценариев выполняться даже при использовании браузеров стандарта W3C DOM. К модели DOM нулевого уровня относятся все объекты, начиная с document (см. рис. 14.1), а также объекты изображений. Доступными будут также практически все свойства и методы этих объектов. Важными являются изменения, внесенные в W3C DOM в систему ссылок на другие эле- менты (будут обсуждаться в следующем разделе). Утешителен тот факт, что старые способы задания ссылок на такие объекты, как формы, элементы форм и изображения, все еще оста- ются доступными. Если бы рабочая группа стала создавать модель “с чистого листа”, вряд ли объект document имел бы свойства, состоящие из массивов форм, ссылок и изображений. Единственная проблема, с которой можно столкнуться, состоит в том, что некоторые по- лезные свойства объекта document “сменили владельца”. Дело в том, что четыре свойства стилей (alinkColor, bgColor, linkColor и vlinkColor) объекта document стали в модели DOM свойствами объекта body (ссылка на него выглядит как document. body). Кроме того, три свойства цвета изменили свои имена (aLink, link, vLink). Оказалось, тем не менее, что теперь в браузерах IE6 и Mozilla обеспечивается совместимость со свойствами цвета объектов более старых документов. Глава 14. Основы объектной модели документа 213
Спецификация модели DOM, в основном, касается только непосредственно документов и их содержимого. Такие объекты, как window, navigator и screen (вплоть до второй версии DOM), частью модели не являются. Поэтому создатели сценариев до сих пор с надеж- дой взирают на разработчиков браузеров, что те решат проблему совместимости для данного конкретного случая. Есть надежда, что в будущем объект window будет добавлен в W3C DOM третьей версии. Недоступные элементы Как уже отмечалось ранее, стандарт W3C DOM нельзя рассматривать как подтверждение спецификации уже существующих браузеров. Многие полезные характеристики объектных моделей браузеров IE и NN в него не вошли. Интересно разработать с помощью DHTML эф- фектную страницу, рассчитанную на использование IE4+ или NN4. Но все же нужно уметь обходиться и без некоторых специфических возможностей, Предоставляемых этими браузе- рами и отсутствующих в стандарте W3C DOM. Эксперимент дескриптора <layer> в стандарте W3C DOM поддержки не нашел. Поэто- му ни такого дескриптора, ни связанной с ним методики составления сценариев вам обнару- жить не удастся. К огромной радости разработчиков сценариев, схема ссылок с использова- нием слоев типа document. имяСлоя (намного более сложная при использовании вложенных слоев) полностью исчезла из объектной модели. Позиционируемый элемент трак- туется как просто еще один элемент, у которого есть некоторые специфические атрибуты стилей, позволяющие перемещать этот элемент по странице, размещать его среди других элементов и скрывать из поля зрения. Среди популярных свойств IE4+, не задействованных в W3C DOM, можно отметить биб- лиотеку элементов HTML document. all и четыре свойства элементов, используемых с це- , лью придать динамизм содержимому страницы: innerHTML, innerText, outerHTML и outerText. Новая концепция W3C предусматривает способы получения массива всех эле- ментов документа. Но генерирование кода HTML для замещения старого или простой встав- ки его в документ подразумевает использование сложной последовательности операторов I (эта проблема обсуждается в разделе “Новые концепции DOM” далее в этой главе). В Mozilla, I тем не менее, разрешено использование свойства объектов innerHTML элементов HTML. “Новая” практика HTML Для того чтобы в полной мере реализовать возможности DHTML, предоставляемые | в IE4+ и W3C DOM, используют метод, который для некоторых умудренных опытом HTML- I разработчиков может показаться принципиально новым. В основе этого метода (выходящего i за рамки спецификации HTML 4.0) заложена проверка типа содержимого контейнера HTML. I Поэтому вместо использования дескриптора <р> для разделения текста на блоки, каждый I текстовый абзац заключается в пару дескрипторов <р>. . . </р>. Если этого не сделать, то ,1 браузер будет трактовать каждый дескриптор <р> как начало абзаца. Заканчивается этот аб- 1 зац как раз перед следующим дескриптором <р> или элементом завершения блока. ! Несмотря на то, что браузеры последних версий корректно воспринимают отсутствие де- I скрипторов завершения блоков (например для элементов td, tr или li), все же рекоменду- I ется вводить в коде закрывающие дескрипторы — так легче представить себе блочную струк- I ТУРУ документа. I Для любого элемента, используемого в сценарии (для изменения его содержимого или свойст- I ва) желательно использовать идентификатор, присвоенный атрибуту элемента, id. Д ля элементов I управления формы в случае предоставления содержимого формы серверу необходимым является 1 использование атрибута name. Но атрибуту id формы можно присвоить и другой идентификатор. 1 214 Часть III. Объекты документа
Для того чтобы корректно сослаться на объект, можно воспользоваться либо идентификатором id, либо представить ссылку в формате document. ссылкаНаФорму. ИмяЭлемента. Иден- тификаторы при этом, как правило, будут теми же, что и значения, которые присваиваются ат- рибуту name формы или элементов формы. По аналогии со значением атрибута name, иденти- фикатор id должен состоять из единого слова (без пробелов), он не может начинаться с цифры (чтобы избежать конфликтов с JavaScript) и в нем не должны использоваться символы пунктуа- ции, за исключением символа подчеркивания. Хотя доступ к элементу может осуществляться по числовому индексу в контексте внешнего для него элемента (такого, как body), это доста- точно рискованный шаг, особенно если содержимое документа находится на стадии разра- ботки. Персональные идентификаторы позволяют намного проще задавать в сценариях ссыл- ки на объекты и работают надежнее. Новые концепции DOM В модели W3C DOM задействованы некоторые концепции, непосредственно относящиеся к иерархической структуре. С точки зрения традиционного подхода, они могут показаться со- вершенно новаторскими. С точки зрения использования этих концепций в сценарии, они оп- ределяют новые способы задания ссылок на элементы и узлы. / Ссылки на элементы Система ссылок на объекты модели нулевого уровня DOM сохранена в следующих поко- лениях W3C DOM с целью поддержания совместимости сценариев. Поэтому на элемент управления формы, атрибуту name которого присвоено значение имяПользователя, ссыл- ка задается обычным образом document.forms[0].имяПользователя или document.имяФормы.имяПользователя Поскольку все элементы в документе подчинены объекту document, то для получения доступа к элементу с известным идентификатором id можно использовать новый метод объек- та document. Это метод document.getElementByld(), параметром которого является строковая версия идентификатора объекта, ссылку на который нужно задать. Для того чтобы воспользоваться этим методом в контексте применяемой в IE4 объектной модели, необходи- мо рассмотреть следующий дескриптор абзаца HTML. <р id="myParagraph" >...</р > ВIE4+ ссылки на элементы можно задавать и так. var elern = document.all.myParagraph; Поскольку библиотека document. all в стандарте W3C DOM не поддерживается, полу- чить доступ к любым элементам по его идентификатору ID можно с помощью упомянутого выше нового метода (доступен в IE5+, Mozl+ и Safari). var elem = documnt.getElementByld("myParagraph"); • К сожалению, создателям сценариев этот метод не покажется простым (в том смысле, что придется следить за состоянием регистра букв в его имени). Обратите внимание, что послед- няя буква (" d") в имени метода — строчная. Иерархия узлов Для того чтобы понять принцип организации модели W3C DOM, следует рассмотреть, как одни объекты в этой структуре вложены в другие. Каждый элемент или фрагмент текста в до- кументе HTML (или XML) является объектом, который содержится в определенном контейнере, Глава 14. Основы объектной модели документа 215
тоже являющимся объектом. Чтобы понять принцип функционирования такой структуры, рассмотрим простой документ HTML. В листинге 14.1 представлена иерархическая структура из вложенных друг в друга элементов и фрагментов строк. <html> <head> <title> A Simple Page </title> </head> <body> <p id="paragraphl"> This is the <em id="emphasisl"> one and only </em> paragraph on the page. </p> </body> </html> To, что отображено в листинге, является объектом document. Объект document созда- ется автоматически при загрузке страницы в браузер. Важно то, что объект document охва- тывает все, что содержится в листинге 14.1. Поэтому в данном случае объект document со- держит один вложенный элемент — HTML. Элемент HTML, в свою очередь, содержит в себе два вложенных элемента: head и body. В элементе head содержится элемент title, а эле- мент title включает фрагмент текста. В элементе body есть элемент р, который состоит из трех частей: фрагмент в виде строки, элемент em и еще одна срока. Следуя терминологии W3C DOM, каждый контейнер, отдельный элемент (как элемент BR в приведенном примере) или фрагмент текста называется узлом. Это фундаментальный строительный блок модели W3C DOM. Когда один контейнер содержит в себе другой, гово- рят, что один узел является родительским, другой — дочерним. Как и в реальной жизни, сис- тема взаимоотношений родительский-дочерний распространяется только на смежные поко- ления. Узел может иметь несколько дочерних узлов или не иметь таковых вообще. Количество узлов третьего уровня (колена), размещенных document +-<html> +—<head> | +-<title> | +—"A Simple Page" +-<body> +—<p ID="paragraph1"> +—"This is the " +-<em ID="emphasis1"> | +-"one and only" +-" paragraph on the page." Puc. 14.3. Дерево структуры уз- лов документа из листинга 14.1 далее в генеалогическом дереве никак не влияет на число дочерних узлов, связанных с родительским узлом. Поэтому согласно листингу 14.1, узел HTML имеет два дочерних уз- ла, a head и body являются узлами-“сестрами” одного и то- го же родительского узла. Элемент body имеет один дочер- ний элемент (р) несмотря на то, что этот дочерний элемент имеет, в свою очередь, три дочерних элемента (два тексто- вых узла и один узел элемента em). Если графически представить иерархическую структуру, заданную в листинге 14.1 , то выглядеть она должна так, как показано на рис. 14.3. В модели W3C DOM, начиная со второй версии, опреде- лено 12 типов различных узлов, семь из которых напрямую 216 Часть III. Объекты документа
используются в документах HTML. Последние приведены в табл. 14.3 (остальные относятся kXML). Из этих 12 типов три являются наиболее общими: документы, элементы и фрагмен- ты текста. В W3C браузерах (IE5+, Mozl и Safari) задействованы все указанные типы узлов. I Если исходный код документа перед дескриптором <html> содержит описание /«•заметку типа документа Document Type Definition (DTD), то браузер будет трактовать узел • DTD как узел-“сестру” элемента HTML. В этом случае родительский узел document содержит два дочерних узла. Тип Номер Имя узла Значение узла Описание IE5+ Moz1 Safari Элемент 1 Имя дескриптора null Любой элемент HTML или XML, имеющий дескрипторы Да Да Да Атрибут 2 Имя атрибута Значение атрибута Пара атрибутов элемента имя-значение Нет Да Да Текст 3 #text Содержимое текста Текстовый фрагмент, содержащийся в элементе Да Да Да Комментарий 8 #comment Текст комментария Документ HTML Нет Да Нет Документ 9 #document null Родительский объект document Нет Да Да Тип документа 10 DOCTYPE null Спецификация DTD Нет Да Нет Фрагмент 11 #document- fragment null Серии из одного или более узлов вне документа Нет Да Да Сравнивая диаграмму структуры страницы, показанной на рис. 14.3, с типами узлов из табл. 14.3 приходим к выводу, что страница состоит из одного узла документа, шести узлов элементов и четырех текстовых узлов. Свойства узлов Узлы имеют широкий набор свойств, большинство из которых являются ссылками на другие узлы, связанные с данным. В табл. 14.4 приведен полный перечень свойств всех типов узлов модели DOM второго поколения. 14.1. ВмАсша абъмсгов умов (модам W3C ЛОМ «Горал поколения) • «.«J. - аямт - • ивяй ' '....«дада Свойство Значение Описание WinlE5+ Mac IE5+ Moz1 Safari nodeName Строка Зависит от типа узла (см. табл, 14.3) Да Да Да Да nodeValue Строка Зависит от типа узла (см. табл. 14.3) Да Да Да Да nodeType Целое число Константа, представляющая типы Частично Да Да Да parentNode Объект Ссылка на следующий Да Да Да Да внешний контейнер Глава 14. Основы объектной модели документа 217
Окончание табл. 14.4 Свойство Значение Описание WinlE5+ MaclE5+Moz1 Safari childNodes Массив Все дочерние узлы в исходном порядке Да Да Да Да firstChild Объект Ссылка на первый дочерний узел Да Да Да Да lastchild Объект Ссылка на последний дочерний узел Да Да Да Да previousSibling Объект Ссылка на предыдущий узел-“сестру" Да Да Да Да nextsibling Объект Ссылка на следующий узел-“сестру" Да Да Да Да attributes Карта узлов NodeMap Массив атрибутов узлов Нет Да Да Да ownerDocument Объект Объект, содержащий документ Нет Да Да Да namespaceURI Строка URL для определения имени (только узлы атрибутов и элементов) Нет Нет Да Да prefix Строка Префикс имени (только узлы атрибутов и элементов) Нет Нет Да Да localName Строка Применимо к узлам с пробелами в имени Нет Нет Да Да заметку Свойства, отображенные в табл. 14.4, вы найдете в главе 15 в списке свойств, которыми в совокупности обладают объекты элементов HTML и которые реали- зованы в IE5+ и Mozilla. Это происходит потому, что элементы HTML, являющие- ся в то же время и узлами, наследуют все свойства прототипа узла. Для того чтобы вам было легче разобраться с ключевыми свойствами узлов, в табл. 14.5 приведены значения для некоторых узлов страницы, описанной в листинге 14.1. Данные этой таблицы следует изучать параллельно со структурой страницы, изображенной на рис. 14.3. Это поможет отследить значения разных узлов. Свойства Узлы document html P "one and only" nodeType 9 1 1 3 nodeName #document html P #text nodevalue null null null "one and only" parentNode null document BODY em previousSibling null null null null nextsibling null null null null childNodes html head "This is the " 218 Часть III. Объекты документа
Окончание табл. 14.5 Свойства Узлы body em " paragraph on the page." firstChild html head "This is the " null lastchild htrnl body " paragraph on the page." null Свойство nodeType является целым числом; его удобно использовать в сценариях при про- смотре набора неизвестных узлов. Большинство из того, что используется в документах HTML, относится либо к типу 1 (элемент HTML), либо к типу 3 (текстовый фрагмент). Внешним кон- тейнером при этом для них является документ (тип 9). Свойство узлов nodeName, как правило, совпадает с именем дескриптора узла HTML (для элементов HTML) или является константой (перед которой стоит символ # — см. табл. 14.3). Что довольно неожиданно, значение свойства nodeValue равно null для всех узлов, кроме узла фрагмента текста. В последнем случае значе- ние указанного свойства равно фактическому содержимому текстовой строки узла. Другими сло- вами, в модели W3C DOM контейнер элементов HTML в виде текстовой строки не используется. Весьма маловероятно, что вы будете задействовать все объектно-ориентированные свой- ства узла. В основном, дело касается способов получения доступа от одного узла к другому. Важное значение имеет свойство parentNode, поскольку оно является ссылкой на содер- жащий данный узел контейнер. Свойства f irstChild и lastchild указывают на первый и последний дочерние узлы внутри контейнера соответственно. Однако в сценариях для про- смотра дочерних узлов, как правило, используется свойство childNodes и цикл повторения for. Если дочерних узлов нет вообще, то длина массива chi IdNodes равна нулю. Методы узлов Действия, приводящие к изменению содержимого узлов в стандарте W3C DOM, подразу- мевают вызов методов, предопределенных для прототипа объекта узла Node. В табл. 14.6 пере- числены такие методы с указанием степени совместимости с браузерами стандарта W3C DOM. -KtPr M .6.объект* м йтмшюсш Метод Описание IE5+ Moz1 Safari appendchild (новыйДочернийУзел) В конец текущего узла добавляется дочерний узел Да Да Да cloneNode (Уровень) Создается копия текущего узла (возможно, с дочерним узлом) Да Да Да hasChiIdNodes() Определяется, содержит ли текущий узел дочерние (логический тип Boolean) Да Да Да insertBefore (новый, Узел) Выполняется вставка одного дочернего (новый) узла перед другим Да Да Да removeChi Id (старый) Удаляется дочерний узел (старый) Да Да Да replaceChild (новый, старый) Старый дочерний (старый) узел замещается НОВЫМ (новый) Да Да Да isSupported (свойство, версия) Определяется, поддерживает ли узел данное СВОЙСТВО (свойство) Нет Да Да Глава 14. Основы объектной модели документа 219
Объектно-ориентированная модель W3C DOM Тем, кто знаком с основами объектно-ориентированного программирования, будет приятно уз- нать, что в модели W3C DOM объектно-ориентированная тенденция выдержана в полной мере. Объект узла Node имеет ряд свойств (табл. 14.4) и методов (табл. 14.6), которые могут насле- доваться любым объектом, производным от объекта Node. Большинство объектов, которые на- следуют характеристики Node, имеют собственные свойства и методы, определяющие особен- ности их поведения. На следующем рисунке показано (с использованием терминологии W3C DOM) структуру дерева наследования, начиная с корневого объекта Node. Большинство эле- ментов этого рисунка определены в базовой части модели DOM. Те же, что выделены полу- жирным шрифтом, определяются в разделе модели, относящемся исключительно к HTML. Node •-Document | +-HTMLDocument +-CharacterData | +-Text | | +-CDATASection | +—Comment +—Attr •—Element | +- HTMLEIement | +- (Each specific HTML element) +-DocumentType +- DocumentFragment •—Notation •-Entity •—Entity Reference •—Processinginstruction Как видно из этого рисунка, отдельные элементы HTML наследуют свойства и методы обще- го для них элемента HTML, который, в свою очередь, является наследственным элементом от базового объекта Element. Последний наследуется от объекта узла Node. При написании сценариев совсем не обязательно помнить структуру наследования объекта узла Node. Она нужна для того, чтобы в дальнейшем легче было разбираться с документа- цией по W3C DOM. Кроме того, теперь понятно, как самые заурядные объекты элементов справляются с таким огромным количеством свойств и методов. Наиболее важными методами, используемыми для изменения содержимого, можно на- звать appendchi ld(), insertBefore (), removechild О и replaceChild (). Обра- тите внимание на следующее: если один из этих методов применяется по отношению к опре- деленному узлу, то данный метод рассматривается как относящийся к родительскому узлу. Например, при удалении узла используется метод removechild () не удаляемого узла, а его родительского узла. Эту особенность можно использовать для создания библиотеки полезных функций, которые определяются без жесткой привязки к иерархической структуре элементам Ниже приведен пример такой достаточно простой функции, выполняющей в сценарии удале- ние элемента из родительского узла. function removeElement(elemID) { var elem = document.getElementByld(elemID); elem.parentNode.removechild(elem); } 220 Часть HI. Объекты документ
По сравнению со стандартной в таких случаях процедурой очистки свойства outerHTML соответствующего объекта в IE4+, предложенный выше метод удаления элементов выглядит несколько мудреным. Хотя такой подход иногда и оправдывает себя в XML, следует при- знать, что группа разработчиков W3C DOM в данном случае интересы сторонников HTML во внимание не приняла. Тем не менее, как будет показано в дальнейшем, не все еще потеряно. Создание содержимого узла Далее мы рассмотрим вопрос о том, как в рамках модели W3C DOM в содержимое стра- ницы вносятся изменения. Способы добавления или замены содержимого с помощью сцена- риев легкими назвать нельзя. Если подобные изменения касаются только текста (например, из- менение текстового содержимого ячейки таблицы), то существует два пути: простой и сложный. При внесении изменений в HTML можно пойти только по сложному пути (несколько полезных советов по этому поводу приведены ниже). Сначала рассмотрим сложные методы, а потом вер- немся к наиболее простым способам изменения текстового содержимого. При создании нового узла в модели DOM используется целый ряд методов объекта document, определяемых в базовой части модели W3C DOM (поэтому они наследуются объектом HTML document). В DOM методы создания узлов определены практически для каждого их типа. При создании документов HTML наиболее важными следует назвать два метода— createElement () и createTextNode (). Первый генерирует элемент с лю- бым дескриптором, имя которого в виде строки передается как параметр метода, а второй создает текстовый узел с текстом, указанным в качестве параметра. Созданный элемент хранится в памяти браузера. В иерархической структуре документа его еще нет. Результатом выполнения метода createElement () будет ссылка на пустой элемент, содержащий, пожалуй, только имя дескриптора. Например, для того чтобы создать элемент Р, нужно использовать такие операторы. var newElem = document.createElement("р"); У нового элемента не будет ни идентификатора id, ни атрибутов, ни содержимого. Для присвоения этому элементу атрибута можно использовать метод setAttribute() (этот метод применим к любому объекту) или присвоить соответствующему свойству объекта зна- чение. Напримёр, чтобы присвоить новому элементу идентификатор, следует воспользовать- ся оператором newElem.setAttribute("id", "newP"); или newElem.id = "newP"; Оба способа можно использовать. Но даже теперь, когда элемент имеет собственный идентификатор, он не является частью документа. Извлечь его с помощью метода document. getElementByld () вам не удастся. Чтобы добавить в абзац содержимое, сгенерируем в виде отдельного объекта текстовый узел. var newText = document.createTextNode("This is the second paragraph.") ; Опять же, этот узел размещается в памяти; подразумевается, что он будет добавлен в ка- честве дочернего к другому узлу. Чтобы введенный таким образом текст стал содержимым абзаца, его можно добавить в качестве дочернего к элементу, размещенному в памяти. newElem.appendChild(newText); Соответствующий код HTML, описывающий новый элемент абзаца, будет иметь такой вид. <р id=l,newP" >This is the second paragraph.</p> Глава 14. Основы объектной модели документа 221
Теперь новый элемент абзаца готов к вставке в документ. В документе со структурой, по- казанной в листинге 14.1, этот дочерний элемент можно добавить к элементу body. document.body.appendchild(newElem); Наконец, новый элемент стал частью иерархической структуры документа. На него теперь можно ссылаться так же, как и на все другие элементы документа. Замена содержимого узла Описанная в предыдущем разделе процедура добавления абзаца приводит к изменению первоначального содержимого страницы— абзац "one and only" теперь далеко не един- ственный на странице (one and only — один-единственный). Как уже отмечалось ранее, изме- нить текстовое содержимое можно либо с помощью метода replaceChiId (), либо при- своив новый текст в качестве значения свойства текстового узла nodeVa lue. Ниже приведен пример использования обоих подходов для изменения содержимого текста элемента ЕМ пер- вого абзаца с "one and only" на "first" (первый). Для того чтобы задействовать метод replaceChild (), сначала в сценарии необходимо сгенерировать текстовый узел с новым текстом. var newText = document.createTextNode("first"); Теперь можно воспользоваться методом replaceChild (). Не забывайте, что этот ме- тод является методом родительского узла по отношению к удаляемому дочернему узлу. В данном случае в качестве родительского узла выступает текст в элементе em. Таким обра- зом, следует вызвать метод replaceChild () элемента em. В методе используется два па- раметра: первый является именем нового узла, а второй представляет собой ссылку на уда- ляемый узел. Поскольку такого рода ссылки в операторах сценария являются достаточно громоздкими, то на промежуточном этапе с помощью метода getElementByld () эта ссылка сохраняется в переменной, которая будет затем использована в качестве параметра. var oldChild = document.getElementByld("emphasisl").childNodes[0]; Теперь в результате вызова метода replaceChild () элемента em старый текст узла бу- дет заменен новым. document.getElementByld("emphasisl").replaceChild(newText, oldChild);. В том случае, если старый узел перед полным удалением нужно перехватить, метод replaceChild () в качестве значения возвращает ссылку на удаляемый узел (который на данном этапе размещается в памяти и не может рассматриваться как часть иерархической структуры документа). Если оператор с методом присвоить переменной, то этот старый узел можно будет в случае необходимости использовать в сценарии. Описанный подход многим покажется слишком нерациональным, особенно если код HTML и так достаточно запутан. К счастью, существует более простой способ заменить один ; текст в элементе на другой. Для этого понадобится только ссылка на замещаемый текстовый узел. Свойству узла nodeValue присваивается строка с новым значением. document.getElementByld("emphasisl").childNodes[0].nodeValue = "first"; 1 Если содержимым элемента является исключительно текст (например, ячейка таблицы! всегда содержит в себе текстовый узел), этот метод вставки текста в W3C DOM будет наибо- лее удобным. Однако в том случае, если необходимо создать второй абзац (как это требова-1 лось ранее) данный подход не сработает. Причина в том, что для использования этого метода! нужно, чтобы узел уже существовал. Поэтому для его создания должен быть задействовав! метод createTextNode(). I 222 Часть III. Объекты Д1
Следует также помнить, что текстовый узел не имеет наследованных стилей. Стиль текста определяется стилем содержащего его элемента HTML. Если у вас есть желание изменить не только сам текст, но и то, как этот текст выглядит, следует внести изменения в свойство Style родительского элемента текстового узла. Браузеры, выполняющие такого рода форма- тирование текстового содержимого и изменение стилей, в этом случае автоматически обно- вят содержимое страницы. Чтобы подвести черту под всем вышесказанным, приведем листинг 14.2, в который по срав- нению с оригиналом документа из листинга 14.1 были внесены определенные изменения. В но- вой версии есть специальная кнопка и сценарий, предназначенные для внесения описанных вы- ше изменений в текстовые узлы. Чтобы увидеть изменения, достаточно перезагрузить страницу. - "Si^ .. лсйвэя мей» KSfdw "-мк. " cap. g — Црфтмг 14.2. ВийМма мммшпмЯ аощцао—°* <html> <head> <title>A Simple Page</title> «script type="text/javascript"> function modify() { var newElem = document.createElement ("p"); newElem.id = "newP"; var newText = document.createTextNode("This Is the second paragraph."); newElem.appendchild(newText); document.body.appendchild(newElem); document.getElementByld("emphasisi").childNodes[0].nodeValue = "first"; } </script> </head> <body> «button onclick="modify()">Add/Replace Text«/button> <p id="paragraphl">This is the <em id="emphasisi">one and only</em> paragraph on the page.</p> </body> </html> В главе 15 детально рассматриваются свойства и методы, наследуемые элементами HTML. Большинство из них реализовано в браузерах IE5+ и W3C DOM. Справку относительно других методов W3C DOM можно найти в разделах главы 18, посвященных объекту document. Фактический стандарт: innerHTML Свойство innerHTML впервые было представлено Microsoft в браузере IE4. Хотя оно и не включено в стандарт W3C DOM, многие пользователи и разработчики успешно применяют его в своих документах. Это свойство позволяет динамически изменять содержимое элемен- тов, представленных HTML-дескрипторами, без необходимости создания и настройки тек- стовых узлов и узлов элементов. Как это ни парадоксально, но большинство браузеров W3C, включая Mozl и Safari, полностью поддерживают свойство innerHTML во всех объектах. При назначении в качестве значения свойства innerHTML уже существующего элемента строки, содержащей дескрипторы HTML, браузер автоматически вставит в дерево узлов новые Глава 14. Основы объектной модели документа 223
элементы. Вы также можете назначать этому свойству строки, не содержащие HTML-дескрип- торы, — таким образом вы приравняете его к свойству innerText, представленному в IE. Несмотря на кажущееся преимущество использования свойства innerHTML, методика поэтапного добавления и изменения текстовых узлов и узлов элементов, с точки зрения брау- зера, кажется более эффективной. Это именно тот случай, когда простой для разработчика код оказывается сложным для браузера. Статичные объекты В объектной модели NN6 DOM (к сожалению, об IE5.X так сказать нельзя) выдержан стиль базового языка JavaScript, обеспечивающий наследование прототипов объектной моде- ли. При загрузке страницы в NN6, основываясь на прототипах каждого из определенных в W3C DOM объектов, браузер создает объекты HTML. Предположим, что для определения типа объекта абзаца туР используется приложение The Evaluator (глава 13). В этом случае в верхнем текстовом поле следует ввести document. getElementByld ("myP") и щелкнуть на кнопке Evaluate. В результате будет выведено сообщение о том, что основой для данного объекта является HTMLParagraphElement — объект модели DOM. Каждый экземпляр объекта элемента Р на странице наследует по умолчанию свойства и методы HTMLParagraph- Element (который, в свою очередь, наследует их от объектов HTMLElement, Element и Node — все они детализированы в JavaScript для спецификации W3C DOM). Прототипам некоторых из этих статичных объектов с помощью сценариев могут быть до- бавлены новые свойства. Для этого используются новые характеристики, добавленные bMozL Два новых метода— _defineGetter_() и _defineSetter_ () — позволяют присвоить объектам в качестве свойств функции. / Эти методы характерны только для Mozilla-совместимых браузеров. Для того /назамп^ чтобы предотвратить возможные коллизии в случае, если в ECMAScript в буду- * щем будут разработаны стандартизованные версии этих характеристик, в их именах (вначале и в конце) необходимо поставить символы подчеркивания. Эти функции будут выполняться каждый раз при вызове свойства (функция, присваивае- мая методом _defineGetter_O) или его изменении (функция, присваиваемая методом' _def ineSetter_ ()). Общим способом использования этих функций является определение их в качестве анонимных функций (глава 33). Ниже приведен пример использования соответ- ствующего синтаксиса для задания прототипам объектов нужного поведения. объект.prototype._defineGetter_("имяСвойства", function ([параметр! [, . . . [, параметр!!] ] ] ) { // Операторы return возвращаемоеЗначение; }) object.prototype._def ineSetter_("имяСвойства", function! [параметр! [, . . . [, параметр!!] ] ] ) { // Операторы return возвращаемоеЗначение; }) Приведенный в листинге 14.3 пример показывает, как в текущем документе элемек HTML добавить свойство (доступное только для чтения). Свойство, в данном случае наз ваемое childNodeDetail, в качестве значения возвращает объект. Объект имеет два св< ства: одно определяет количество дочерних узлов элемента, а второе — количество дочер 224 Часть III. Объекты nt
текстовых узлов. Ключевое слово this в описании функции является ссылкой на объект, для которого и определяется свойство. Поскольку функция запускается каждый раз при обраще- нии к свойству, то все вносимые в сценарии изменения в содержимое страницы после ее за- грузки будут отображаться в возвращаемом свойством значении. «script type="text/javascript"> if (HTMLElement) { HTMLElement.prototype.___defineGetter__("childNodeDetail", function() { var result = {elementNodes:0, textNodes:0 } for (var i = 0; i < this.childNodes.length; i++) { switch (this.childNodes[i].nodeType) { case 1: result.elementNodes++; break; case 3: result.textNodes++; break; return result; }) } </script> Принцип использования этого свойства точно такой же, как и прочих свойств объекта. var BodyNodeDetail = document.body.childNodeDetail; Возвращаемое в данном случае в качестве результата значение свойства является объек- том. Таким образом, для получения доступа к одному из значений свойств можно задейство- вать самый обычный синтаксис JavaScript. var BodyElemNodes Count = document.body.childNodeDetail.elementNodes; Двунаправленная модель событий Несмотря на явное и радикальное отличие моделей событий в NN4 (движение вниз по ие- рархической структуре) и в IE4 (события всплывают вверх по структуре), в модели W3C D0M (вторая версия) сделана серьезная попытка применить обе эти модели. В результате вы сможете обрабатывать события независимо от того, в каком направлении они перемещаются. Для того чтобы избежать конфликтов с уже существующей в моделях событий терминологи- ей, в модели W3C для свойств и методов введено много новых терминов. В некоторых случа- ях приходится использовать характеристики нескольких объектных моделей. В модели событий W3C представлена новая концепция приемника событий. Механизм приема событий основан на указании объекту типа ответной реакции в случае возникновения событий определенного рода (это очень напоминает ситуацию, когда атрибуты обработчиков событий в дескрипторах HTML отвечают на события). Однако в стандартах DOM подчерки- вается, что при определении приемников событий желательно использовать методы, больше ориентированные на сценарии. Так, метод addEventListener () доступен для каждого уз- ла в иерархии документа. С помощью этого метода браузеру можно указать, следует ли со- бытие отправить дальше вверх по иерархической структуре (такое поведение задается по Глава 14. Основы объектной модели документа 225
умолчанию и при использовании обработчиков событий HTML атрибутивного типа), или оно должно захвачиваться на определенном более высоком уровне. Вызываемые приемником событий функции получают всего один параметр, состоящий из объекта события, свойства которого содержат необходимую информацию о событии (например, такие данные, как расположение указателя мыши при щелчке, код нажатой на клавиатуре кла- виши или ссылка на объект назначения). Например, если форма содержит кнопку, которая, в свою очередь, вызывает функцию, выполняющую определенные вычисления, то в W3C DOM наиболее приемлемым будет следующий способ определения обработчика события. document.getElementByld("callButton").addEventListener("click", doCalc, false); Методу addEventListener () передаются три параметра. Первый параметр является строкой с указанием события, которое отслеживается. Второй параметр определяет функцию, вызываемую при наступлении события. Третий параметр — это значение логического типа. Ес- ли такое значение равно true, то это значит, что должен производиться перехват указанного события, когда бы оно ни было направлено к данному объекту. В этом случае вызываемая функ- ция получает нужные данные из передаваемого ей в качестве параметра объекта события. function doCalc(evt) { // Ссылка на форму, содержащую элемент кнопки var form = evt.target.form; var results = 0; // Операторы для выполнения вычислений form, result .value = results; } Чтобы изменить приемник события, сначала используйте метод removeEventListenerO для очистки старого приемника, а затем для присвоения нового примените (с указанием па- раметров) метод addEventListener (). По сравнению с IE4, в модели событий W3C другой является и процедура блокировки вы- полнения событием действий по умолчанию. В IE4 (так же, как и в NN3, и NN4) можно отме- нить предусмотренные по умолчанию действия, заставив обработчик события сгенерировать 1 результат return false. Данный подход остался доступным и в IE5+, однако компания 1 Microsoft предложила использовать новое свойство объекта window.event с именем I returnvalue. Если где-либо в функции, вызываемой обработчиком события, установить это I значение равным false, то событие будет отменено обработчиком прежде, чем обработчик ус-1 пеет что-нибудь выполнить. В модели событий W3C для подобных целей используется метод preventDef ault () объекта события. Метод отменяет выполняемые событием по умолчанию операторы. Он может использоваться в функциях, вызываемых при наступлении события. Детальная информация о событии содержится в объекте события, который подставляется I в функцию обработчика события. Если назначить обработчик событий с помощью метода W3C ! DOM addEventListener () или свойства обработчика событий, то объект события будет передан в обработчик автоматически (как единственный параметр функции обработки события). J function swap(evt) { // операторы обработки объекта события в W3C DOM } Если же события задаются с помощью атрибутов дескриптора, то объект события обяза-1 тельно необходимо включить в вызов функции обработки события. <а href="http://www.example.com" onmouseover="swap(event)"> ' К сожалению, ни в IE5, ни в IE6 для Windows, а также IE5 для Мас синтаксис W3C DOM 1 описания событий применения не нашел. Но вы можете комбинировать в создаваемых доку-1 ментах обе модели обработки событий. Небольшие примеры подобного поведения сценария! приведены далее в этой главе и в главе 25. i 226 Часть III. Объекты документа!
Комбинирование объектных моделей Необходимость создания таких страниц, которые могли бы просматриваться максимально возможным числом браузеров различных типов, находится в прямой зависимости .от того разнообразия моделей браузеров, которые задействованы потенциальными пользователями. Из уже сказанного ранее в этой главе можно сделать вывод, что сценарии, написанные для более старых версий браузеров (Netscape Navigator 2 или Explorer 3), будут, скорее всего, ра- ботать и в браузерах самых последних версий. При этом в них даже не придется вносить из- менения. Однако, если ориентироваться при создании программных продуктов на браузеры старых версий, будет невозможно в полной мере задействовать уникальные возможности, в частности, DHTML, предоставляемые в браузерах последних типов. Поэтому приходится выбирать “золотую середину” между, как минимум, четырьмя классами браузеров (не под- держивающие DHTML, NN4, IE4/5 и браузеры стандарта W3C DOM, который реализован в IE6 и Mozl) и запросами пользователей. Более того, пользовательские запросы со временем изменяются. Например, число пользователей с браузерами, не поддерживающими DHTML hNN4, со временем будет уменьшаться, а доля браузеров Microsoft IE DOM (IE4+) и браузеров стацдарта W3C DOM (IE6+ и Mozl+) — увеличиваться. Если процент пользователей с брау- зерами NN4 относительно небольшой, то можно не беспокоиться по поводу неэффективного использования DHTML в этом браузере и отнести при анализе потенциальной аудитории пользователей с NN4 к группе пользователей с браузерами, не под держивающими DHTML. Для каждого приложения или Web-узла следует заранее разработать стратегию использо- вания сценариев для реализации различных характеристик. При этом помните, что в рамках одного подхода предусмотреть абсолютно все возможные ситуации не удастся. Ориентиро- ваться следует на основные типы браузеров, используемые при посещении узла (для Web- узлов таких типов браузеров достаточно много, для локальной сети может быть и один), а также на предполагаемый уровень использования DHTML. Далее в этом разделе представлены три концептуальных подхода, призванных помочь разработчикам страниц. Они приведены по, так называемой, степени “агрессивности”. Воз- можно, какие-то из них понравятся читателю больше, какие-то — меньше. Однако ознако- миться с ними в любом случае полезно. Консервативный подход В рамках данного подхода подразумевается задействовать относительно скромные воз- можности по взаимодействию пользователя со страницей с помощью форм и средств предва- рительной загрузки изображений. Диапазон поддерживаемых браузеров будет достаточно широк. Среди них — как браузеры, которые управляют сценариями, так и не поддерживаю- щие сценарии программы. Одна версия страницы используется для обслуживания всех посе- тителей независимо от типа браузера. В том случае, если форма предоставляет информацию от пользователя для серверной CGI- программы, которая затем записывает данные в базу данных или выполняет поиск по указанным критериям, для ввода данных целесообразно использовать стандартные элементы формы. В поддерживающих сценарии браузерах можно организовать предварительную проверку кор- ректности введенных в поля формы данных. В этом полезными станут обработчики событий текстового поля onchange и формы onsubmit. Не поддерживающие сценарии браузеры про- игнорируют наличие обработчиков событий и отправят такую форму серверу, какой она есть. В этом случае проверка корректности данных формы полностью возлагается на сервер. В по- следнем случае из-за увеличения объема передаваемых данных скорость работы падает. Для того чтобы реализовать предварительную загрузку изображений, они заключаются в дескрипторы ссылки. Функции предварительной загрузки изображений в такой ситуации Глава 14. Основы объектной модели документа 227
следует вызывать с помощью обработчиков событий ссылки onmouseover и onmouseout Чтобы “отсеять” браузеры первого поколения, в которых изображения в качестве объектов и воспринимаются, в функциях обработчиков событий операторы необходимо задать внутри конструкции if, в условии которой выполняется проверка наличия массив; document. images. Браузеры старого типа, в которых такой массив не используется, ника ких действий выполнять не будут. function imageOn(imgName) { if (document.images) { document.images[imgName].src = onlmages[imgName] .src; Подобные операторы сценария в разделе head предназначены для предварительного кэ ширования изображений в памяти при загрузке страницы. if (document.images) { var onlmages = new Array(); onlmages["home"] = new Image(50,30) ,- onlmages["home"].src = "images/homeOn.gif"; В поддерживающих сценарии браузерах при загрузке страницы можно также с помощьк метода document .write () генерировать новое содержимое, добавляемое на страницу. На- пример, можно сделать так, чтобы страница приветствовала пользователя в зависимости oi времени суток “Доброе утро!”, “Добрый день!” и т.д. Для не поддерживающих сценарии браузеров в этом случае в дескрипторе <noscript> указывается стандартное приветствие “для любого времени суток”. Умеренная концепция В этом случае страницы используют таблицы стилей. Основная идея заключается в том чтобы пользователи всех типов браузеров обращались, как и ранее, к одной и той же версии страницы HTML, но пользователям с браузерами последних версий предоставляются специ- альные возможности (поскольку их браузеры эти возможности поддерживают). Стиль объекта, если он поддерживается браузером, изменяется в ответ на действия пользо- вателя (например, при наведении указателя мыши на ссылку ссылка и ее фон выделяются цве- том). Одним из элементов дизайна страницы является форма, размещаемая в таблице. Если пользователь в определенное текстовое поле вводит значение, внизу таблицы выводится вычис- ленный результат, обычно в качестве содержимого ячейки таблицы (или в другом текстовом поле). При таком подходе придется в определенных местах сценария выполнять сортировку- брау- зеров по типам и версиям в зависимости от того, как используемые свойства трактуются этими браузерами. Тем самым вы “отфильтруете” браузеры старых версий и браузеры, которые не под- держивают сценарии. Такую сортировку лучше (и нужно) проводить, частично или полностью ба- зируясь на методе детектирования объектов (см. ниже). В табл. 14.7 представлены ключевые объекты для описанного подхода с указанием, какими типами браузеров они поддерживаются. Динамические стили Для получения доступа к динамическим стилям в объектных моделях IE4+ и W3C элемен- ты используют свойство style, с помощью которого и можно добраться до настроек табли- цы стилей. Этот факт существенно упрощает жизнь разработчикам страниц, поскольку в ус- ловной конструкции if можно проверить для данного объекта наличие свойства style, а в зависимости от результата проверки выполнить разные операторы (или не выполнить вообще). 228 Часть III. Объекты документа
Характеристика Замечания Динамическая поддержка Вычисление форм Поддерживается в IE4+ и браузерах W3C DOM с помощью свойства style объектов элементов HTML Если только не требуется выполнять проверку данных (режим Y2K) или синтаксический анализ выражений, доступно во всех без исключениях поддерживающих сценарии браузерах Динамическое содержимое IE4+ и браузеры W3C DOM поддерживают возможности DHTML по управлению ячейками таблиц, но в объектных моделях IE и W3C для изменения содержимого ячеек таблицы используются разные подходы. Можно применить также нестандартное, но удобное свойство ячейки innerHTML. В более старых версиях браузеров ячейка должна содержать для отображения результата текстовое поле. Для не поддерживающих сценарии браузеров ячейка должна иметь кнопку для отправки формы в CGI-программу на сервер, в результате чего выполняются необходимые вычисления и возвращается результат на страницу function hilite(elem) { if (elem.style) { elem.style.fontweight = "bold"; > ’ Если обработчик события, генерирующий изменения, размещается внутри обрабатывае- мого элемента (например, обработчик события onmouseover элемента span, содержащего какой-то текст), то соответствующее событие в браузерах, не поддерживающих свойство style, обрабатываться не будет. Хорошо, правда, что браузеры, в которых реализовано свойство style, поддерживают все элементы объектной модели. Для того чтобы обойти не- совпадение в выполнении ссылок на объекты в объектных моделях ЕЕ4+ и W3C, этот объект можно передать в качестве параметра функциям обработчиков событий. <span onmouseover="hilite(this)" onmouseout="revert(this)" onclick=”go(</span> При таком подходе нет необходимости проводить детектирование версий браузеров, по- скольку вызываемая обработчиком события функция не использует специфическую для DOM ссылку на объект. Переменные ветвления Одним больше нравится выполнять детектирование версий браузеров, другим — детекти- рование объектов. В умеренной концепции сортировать браузеры в зависимости от их версии можно путем организации процесса распознавания объектных моделей IE4+ и W3C DOM. Главными действующими лицами при этом будут, как нетрудно догадаться, глобальные пе- ременные. Для начала инициализируем две глобальные переменные. function getlEVersion() { var ua = navigator.userAgent; var lEoffset = ua.indexOf("MSIE "); return parseFloat(ua.substring(IEoffset+5, ua.indexOf(";", leoffset))); } var isIE4 = ((navigator.appName.indexOf("Microsoft") == 0 && parselnt(getlEVersion()) >= 4)); var isW3C = (document.documentElement) ? true : false; Глава 14. Основы объектной модели документа 229
Функция getlEVersion () в данном случае с помощью свойства navigator. userAgent определяет точную версию браузера IE. Обе глобальные переменные имеют значения логиче- ского типа. Хотя каждая из этих переменных хранит какую-то свою информацию, вместе они могут дать очень полезные сведения о браузере. В таблице на рис. 14.4 представлены данные выполнения оператора AND (&&) (логическое "и") в условной конструкции и значения двух глобальных переменных. Например, если нужно, чтобы операторы в условной конструкции выполнялись только для IE4, условие для блока if будет выглядеть так. if (isIE4 && !isW3C) {-.-} isIE4 isW3C isIE4 && is W3C true true IE5+ true false ТолькоIE4 false true Только W3C (не IE) false false Старые браузеры Рис. 14.4. Таблица значений для оператора AND и двух глобальных переменных Поскольку в IE5+ объектные модели Microsoft и W3C перекрываются, то при запуске сцена- рия придется определить используемую модель для каждого случая. Может возникнуть необхо- димость организовать вложенные условные конструкции if. Если, скажем, сначала сценарий будет развиваться по варианту W3C, то IE5+ запустит ветвь сценария с синтаксисом W3C DOM. Динамическое содержимое Глобальные переменные ветвления могут использоваться как функциями, вызываемыми обработчиками событий, так и сценариями, выполняемыми при загрузке страницы. Второй вариант бывает полезен тогда, когда необходимо при загрузке страницы для пользователей одних типов браузеров показывать один документ HTML, а для пользователей других типов браузеров — другой. В таком случае вызывается ячейка таблицы, в которой отображается ре- зультат вычислений формы в HTML. В некоторых браузерах результат отображается в тек- стовом поле таблицы. В не поддерживающих сценарии браузерах для отправки данных фор- мы используется специальная кнопка. В разделе Body страницы в сценарии для отображения результата применяются элемент td и метод document. write (). Для того чтобы в ранних версиях Netscape Navigator не возникало проблем, следует динамически записывать не только содержимое ячейки, но и весь элемент td. Если большое количество пользователей работает со старыми версиями Netscape Navigator, имеет смысл динамически записать всю таблицу. Ниже показано, какой будет структура соответствующей формы и таблицы. <form name="calculator" action="http://xxx/cgi-bin/calculate.pl" onsubmit="return false"> <table> <tr> <td>...</td> «script type="text/javascript"> if (isIE4 || isW3C) { document.write("<td id=1 result1>0</td>"); } else { i 230 Часть III. Объекты документ!
document.write("<td>"); document.write("cinput type='text' name='result' size='10' value=101 />"); document.write("</td>"); } </script> <noscript> <td>Click 'Submit' for Results</td> </noscript> </tr> </table> <noscript> cinput type="submit" /> c/noscript> c/form> В предыдущем программном коде предполагалось, что все другие ячейки таблицы содер- жат текстовые поля, обработчики событий Onchange которых запускают сценарии для вы- полнения вычислений. Эти сценарии выполняются по-разному для браузеров двух различных классов в соответствии с их объектными моделями. function calculate(form) { var results; // Инструкции для вычисления значения переменной results if (is!E4) { document.all.result.innerText = results; } else if (isW3C) { document.getElementByld("result").childNodes[0].nodeValue = results; } else { document.calculator.result.value = results; } } Для того чтобы добавить динамическое содержимое в NN4, придется потрудиться немно- го больше. Решение проблемы обычно заключается в использовании элемента div внутри элемента span. Первый позиционируется на странице жестко, второй — относительно дру- гих элементов. После этого в сценариях можно вызвать метод document. write () для соз- дания нового содержимого глубоко вложенного элемента div. При этом система ссылок бу- дет достаточно сложной, поскольку приходится указывать документы и слои. Однако независимо от того, как далеко разработчик страницы зайдет в своем желании добавить в NN4 динамическое содержимое, браузер NN4 не будет автоматически масштабировать таб- лицы или ячейки, чтобы подогнать их размеры под размеры текста. Без автоматического вос- создания страницы, которая используется в IE5+ и браузерах W3C DOM, запись данных на позиционируемый слой в NN4 не приведет к перемещению остального содержимого страницы. Радикальный подход Под “радикализмом” в данном случае подразумевается желание создавать страницы с наиболее полным использованием возможностей DHTML, включая позиционируемые эле- менты на странице. Ведь перетаскивать элементы так весело! Применение подобного рода характеристик требует предварительного анализа будущей пользовательской аудитории и используемых этой аудиторией типов браузеров. В то время как Глава 14. Основы объектной модели документа 231
некоторые средства DHTML (например, CSS) при работе с браузерами устаревших версий с трудом поддерживаются (содержимое отображается, хотя не всегда в наилучшем виде), с пози- ционируемыми элементами дело обстоит совсем плохо. Дело в том, что в старых версиях брау- зеров атрибуты CSS, отвечающие за размещение элементов на странице, порядок отображения в стеке и режим отображения полностью игнорируются. Когда такая страница загружается в брау- зер поколения ниже четвертого, все элементы упорядочиваются в соответствии с их размещением в исходном коде страницы. И те элементы, которые, предполагалось, будут позиционированны- ми, скрытыми или наложенными на другие элементы, отображаются “в старом добром стиле”. Для того чтобы добиться наибольшего эффекта, при попытке пользователя получить доступ к данному Web-узлу следует провести предварительное тестирование версии браузера, исполь- зуемого этим пользователем. Делать это лучше “на лету”; все браузеры, которые не удовлетво- ряют требованиям страницы, должны отсеиваться заранее. Эти браузеры можно перенаправлять “мимо” данного узла или к другой странице, где они смогут получить необходимую информа- цию (хотя, наверняка, и не в таком привлекательном виде, как на основной странице). Для этих целей создаются индексные страницы ветвления. О них речь уже шла в предыдущей главе. Когда не поддерживающие режим DHTML браузеры будут отфильтрованы, ситуация ста- нет проще, но не до конца. Положительным остается следующий момент: теперь не нужно ломать голову, как предусмотреть всевозможные проблемы с версиями старых, не всегда полностью отлаженных, браузеров. Но все равно придется решать, какую из трех моделей по- зиционирования элементов выбрать: Ш4+, NN4 или W3C. За редким исключением (если ис- пользуются браузеры только одного конкретного типа или те, что поддерживают только один стандарт DOM), наверняка возникнет желание заручиться поддержкой хотя бы для двух из них. Из перечисленных трех моделей модель NN4, с точки зрения взаимодействия с HTML, яв- ляется наилучшей. Если же использовать позиционируемые элементы div и span, то во всех поддерживающих DHTML браузерах, кроме NN4, содержимое страницы будет, скорее всего, отображаться идентично. Поэтому логично было бы в разделе Body ввести сценарий, кото- рый динамически генерирует HTML-код, используя при этом для NN4 дескриптор <1ауег> и позиционируемые элементы <div> для остальных браузеров. / Браузеры IE4+ могут использовать одну и ту же объектную модель, однако к ко- дам DHTML в разных браузерах это не относится. Microsoft внесла изменения • в отдельные атрибуты стилей так, что стандартам CSS больше соответствует 1Е5х В IE6 реализована полная поддержка CSS Level 1 Использование библиотек сценариев Как и с обычными страницами, при использовании динамического содержимого также можно использовать библиотеки сценариев. Библиотеками являются внешние файлы с рас- ширением . j s и содержащие фрагменты'кода сценария. Сценарии могут иметь самое разное назначение (для использования в методе document.write О в начальной странице и для организации взаимодействия с пользователем). Учитывая то, что не поддерживающие DHTML браузеры были уже отсеяны ранее, в таких сценариях остается проверить только то, для какой объектной модели следует загружать библиотеку. var isIE4 = ((navigator.appName.indexOf("Microsoft") == 0 && parselnt(navigator.appVersion) == 4)); var isW3C = (document.documentElement) ? true : false; if (isW3C) { // Приоритетность предоставляется модели W3C IE5+ document.write("«script type=’text/javascript’ src=’page3_W3C.j s1> <" + "\/script>"T; } else if (isIE4) { 232 Часть III. Объекты документа
document.write("<script type='text/javascript1 src='page3_IE4.js'> <" + "\/script>"); } else { document.write("<script type=1 text/javascript' src='page3_generic.js'x" + "\/script>"); } В каждом операторе создания дескриптора <script> используется отдельный файл, ко- торый применим при вызове метода document. write () только в указанных браузерах (особенно в NN4). Когда эти библиотеки будут указаны в коде страницы, в операторах сценария из этих биб- лиотек в дальнейшем можно вызывать функции генерирования конкретного элемента или на- бора элементов в объектной модели HTML, оптимизированной для текущего браузера. Ко- нечно, совсем не обязательно для каждой модели использовать свою библиотеку. Может оказаться удобным хранить все сценарии в одной библиотеке и использовать индексную сор- тировку для разных типов браузеров. Такую сортировку в библиотеках удобно реализовать с помощью глобальных переменных сценария начальной страницы HTML. Библиотеку с по- мощью метода детектирования объектов можно сделать вообще самодостаточной. Обработка событий Благодаря тому, что в модели событий W3C DOM реалйзована схема передачи событий вверх по структуре, практически идентичная той, которая имеется в IE4+, эта модель событий может с успехом использоваться в браузерах стандарта IE4+ и W3C DOM. Тем не менее, не- значительные различия все же есть. В IE4+ объект события не передается в качестве пара- метра функции, вызываемой обработчиком события. Наоборот, объект события IE event яв- ляется свойством объекта окна window. Поэтому в функциях нужно проверять передаваемый параметр; в случае использования IE на его место подставляют объект window. event. function calculate(evt) evt = (evt) ? evt : window.event; // Операторы обработки события } Придется проверять и другие свойства событий в сценарии. Например, в IE целевой объект, получающий событие, называется srcElement, в то время как в W3C DOM это target. Отмена поведения, заданного объекту по умолчанию (например, отменить предоставление формы в случае отрицательного результата проверки правильности ее содержимого) в этих моделях выполняется также по-разному (хотя старый метод возвращения обработчиком со- бытия HTML результата return false будет работать). Более подробно эта тема рассмот- рена в главе 25. Режимы совместимости стандартов Как Microsoft, так и Netscape/Mozilla в свое время создали и использовали в своих браузерах такие средства CSS, которые в будущих стандартах оказались неприемлемыми (в результате противостояния так и не родилась истина). Для компенсации возникшей разницы в поддержи- ваемых объектных моделях и обеспечения разработчика возможностью выбора рабочей среды создатели браузеров решили пополнить HTML новым дескриптором заголовка документа <!DOCTYPE>. С его помощью разработчики могут указать, каким стандартам соответствует создаваемый ими документ: старым или новым. К сожалению, элемент DOCTYPE поддержива- ется только современными версиями браузеров — WinIE6, Мас1Е5 и Mozilla. Глава 14. Основы объектной модели документа 233
Если разница между двумя описанными выше режимами программирования не очень ве- лика, то поддерживаемые в IE6 средства CSS и динамического HTML не всегда совместимы со стандартами. В частности, это касается элементов с рамками, полями и заливкой. К тому же, размер элементов в IE6 изменяется несколько не так, как это принято в стандартах CSS Чтобы перевести современные браузеры в режим поддержки стандартов, вам необходимо включить в верхнюю часть документа следующий элемент. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3,org/TR/REC-html40/loose.dtd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtmll/DTD/xhtmll-frameset.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtmll/DTD/xhtmll-strict.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtmll1.dtd"> Обратите внимание, что старые версии WinIE5, WinIE5.5 полностью игнорируют режим поддержки стандартов и работают исключительно в старом режиме, независимо от указанных в элементе <! DOCTYPE> настроек. Тем не менее, добавление этого дескриптора вполне оправдано, поскольку в современных браузерах переход в режим совместимости является целесообразным. Мы поедем, мы помчимся... В последних двух главах рассматривались вопросы, описывающие базовый язык и объект- ные модели. То, о чем выше шла речь, должен знать и уметь каждый, кто разрабатывает стра- ницы с использованием JavaScript. Главная наша задача— научить читателя самостоятельно принимать решения о приоритетности факторов, влияющих на методы создания страниц. С это- го момента вся ответственность при поиске “золотой середины” ложится на ваши плечи. В следующих главах частей Ш и IV более подробно будут описываться особенности базово- го языка и объектных моделей. Эти знания помогут вам в дальнейшем сориентироваться в том, какие объекты, свойства, методы и обработчики событий разумнее всего использовать в собст- венных программных разработках. Это же относится и к возможности использования браузеров разных типов. Большинство приведенных примеров являются готовыми страницами HTML. Их можно загружать в любой браузер и смотреть, как они выполняются. Используйте приложение The Evaluator (глава 13). С его помощью удобно отслеживать вносимые изменения в файлы и проверять уровень своих познаний JavaScript и характеристик браузеров разных типов. Язык и объектные модели постоянно развиваются и совершенствуются. Объем словаря терминов языка программирования растет просто фантастическими темпами. Чтобы все это освоить, нужно время. Не стоит пытаться запомнить абсолютно все термины. Главное — по- нять основные подходы. Терминология никуда не денется. Упорство и труд все перетрут! 234 Часть III. Объекты документа
Основные объекты HTML-элементов Explorer 4+ и Mozilla-совместимые браузеры задают большой набор объектов, представляющих собой Г “основные” элементы языка HTML и повсеместно приме- k няемые в сценариях. Основные элементы можно разделить г на две группы. Одна группа, в которую входят, например, [ элементы Ъ и strike, определяет стили шрифтов, приме- k няемые к вложенным текстовым последовательностям. По- L требность в подобных элементах (и объектах, представляю- f ’ щих эти элементы) постепенно исчезает по мере того, как Г многие браузеры расширяют поддержку стилевых специфи- s кадий. Вторая группа элементов контекстно изменяет содер- жимое, заключенное в открывающий и закрывающий деск- г рипторы. Примерами контекстных элементов могут служить L hl, blockquote и широко используемый элемент р. Зачас- t тую браузеры используют специальные методы представ- F” ления контекстных элементов по умолчанию (например, увеличенный полужирный шрифт для дескриптора <Ы>), [ *_ однако нельзя считать первичной целью таких дескрипторов получение элементов определенного вида. Ни один формаль- р ный стандарт не указывает явно, что текст внутри элемента em должен быть отображен курсивом: такой стиль стал тра- . дицией лишь благодаря браузерам первых версий. Все эти основные элементы содержат большое количество используемых в сценариях свойств, методов и обработчиков I событий, которые присущи не только основным элементам, но и всем элементам, отображение которых возможно. Это могут быть даже дополнительные, специфические для данного эле- мента свойства, методы и/или обработчики событий, о кото- рых будет рассказано подробно в следующих главах этого об- зора. Общие свойства, методы и обработчики событий для каждого элемента будут подробно описаны лишь в этой гла- ве (кроме случаев, когда с некоторыми объектами связано определенное поведение, ошибка или особенность примене- ния). В последующих главах описание каждого объекта вклю- чает список тех его свойств, методов и обработчиков собы- тий, которые являются уникальными для него и не включают общие элементы (это позволяет избежать трудностей при поиске свойств, специфических для данного объекта).
Общие объекты В табл. 15.1 перечислены все объекты, которые относятся к “основным” в JavaScript, они обладают общими свойствами, методами и обработчиками событий, (см. следующие делы) и не содержат специальных элементов, требующих отдельного рассмотрения. {^сяовкыв обито мммежм ffiW. Объекты форматирования Контекстные объекты ь acronym big address center cite i code nobr dfn rt del ruby div s em small ins strike kbd sub listing sup P tt plaintext u pre wbr samp span strong var xmp Свойства Методы Обработчики событий accessKey addBehavior() onactivate all addEventListener() onbeforecopy attributes appendChild() onbeforecut behaviorUrns applyElement() onbeforedeactivate canHaveChiIdren attachEvent() onbeforeeditfocus canHaveHTML blur() onbeforepaste childNodes clearAttributes() onblur children click() onclick className cloneNode() oncontextmenu clientHeight componentFromPoint() oncontrolselect 236 Часть III. Объекты документ»
Продолжение таблицы Свойства Методы Обработчики событий clientLeft contains() oncopy clientTop detachEvent() oncut clientwidth dispatchEvent() ondblclick contentEdi table fireEvent() ondeactivate currentstyle focus() ondrag dataFld getAdjacentText() ondragend dataFormatAs getAttribute() ondragenter dataSrc getAttributeNode() ondragleave dir getAttributeNodeNS() ondragover disabled getAttributeNS() ondragstart document getBoundingClientRect() ondrop filters getClientRects() onfilterchange firstChild getElementsByTagName() onfocus height getElementsByTagNameNS() onhelp hideFocus getExpression() onkeydown id hasAttribute() onkeypress innerHTML hasAttributeNS() onkeyup innerText hasAttributes() onlosecapture isContentEditable hasChildNodes() onmousedown isDisabled insertAdjacentElement() onmouseenter isMultiLine insertAdj acentHTML() onmouseleave isTextEdit insertAdjacentText() onmoiisemove lang insertBefore() onmouseout language item() onmouseover lastchild isSupported() onmouseup length mergeAttributes() onpaste localName normalize() onp roper tychange namespaceURI releasecapture() onreadystatechange nextSibling removeAttribute() onresize nodeName removeAttributeNode() onresizeend nodeType removeAttribute()NS onresizestart nodeValue removeBehavior() onselectstart offsetHeight removechild() offsetLeft removeEventListener() offsetparent removeExpression() offsetTop removeNode() offsetwidth replaceAdj acentText() outerHTML replaceChild() Глава 15. Основные объекты HTML-элементов 237
Окончание таблицы Свойства Методы Обработчики событий outerText replaceNode() ownerDocument scrollIntoView() parentElement setActive() parentNode setAttribute() parentTextEdit setAttributeNode() prefix setAttributeNS() previousSibling setAttributeNodeNS() readyState setcapture() recordNumber setExpression() runtimestyle swapNode() scopeName tags() scrollHeight scrollLeft scrollTop scrollwidth sourceindex style tabIndex tagName tagUrn title uniquelD urns() Синтаксис Для доступа к свойствам или методам элемента используется следующий код. (IE4+) [document.all.]мдентификаторОбъекта.свойство|метод([параметры]) (IE5+/W3C) document.getElementByld(идентификаторОбъекта).свойство|метод ( [параметры] ) Описание объектов Все объекты, перечисленные в табл. 15.1, представляют в DOM элементы HTML, которые ' влияют или на стиль шрифта, или на контекстное содержимое части элемента HTML. Большой набор свойств, методов и обработчиков событий, связанных с этими объектами, применим, фак- тически, ко всем объектам DOM, представляющим элементы HTML. Все обсуждаемые в этой главе подробности применимы к десяткам объектов, описанных в последующих главах. 238 Часть III. Объекты документа
Свойства accessKey Значение: односимвольная строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Для многих элементов можно указать клавишу (букву, цифру или символ пунктуации), нажатие которой в сочетании с <Alt> (в ОС Win32) или <Ctrl> (в MacOS) активизирует этот элемент. Активный элемент — это тот, который отвечает в данный момент за действия, вы- полняемые с помощью клавиатуры. Если активный элемент находится за пределами видимой области, документ будет прокручен таким образом, чтобы отобразить его на экране (смотрите также метод scrollIntoViewO). Указанный символ может вводиться в верхнем или ниж- нем регистре, однако распознания регистра не происходит. Если один символ присвоить не- скольким элементам, то значение accessKey позволит циклически просмотреть их все. В некоторых случаях браузер Internet Explorer предоставляет свойству accessKey до- полнительные возможности. Например, если значение accessKey присвоить объекту эле- мента label, то активным станет тот элемент формы, которой связан с этой надписью. Кро- ме того, когда активной становится кнопка, нажатие клавший пробела приводит к тому же эффекту, что и щелчок мыши на ней. Обратите внимание на выбор клавиш в качестве значений accessKey. Если присвоить значение, которое обычно используется для доступа к встроенным меню браузера в Windows (например <Alt+F> для обращения к меню Файл), то оно изменит поведение браузера по умолчанию. Для пользователей, которые привыкли управлять меню с клавиатуры, такое ис- пользование комбинаций клавиш может показаться неудобным. Пример В листинге 15.1 приведен пример использования свойства accessKey для управления кла- виатурой при навигации по Web-странице. После загрузки этого сценария измените окно браузера таким образом, чтобы скрыть страницу под второй разделительной линией. Введите символ в раздел Settings и нажмите <Enter> (часто при этом компьютер издает гудок). Далее нажмите <Alt> (в Windows) или <Ctrl> (в Мас) и нажмите эту же клавишу. Вы должны уви- деть элемент, расположенный под второй разделительной линией. <html> <head> <title>accessKey Property</title> <script type="text/javascript"> function assignKey(type, elem) { if (window.event.keyCode ==13) { switch (type) { case "button": document.forms["output"].accessl.accessKey = elem.value; break; case "text": document.forms["output"].access2.accessKey = elem.value; break; Глава 15. Основные объекты HTML-элементов 239
case "table": document.getElementByld("myTable").accessKey = elem.value; } return false; } } c/script> c/head> cbody> chl>accessKey Property Labc/hl> <hr /> Settings:cbr /> <form name="input"> Assign an accessKey value to the Button below and press Return: <input type="text" size="2" maxlength="1" onkeypress=" return assignKey('button', this)" /xbr /> Assign an accessKey value to the Text Box below and press Return: cinput type="text" size="2" maxlength="l" onkeypress="return assignKey('text', this)" ^>cbr /> Assign an accessKey value to the Table below (IE5.5+ only) and press Return: cinput type="text" size="2" maxlength="1" onkeypress="return assignKey('table', this)" /> c/form> cbr /> Then press Alt (Windows) or Control (Mac) + the key.<br /> cem>Size the browser window to view nothing lower than this line.c/em> chr / > cform name="output" onsubmit="return false"> cinput type="button" name="accessl" value="Standard Button" /> cinput type="text" name="access2" /> c/form> ctable id="myTable" cellpadding="10" border="2"> ctr> cth>Quantityc/th> cth>Descript ionc/th> cth>Pricec/th> </tr> ctbody bgcolor="red"> ctr> ctd width="100">4c/td> ctd>Primary Widgetc/td> ctd>$14.96c/td> </tr> ctr> ctd>10c/td> ctd>Secondary Widgetc/td> ctd>$114.96c/td> c/tr> c/tbody> c/table> c/body> c/html> См. также метод scrollintoView (). 240 Часть III. Объекты документа
all Значение: массив вложенных объектов элементов Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство all представляет собой набор (массив) всех элементов HTML и (в IE5+) дескрип- торов XML в области действия текущего объекта. Элементы массива расположены в таком же порядке, как в исходном коде. Массив не включает в себя текстовое содержимое элементов. Для элементов-контейнеров языка HTML порядок появления в исходном коде зависит от позиции открывающего дескриптора элемента, а закрывающие дескрипторы не учитываются. Для элементов языка XML все закрывающие дескрипторы включаются в массив отдельно. Каждый набор document. all содержит объекты элементов html, head, title и body даже тогда, когда они опущены в исходном коде. Объектная модель создает эти объекты для каждого документа, загруженного в окно или фрейм. Если ссылка document .all имеет наиболее общее применение, то свойство all существует для любого элемента-контейнера. Например, document.forms [0] .all предоставляет доступ ко всем элементам, опреде- ленным в первой форме документа. Доступ к любому элементу возможен благодаря указанию идентификатора, присвоенного его атрибуту id, в строковой форме (а также целочисленного индекса). Вместо использова- ния малоэффективной функции eval () для преобразования строки в ссылку на объект дос- таточно просто указать имя элемента как индекс массива. var paragraph = document.all["myP"] Internet Explorer для индексов одного набора позволяет использовать и квадратные, и круг- лые скобки. Два следующих примера выполняются одинаково. var paragraph = document .all ["myP11 ] var paragraph = document.all("myP") В тех редких случаях, когда несколько элементов набора all имеют одинаковый иденти- фикатор, синтаксис, в котором представлен строковый индекс, отвечает набору идентично именованных элементов. Тем не менее, можно воспользоваться вторым аргументом (в круг- лых скобках) для указания целочисленного индекса в исходном наборе, соответствующем оп- ределенному элементу. var secondRadio = document.all("groupO", 1) Более приемлемым вариантом для доступа к элементам набора является метод item() (о нем рассказано далее в этой главе). var secondRadio = document.all.item("groupO",1) Для извлечения из набора определенного поднабора элементов, названия дескрипторов которых соответствуют заданному критерию, используется метод tags () (подробнее о нем рассказано далее в этой главе). Свойство all браузера IE эмулируется в некоторых других типах браузеров. Фрагмент кода, необходимый для этого, приведен в главе 18 (используется метод document. getElementByld ()). Пример Используйте приложение Evaluator (глава 13) для изучения коллекции all. Введите в нижнее текстовое поле одно из следующих выражений. Для каждого из них внимательно изучите возвращаемый результат. document.all туТаЫе. all myP.all Глава 15. Основные объекты HTML-элементов 241
Если вы встретите в коллекции нумерованный элемент, то сможете определить, какой де- скриптор сопоставляется с этим элементом. Например, если для элемента document. all возвращен результат document.all. 8= [object], то введите в самое верхнее поле сле- дующее выражений. document.al1[8].tagName См. также методы item (), tags (). attributes Значение: массив, содержащий атрибуты объекта Только для чтения Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safari+ Свойство attributes представляет собой массив атрибутов, заданных для элемента. В брау- зере IE5+ этот массив содержит каждое возможное свойство, определенное для элемента,— даже в том случае, когда атрибут не указан в дескрипторе HTML явно. Кроме того, любые атри- буты, заданные при выполнении сценария, например с помощью метода setAttributeO, не изменяют значений массива. Другими словами, в IE5+ массив attributes зафиксирован таким образом, что все атрибуты, не указанные явно в дескрипторе HTML, принимают значе- ния по умолчанию. Свойство attributes в браузерах Mozilla возвращает массив, называемый картой име- нованных узлов (в терминологии W3C DOM), а также объект со своими свойствами и мето- дами, с помощью которых сохраняются и считываются значения атрибутов. Например, для доступа к индивидуальным объектам атрибутов в W3C DOM можно воспользоваться метода- ми getNamedltem (имяАтрибута) и item (индекс). В IE5+ и Mozl+ реализованы различные представления о том, каким должен быть объект атрибута. В табл. 15.2 приведены свойства объекта атрибута, определенные в двух объектных моделях. Больший набор свойств в Mozl+ указывает на зависимость объектной модели брау- зера от модели наследования узлов W3C DOM, которая была рассмотрена в предыдущей главе. •ЙСТМ PvMCTtAttribute Свойство IE5+ Moz1+ Описание attributes Нет Да Массив вложенных объектов атрибутов (null) childNodes Нет Да Массив дочерних узлов firstChild Нет Да Первый дочерний узел lastchild Нет Да Последний дочерний узел localName Нет Да Имя в текущей области определения name Нет Да Имя атрибута nameSpaceURI Нет Да URI пространства имен XML nextSibling Нет Да Следующий узел-“сестра” nodeName Да Да Имя атрибута nodeType Нет Да Тип узла (2) nodeValue Да Да Значение, присвоенное атрибуту ownerDocument Нет Да Ссылка на Объект document ownerElement Нет Да Ссылка на узел элемента parentNode Нет Да Ссылка на родительский узел 242 Часть III. Объекты документа
Окончание табл. 15.2 Свойство IE5+ Moz1+ Описание prefix Нет Да Префикс пространства имен XML previousSibling Нет Да Предыдущий узел-“сестра” specified Да Да Указывает, был ли атрибут задан в дескрипторе явно (значение логического типа) value Нет Да Значение, присвоенное атрибуту Наиболее полезным является свойство specified, имеющее логический тип. В IE оно позволяет узнать, указан ли атрибут в дескрипторе явно. Поскольку в Mozl браузер возвра- щает только атрибуты, заданные явно, это значение всегда истинно. Пример Используйте приложение Evaluator (глава 13) при изучении массива attributes для от- дельных элементов документа. Введите каждое из приведенных ниже выражений в нижнее поле; возвращаемый массив значений вы увидите в поле Results. document.body.attributes document.getElementByld("myP").attributes document.getElementByld("myTable").attributes ВIE5+ и W3C DOM-совместимых браузерах сравните возвращаемые в каждом случае ре- зультаты. Для ознакомления со свойствами отдельного атрибута в WinIE5+ в нижнем поле введите следующее выражение. document.getElementByld("myP").attributes["class"] В браузерах MacIE5 и W3C DOM используется следующий синтаксис. document.getElementByld("myP").attributes.getNamedltem("class") См. также методы getAttribute (), mergeAttributes (), removeAttribute (), setAttribute (). behaviorUrns Значение: массив URN-строк поведения Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Свойство behaviorUrns предназначено для того, чтобы содержать список адресов в фор- ме URN (Uniform Resource Names — унифицированных имен объектов) всех типов поведе- ния, назначенных текущему объекту. При отсутствии поведений длина массива равна нулю. Однако на практике IE5+ всегда возвращает массив пустых строк. Возможно, потенциальным влиянием сценария на список URN является риск потери конфиденциальности. Следующая функция используется в более сложных HTML-поведениях, поддерживаемых в WinlE (см. листинг 15.19). Она возвращает длину массива behaviorUrns, а также отображает URL-адрес присоединенного поведения (в случае возвращения значения). function showBehaviors() { var num = document.getElementByld("myP").behaviorUrns.length; var msg = "The myP element has " + num + " behavior(s). if (num >0) { msg += "Name(s): \r\n"; for (var i = 0; i < num; i++) { msg += document.getElementByld("myP").behaviorUrns [i] + "\r\n"; Глава 15. Основные объекты HTML-элементов 243
} alert(msg); } См. также метод urns (). canHaveChildren Значение: булевого типа Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Полезное в некоторых ситуациях при обработке динамического содержимого свойство canHaveChildren показывает, может ли определенный элемент содержать дочерние эле- менты (вложенные элементы). Большинство элементов, содержащих открывающий и закры- вающий дескрипторы (в частности, основные элементы, о которых рассказано в этой главе), могут содержать вложенные элементы. В современных объектных моделях вложенный эле- мент называется дочерним элементом своего родительского контейнера. Пример В листинге 15.2 приведен пример использования свойства canHaveChildren для визу- ального распознавания элементов документа, которые имеют вложенные элементы. В данном случае различие между объектами, имеющими вложенные элементы, и объектами, не имею- щими таковых, задается специальным цветом. Первая кнопка на странице позволяет окрасить каждый отображаемый на экране объект документа красным цветом (изменяется свойство color). Таким образом, все элементы документа (даже не имеющие дочерних элементов, Hit пример, hr и input) приобретают указанный цвет. Если же щелкнуть на большей кнопке, тс j цвет изменит только те объекты, которые имеют вложенные элементы. <html> <head> <title>canHaveChildren Property</title> «script type="text/javascript"> function colorAHO { var elems = document.getElementsByTagName("*"); for (var i = 0; i < elems.length; i++) { elems[i].style.color = "red"; } } function colorChildBearingO { var elems = document.getElementsByTagName("*"); for (var i = 0; i < elems.length; i++) { if (elems[i].canHaveChildren) { elems[i].style.color = "red"; </script> </head> <body> <hl>canHaveChildren Property Lab</hl> <hr /> 244 Часть III. Объекты докум&
«form name="input"> «input type="button" value="Color All Elements" onclick="colorAll () " />«br /> «input type="button" value="Reset" onclick="history.go(0)" /> <br / > «input type="button" value="Color Only Elements That Can Have Children" onclick="colorChildBearing()" /> «/form> <br /> «hr /> «form name="output"> «input type="checkbox" checked="checked" />Basic checkbox .«input type="text" name="access2" value="Some text." /> «/form> «table id="myTable" cellpadding="10" border="2"> <tr> <th>Quantity«/th> <th>Description«/th> «th>Price«/th> «/tr> «tbody> <tr> «td width="100">4«/td> <td>Primary Widget«/td> <td>$14.96«/td> </tr> <tr> «td>10«/td> «td>Secondary Widget«/td> <td>$114.96«/td> </tr> «/tbody> «/table> «/body> </html> См. также: свойства childNodes, firstChild, lastCh|ld, parentElement, parentNode; методы appendChild (), hasChildNodes (), removechild (). canHaveHTML Значение: булевого типа Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Не все (хотя многие) элементы HTML являются контейнерами HTML-кода. Свойство canHaveHTML позволяет сценарию проверить, может ли определенный объект включать HTML-код, например при вставке или замене методами объекта. Для элемента р, например, данное свойство имеет значение true, а для элемента Ьг — false. Пример Используйте приложение Evaluator (глава 13) для изучения свойства canHaveHTML. Вве- дите каждое из приведенных ниже выражений в нижнее поле; возвращаемый массив значе- ний вы увидите в поле Results. document.getElementByld("input").canHaveHTML document.getElementByld("myP").canHaveHTML Глава 15. Основные объекты HTML-элементов 245
Первое выражение возвращает значение f al se, поскольку элемент input (в данном случае верхнее текстовое поле) не имеет вложенных HTML-элементов. Наряду с этим элемент myP принимает HTML-содержимое. См. также методы appendchild(), insertAdj acentHTML(), insertBefore(). childNodes Значение: массив объектов узлов Только для чтения Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство childNodes представляет собой массив объектов узлов, содержащихся в те- кущем объекте. Обратите внимание, что дочерние узлы состоят из объектов элементов и текстовых узлов. В зависимости от содержимого текущего объекта, количество элементов в childNodes и число наборов дочерних узлов могут отличаться. Если массив childNodes просматривается в цикле for с целью обработки по- следовательности элементов HTML (или XML), помните, что браузер может вос- I принимать пробелы в исходном коде (пустые строки или простые символы раз- gj^ рыва строки между элементами) как текстовые узлы. Эта потенциальная проблема присутствует в Mac IE5 и Moz1 (возможно, она будет исправлена в по- следующих версиях). Лишние текстовые узлы, если они присутствуют в докумен- те, как правило, окружают блоковые элементы. Большая часть циклов, просматривающих массив childNodes, предназначена для проверки, подсчета или изменения узлов элементов внутри набора. Если та- ковой является задача и вашего сценария, то до выполнения обработки про- верьте каждый узел из массива childNodes и убедитесь, что свойство nodeType имеет значение 1 (элемент). В ином случае такой узел необходимо пропустить. Примерная структура цикла выглядит следующим образом. for (var i = 0; i < myElem.childNodes.length; i++) { if (myElem. childNodes [i] .nodeType == 1) { операторы обработки i-го узла Присутствие “скрытых” текстовых узлов влияет также и на свойства f irstchild и lastchild, описанные далее в этой главе. Пример В листинге 15.3 содержится пример функции просмотра дочерних узлов заданного роди- тельского узла. Функция walkChildrenNodes (), представленная в листинге, собирает сведения и возвращает иерархическую структуру дочерних узлов для HTML-элемента доку- мента (по умолчанию) или любого другого элемента, идентификатор которого подставлен в качестве аргумента. Эта функция встроена в приложение The Evaluator, поэтому структура дочерних узлов указывается именно для этой страницы. Введите в верхнем поле приложения The Evaluator следующие выражения. walkChildNodes() walkChildNodes(getElementByld("myP")) Результат, возвращаемый функцией, представляет взаимоотношения между дочерними узлами заданного элемента. Функция просматривает вложенные элементы до самого ниж- него уровня (пока все они не будут каталогизированы). Узлы подписываются соответст- вующим образом, чтобы их можно было легко идентифицировать и сравнить с элемент! исходного HTML-кода. 246 Часть III. Объекты доку/
function walkChildNodes(objRef, n) { var obj; if (objRef) { if (typeof objRef == "string") { obj = document.getElementByld(objRef); .} else { obj = objRef; } else { obj = (document.body.parentElement) ? document.body.parentElement : document.body.parentNode; } var output = "" ; var indent = ""; var i, group, txt; if (n) { for (i = 0; i < n; i++) { indent += "+-------"; } else { n = 0; output += "Child Nodes of <" + obj.tagName; output += ">\n=====================\n"; group = obj.childNodes; . for (i = 0; i < group.length; i++) { output += indent; switch (group[i].nodeType) { case 1: output += "<" + group [i] . tagNpime; output += (group[i].id) ? " ID=" + group[i].id : ""; output += (group[i].name) ? " NAME=" + group[i].name : ""; output += ">\n"; break; case 3 : txt = group[i].nodeValue.substr(0,15); output += "(Text:\"" + txt.replace(/[\r\n]/g,"<cr>"); if (group[i].nodevalue.length > 15) { output output += "\"]\n"; break; case 8 : output += "[!COMMENT!]\n"; break; default: output += "[Node Type = " + group[i].nodeType + "]\n"; } if (group[i].childNodes.length > 0) { output += walkChildNodes(group[i], n+1); return output; См. также: свойства nodeName, nodeType, nodevalue, parentNode; методы cloneNode(), hasChildNodes(), removeNode(), replaceNode(), swapNode(). Глава 15. Основные объекты HTML-элементов 247
children Значение: массив объектов элементов Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство children представляет собой массив объектов элементов, содержащихся в те- кущем объекте. В отличие от свойства childNodes, свойство children не учитывает тек- стовые узлы, а следует иерархии элементов HTML (и XML) с точки зрения текущего объекта. Текущий объект “видит” только прямые дочерние элементы. Если необходимо обратиться ко всем объектам элементов, вложенным внутрь данного объекта (независимо от уровня их вло- женности), следует воспользоваться набором all. Пример В листинге 15.4 продемонстрировано, как с помощью свойства children можно про- смотреть все дочерние узлы заданного элемента. Эта функция собирает сведения и возвраща- ет иерархическую структуру дочерних узлов для HTML-элемента документа (по умолчанию) или любого другого элемента, чей идентификатор которого подставлен в качестве аргумента. Эта функция встроена в приложение The Evaluator, поэтому структура дочерних узлов указы- вается именно для этой страницы. Введите в верхнем поле приложения The Evaluator, запу- щенного в IE5+, следующие выражения. walkchildren() walkchildren ("myP") Результат, возвращаемый функцией, представляет взаимоотношения между дочерними узлами заданного элемента. Функция просматривает вложенные элементы до самого нижнего уровня, пока все они не будут каталогизированы. Узлы подписываются соответствующим образом, что-, бы их можно было легко идентифицировать и сравнить с элементами исходного HTML-кода. function walkchildren(objRef, n) { var obj; if (objRef) { if (typeof objRef == "string") { obj = document.getElementByld(objRef); } else { obj = objRef; } } else { obj = document.body.parentElement; } var output = ""; var indent = ""; var i, group; if (n) { for (i = 0; i < n; i++) { indent += " + " ; } } else { n = 0; output += "Children of <" + obj.tagName; output += ">\n=====================\n"; } group = obj.children; 248 Часть III. Объекты
;ч for (i = 0; i < group.length; i++) { output += indent + "<" + group[i].tagName; output += (group[i].id) ? " ID=" + group[i] .id : ""; output += (group [i] .name) ? " NAME=" + group[i].name : ""; output += ">\n"; if (group[i].children.length > 0) { ,- output += walkchildren(group[i], n+1); } } return output; 2 См. также: свойства canHaveChildren, firstChild, lastchild, parentElement; ;методы appendChild(), removechild(), replaceChild(). className Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari+ Имя класса— это идентификатор, присвоенный атрибуту class элемента. Чтобы навя- зать правило CSS нескольким элементам документа, следует присвоить один и тот же иден- тификатор атрибуту class этих элементов и использовать его (с точкой в начале) при выбо- ре правила CSS. Свойство className позволяет применять различные правила CSS при ‘ управлении из сценария. Пример Стиль элемента имеет два состояния: “подключен” и “отключен”. В листинге 15.5 свойст- ву className назначается либо пустая строка, либо имя класса CSS-стиля. Если это свойст- ' во приравнивается пустой строке, то элемент hl форматируется соответственно правилам по умолчанию. Когда же вы щелкаете на кнопке, форматирование задается CSS-стилем, а не стандартными правилами. <html> <head> <title>className Property«/title> «style type="text/css"> .special {font-size:16pt; color:red} </style> «script type="text/javascript"> function togglespecialstyle(elemID) { var elem = (document.all) ? document.all(elemID) : document.getElementByld(elemID); if (elem.className == " ") { elem.className = "special"; } else { elem.className = } } «/script» «/head» «body» Глава 15. Основные объекты HTML-элементов 249
<hl>classNatne Property Lab</hl> <hr /> < form name ="input"> cinput type="button" value="Toggle Class Name" onclick="toggleSpecialStyle('headl')" /> </form> cbr /> chi id="headl">ARTICLE Ic/hl> cp>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.c/p> chl>ARTICLE IIc/hl> cp>A well regulated militia, being necessary to the security of a free state, the right ,of the people to keep and bear arms, shall not be infringed.c/p> c/body> c/html> Вы можете создать несколько вариантов правила стиля с различными идентификаторами выбора класса. См. также: объекты rule, stylesheet (глава 26); свойство id. clientHeight clientwidth Значения: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN7, Mozl+, Safari+ Два этих свойства содержат высоту и ширину содержимого элемента в пикселях. Их сти- ли позволяют задавать параметры высоты и ширины. Теоретически эти величины не учиты- вают отступы, границы или поля, определяемые в таблицах стилей. Однако на практике раз- личные комбинации границ, отступов и полей влияют на эти значения самым неожиданным образом. Один из наиболее надежных способов применения свойства clientHeight позво-' ляет, например, определить, где заканчивается текст переполненного элемента. Для объекта document.body свойства clientHeight и clientwidth возвраща! внутреннюю высоту и ширину окна или фрейма (плюс-минус несколько пикселей). Данн свойства замещают собой необходимые, но не существующие в IE, свойства окна. В браузере Internet Explorer 5+ почти все объекты, представляющие элементы HTML, с держат эти свойства. В 1Е4 эти свойства применимы только к следующим объектам: bod button, caption, div, embed, fieldset, legend, marquee, table, td, textarea, thHtr. Пример В листинге 15.6 для IE содержится пример динамического изменения содержимого ст ницы. В данном примере используются свойства clientHeight и clientwidth элеме div, который представляет на странице текст абзаца. В таблице стилей задается только i рина элемента div, поэтому текст абзаца вводится в документе в виде столбца. Свойс clientHeght определяет высоту этого столбца. С его помощью на странице определяс место отображения логотипа, который обычно располагается сразу же под объектом div, зависимо от количества введенного в абзац текста. 250 ЧастьШ. Объекты д<
<html> <head> «title>clientHeight and clientwidth Properties«/title> «script type="text/javascript"> function showLogoO { var paragraphW = document.getElementByld("myDIV”). clientwidth; var paragraphH = document.getElementByld("myDIV"). ' clientHeight; // устранение различия платформ Windows/Мас var paragraphTop = (document.getElementByld("myDIV"). clientTop) ? document.getElementByld("myDIV").clientTop : document.getElementByld("myDIV").offsetTop; var logoW = document.getElementByld("logo").style.pixelwidth; // горизонтальное центрирование логотипа в абзаце document.getElementByld("logo").style.pixelLeft = (ParagraphW-logoW) / 2; // Расположение изображения в конце абзаца document.getElementByld("logo").style.pixelTop = paragraphTop + paragraphic- document. getElementByld ("logo") .style.visibility = "visible"; } </script> </head> <body> «button onclick^"showLogo()">Position and Show Logo Art«/button> «div id="logo" style="position:absolute; width:120px; visibility:hidden"> «img alt="image" src="logo.gif" /> «/div> «div id="myDIV" style="width:200px"> «p>Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.«/p> «/div> «/body> «/html> Чтобы правильно рассчитать расположение логотипа, примите во внимание, что свойство offsetTop задает расположение элемента div относительно его контейнера (объекта body). Пользователи Mac IE для этих целей применяют также свойство clientTop. В таком случае расположение логотипа рассчитывается следующим образом: к значению offsetTop прибав- ляется значение clientTop для элемента div (заносится в переменную paragraphTop). См. также свойства of f setHeight, offsetwidth. clientLeft clientTop Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Глава 15. Основные объекты HTML-элементов 251
Назначение и имена свойств clientLeft и clientTop не совпадают. В отличие от clientHeight и clientwidth, которые соответствуют размеру содержимого элемента, свойства clientLeft и clientTop возвращают информацию о ширине границы элемен- та — при условии, что элемент позиционируемый. Если граница не задана или же элемент не позиционирован, эти значения равны нулю (хотя объект document. body может определить толщину в несколько пикселей в каждом из случаев). Если вам требуется вычислить левую верхнюю координату элемента, более подходяпщми в WinlE являются свойства of f setLeft и of f setTop; однако, как показано в листинге 15.6, свойство clientTop возвращает впол- не пригодное для использования в MacIE значение. В сущности, в IE5+ все элементы имеют свойства clientLeft и clientTop; в IE4 такие свойства присущи только объектам body, button, caption, embed, fieldset, legend, marquee и textarea. См. также свойства of fsetLef t, of fsetTop. contentEditable Значение: булевого типа Чтение/Запись Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- B IE5.5 представлена концепция редактируемого HTML-содержимого страницы. Дескрипто- ры элементов могут включать атрибут contenteditable, значение которого содержится в свойстве элемента contentEditable. По умолчанию значение этого свойства равно inherit; таким образом, свойство наследует установки контейнеров иерархической структуры HTML за пределами тела элемента. Если свойство contentEditable имеет значение true, то элемент и все вложенные в него элементы наследуют это значение, делая содержимое редак- тируемым; и наоборот, значение false отключает возможность изменения содержимого. Пример В листинге 15.7 продемонстрировано использование свойства contentEditable, кото- рое позволяет редактировать текст Web-страницы. При щелчке на кнопке загруженной стра- ницы выполняется функция toggleEdit (), которая изменяет состояние “редактируемости” текста на противоположное. Переключение состояния выполняется с помощью свойства contentEditable элемента div. Для большего эффекта текст абзаца приобретает краснь цвет — таким образом сразу становиться ясно, какой элемент страницы подвергается изменению. ЛйсЭДг 15.7. Мйшльэое»ммёвгёгта conteuatK^ltebl* <html> <head> «style type="text/css"> .normal {color: black} .editing {color: red} </style> «script type="text/javascript"> function toggleEdit() { var newState = JeditableText.isContentEditable; editableText.contentEditable = newState; editableText.className = (newState) ? "editing" : "normal"; editBtn.innerText = (newState) ? "Disable Editing" : "Enable Editing"; } </script> <title> </title> 252 Часть III. Объекты at
. </head> t, <body> <hl>Editing Contentsc/hl> chr /> <p>Turn on editing to modify the following text:c/p> <div id="editableText"> Edit this text on the fly.... </div> <pxbutton id="editBtn" onclick="toggleEdit()" onfocus="this.blur () ">Enable Editing</buttonx/p> </body> </html> См. также свойство isContentEditable. Только для чтения currentStyle Значение: объект style Совместимость: WinIE5+, MacIE5+, NN-, Moz-, Safari- Каждый элемент имеет атрибуты стилей, даже если ими являются настройки браузера по ь умолчанию. Так как объект style элемента отражает только те свойства, которые были явно . .установлены операторами определения CSS-стилей, свойством style объекта element нельзя t воспользоваться для чтения настроек стилей, примененных к элементу. Именно здесь и ока- швается полезным свойство currentstyle. Эго свойство возвращает предназначенный только для чтения объект style, содержащий значения всех свойств style, применимых к элементу. Если свойство style установлено опе- ратором CSS явно или командами сценария, считывание свойства приводит к получению пра- вильного значения. Таким образом, сценарий может запросить каждое свойство для проверки . необходимости внесения изменений. Например, если текст находится внутри дескриптора ‘ <еш>, браузер по умолчанию использует для шрифта курсивное начертание. Это свойство никак >;ие отражается в объекте style элемента (свойство fontstyle), поскольку курсив не был ус- • I тановлен средствами CSS; с другой стороны, свойство currentstyle. fontstyle объекта L. element содержит реальное свойство fontstyle, соответствующее курсивному шрифту. , Пример г Для изменения свойства style вам необходимо обратиться к объекту style. Ис- ' пользуйте приложение The Evaluator (глава 13) для сравнения этого свойства в объектах currentstyle и style. Например, неизмененная копия приложения содержит элемент ет, •/ который имеет идентификатор myEm. Введите в нижнее поле выражение document. get - ElementByld ("туЕт"). style и нажмите <Enter>. Обратите внимание, что для большинства свойств значения не заданы. Теперь введите в нижнее поле выражение document .getElementByld ("myEm") . currentstyle. Теперь в результате у каждо- ь го свойства будет определенное значение. 1 См. также объекты runtimestyle, style (глава 26); window.getComputedStyle О в W3C DOM-совместимых браузерах (глава 16). dataFld f dataFonnatAs ' dataSrc Значение: строка Совместимость: WinIE4+, MacIE5, NN-, Moz-, Safari- Чтение/Запись Глава 15. Основные объекты HTML-элементов 253
Свойства dataFld, dataFormatAs и dataSrc (вместе с такими специфическими для элемента свойствами, как dataPageSize и recordNumber) являются частью средств Internet Explorer внедрения данных с помощью элементов управления ActiveX. Internet Explorer версии 4 и выше для Win32 имеет несколько объектов ActiveX, которые встроены в браузер и используются для прямой передачи данных между Web-страницей и их источни- ком. К источникам данных относят текстовые файлы, файлы XML, HTML и внешние базы данных. Внедрение данных является довольно серьезной темой, включающей обсуждение DSO (Microsoft Data Source Objects — объекты источников данных Microsoft), ODBC и JDBC. Внедрение данных является мощным средством и используется не только администраторами баз данных. Поэтому обсуждение трех основных свойств— dataFld, dataFormatAs и dataSrc — затрагивает тему внедрения данных. С помощью средств внедрения данных любая страница способна получить доступ, сортировать, отображать и фильтровать (но не обновлять) данные, загруженные на страницу из внешнего текстового файла (обычно симво- лом-разделителем данных является запятая или символ табуляции). Загрузить данные из внешнего текстового файла в документ позволяет средство TDC (Tabular Data Control — управление табличными данными). Ссылка на данные задается с помощью объекта TDC внутри дескриптора <obj ect > и дополнительных параметров (например, URL текстового файла и символа-разделителя). Элемент obj ect может находиться в любом месте документа внутри дескрипторов body. (Обычно их размещают в нижней части кода, чтобы' отображение страницы происходило перед загрузкой элемента управления.) Ссылка на дан- ные просто указывает их расположение браузеру, но сам по себе код страницы не отображает; данные на странице. Тем, кому не приходилось работать со встроенными объектами в IE, значение атрибута classidl может показаться несколько странным. Некоторых пугает вид используемого для идентификации^ данных значения GUID (Globally Unique Identifier — глобальный уникальный идентификатор) j объекта. Это значение необходимо указывать точно так, как показано в следующем примере,! чтобы элемент ActiveX мог запуститься. Объект имеет в HTML следующий синтаксис. cobject ID="objName" CLASSID=’’clsid:333C7BC4-460F-11D0-BC04 . -0080С7055А83"> J <param name="DataURL" value="url"> [необязательные дополнительные параметры] </object> 1 В табл. 15.3 перечислены параметры, доступные для использования в объекте TDC. Обяза-1 тельным является только параметр DataURL; остальные (например FieldDelim, UseHeaderJ RowDelim и EscapeChar) используются в зависимости от природы источника данных. 1 Описание Параметр CharSet DataURL EscapeChar FieldDelim Language TextQualifier Кодовая страница исходного файла с данными. Значение по умолчанию latini URL исходного файла с данными (относительный или абсолютный) Символы перехода, которые являются также разделителями данных. По умолчанию значение не установлено. Обычно указывают символ “\”. Символ-разделитель полей в записи. По умолчанию запятая (,).&#о э ,- Код языка ISO исходных данных. По умолчанию en-us. I Дополнительный символ, окружающий поля данных. По умолчанию значение не установлено 254 Часть III. Объекты д<
Окончание табл. 15.3 Параметр Описание RowDelim Символ-разделитель записей. По умолчанию символ новой строки (nl) UseHeader Имеет значение true, если первая строка данных в файле содержит имена полей. Значение по умолчанию false В Значение, присвоенное атрибуту id элемента obj ect, является идентификатором, с по- К мощью которого сценарии взаимодействуют с данными после того, как и страница, и данные | уже полностью загружены. Поэтому на странице могут загружаться только объекты TDC с уникальными именами, определяющими количество исходных файлов данных, которые К требуется открыть одновременно. к Исходное внедрение данных в элементы HTML обычно происходит при присвоении зна- Е чений атрибутам элементов datasrc и dataf Id. Атрибут datasrc указывает на иденти- !• фикатор DSO (совпадающий с атрибутом id элемента obj ect с символом “решетки” впереди), г а атрибут dataf Id— на имя поля, из которого следует извлечь данные. Когда внедрение I данных выполняется для такого интерактивного элемента, как таблица, записи отображаются I? как последовательные строки таблицы (подробнее об этом см. далее). L Если необходимо, чтобы элемент HTML (отличный от таблицы), который отображает Г данные, мог изменить их, следует указать значения свойств dataSrc и dataFld. Эти свой- Г ства применимы к поднабору элементов HTML, которым можно поставить в соответствие г; внешние данные: объекты a, applet, body, button, div, frame, ifrarne, img, input к; (большинство типов), label, marquee, obj ect, param, select, span и textarea. |f В некоторых случаях источники данных могут содержать блоки форматированного Ft HTML-текста, который необходимо отображать внутри элемента. Если не указано обратное, К' браузер отображает поля исходных данных как обычный текст — даже если в нем содержатся I деофипторы HTML-форматирования. Для того чтобы при отображении учитывался и код jk? HTML, свойство dataFormatAs (или, скорее, атрибут дескриптора dataf ormatas) необ- I ходимо установить в значение html. По умолчанию оно имеет значение text. г Пример F Листинг 15.8 представляет простой документ, с которым связано два объекта TDC. Внеш- г ние файлы представлены документом U.S Bill of Rights, сохраненным в разных форматах. Г Первый файл будет представлен в традиционном текстовом формате с данными, разделен- п ными символами табуляции — он содержит всего две записи. В первой записи приведены 1 имена полей—"Article 1", "Article 2 " и т.д. (которые разделены символами табуля- I ции). Вторая запись содержит разделенные символами табуляции значения полей (они пред- ‘ ставлены в формате HTML). <hl>ARTICLE I</hlxp>Congress shall make...</p> i Второй файл включает полный текст закона Bill of Rights в простом формате, не содер- * жащем дескрипторы HTML. I При загрузке кода из листинга 15.8 первая статья закона Bill of Rights отображается на к странице в синей рамке. Кнопки на странице позволяют переходить от одной статьи к другой. Г Поскольку данные внешних файлов представлены в стандартных форматах, функции г nextFieldO HprevFieldO легко определяют имя следующего поля и назначают соот- L ветствующее значение свойству dataField. В процессе открытия страницы в браузер за- > гружаются все необходимые данные, поэтому операции перехода по статьям выполняются г практически незамедлительно. - ► Глава 15. Основные объекты HTML-элементов 255
chtml> chead> ctitle>Data Bindingc/title> cstyle type="text/css"> #display {width:500px; border:lOpx ridge blue; padding:20px} .hiddenControl {display:none} c/style> escript type="text/javascript"> function nextField() { var elem = document.getElementByld("display") ; var fieldName = elem. dataFld,- var currFieldNum = parselnt(fieldName.substring(7, fieldName.length),10); currFieldNum = (currFieldNum ==10) ? 1 : ++currFieldNum; elem.dataFld = "Article" + currFieldNum; function prevFieldO { var elem = document.getElementByld("display"); var fieldName = elem.dataFld; var currFieldNum = parselnt(fieldName.substring(7, fieldName.length),10); currFieldNum = (currFieldNum == 1) ? 10 : --currFieldNum; elem.dataFld = "Article" + currFieldNum; } function toggleComplete() { if (document.getElementByld("buttonWrapper").className == , "") { document.getElementByld("display").dataSrc = "#rights_raw"; document.getElementByld("display").dataFld = "columnl"; document.getElementByld("display").dataFormatAs = "text"; document.getElementByld("buttonwrapper").className = "hiddenControl"; } else { document.getElementByld("display") .dataSrc = "#rights_html",'' document.getElementByld("display").dataFld = "Articlel"; document.getElementByld("display").dataFormatAs = "HTML"; document.getElementByld("buttonWrapper").className = ""; 1 } } c/script> c/head> cbody> chl>U.S. Bill of Rightsc/hl> cform> cinput type="button" value="Toggle Complete/Individual" onclick="toggleComplete()" /> cspan id="buttonwrapper" class=""> cinput type="button" value="Prev" onclick="prevFieldO" /> | cinput type="button" value="Next" onclick="nextField()" /> J c/span> c/form> 256 Часть III. Объекты Д1
t <div id="display" datasrc="#rights_html" datafld="Articlel" L. dataformatas="HTML"> * </div> cobject id="rights_html" classid="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83"> cparam name="DataURL" value="Bill of Rights.txt" /> cparam name="UseHeader" value="True" /> cparam name="FieldDelim" value="&#09;" /> c/object> cobject id="rights_raw" classid="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83"> cparam name="DataURL" value="Bill of Rights (no format).txt" /> cparam name="FieldDelim" value="\" /> cparam name="RowDelim" value="\" /> c/object> c/body> </html> Еще одна кнопке на странице позволяет переключаться между исходной урезанной версией документа и его полным вариантом. Для загрузки всего документа в виде единой записи па- раметрам FieldDelim и RowDelim второго элемента object вместо значений по умолча- нию назначаются символы, которые никогда не встречаются в документе. Поскольку внешний файл в тексте не содержит имени поля, то в качестве значения по умолчанию принимается единственное поле с данными (columnl для единственного столбца в документе). В функции toggleComplete свойство dataSrc изменяет свое значение на идентификатор требуемого .элемента object. Свойство dataField принимает значение используемого источника дан- ных, а свойство dataFormatAs определяет тип исходных данных в выбранном источнике данных. При отображении на странице всего исходного документа можно скрыть два пере- ключателя, назначив элементу span, содержащему эти переключатели, значение className. Как несложно догадаться, значение SpanName является идентификатором класса для таблицы стилей документа. Как только функция toggleComplete () приравняет свойство className к пустой строке, в силу вступают стандартные правила стилей. Следующий пример демонстрирует эффективность применения в сценариях объектов TDC. Листинг 15.9 позволяет отобразить на странице таблицу данных, созданную на основе текстового файла, в котором значения разделены символами табуляции. Файл данных состо- ит из восьми столбцов, заголовок каждого столбца рассматривается как имя поля: Year, Best Picture, Best Director, Best Director Film, Best Actress, Best Actress Film, Best Actor и Best Actor Film. На конечной странице отображаются данные толь- ко для пяти полей: Year, Film, Director, Actress и Actor. Обратите внимание, как в представленном листинге в таблицу вставляются данные из исходной таблицы источника. “Динамическая” часть кода этого примера определяет способы сортировки и фильтрации данных, загруженных в браузер, не требуя при этом повторного обращения к исходному фай- лу данных. Свойства Sort и Filter объекта TDC позволяют оперировать данными, уже за- груженными в браузер. В самом простом случае сортировка выполняется по отдельному по- лю (или полям, согласно списку, в котором имена полей разделены точками с запятыми). Поставив перед именем поля знак “плюс” или “минус”, вы сможете соответственно задать сортировку в возрастающем или ниспадающем порядке. После установки свойства Sort объекта data вызывается метод Reset О, который потребует применить новое свойство. Данные в таблице сразу будут обновлены в соответствии с проведенными изменениями. Подобным образом вы можете отображать в таблице только те данные, которые удовле- творяют определенным условиям. В листинге 15.9 интерфейсом для задания свойства Filter служит два раскрывающихся списка и два переключателя. Например, вы можете указать Глава 15. Основные объекты HTML-элементов 257
отобразить на странице записи только для премии Best Picture, завоеванной тем же фильмом, за игру в котором была получена премия Best Actress. Выражения фильтрации данных с ис- пользованием полей, выглядит намного проще, чем словесная формулировка задачи. dataObj.Filter = "Best Picture" = "Best Actress Film"; <html> <head> <title>Data Binding - Sorting«/title> «script type="text/javascript"> function sortByYear(type) { oscars.Sort = (type == "normal") ? "-Year" : "+Year"; oscars.Reset(); function filterlnCommon(form) { var filterExprl = form.filterl.options[form.filterl.selectedlndex].value; var filterExpr2 = \ form.filter2.options[form.filter2.selectedlndex].value; var operator = (form.operator[0].checked) ? "=" : var filterExpr = filterExprl + operator + filterExpr2; oscars.Filter = filterExpr; oscars.Reset(); } «/script> </head> <body> <hl>Academy Awards 1978-1997</hl> <form> <p>Sort list by year <a href="javascript: sortByYear('normal')">from newest to oldest</a> or <a href="javascript:sortByYear('reverse')">from oldest to newest«/a>.</p> <p>Filter listings for records whose «select name="filterl" onchange="filterlnCommon(this.form)"> «option value="Best Picture">Best Picture«/option> «option value="Best Director Film">Best Director's Film«/option> «option value="Best Actress Film">Best Actress' Film«/option> «option value="Best Actor Film">Best Actor's Film«/option> «/select> «input type="radio" name="operator" checked="checked" onclick="filter!nCommon(this.form)" /> is «input type="radio" name="operator" onclick= "filterlnCommon(this.form)" />is not «select name="filter2" onchange="filterInCommon(this.form)"> «option value="Best Picture">Best Picture«/option> «option value="Best Director Film">Best Director's Film«/option> «option value="Best Actress Film">Best Actress' Film«/option> «option value="Best Actor Film">Best Actor's Film«/option> </select>«/p> 258 Часть III. Объекты
. </form> ctable datasrc="#oscars" border="l" align="center"> f cthead style="background-color:yellow; text-align:center"> <tr> <td>Year</td> <td>Film</td> <td>Director</td> <td>Actress</td> <td>Actor</td> </tr> , </thead> <tr> <tdxdiv id="coll" datafld="Year"x/divx/td> <tdxdiv id="col2" datafld="Best Picture"x/divx/td> <tdxdiv id="col3" datafld="Best Director" x/divx/td> <tdxdiv id="col4" datafld="Best Actress"x/divx/td> <tdxdiv id="col5" datafld="Best Actor"></divx/td> </tr> </table> cobject id="oscars" classid="clsid:333C7BC4-460F-llD0-BC04- 0080C7055A83"> <param name="DataURL" value="Academy Awards.txt" /> <param name="UseHeader" value="True" /> <param name="FieldDelim" value="&#09;" /> </object> </body> </html> См. также свойства recordNumber, table.dataPageSize. dir ч Значение: "Itr" | "rtl" Чтение/Запись Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство dir (основанное на атрибуте DIR практически всех текстовых элементов HTML) управляет тем, как отображается текст элемента: слева направо (по умолчанию) или справа налево. Как правило, это свойство (и атрибут HTML) используется для переопределе- ния направления вывода текста в кодировке, определенной стандартом Unicode. Пример Изменение этого свойства в стандартной американской версии браузера приводит к изме- нению начальной точки каждой строки с левого края страницы на ее правый край (при этом порядок письма слева направо соблюдается). Вы можете смело экспериментировать в прило- жении The Evaluator с этим свойством, введя в нижнем поле следующее выражение. document.getElementByld("myP").dir = "rtl" См. также свойство lang. disabled Значение: булевого типа Чтение/Запись Совместимость: WinIE4+, МасТЕ4+, NN6+, Mozl+, Safari 1+ Напомним, что лишь некоторые элементы в IE4 и IE5 имеют свойство disabled, однако в IE5.5+ это свойство присуще всем элементам HTML. Отключение элемента HTML (например Глава 15. Основные объекты HTML-элементов 259
элемента формы) обычно делает его “недоступным”, указывая на то, что данный элемент ве является активным. Отключенный элемент не получает никаких событий. Кроме того, его нельзя использовать ни вручную, ни средствами сценария (хотя отключенные текстовые поля в Мас1Е4 по ошибке иногда активизируются). Тем не менее, пользователь имеет возможность выделить и скопировать содержимое отключенного текстового элемента. ЛЕсли элемент формы отключен, то его данные не отправляются на сервер вме- жшйу сте с данными остальных элементов. Если необходимо, чтобы Элемент формы был ( _***** “блокирован”, но при этом его данные отправлялись на сервер, следует воспольэо-] ваться обработчиком события onsubmit элемента form. В нем нужно “разблоки- ровать” элемент управления формы непосредственно перед отправкой данных 1 Пример Используйте приложение The Evaluator (глава 13) для изучения свойства disabled как у эле- ментов W3C DOM (IE4+), так и обычных HTML-элементов (IE5.5+). В первом случае посмот-| риге, что произойдет, если отключить текстовую область с помощью следующего выражения. document.forms[0].output.di sabled = true Текстовая область недоступна только для ввода данных, но вы все еще можете в сценария задать свойство value поля. В IE5.5+ элемент myP отключается с помощью следующего выражения в верхнем поле. 1 document.getElementByld("myP").disabled = true Пример текста абзаца при этом окрашивается в серый цвет. См. также свойство isDisabled. ' Только для чтеыя 4 s- document Значение: объект document Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- 13 контексте объектов элементов HTML в IE4+ свойство document является ссылкой d документ, содержащий данный объект. Хотя вам вряд ли понадобится это свойство, оно мо- жет оказаться полезным в сложных сценариях или библиотеках, обрабатывающих объема универсальным образом и поэтому не имеющих сведений об указывающем на документ эя> менте, в котором содержится определенный объект. Кроме того, ссылка на документ мояа понадобиться для поиска в нем родственных объектов. Версия этого свойства в вариагл W3C (реализованная в Мас1Е5, но не в WinIE5.5) имеет имя ownerDocument. Пример Следующая упрощенная функция принимает параметр, представляющий любой обчв в иерархической структуре документа. Функция возвращает ссылку на документ, содерж '«я объект, с помощью которой можно обратиться к другим объектам страницы. function getCompanionFormCount(obj) { var ownerDoc = obj.document; return ownerDoc.forms.length; Поскольку переменная ownerDoc содержит корректную ссылку на объект document оператор return использует эту ссылку для возвращения одного их свойств объекта. См. также свойство ownerDocument. 260 Часть III. Объекты д
filters [] «V- « <• Значение: массив Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Филыпры — это специфические для IE дополнения к таблицам стилей, отвечающие за эф- фектное представление текста (они, например, добавляют к символам тень) и анимационные эффекты перехода от скрытых к отображаемым элементам. Каждая спецификация фильтра яв- ляется объектом filter. Свойство filters содержит массив объектов filter, определен- ' вых для текущего элемента. Фильтры можно применять для следующих элементов: body, button, img, input, li, marquee, ol, table, td, textarea, th, ul, а также позициони- руемых элементов div и span. Подробно о фильтрах таблиц стилей речь пойдет в главе 26. См. также объект filter. firstChxld lastchild Значение: ссылка на объект узла Только для чтения Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Объектные модели документов, основанные на W3C DOM, построены в соответствии с ие- рархической структурой— схемой узлов. Каждый объект, определенный в HTML, является уз- лом на этой схеме. Каждый из них взаимосвязан с другими узлами. Взаимоотношения описыва- ются такими терминами: родительские (parents), “братские” (siblings) и дочерние (children). Дочерний узел — это элемент, содержащийся в другом элементе. Контейнер является ро- дительским по отношению к такому элементу. Так же, как элемент HTML может содержать любое количество дочерних элементов, родительский объект может содержать несколько или ви одного дочернего элемента. Список таких дочерних объектов (возвращаемый как массив) вы получите, если используете свойство childNodes. var nodeArray = document.getElementByld("elementID").childNodes Как отмечалось, данный массив (и его свойство length) применяется для получения ука- зателей на первый и последний дочерние узлы, свойства f irstChild и lastchild явля- ются альтернативными способами представления подобных объектов. Они особенно полезны в случае, когда необходимо вставить новый дочерний элемент впереди или за уже сущест- вующими дочерними элементами. Для добавления элементов к списку узлов документа при- меняется (в IE) метод insertAdjacentElement О или любой другой метод, указываю- щий на конкретный объект. S3^ Обратитесь к описанию свойства childNodes ранее в этой главе, где рассказа- но о “скрытых” узлах, присутствующих в некоторых версиях браузеров. Они могут 1 влиять на использование свойств f irstChild и lastchild. Пример В листинге 15.10 содержится пример использования свойств f irstChild и lastchild для получения доступа к дочерним узлам. Это весьма поучительный пример, в котором в су- ществующий элемент ol добавляются и удаляются элементы li. Таким образом, вы може- те ввести любой текст в начало или в конец списка. Воспользовавшись свойствами f irstChild и lastchild, вы упростите себе задачу перемещения в конец списка. В качестве функции, заменяющей дочерний узел, в данном случае используется метод repl aceChi Id (). Глава 15. Основные объекты HTML-элементов 261
Наряду с этим в IE4+ вы можете изменить свойство innerText объектов, возвращаемых свойствами f irstChild и lastchild. Этот пример весьма показательный при добавлении элементов в список — браузер автоматически перенумерует элементы, чтобы сохранить об- щий порядок следования элементов. <httnl> <head> <title>firstChild and lastchild Properties</title> «script type="text/javascript"> function makeNewLI(txt) { var newitetn = document.createElement("LI"); newltem.innerHTML = txt; return newltem; } function prepend(form) { var newltem = makeNewLI(form.input.value); var firstLI = document.getElementByld("myList").firstChild; document.getElementByld("myList").insertBefore(newltem, firstLI); } function append(form) { var newltem = makeNewLI(form.input.value); var- lastLI = document.getElementById("myList").lastchild; document.getElementByld("myList").appendchild(newltem); } function replaceFirst(form) { var newltem = makeNewLI(form.input.value); var firstLI = document.getElementByld("myList").firstChild; document.getElementByld("myList").replaceChild(newltem, firstLI); } function replaceLast(form) { var newltem = makeNewLI(form.input.value); var lastLI = document.getElementByld("myList").lastchild; / document.getElementByld("myList").replaceChild(newltem, lastLI); } </script> </head> <body> <hl>firstChild and lastchild Property Lab</hl> <hr /> <form> <label>Enter some text to add to or replace in the OL element:</label><br /> J «input type="text" name="input" size="50" /><br /> «input type="button" value="Insert at Top" J onclick="prepend(this.form)" /> «input type="button" value="Append to Bottom" onclick="append(this.form)" /><br />1 «input type="button" value="Replace First Item" onclick="replaceFirst(this.form)" /> «input type="button" d value="Replace Last Item" onclick="replaceLast(this.form)" />j </form> d 262 Часть III. Объекты Д1
I л <ol id="myList"> <li>Initial Item l</li> <li>Initial Item 2</li> L <li>Initial Item 3</li> <li>Initial Item 4</li> </ol> ' </body> </html> , См. также: свойства nextSibling, parentElement, parentNode, previousSibling; ’ методы appendChild (), hasChildNodes (), removechild (), removeNode (), replace- ’ Child(), replaceNode (). height width I Значение: целочисленное или строковое (процентное) Чтение/Запись и Только для чтения 1 Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Свойства height и width, описываемые в данном случае, не следует путать со свойствами, описываемыми в стиле элемента (они имеют идентичные имена). Данные свойства, скорее, от- ‘ ражают значения, обычно присвоенные атрибутам-height и width таких элементов, как img, I applet, table и т.д. Поэтому доступ к ним осуществляется непосредственно из объекта (например document .getElementByld ("myTable") .width в IE4+), а не с помощью объ- I екта style (например document. getElementByld ( "myDIV") . style. width). Только те элементы, для которых стандарт HTML 4.x предусматривает наличие атрибутов height ’ и width, имеют соответствующие свойства. Эти свойства могут принимать целочисленные значения в пикселях (числа или строки) или процентах (только строки). Прежде чем задать процентное значение, его необходимо преобразовать в числовое с помощью функции parselntO. Если атрибуты элемента height и width установлены в процентах, в ГЕ4+ с помощью свойств clientHeight Ц| clientwidth можно получить примерные размеры в пикселях. В большинстве современных браузеров свойства объекта image предназначены и для чтения, и для записи, так как размер объекта image в IE4+ и Mozl+ можно изменить после загрузки страницы. То же самое справедливо и для некоторых других объектов (например table), но не обязательно для всех тех, которые поддерживают эти свойства. В большинстве случаев невозможно установить значения этих свойств меньшими, чем это тре- буется для представления элемента. Особенно это справедливо для таблиц. Если попытаться уста- новить свойство height в значение, меньшее количества пикселей, требуемого для отображения таблицы (именно так это определено в ее настройках стилей), изменения не будут проведены (хотя свойство и будет содержать искусственно меньшее значение). Однако для других объектов (например изображений) их размер можно установить любым, и браузер проведет необходимое масштабирование. Если же требуется отобразить только часть элемента (другими словами, об- резать), для указания отображаемой области следует воспользоваться таблицами стилей. Пример Следующий пример демонстрирует возможности свойства width по увеличению ширины таблицы на 10%. var tableW = parselnt(document.getElementByld("myTable").width); document.getElementByld("myTable").width = (tableW * 1.1) + "%"; Глава 15. Основные объекты HTML-элементов 263
Поскольку исходно атрибут width для элемента table задан в виде процентного значе- ния, то в сценарии изменение данного свойства также определяется в процентах. См. также свойства clientHeight, clientwidth или style.height, style.width. hideFocus Чтение/Запись Значение: булевого типа Совместимость: WinIE5.54-, MacIE-, NN-, Moz-, Safari- B браузере IE для Windows кнопки и другие элементы формы при активизации обознача-1 ются пунктирным прямоугольником. Если в IE54- установить атрибут tabindex или свойст- во tabindex любого элемента, он также будет выделен пунктирной линией при активиза- ции. Существует возможность активизировать элемент, но не отображать для него 1 пунктирную границу. Для этого необходимо определить свойство hideFocus объекта эле-1 мента со значением true (по умолчанию оно имеет значение false). Отключение пунктирной линии не отменяет активизацию самого элемента. Если актив- j ный элемент находится за пределами видимой области, страница прокручивается до этого I элемента. Элементы управления форм, воспринимающие введение данных с клавиатуры] (например нажатие клавиши символа пробела для выставления или снятия флажка), продол-1 жают выполняться так же, как обычно. В некоторых случаях пунктирный прямоугольник] указывающий на активизацию элемента, нарушает дизайн страницы. Свойство hideFocus! позволяет управлять отображением элементов и поддерживать их совместимость с другими] страницами. В дескрипторе HTML нет соответствующего атрибута, поэтому для установи! свойства hideFocus необходимых элементов после загрузки страницы следует воспольэаЛ ваться обработчиком события onload. 1 Пример 1 Используйте приложение The Evaluator (глава 13) для изучения свойства hideFocus в IE5.51 Введите следующее выражение в верхнее текстовое поле для задания свойству tabindex элемем та туР значения, при котором последний активизируется и обрамляется пунктирной линией. I document.getElementByld("jnyP").tabindex =1 J Нажмите несколько раз клавишу <Tab> — абзац должен быть выделен пунктирной раЛ кой. Далее отключите пунктирную рамку для выделенного абзаца. р document.getElementByld("myP").hideFocus = true Я В дальнейшем, сколько бы раз вы ни нажимали <ТаЬ>, пунктирная линия вокруг абэнш так и не появится, хотя сам элемент абзаца активизируется. Чтобы убедиться в том, что объем все-таки активизируется, прокрутите страницу вниз и так, чтобы абзац скрылся из виду (можем просто изменить размер окна). Щелкните на одном из визуально активизируемых элемекпм страницы и медленно несколько раз нажмите клавишу <ТаЬ> — в строке адреса должен поЛ виться курсор. Нажмите <ТаЬ> еще раз. Страница автоматически будет прокручена к текст,Я абзаца, хотя пунктирная рамка вокруг него отображаться не будет. Я См. также: свойство tabindex; метод srcollIntoView (). Я id (См. в текс Значение: строка Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойство id возвращает идентификатор, присвоенный атрибуту ID элемента в к HTML. Сценарий не может ни изменить идентификатор существующего элемента, ни ц своить его элементу без идентификатора. Но если в сценарии создается новый элемент, ск ство id позволяет присвоить ему идентификатор. 264 Часть III. Объекты док]
Пример При написании сценариев вам редко придется прибегать к услугам этого свойства. Исключени- ем являются Web-страницы, в которых необходимо просмотреть все имена элементов, заданные разработчиком. После этого можно смело ссылаться на объекты документа по их идентифика- торам (с помощью метода document .getElementByld (идентификатор Элемента)). Ес- ли по определенным причинам в сценарии не известен идентификатор элемента, например, второго абзаца документа, то его можно получить с помощью следующего выражения. • var elemlD = document.getElementsByTagName("р")[1].id; См. также свойство className. innerHTML innerText Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Один из способов доступа к содержимому элемента в браузере Internet Explorer заключа- ^ется в использовании свойств innerHTML и innerText. (Браузеры Mozl+/NN6+ позволяют применять только свойство innerHTML.) Все содержимое, определенное этими “внутренними” свойствами, состоит из данных, заключенных между открывающими и закры- вающими дескрипторами элемента, исключая последние (см. также свойства outerText и outerHTML). Задав эти внутренние свойства, вы всегда сможете изменить определенную часть страницы после ее загрузки. Свойство innerHTML задает не только текстовое содержимое элемента, отображаемое на странице, но также все дескрипторы HTML в нем. (Если в содержимом нет дескрипторов, то текст будет представлен в таком виде, в каком есть.) Например, рассмотрим следующий ис- ходный HTML-код. <р id="paragraphl">"How <em>are</em> you?" he asked.</p> В этом случае значение свойства innerHTML объекта абзаца (document. getElement - -Byld ("paragraphl") . innerHTML) будет таким. "How <em>are</em> you?" he asked. Браузер интерпретирует все дескрипторы HTML, включенные в строку innerHTML, как элементы HTML. Это значит, что в результате присвоения свойству innerHTML строки с HTML-содержимым на страницу можно будет добавить новые вложенные элементы (или, в современной терминологии, дочерние узлы). При вставке нового содержимого объектная модель документа корректируется автоматически. В отличие от описанного вами, свойство innerText включает только текстовое содер- ,жимое. В примере, приведенном ранее, значение свойства innerText (document.get- ElementByld ("paragraphl") . innerText) будет таким. "How are you?" he asked. Важно учесть следующее: когда свойству innerText присваивается строка, содержащая дескрипторы HTML, последние вместе с угловыми скобками выводятся на страницу и не ин- терпретируются как элементы HTML. Для корректировки HTML-кода таких элементов, как FRAMESET, HTML, HEAD, TITLE и связанных с таблицей объектов, не следует пользоваться свойством innerHTML. Структура таблицы будет изменена специальными методами, которые создают или форматируют стро- ки, столбцы и ячейки (глава 37). Однако ничто не мешает изменить содержимое ячейки с по- мощью свойства innerHTML или innerText. Глава 15. Основные объекты HTML-элементов 265
Если вставляемый код HTML содержит элемент <script>, то в открывающем дескрип- торе необходимо задать атрибут defer. Это справедливо и для сценариев, содержащих оп- ределения функций. Пример Листинг 15.11 содержит пример использования свойств innerHTML и innerText для динамического изменения содержимого страницы. Данная страница содержит элемент hl и элемент абзаца. Суть примера заключается в демонстрации разницы в обоих свойствах. Два текстовых поля содержат одинаковые комбинации текста и HTML-дескрипторов, с помощью которых изменится содержимое элементов. Если вы примените значение в первом текстовом поле к свойству innerHTML объекта label 1, то первое слово надписи будет отображена курсивом. Кроме того, текст в скобках отображается меньшим шрифтом (благодаря его включению в элемент span и применению специальной таблицы стилей). Если вы назначите содержимое поля свойству innerText объекта labell, то он весь будет отображен в тексте абзаца. Вы можете ввести в текстовые поля этого документа другие выражения. Узнайте, что произойдет, если в тексте обоих полей используется дескриптор <br>. <html> <head> <title>innerHTML and innerText Properties</title> <style type="text/css"> hl {font-size:18pt; font-weight:bold; font-family:"Comic Sans MS", Arial, sans-serif} .small {font-size:12pt; font-weight:400; color:gray} </style> <script type="text/javascript"> function setGroupLabelAsText(form) { var content = form.textInput.value; if (content) { document.getElementByld("label1").innerText = content; } } function setGroupLabelAsHTML(form) { var content = form.HTMLInput.value; if (content) { document.getElementById("labell").innerHTML = content; </script> </head> <body> <form> <p><input type="text" name="HTMLInput" value="&lt; I&gt,-First&lt;/I&gt; Article &lt;span class='small'&gt;(of ten)&lt;/span&gt;"size="50" /> cinput type="button" value="Change Heading HTML" onclick="setGroupLabelAsHTML(this.form)" /></p> <p><input type="text" name="textInput" value="&lt;I&gt;First&lt;/I&gt; Article &lt;span class='small1&gt;(of ten)&lt;/span&gt;" size="50" /> <input type="button" value="Change Heading Text" 266 Часть III. Объекты
onclick="setGroupLabelAsText(this.form)" /></p> </form> <hl id=”labell"> ARTICLE I </hl> <p>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.</p> </body> </html> См. также: свойства outerHTML, outerText; метод replaceNode (). isContentEditable Значение: булевого типа Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Свойство isContentEditable возвращает значение булевого типа, указывающее, являет- ся ли объект элемента редактируемым (см. выше описание свойства contentEditable). Если свойство contentEditable родительского элемента имеет значение true, то свой- ство contentEditable вложенного элемента, скорее всего, имеет значение по умолчанию inherit. Но так как родительский элемент является редактируемым, то свойство isContent - Editable дочернего элемента возвращает значение true. Пример Используйте приложение The Evaluator (глава 13) для экспериментов с обоими свойствами isContentEditable и contentEditable элемента туР и вложенных элементов туЕМ. Про- верьте текущее значение свойств для элемента туЕМ, введя в верхнее поле следующее выражение. туЕМ.isContentEditable Исходное значение свойства равно false, поскольку ни один из элементов высшего уровня в иерархической структуре не разрешено редактировать. Далее мы сделаем редакти- руемым родительский элемент туР. тур.contentEditable = true Теперь редактированию подлежит весь элемент туР, поскольку дочерний объект по умолчанию наследует свойства родительского. Для проверки этого утверждения введите в верхнем поле следующее выражение. туЕМ.isContentEditable Несмотря на то, что элемент туЕМ подлежит редактированию, свойство contentEditable при этом не изменяется. туЕМ.contentEditable Это свойство по-прежнему содержит значение по умолчанию inherit. Дополнительные примеры использования этих свойств приведены в листинге 15.7. См. также свойство contentEditable. IsDisabled Значение: булевого типа Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Глава 15. Основные объекты HTML-элементов 267
Свойство isDisabled возвращает значение булевого типа, указывающее, является ли оп- ределенный объект элемента отключенным (см. предыдущее обсуждение свойства disabled). Это свойство является чрезвычайно полезным по следующей причине: если свойство disabled родительского элемента имеет значение true, то свойство disabled вложенного элемента, скорее всего, будет иметь значение по умолчанию false. Но поскольку родительский элемент является отключенным, то свойство isDisabled дочернего элемента возвращает значе- ние true. Другими словами, свойство isDisabled возвращает реальный статус элемента, независимо от установок его свойства disabled. Пример Используйте приложение The Evaluator (глава 13) для экспериментов с обоими свойства- ми disable и isDisabled элемента myP и вложенных элементов туЕМ. Проверьте теку- щее значение свойств для элемента туЕМ, введя в верхнее поле следующее выражение. туЕМ.isDisabled Исходное значение свойства равно false, поскольку ни один из элементов высшего уровня в иерархической структуре не отключен. Далее мы отключим родительский элемент myP. myP.disabled = true Теперь элемент myP (включая все его дочерние объекты) отключен. Для проверки этого утверждения введите в верхнем поле следующее выражение. туЕМ.isDisabled Несмотря на то, что элемент туЕМ отключен, его свойство disabled при этом не изменяется. туЕМ.disab1ed Это свойство по-прежнему содержит значение по умолчанию false. См. также свойство disabled. IsMultiLlne Значение: булевого типа Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Свойство is Multi Line возвращает значение булевого типа, указывающее на то, может ли элемент занимать или содержать более одной текстовой строки. Бажно следующее: это значение не указывает, занимает ли элемент несколько строк; скорее, данное свойство демон- стрирует возможность или невозможность этого. Например, текстовый элемент input не может занимать несколько строк, поэтому свойство isMultiLine для него содержит значе- ние false. Элемент BUTTON может в нескольких строках содержать свою текстовую под- пись, поэтому это его свойство имеет значение true. Пример Приложение The Evaluator (глава 13) позволяет считывать значение свойства isMultiline элементов страницы. Введите в верхнее поле следующие выражения. document.body.isMultiLine document.forms[0].input.isMultiLine myP.isMultiLine myEM.isMultiLine Все элементы, за исключением текстовых полей, поддерживают ввод данных в не- сколько строк. 268 Часть III. Объекты документа
. IsTextEdit • Значение: булевого типа Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство isTextEdit указывает, можно ли на основе его содержимого создать объект WinlE TextRange. (См. объект TextRange в главе 35.) Объекты TextRange в IE4+ для Windows можно создать на основе ограниченного набора объектов: body, button, некото- рых элементов форм (text/ password, hidden, button, reset и submit) и объекта - textarea. В MacIE5 это свойство всегда возвращает значение false. Пример Рекомендуется всегда проверять это свойство перед выполнением метода createText- Range () текущего объекта. Ниже приведет стандартный код этой операции. if (document.getElementByld("myObject").isTextEdit) { var myRange = document.getElementByld("myObj ect").createTextRange(); [дополнительные операторы управления диапазоном myRange] } См. также: метод createRange (); объект TextRange (глава 35). lang Значение: кодовая страница языка ISO Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 13- Свойство lang управляет набором символов, используемым для отображения текстового содержимого элемента, когда настройки браузера по умолчанию не применяются. По умол- чанию это свойство содержит пустую строку, если только атрибуту lang в дескрипторе эле- мента не присвоено значение. Изменение этого свойства средствами сценария пока никак не проявляется в современных версиях браузеров. Пример В качестве значений свойства lang указывают текстовые строки, содержащие коррект- ные коды ISO языков. В данном коде обязательно указывается идентификатор языка ("fr" для французского языка), а также необязательный суффикс региона, в котором используется данных язык (например, "fr-ch" для швейцарского французского). Код задания швейцар- ского немецкого языка ввода выглядит следующим образом. document.getElementByld("specialspan").lang = "de-ch"; language Значение: строка Чтение/Запись Совместимость: WinIE43-, Мас1Е4з-, NN-, Moz-, Safari- Архитектура браузеров IE4+ позволяет использовать несколько механизмов добавления сце- нариев. В базовой версии браузера для Windows содержится два варианта сценариев: JScript (совместимый с JavaScript) и Visual Basic Scripting Edition (VBScript). По умолчанию задается значение JScript. Если же в операторах, включенных в обработчики событий атрибутов деск- риптора, требуется использовать VBScript или какой-либо другой язык сценариев, браузеру можно указать, какой именно язык сценариев следует применять для обработки операторов, ус- тановив атрибут LANGUAGE дескриптора. Свойство language обеспечивает сценарию доступ к этому атрибуту. Если только вы не собираетесь изменять обработчик событий HTML-кода Глава 15. Основные объекты HTML-элементов 269
и заменять его оператором VBScript (или любого другого языка, несовместимого с JScript и установленного в браузере), вам не потребуется изменять (или читать) это свойство. К допустимым значениям относят JScript, javascript, vbscript и vb's. Браузеру других производителей имеют собственные идентификаторы для использования в этом свой- стве. Так как атрибут language задается также в дескрипторе <script>, Internet Explorers воспринимает и оператор language= " xml". См. также объект элемента script. lastchild (см. firstchild) length Значение: целочисленное Только для чтения и Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство length возвращает количество элементов в массиве или наборе объектов. Ча- ще всего это свойство используют в условии цикла for. Если в массивах и наборах индекса- ция производится с нуля, значение length представляет собой реальное количество элемен- тов в группе. Поэтому для просмотра всех элементов условное выражение должно включать , знак “меньше” (<), а не “меньше или равно” (<=), как показано в следующем примере. for (var i = 0; i < someArray.length; i++) {...} < Для просмотра массива в обратном порядке (т.е. начиная с последнего элемента и заканчивая первым) исходное выражение должно инициализировать счетчик цикла следующим образом. ’ for (var i = someArray.length — 1; i >= 0; i--) {...} В большинстве массивов и наборов свойство length предназначено только для чтения"! и зависит только от количества элементов в группе. Однако в современных версиях браузеров в массивах элементов (areas, options и объекту select) можно создать заполнители для i последующего размещения в них данных. Подробно эта возможность описана в разделах, по-1 священных объектам элементов area, select и option. В обычном массиве JavaScript значение length можно изменять, либо удаляя элементы в конце, либо резервируя место для, дополнительных элементов. Подробнее об объекте Array речь пойдет в главе 30. Пример Введите в верхнем поле приложения the Evaluator следующие выражения, чтобы ознако- миться со значениями свойства length для различных объектов. Обратите внимание на то, что отдельные выражения поддерживаются далеко не всеми браузерами. (All browsers) document.forms.length (All browsers) document.forms[0].elements.length (NN3+, IE4+) document.images.length (NN4+) document.layers.length (IE4+) document .all. length (IE5+, W3C) document.getElementByld("myTable”).childNodes.length См. также объекты area, select, option и array. localName namespaceURI prefix Значение: строка Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Только для чтения 270 Часть III. Объекты документа
Три свойства localName, namespaceURI и prefix применимы к любому узлу в XML- документе, в котором в дескрипторе XML задается пространство имен URI. Несмотря на то, что в NN6 все три свойства имеют все объекты элементов (и узлов), они не возвращают требуемых значений. Ситуация исправлена в Mozilla-совместимых браузерах. Именно в этом описании рас- сказано, какие значения будут содержать данные свойства. Рассмотрим следующий XML-код. <х xmlns:bk='http://bigbooks.org/schema1> <bk:title>To Kill a Mockingbird</bk:title> </x> Элементу дескриптора <bk: title> задается пространство имен URL определенное для блока кода, поэтому свойство namespaceURI элемента возвратит строку http: //bigbooks. org/ schema. Имя дескриптора состоит из префикса (до двоеточия) и локального имени (после двоеточия). В приведенном выше примере свойством prefix элемента, определенного дескриптором <bk:title>, является bk, а свойством localName — title. Свойство localName любого узла возвращает то же значение, что и свойство nodeName, например #text для текстового узла. Более подробная информация о пространстве имен XML приведена по адресу http://www.w3.org/TR/REC-xml-names. См. также свойства scopeName, tagUrn. nextSibling previousSibling Значение: ссылка на объект Только для чтения Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Элементы-“братья” — это элементы, находящиеся на одном уровне вложенности. Напри- мер, элемент р имеет два дочерних узла (em и span). Два дочерних узла являются элемента- ми-“братьями” по отношению друг к другу. <p>MegaCorp is <em>the</em> source of the <span class="hot">hottest</span> gizmos.</p> Порядок следования элементов-“братьев” полностью определяется их порядком задания в исходном коде. Поэтому в предыдущем примере элемент em не имеет свойства previous- Sibling. Точно так же элемент span не имеет свойства nextSibling. Данные свойства обеспечивают еще один способ просмотра элементов, находящихся на одном уровне. Пример Следующая функция назначает одно и то же имя класса всем дочерним узлам элемента. function setAHChildClasses (parentElem, className) { var childElem = parentElem.firstChild; while (childElem.nextSibling) { childElem.className = className; childElem = childElem.nextSibling; } } Этот код представляет не единственный способ выполнения текущей задачи. С помощью цикла for вы также можете просмотреть коллекцию childNodes родительского элемента. См. также: свойства firstChild, lastchild, childNodes; методы tiasChildNodes (), insertAdjacentElement (). Глава 15. Основные объекты HTML-элементов 271
nodeName Значение: строка Только для чтения Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Для элементов HTML и XML имя узла совпадает с именем дескриптора. Свойство nodeName включено для совместимости с архитектурой узлов, формально описанной стандартом W3C DOM. Значением свойства, как и для tagName, является строка с именем дескриптора, где все символы принадлежат верхнему регистру (даже если в исходном HTML-коде дескрипто- ры введены символами нижнего регистра). Некоторые узлы (например, текстовое содержимое элемента) не имеют соответствующих дескрипторов. Свойство nodeName для таких узлов имеет специальное значение: #text. Другим типом узла является атрибут элемента. Для атрибута свойство nodeName возвращает имя атрибута. Более подробно свойства объекта Node описаны в главе 14. Пример Следующая функция демонстрирует один из способов (далеко не самый эффективный) назначения имени класса каждому элементур в документе IE5+. function setAllPClasses(className) { for (var i = 0; i < document.all.length; i++) { if (document.al1[i].nodeName == "P") { document.all [i] .className = className } } } Более эффективный способ предполагает использование метода getElementByld0 для получения коллекции элементов р и последовательного их изменения. См. также свойство tagName. nodeType Значение: целочисленное Только для чтения Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Спецификация W3C DOM определяет набор констант, которые указывают тип узла. Не все эти значения реализованы в браузерах, совместимых с W3C DOM, хотя NN6 включает на две константы больше, чем IE5. В табл. 15.4 перечислены значения nodeType, поддержи- ваемые текущими версиями браузеров. Тлбмв 15.4. Зшненм сойстжа jrataTyDd . Значение Описание WintE * MaclE NN/Moz Safari 1 Узел элемента 5 5 NN6 1 2 Узел атрибута 6 5 NN6 1 3 Текстовый узел (#text) 5 5 NN6 1 4 Узел раздела CDATA - - - 5 Узел ссылки на сущность - - - - 6 Узел сущности - - - - 7 Узел обработки инструкций - - - - 272 Часть III. Объекты документа
Окончание табл. 15.4 Значение Описание WinlE MacIE NN/Moz Safari 8 Узел комментария 6 5 NN6 - 9 Узел документа 5 5 NN6 1 10 Узел типа документа - - NN6 1 11 Узел фрагмента документа 6 5 NN6 1 12 Узел примечания - - - - Значение nodeType автоматически присваивается элементу независимо от того, суще- ствует он в исходном HTML-коде документа или создается сценарием на лету. Например, если новый элемент создается одним из способов, задаваемых сценарием (например, при- своение строки с дескрипторами HTML-свойству innerHTML или явный вызов метода document. createElement ()), то его свойство nodeType содержит значение 1. Mozilla-совместимые браузеры превосходят остальные в том, что касается определения на- бора значений nodeType для констант свойства Node в спецификации W3C DOM. В табл. 15.5 приведен полный перечень значений, определяемый спецификацией DOM 2 (в NN6 поддер- живаются не все свойства). Замена целочисленных значений этими константами улучшает читаемость сценария. Например, гораздо проще понять сценарий, если вместо if (myElem.nodeType == 1) {...} используется if (myElem.nodeType == Node.ELEMENT_NODE) {...} Константа Значение nodeType Node.ELEMENT_NODE 1 Node.ATTRIBUTE_NODE 2 Node. TEXT_NODE 3 Node. CDATA_SECTION_NODE 4 Node. ENTITY_REFERENCE_NODE 5 Node.ENTITY_NODE 6 Node. PROCESSING_INSTRUCTION_NODE 7 Node. COMMENT_NODE e Node. DOCUMENT_NODE 9 Node. DOCUMENT_TYPE_NODE 10 Node. DOCUMENT_FRAGMENT_NODE 11 Node.NOTATION_NODE 12 Пример Вы можете изучить свойство nodeType в приложении The Evaluator. Начните с анализа эле- мента р, имеющего идентификатор туР. Сам элемент р имеет свойство nodeType, равное 1. document.getElementByld("myP").nodeType Глава 15. Основные объекты HTML-элементов 273
Этот элемент включает три дочерних узла: текстовая строка (nodeName #text), эле- мент em (nodeName em) и остальной текст элемента (nodeName #text). Если запросить свойство nodeType для одной из текстовых составляющих, то будет возвращено значение 3. document.getElementByld("myP").childNodes[0].nodeType См. также свойство nodeName. nodeValue Значение: число, строка или null Чтение/Запись Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Для текстового узла свойство nodeValue сохраняет реальный текст, содержащийся в нем. Такой узел не может содержать вложенных элементов, поэтому свойство nodeValue представляет собой еще один способ чтения и изменения того, что реализовано в браузере Internet Explorer как свойство innerText. Из всех типов узлов, которые поддерживаются браузерами, совместимыми с W3C D0M, только текстовые узлы и узлы атрибутов имеют доступные для считывания значения. Значение узла элемента всегда null. Для узла атрибута свойство nodeValue содержит значение, при- своенное атрибуту. Согласно стандарту W3C DOM, значения атрибутов должны быть строко- выми. Однако браузер WinIE5 возвращает значение числового типа, если оно включает только символы цифр. Даже если свойству nodeValue присвоить строковое значение, оно будет пре- образовано в тип Number. NN6 и Мас1Е5 во всех случаях возвращают значения nodeValue как строки (и преобразуют числовые значения в строковые при присвоении этому свойству). Пример С помощью свойства nodeValue выполняется целый ряд практических задач. Далее ис-. пользуем это свойство для увеличения ширины объекта textarea на 10%. Значение свойст- ва nodeValue перед подстановкой в математические выражения необходимо преобразовать в целое число. > function widenCols(textareaElem) { var colWidth = parselnt(textareaElem.attributes["cols"].nodeValue, 10) ,- textareaElem.attributes["cols"].nodeValue = (colWidth * 1.1); , } В еще одном примере мы заменим текст элемента, предположив, что последний не имеет I вложенных элементов. function replaceText(elem, newText) { if (elem.childNodes.length == 1 && elem.firstChild.nodeType == 3) { i elem.firstChild.nodeValue = newText; 11 Создавая функцию, мы предполагали, что элемент содержит всего один дочерний узел j текстового типа. Во втором примере в качестве альтернативы также можно использовать] следующее выражение, в котором используется свойство innerText. elem.innerText = newText; См. также свойства attributes, innerText, nodeType. ; offsetHeight ! offsetwidth 1 Значение: целочисленное Только для чтения] Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ J 274Часть III. Объекты документ
Эти свойства, которые обычно связываются с высотой и шириной элементов, настолько про- тиворечивы, что часто вводят в заблуждение даже самых опытных разработчиков. Причина состо- ит в конфликте объектных моделей Internet Explorer и W3C DOM. Оба свойства впервые появились в IE4. Хотя они и не включены в стандарт W3C, многие браузеры (в том числе Mozilla и Safari) поддерживают их, поскольку разработчикам сценариев весьма сложно от них отказаться. При переводе IE6 в режим совместимости (см. главу 14) значения этих свойств определяют реальную высоту и ширину содержимого элемента, независимо от настроек полей, границ и вы- равнивания текста. Но свойство offsetwidth всегда содержит полную ширину (включает границы, поля и отступы) содержимого элемента. Это же поведение наблюдается в модели W3C, которое поддерживается всеми W3C DOM-совместимыми браузерами. Наряду с этим в IE6 и ста- рых версиях WinlE при расчете указанных свойств учитываются ширина границ и отступы. Помните, что для обычного элемента, высота и ширина которого не указаны, свойство offsetHeight определяется реальной высотой содержимого элемента после обтекания и выравнивания текста. Но свойство offsetwidth всегда содержит полную ширину (вклю- чает границы, поля и отступы) содержимого элемента. Поэтому свойство offsetwidth не позволяет определить реальную ширину текстового содержимого, которая меньше, чем пол- ная ширина родительского элемента. Чтобы найти реальную ширину текста внутри элемента, его необходимо заключить внутрь элемента (например span), после этого проверьте свойст- во offsetwidth последнего. Пример В WinIE4+ свойствами offsetHeight и offsetwidth иногда можно успешно заменить свойства clientHeight и clientwidth, как показано в листинге 15.6. Одно из достоинств свойств offsetHeight и offsetwidth (по сравнению с clientHeight и clientwidth) состоит в том, что первые имеют заданные значения даже в том случае, когда они не указаны явно в атрибутах дескриптора HTML. Так происходит по той причине, что эти значения уста- навливаются автоматически при ссылке на родительский элемент — чаще всего body. В IE5+ и W3C DOM-совместимых браузерах вы можете использовать приложение The Evaluator для знакомства со свойствами offsetHeight и offsetwidth самых разных элементов страницы. Введите в верхнее поле следующие выражения. document.getElementByld ("myP11) . offsetwidth document.getElementByld("myEM").offsetwidth document.getElementByld("myP").offsetHeight document.getElementByld("myTable").offsetwidth См. также свойства clientHeight, clientwidth. offsetLeft offsetTop Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойства offsetLeft и offsetTop имеют те же недостатки, что и offsetHeight и offsetwidth, когда к элементу добавляются границы, поля и отступы. Однако свойства offsetLeft и offsetTop являются полезными при получении координат элемента, позицио- нированного внутри родительского элемента (даже если элементы не позиционируются явно). Л. Свойства offsetLeft и offsetTop для позиционироранных элементов в брау- зере MaclE возвращают значения, отличающиеся от style.left и style.top * для одного и того же элемента. В качестве примера обратитесь к листингу 39.17, где показано, как устранить эти расхождения без введения точных корректирую- щих значений в исходный код. Глава 15. Основные объекты HTML-элементов 275
Элемент, используемый в качестве “точки отсчета” для этих свойств, — это узел, возвра- щаемый свойством offsetParent. Чтобы определить точную позицию конкретного элемента, необходимо добавить код, последовательно просматривающий структуру offsetParent до тех пор, пока свойство не возвратит значение null. Свойства of f setLef t и off setTop не являются частью спецификаций W3C DOM, од- нако их реализовали во многих браузерах, поскольку они удобны для выполнения ряда задач, решаемых посредством сценариев динамического HTML. Используя эти два свойства в сце- нарии можно получить координаты в пикселях любого блокового или внутритекстового эле- мента. Измерения отсчитываются от элемента body, однако в будущем это, скорее всего, бу- дет изменено (см. описание свойства offsetParent далее в этой главе). Пример Следующий сценарий для IE содержит выражения, в которых все четыре offset- свойства, задающие размеры, используются для позиционирования элемента div. Этот эле- мент должен полностью покрывать элемент span, расположенный в элементе р. Указанный прием часто используется при подготовке опросов, в которых от ответа респондента зависит расположение текстового кадра. При получении ответа, верхний элемент div скрывается, чтобы показать корректный результат. document.all.blocker.style.pixelLeft = document.all.span2.offsetLeft document.all.blocker.style.pixelTop = document.all.span2.offsetlop document.all.blocklmg.height = document.all.span2.offsetHeight document.all.blocklmg.width = document.all.span2.offsetwidth Поскольку свойство offsetParent для элемента span представляет элемент body, то располагаемый поверх элемент div должен позиционироваться в таком же контексте. Что и отражается в значениях свойств pixelLeft и pixelTop (обратите внимание, что указан- ные свойства задаются для объекта style элемента). С помощью свойств offsetHeight и offsetwidth определяется расположение в документе элемента span (в рассматривае- мом примере не используются поля, границы и отступы). Полученные значения применяются при позиционировании на странице элемента div. В отдельных ситуациях приведенный выше код содержит потенциальные ошибки. Если текст элемента span2 переносится на новую строку, то новое значение offsetHeight вполне корректно определяет высоту элемента, необходимую для “закрытия” обоих строк. Тем не менее, элемент blocklmg отображается на странице в виде прямоугольника. Други- ми словами, этот элемент не преобразуется в две отдельные полосы, необходимые для скры- тия двух текстовых строк. См. также свойства clientLeft, clientTop, offsetParent. offsetParent Значение: ссылка на объект Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство offsetParent возвращает ссылку на объект, действующий как “точка отсче- та” позиционирования текущего элемента. Значения свойств of f setLef t и of f setTop из- меряются относительного левого верхнего угла объекта of f set Parent. Возвращаемый объект — это, как правило (но не всегда), расположенный на уровень выше блоковый контейнер. Для большинства элементов документа объектом offsetParent являет- ся document. body (за исключением некоторых элементов в определенных браузерах). Ячейки таблицы, например, имеют различные элементы offsetParent в различных браузерах. 276 Часть III. Объекты документа
Браузер Свойство offsetParent элемента TD WinlE4 tr WmlE5+/NN7+/Moz1 + MacIE NN6 table table body Это свойство для позиционируемых элементов также возвращает различные результаты вразных браузерах. В Е значением свойства offsetParent позиционируемого элемента первого уровня является body; значением вложенного позиционируемого элемента (напри- мер, одного абсолютным образом позиционированного элемента div внутри другого) будет внешний контейнер (другими словами, узел позиционируемого внутреннего элемента). Пример Вы можете использовать свойство offsetparent для определения расположения на странице вложенного элемента. В листинге 15.12 показан сценарий, просматривающий ие- рархическую структуру объектов offsetParent в WinE, с помощью которых определяется расположение на странице вложенных элементов. Цель кода, приведенного в этом листинге, — расположить изображение в левом верхнем углу второй ячейки таблицы. Сама таблица нахо- дится по центру страницы. Обработчик событий onload вызывает функцию setlmagepositionf). Эта функция сначала назначает булев флаг, который определяет тип используемых свойств: client или offset. Браузеры WinE4 и МасЕ5 используют свойства client, a WinE5+— свойства offset. В цикле while просматриваются свойства offsetParent для всех объектов, на- чиная с уровня ячейки. При этом из просмотра исключается объект document. body, в ко- тором собственно и задается расположение изображения. В Е5 цикл выполняется всего раз, поскольку элемент table располагается в иерархической структуре между элементами body и cell. В Е4 цикл выполняется дважды: для элементов table и tr. Наконец, полученные суммарные значения применяются к свойствам позиционирования стиля объекта div, а само изображение отображается на экране. <html> <head> <title>offsetParent Property</title> <script type="text/javascript"> function setlmagePosition(){ var x = 0; var у = 0; var offsetPointer = document.getElementByld("myCell"); while (offsetpointer) { x += offsetPointer.offsetLeft; y += offsetPointer.offsetTop; offsetPointer = offsetPointer .offsetParent ; } if (navigator.userAgent.indexOf("Mac") != -1 && typeof document.body.leftMargin != "undefined") { x += document.body.leftMargin; у += document.body.topMargin; } Глава 15. Основные объекты HTML-элементов 277
document.getElementByld("myDIV").style.left = x + "px"; document.getElementByld("myDIV").style.top = у + "px"; document.getElementByld("myDIV").style.visibility = "visible"; } </script> </head> <body onload="setImagePosition()"> <hl>The offsetParent Property</hl> <hr /> <p>After the document loads, the script positions a small image in the upper left corner of the second table cell.</p> «table border="l" align="center"> <tr> <td>This is the first cell</td> <td id="myCell">This is the second cell.</td> </tr> </table> <img id="myDIV" alt="image" src="end.gif" height="12" width="12" style="position:absolute; visibility:hidden; height:12px; width: 12px" /> </body> </html> См. также свойства of f setLef t, of f setTop, of fsetHeight, offsetwidth. outerHTML outerText Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Один из способов, которым Internet Explorer представляет элемент для использования в сценариях, является задание свойств outerHTML и outerText. Основное отличие между этими двумя свойствами состоит в том, что outerHTML включает открывающий и закрываю- щий дескрипторы, a outerText — только текст, включенный в элемент (в том числе и текст всех вложенных элементов). Свойство outerHTML содержит не только текст, отображаемый на странице, но и все де- скрипторы HTML, находящиеся внутри элемента. В качестве примера рассмотрим следую- щий блок HTML-кода. <р id="paragraphlHow <em>are</em> you?" he asked.</p> Значение свойства outerHTML объекта P (document.all .paragraphl .outerHTML) в точности совпадает с исходным кодом. Браузер интерпретирует все дескрипторы HTML, содержащиеся в строке, как присвоен- ные свойству outerHTML. Таким образом, это свойство позволяет удалить (значение свойст-' ва— пустая строка) или заменить весь дескриптор. При внесении каких-либо изменений в HTML таким способом объектная модель документа корректируется автоматически. В отличие от описанного выше, свойство outerText содержит лишь информацию о тексте внутри элемента. Значение свойства outerText (document.all.paragraphl.innerText)! из предыдущего примера выглядит как абзац текста. "How are you?" he asked. Ничего необычного, поскольку в большинстве случаев свойства innerText и outerTextj возвращают идентичные строки. j 278 Часть III. Объекты докуют
Пример В листинге 15.13 продемонстрирован пример использования в IE свойств outerText и outerHTML для получения доступа к Web-странице и ее динамического изменения. Стра- ница, сгенерированная с помощью кода в листинге 15.13 (только в IE4+), содержит лишь за- головок hl и абзац с текстом. Цель данного примера — продемонстрировать разницу в этих двух свойствах. Два текстовых поля приложения содержат одинаковый текст и HTML- дескрипторы, с помощью которых заменяется текст заголовка над абзацем. Если вы назначите свойству outerHTML содержимое первого текстового поля, то эле- мент hl будет заменен на элемент span, атрибуту class которого назначена другая таблица сталей, определенная ранее в документе. Обратите внимание, что идентификатор этого эле- мента span подобен идентификатору исходного элемента hl. Это позволяет сценарию вто- рой кнопки обращаться к объекту. Однако второй сценарий заменяет текст элемента hl ис- ходным кодом в текстовом поле. Используйте представленную на экране страницу для ввода других значений в текстовые поля. <html> <head> <title>outerHTML and outerText Properties</title> «style type="text/css"> hl {font-size:18pt; font-weight:bold; font-family:"Comic Sans MS", Arial, sans-serif} .heading {font-size:20pt; font-weight:bold; font-family:"Arial Black", Arial, sans-serif} </style> «script type="text/javascript"> function setGroupLabelAsText(form) { var content = form.textinput.value; if (content) { document.getElementByld("labell").outerText = content; } } function setGroupLabelAsHTML(form) { var content = form.HTMLInput.value; if (content) { document.getElementByld("labell").outerHTML = content; } } «/script> t «/head> «body> «form> «p>«input type="text" name="HTMLInput" value="&lt;SPAN ID='labell' CLASS='heading'&gt;Article the First&lt;/SPAN&gt;"size="55" /> «input type="button" value="Change Heading HTML" onclick="setGroupLabelAsHTML(this.form)" />«/p> «p>«input type="text" name="textlnput" value="&lt,-SPAN ID='labell' CLASS= 'heading' &gt;Article the First&lt;/SPAN&gt;" size="55" /> «input type="button" value="Change Heading Text" onclick="setGroupLabelAsText(this.form)" />«/p> «/form> Глава 15. Основные объекты HTML-элементов 279
<hl id="labell">ARTICLE I</hl> <p>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.</p> </body> </html> См. также: свойства innerHTML, innerText; метод replaceNode (). ownerDocument Значение: ссылка на объект document Только для чтения Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство ownerDocument имеют все элементы в объектных моделях документа W3C DOM. Значением свойства является узел документа, содержащего данный элемент или узел. Если в сценарии используется ссылка на элемент или узел (например, если он передан функ- ции как параметр), свойство ownerDocument объекта обеспечивает возможность создания ссылок на другие объекты в этом же документе или получения доступа к свойствам и мето- дам объектов документа. Версия IE этого свойства называется просто document. Пример Используйте приложение The Evaluator (глава 13) для изучения свойства ownerDocument. Введите в верхнее текстовое поле следующее выражение. document.body.childNodes[5].ownerDocument Возвращаемый результат представляет ссылку на объект document. Вы можете исполь- зовать его для изучения свойств документа, как показано в следующем выражении, которое также следует ввести в верхнее поле. document.body.childNodes[5].ownerDocument.URL Этот оператор возвращает свойство document. URL для документа, содержащего дочер- нииузел. См. также объект document. parentElement Значение: ссылка на объект элемента или nul 1 Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство parentElement возвращает ссылку на элемент, внешний по отношению к данному. Такое взаимоотношение родительских и дочерних узлов между элементами часто (но не всегда) совпадает со взаимоотношением между узлами (см. описание свойства parentNode далее в этой главе). Различие состоит в том, что свойство parentElement возвращает эле- менты HTML, в тр время как узел не обязательно является таковым (например, узлом может быть атрибут дескриптора или заключенный в него блок текста). Кроме того, между свойствами parentElement и offsetParent существует разли- чие. Последнее возвращает элемент, который находится на определенном расстоянии от дан- ного элемента в иерархии, но является родителем относительно “точки отсчета” при пози- ционировании. Например, свойство parentElement элемента td в большинстве случаев содержит ссылку на внешний элемент TR, однако свойство offsetParent для этого же элемента равно элементу table. 280 Часть III. Объекты документа
С помощью свойства parentElement сценарий может “пройти” по иерархии элемен- тов. Вершиной цепочки родительских элементов является элемент HTML. Его свойство parentElement возвращает значение null. Пример Вы можете экспериментировать со свойством parentElement в приложении The Evaluator. Его документ содержит элементы р и myP. Введите следующие выражения из лево- го столбца в верхнее текстовое поле приложения и нажмите <Enter>. Выражение Результат document.getElementByld("myP") .tagName p document.getElementByld("myP") .parentElement [object] document.getElementByld("myP") .parentElement.tagName body document.getElementByld("myP") .parentElement.parentElement [object] document.getElementByld("myP") tagName .parentElement.parentElement. html document.getElementByld("myP") parentElement.parentElement .parentElement. null См. также свойства offsetParent, parentNode. parentNode Значение: ссылка на объект элемента или null Только для чтения Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство parentNode возвращает ссылку на узел, внешний по отношению к данному и отображаемый как объект, принадлежащий документу. Для стандартного объекта элемента свойство parentNode совпадает со свойством parentElement в IE, так как оба объекта имеют взаимоотношения родительских и дочерних узлов во всех элементах. Однако узлами могут быть представлены и другие типы данных. Последние включают фрагменты текста внутри элемента. Свойство parentNode фрагмента текста представляет собой внешний узел или элемент, включающий в себя этот фрагмент. Объект текстового узла в IE не имеет свойства parentElement. Пример Используйте приложение The Evaluator для изучения свойства parentNode для узлов разных типов. Начните с ввода в верхнем поле следующих выражений. document.getElementByld("myP").parentNode.tagName document.getElementByld("myP").parentElement.tagName (только в IE) Теперь изучите свойства с точки зрения узла первого текстового фрагмента элемента myP. document.getElementByld("myP").childNodes[0].nodevalue document.getElementByld("myP").childNodes[0].parentNode.tagName document.getElementByld("myP") .childNodes [0] .parentElement (только в IE) Обратите внимание, что в IE текстовый узел не имеет свойства parentElement. См. также свойства childNodes, nodeName, nodeType, nodeValue, parentElement. Глава 15. Основные объекты HTML-элементов 281
parentTextEdit Значение: ссылка йа объект элемента или null Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Только немногие объекты в модели IE могут создать блок текста (см. объект TextRange в главе 35). Для нахождения ближайшего к объекту внешнего контейнера, способного гене- рировать текстовый блок, используется свойство parentTextEdit. Если элемент со- держится в иерархии, то возвращается ссылка на его объект. В ином случае (например document. body. parentTextEdit) свойство принимает значение null. Пример В листинге 15.14 приведен пример, в котором продемонстрировано использование свой- ства parentTextEdit для создания текстового диапазона. Страница, представляемая кодом из листинга 15.14, содержит абзац латинского текста, три переключателя, с помощью кото- рых указывается размер выделяемого текстового фрагмента. При щелчке в тексте абзаца об- работчик событий onclick вызывает функцию selectchunk(). Эта функция сначала проверяет, какой из переключателей выставлен, а затем определяет выделяемый текстовый фрагмент (относительно места щелчка пользователем). В данном сценарии свойство parentTextEdit используется для проверки того, можно ли использовать элемент, на котором щелкнул пользователь, для создания выделяемого текстового фрагмента. С помощью методов объекта TextRange текстовый фрагмент сначала сжимается в одну точку, далее он перемещается в точку щелчка и расширяется до указанного фрагмента. Обратите особое внимание на необычное поведение метода expand () объекта TextRange. При указании выделить все предложение IE автоматически не рассматривает начало элемента р как начало предложения. Началом в данном случае является точка (которой заканчивается предыдущее предложение). Поэтому в конец предыдущего элемента добавляется еще одна крытая (окрашенная в белый цвет) точка. Таким образом удается исключить из выделения “истинную” точку предыдущего элемента р. <html> <head> <title>parentTextEdit Property</title> <style type="text/css"> p {cursor:hand} </style> «script type="text/javascript"> function selectchunk() { var chunk, range; for (var i = 0; i < document.forms[0].chunk.length; i++) { i f (document.forms[0].chunk[i].checked) { chunk = document.forms[0].chunk[i].value; break; var x = window.event.clientX; var у = window.event.clientY; if (window.event.srcElement.parentTextEdit) { range = window.event.srcElement.parentTextEdit. createTextRange(); range.collapse(); 282 Часть III. Объекты документа
range.moveToPoint(х, у); range.expand(chunk); range.select(); </script> </head> <body bgcolor="white"> <form> <p>Choose how much of the paragraph is to be selected when you click anywhere in it:<br /> cinput type="radio" name="chunk" value="character" checked="checked" />Character cinput type="radio" name="chunk" value="word" />Word cinput type="radio" name="chunk" value="sentence" />Sentence cfont color="white">. </fontx/p> ; c/form> cp onclick="selectChunk()">Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, guis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in eprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> c/body> </html> См. также: свойство isTextEdit; объект TextRange (глава 35). previousSibling (См. nextsibling) readyState Значение: строка (целочисленное для объекта obj ect) Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- До начала обработки объекта или его данных, в сценарии можно проверить загружен- ность объектом всех вспомогательных данных (например внешние файлы изображений или аудио-/видеоклипы). Свойство readyState отображает состояние загрузки элемента. ' Возможные значения и их описание приведены в табл. 15.6. Значение HTML Значение OBJECT Описание complete interactive 4 Элемент и данные полностью загружены з Данные загружены или не загружены полностью, однако пользователь может взаимодействовать с элементом loaded loading uninitialized 2 Данные загружены, объект может начинать использоваться 1 Данные загружаются о Объект еще не начал загрузку данных Глава 15. Основные объекты HTML-элементов 283
Для большинства элементов HTML это свойство имеет значение complete. Большин- ство других состояний применяется с такими элементами, как img, embed и object, ко- торые загружают внешние данные и даже запускают другие процессы (например элементы управления ActiveX). Предупреждение: не стоит думать, что свойство readyState позволяет определить, су- ществует ли объект в документе (например, по значению uninitialized). Если такого объекта нет, то он не может иметь свойства readyState — это приводит к ошибке в сцена- рии: объект не определен. Если сценарий необходимо запустить лишь после того, как засу- жены все элементы и их данные, следует использовать обработчик события onload для эле- мента body или обработчик события onreadystatechange для текущего объекта (проверив, что свойство readyState имеет значение complete). Пример Чтобы удостовериться в том, что свойство readyState отличается от complete, изу- чите и выполните код, вводимый в дескрипторе <img> (см. ниже). <img id="mylmgn src="somelmage.gif"> <script type="text/javascript"> alert(document.getElementByld("mylmg").readyState); </script> Вставьте этот фрагмент кода в документ, загружаемый с помощью низкоскоростного се- тевого соединения. Если изображение отсутствует в кэше браузера, то будет получен резуль- тат uninitialized или loading. Последнее означает, что объект img существует, но его данные еще не начали передаваться с сервера. При повторной перезагрузке страницы изо- бражение загружается не из сервера, а из кэша браузера, поэтому свойство readyState принимает значение complete. См. также обработчик события onreadystatechange. recordNumber Значение: целочисленное или null Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Практически все объекты включают свойство recordNumber (оно применяется при вне- дрении объектов в Internet Explorer (для Windows) для представления повторяющихся дан- ных). Например, при отображении 30 записей из внешнего источника в таблице элемент tr встречается в HTML-коде только один раз. Однако браузер повторяет строку таблицы (и ее компоненты-ячейки) для размещения всех 30 строк данных. Свойством recordNumber объ- екта tr можно воспользоваться для определения, например, на какой строке был проведен щелчок мышью. Распространенным применением этого свойства является внедрение данных, позволяющее обновлять записи. Например, можно создать сценарий, который при выборе нередактируемой строки отображает данные записи в отдельном редактируемом поле или в другом элементе страницы. Если объект не привязан к источнику данных (или он является неповторяющимся объектом), свойство recordNumber содержит значение null. Пример В листинге 15.15 показано, как можно использовать свойство recordNumber для пере- хода к определенной записи в последовательности данных. Источник данных представляет собой небольшой текстовый документ, в котором значения разделены символами табуляции. 284 Часть III. Объекты документа
В нем содержится всего 20 записей. Отображаемая на странице таблица связана с этим ис- точником данных. С ним также связаны три элемента span, которые представляют тексто- вый абзац в верхней части документа. Щелчок на данных строки в таблице документа приво- дит к соответствующему изменению текстовых данных в верхнем абзаце. Сценарий этой страницы занимает всего одну строку кода. При вызове обработчика собы- тия one lick для повторяемого объекта tr функция получает в качестве аргумента ссылку на этот объект tr. Копия данных из внешнего источника сохраняется в объекте recordset. Свойство AbsolutePosition объекта recordset указывает на номер выбранной записи (по умолчанию выбирают первую запись). В сценарии этому свойству назначается номер строки, на которой щелкнул пользователь. Поскольку все три элемента span обращаются к одному и тому же источнику данных, то их содержимое немедленно обновляется, чтобы со- ответствовать изменившемуся объекту recordset.’ Обратите внимание, что третий элемент span связан с полем источника данных, которое не представлено в таблице страницы. <html> <head> <title>Data Binding (recordNumber)</title> <style type="text/css"> .filmTitle {font-style:italic} </style> «script type="text/javascript"> // установка указателя в записи, на которой выполнен щелчок function setRecNum(row) { document.oscars.recordset.AbsolutePosition = row.recordNumber; } </script> </head> <body> <pxb>Academy Awards 1978-1997</b> (Click on a table row to extract data from one record.)</p> <p>The award for Best Actor of «span datasrc="#oscars" datafld="Year"x/span> &nbsp;went to «span datasrc="#oscars" datafld="Best Actor" x/span> &nbsp;for his outstanding achievement in the film «span class="filmTitle" datasrc="#oscars" datafld="Best Actor Film"x/span>.«/p> «table borders"1" datasrc="#oscars" align="center"> «thead style="background-color:yellow; text-align:center"> <tr> <td>Year«/td> <td>Film«/td> <td>Director«/td> <td>Actress«/td> <td>Actor«/td> </tr> </thead> <tr id="repeatableRow" onclick="setRecNum(this)"> «tdxdiv id="coll" datafld="Year"x/divx/td> «tdxdiv class="filmTitle" id="col2" datafld="Best Picture" x/divx/td> «tdxdiv id="col3" datafld="Best Director"x/divx/td> «tdxdiv id="col4" datafld="Best Actress"x/divx/td> «tdxdiv id="col5" datafld="Best Actor"x/divx/td> Глава 15. Основные объекты HTML-элементов 285
</table> «object id="oscars" classid="clsid:333C7BC4-460F-llDO-BC04- 0080C7055A83"> <param name="DataURL" value="Academy Awards.txt" /> <param name="UseHeader" value="True" /> <param name="FieldDelim" value="&#09;" /> </object> </body> </html> См. также: свойства dataFld, dataSrc; объекты table, tr (глава 37). runtimes ty 1 e Значение: объект style Только для чтения Совместимость: WinIE5+, MacIE5+, NN-, Moz-, Safari- C помощью свойства runtimestyle можно определить настройки стилей браузера по умолчанию. Объект style, который возвращает это свойство, принимает все атрибуты сти- лей и настройки по умолчанию во время загрузки страницы. Это свойство не отображает зна- чений, присвоенных элементам стилевыми спецификациями в документе или в сценариях. Значения, возвращаемые этим свойством, отличаются от значений currentstyle. Послед- ние включают данные о значениях, которые не присвоены в стилях явно, но подвержены влиянию браузера. Свойство runtimestyle отображает неустановленные значения для стиля как пустые или нулевые. Пример Чтобы изменить свойство стиля, обратитесь к объекту style. Приложение The Evaluator (глава 13) позволяет сравнить свойства объектов runtimestyle и style элемента. Напри- мер, неизмененная копия приложения The Evaluator содержит элемент его с идентификатором "туЕМ". Введите в верхнее поле приведенные далее выражения. document.getElementByld("туЕМ").style.color document.getElementByld("туЕМ").runtimestyle.color Исходно оба свойства не имеют значений. Теперь назначьте цвет свойству style, вос- пользовавшись следующим выражением. document.getElementByld("туЕМ").style.color = "red" Если после этого вы повторно введете два первых выражения, то увидите, что объект style изменился, а объект runtimestyle — нет (по-прежнему не имеет значения). См. также: свойство currentstyle; объект style (глава26). scopeName Значение: строка Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Свойство scopeName непосредственно связано с данными XML, включенными в доку-, мент. При подключении XML-кода указывается одно или несколько пространств имен XML, определяющих “владельца” определенного дескриптора. Это необходимо для предотвраще- ния конфликтов, которые могут возникнуть в документе между одинаковыми именами деск- рипторов из различных источников. (Подробно объекты XML рассмотрены в главе 41.) 286 Часть III. Объекты документа
Пространство имен XML определяется как атрибут деофиптора <html >, в который по- мещается документ. <html xmlns:fred=1 http://www.someURL.com1> После этого значение пространства имен включается во все дескрипторы документа. <fred:first_name id="fredfirstname"/> Чтобы найти “владельца” пространства имен элемента, необходимо получить его свойство scopeName. В предыдущем примере свойство scopeName имело значение Fred. Для обычных элементов HTML возвращаемое значение всегда равно html. Свойство scopeName доступно только в IE5+ для Win32 и UNIX. Аналогичное свойство в W3C DOM называется localName. Пример Если вы имеете в своем распоряжении тестовый документ, содержащий XML-код, то можете использовать методы document. write () или alert () для просмотра свойства scopeName. document .getElementByld (пидентификаторЭлемента") . scopeName См. также свойство tagUrn. scrollHeight scrollwidth Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN7+, Mozl+, Safaril+ Свойства scrollHeight и scrollwidth содержат значения размера объекта, не зави- сящие от того, какая его часть видна на странице. Таким образом, если в окне браузера при- сутствует вертикальная полоса прокрутки и объект выходит за пределы видимой области ок- ' на, свойство scrollHeight учитывает полный размер (как если бы пользователь прокрутил ” страницу вниз для отображения всего элемента). Для большинства элементов, которые не имеют своих полос прокрутки, свойства scrollHeight и scrollwidth обладают теми же значениями, что clientHeight и clientwidth. Пример Приложение The Evaluator (глава 13) предоставляет возможность детально изучить свой- ство textarea. Чтобы получить список свойств объекта body, сначала введите в нижнее поле следующее выражение. document.body Далее введите в верхнее поле приведенное ниже выражение, чтобы получить свойство scrollHeight для объекта textarea, который состоит из нескольких строк и имеет иден- тификатор output. document.getElementByld("output").scrollHeight В результате в области вывода будет отображено большое числовое значение (несколько сотен пикселей). Это означает, что вы можете прокрутить содержимое элемента output для отображения других частей элемента. Один раз щелкните на кнопке Evaluate. Предыдущий результат занимает по высоте всего одну строку, 13-ую или 14-ую, в зависимости от исполь- зуемого шрифта, поэтому свойство scrollHeight объекта textarea принимает именно это значение. Свойство scrollwidth этого объекта имеет фиксированное значение, опре- деленное атрибутом cols элемента. См. также: свойства clientHeight, clientwidth; метод window, scroll (). Глава 15. Основные объекты HTML-элементов 287
scrollLeft scrollTop Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN7+, Mozl+, Safaril+ Если элемент является прокручиваемым (другими словами, имеет собственные полосы прокрутки), с помощью свойств scrollLeft и scrollTop можно определить, насколько он прокручен в горизонтальном и вертикальном направлениях. Величины измеряются в пик- ' селях. Для непрокручиваемых элементов эти свойства всегда равны нулю, даже если они со- держатся внутри прокручиваемых элементов. Например, если прокрутить окно браузера (или фрейм) по вертикали, свойство scrollTop объекта body будет указывать расстояние между i вершиной объекта (за пределами видимой области) и первой видимой строкой пикселей эле- мента. Тем не менее, свойство scrollTop таблицы внутри документа всегда равно нулю. В NN до версии 7 (Mozl) прокрутка элемента body выполняется с точки зрения окна. Ес- ли необходимо определить, насколько прокручена страница (в пикселях), воспользуйтесь свойствами window, scrollx и window. scrollY. В сценариях, в которых отслеживаются события, связанные с мышью, в IE нужно прини- мать в расчет свойства scrollLeft и scrollTop для компенсации прокрутки страницы^ (см. событие Event в главе 25). Пример Приложение The Evaluator (глава 13) позволяет исследовать эти два свойства для объекта тек-1 стовой области, в которой представлены результаты вычислений. Для начала введите в нижнее 1 текстовое поле следующее выражение, позволяющее отобразить список свойств элемента body. I document.body i Используйте полосу прокрутки текстовой области для смещения в нижнюю часть списка. 1 Далее введите следующее выражение в верхнее текстовое поле. document.getElementByld("output").scrollTop В качестве результата вы получите число, определяющее расстояние, на которое тексте-1 вая область была прокручена в вертикальном направлении. Щелкните на кнопке Evaluate ] еще раз. При этом будет возвращен результат 0. Это означает, что в текстовой области было! недостаточно данных для выполнения прокрутки (в ней находилась всего одна текстовая! строка с предыдущим результатом 0). Поскольку горизонтальная полоса прокрутки вообще! не отображается, то и свойство scrollLeft тоже остается неизменным. | См. также: свойства clientLeft, clientTop; метод window, scroll (). | sourceindex ) Значение: целочисленное Только для чтени! I Совместимость: WmIE4+, MacIE4+, NN-, Moz-, Safari- 1 Свойство sourceindex возвращает числовой индекс (начиная с нуля) объекта в полной! наборе элементов документа. £ Пример I Операции с описываемым свойством весьма однозначны, этого не скажешь о набора свойств объекта document. all. Вы можете использовать приложение The Evaluator для опри деления того, корректно ли соотносятся индексы, возвращаемые свойствами sourceindexfl и document .all (например, в IE4+). « 28SЧасть III. Объекты докумкА
Для начала загрузите приложение The Evaluator и введите в верхнее поле следующее выражение. а = О При выполнении этого выражения в поле результатов должен появиться ноль. Далее вве- дите в верхнее поле следующее выражение. document.all [a] .tagName + " [" + а++ + "] " В этом выражении много знаком “плюс”, поэтому отнеситесь к их вводу особенно внима- тельно. После выполнения этого выражения глобальная переменная а увеличит свое значение, позволив просматривать элементы в порядке их представления в коде. Значение свойства sourceindex для каждого HTML-дескориптора приводится в квадратных скобках в поле Results. html [0] head [1] title [2] Продолжайте выполнять это выражение до тех пор, пока не достигнете конца кода и не по- лучите сообщение об ошибке (пока не просмотрите все элементы массива document.all). Сравните полученные объекты с исходным HTML-кодом. См. также метод item (). style Значение: ссылка на объект style Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство style представляет собой “шлюз” к настройкам стилей элемента. Значением свойства является объект style, свойства которого позволяют получать и изменять установ- ки стилей. Как правило, сценарии не управляют объектом style целиком, а используют его свойства для подключения эффектов анимации, отображения или скрытия элемента. Измене- ние свойств объекта style может повлиять на разметку .страницы. Например, установка , большего размера шрифта элемента приводит к переформатированию абзаца. Между свойствами объекта style в IE и NN существует немало различий. Более подроб- но об объекте style рассказано в главе 26. Пример Многие действия, выполняемые с помощью свойства style, требуют управления объек- том style. Используйте приложение The Evaluator, и вы сможете ознакомиться со свойства- ми этого объекта в самых разных браузерах. Для начала введите следующее выражение в нижнее текстовое поле. document.body.stylе Теперь просмотрите свойства объекта style для элемента таблицы, которая включена в страницу приложения The Evaluator. Введите в нижнее поле такое выражение. document.getElementByld("myTable").style В обоих случаях значения свойств объекта style весьма ограничены. См. также: свойства currentstyle, runtimestyle; объект style (глава 26). tabindex Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство tabindex управляет тем, в какой момент при последовательном нажатии кла- виши <ТаЬ> текущий элемент активизируется. Очевидно, что это свойство имеют только те Глава 15. Основные объекты HTML-элементов 289
элементы, которые способны к активизации. ВIE5+ количество таких элементов больше, чем в других браузерах; тем не менее, почти во всех браузерах это свойство поддерживается большинством основных элементов (например элементы ввода данных форм), для которых оно может понадобиться. В большинстве случаев браузеры по умолчанию рассматривают элементы форм как акти- визируемые. Элементы, которые не добавляются на формы, не активизируются, если только их свойство tabindex (или атрибут дескриптора tabindex) не заданы специально. Если свойство tabindex определенного элемента формы равно 1, то он будет активизироваться первым. Остальные элементы при нажатии клавиши <ТаЬ> будут активизироваться в порядке задания в документе. Если два элемента имеют значение свойства, равное 1, то сначала выде- ляется тот из них, который расположен в документе первым, а затем все остальные элементы. В браузере Internet Explorer, если вы установите значение свойства tabindex равным -1, элемент можно будет полностью устранить из последовательности активизируемых объектов. Пользователи все равно смогут вносить изменения в содержимое такого элемента, однако при последовательном нажатии клавиши <ТаЬ> он выделяться не будет. Пример Листинг 15.16 содержит простой сценарий, демонстрирующий принципы управления по- рядком активизации элементов с помощью свойства tabindex. Например, из него вы узнае- те не только о том, как изменить порядок активизации элементов форм, но и как обратиться к элементам формы, которые не включены в порядок активизации в IE. На указанной страни- це самая верхняя форма (именуемая lab) содержит четыре элемента. Сценарий запускается с помощью кнопок нижней формы. Обратите внимание, что свойство tabindex для всех трех кнопок нижней формы установлено в значение -1, поэтому эти кнопки не рассматрива- ются при формировании порядка активизации элементов в IE. При загрузке страницы порядок активизации элементов по умолчанию для формы lab изменяется. При нажатии клавиши <ТаЬ> получаемый результат будет полностью зависеть от. используемого браузера. В IE сначала выделяется строка адреса, затем активизируется окно( документа или кадр (в случае использования многокадрового документа). Только после этого' активизируется форма и ее элементы. В NN6+ вы должны щелкнуть в любом месте формы, чтобы предоставить пользователю возможность активизировать элементы формы. Следующий простой сценарий инвертирует порядок активизации элементов. Для этого используется цикл for и две переменные. Таким образом, последнему элементу назначается самый меньший индекс tabindex. Функция skip2 О устанавливает свойство tabindex второго текстового поля равным -1. В результате последнее удаляется из порядка активиза-1 ции элементов в IE. Обратите внимание, что вы всегда можете щелкнуть в поле и ввести] в нем необходимый текст. В NN6+ нельзя изменить это свойство так, чтобы исключить cool' 1 ветствующий элемент из списка активизации. <html> <head> <title>tablndex Property</title> «script type="text/javascript"> function invert() { var form = document.lab; for (var i = 0, j = form.elements.length; i < form.elements.length; i++, j--) { form.elements[i].tabindex = j; 290 Часть III. Объекты
} } function skip2() { if (navigator.userAgent.indexOf("MSIE") != -1) { document.lab.text2.tabindex = -1; } else { alert("Not available."); } } function resetTab() { var form = document.lab; for (var i = 0; i < form.elements.length; i++) { form.elements[i].tabindex = 0; } } </script> </head> <body> <hl>tablndex Property Lab</hl> <hr /> <form name="lab"> Text box no. 1: cinput type="text" name="textl" /><br /> Text box no. 2: cinput type="text“ name="text2" />cbr /> cinput type="button" value="A Button" />cbr /> cinput type="checkbox" />And a checkbox c/form> chr /> cform name="control"> cinput type="button" value="Invert Tabbing Order" tabindex="-1" onclick="invert()" />cbr /> cinput type="button" value="Skip Text box no. 2 (IE Only)" tabindex="-l" onclick="skip2()" />cbr /> cinput type="button" value="Reset to Normal Order" tabindex="-l" onclick="resetTab()" /> </form> c/body> c/html> Последняя функция resetTab () устанавливает свойство tabindex для формы lab равным нулю, что приводит к восстановлению исходного порядка активизации элементов. См. также методы blur (), focus (). tagName Значение: строка Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство tagName возвращает строку с именем дескриптора HTML или (в IE5+ и NN6) XML объекта элемента. Все значения tagName содержат символы только верхнего регистра, даже если в исходном коде они указаны иначе. Такая согласованность облегчает сравнение строк. Например, при запуске определенных действий для некоторых (не для всех) элементов можно воспользоваться следующей функцией, содержащей оператор switch. function processObj(objRef) { switch (objRef.tagName) { Глава 15. Основные объекты HTML-элементов 291
case "TR": [операторы управления объектом строки] break; case "TD": [операторы управления объектом ячейки] break; case "COLGROUP": [операторы управления объектом группы столбцов] break; default: [операторы управления другими объектами] } } Пример Вы также можете использовать свойство tagName для программирования действий, подобных тем, которые представлены в предыдущем примере по управлению свойством sourceindex. В предыдущем примере свойство tagName считывалось для объектов ис- ходного порядка активизации. См. также: свойство nodeName; метод getElementsByTagName (). tagUrn См. свойство scopeName title Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ В стандарте W3C утверждается, что свойство title (н атрибут TITLE) необходимо использовать как “подсказку”. Многие браузеры выводят текст (присвоенный свойству или атрибуту) прн наведении указателя мыши на элемент. Преимущество записи значений в это свойство заключается в возможности изменения текста подсказки элемента в ответ на взаимодействие с пользователем. Подсказка отображает информацию о назначении знач- ков и ссылок на странице. Кроме того, она может содержать краткое резюме страницы, на которую указывает ссылка, что позволяет пользователю просмотреть информацию без пе- рехода на другую страницу. В данном случае не рекомендуется использовать подсказки для отображения важных све- дений. Не все пользователи достаточно терпеливы, чтобы навести указатель мыши и дож- даться, когда появится подсказка. С другой стороны, пользователь скорее заметит появление подсказки, чем сообщение в строке состояния (хотя последнее и появляется мгновенно). Пример В листинге 15.17 показано, как можно использовать свойство title для создания всплы- вающих подсказок. Простой элемент абзаца в представленной странице имеет всплывающую , подсказку “First Time!”. Эта подсказка будет отображена на экране, если вы наведете указа- I тель мыши на текст абзаца н задержите его там на несколько секунд. Кроме того, с помощью обработчика событий mouseover и переменной counter ведется учет количества наведе- ; ний пользователем указателя мышн на абзац. В каждой следующей подсказке вы получите : сведения о количестве выполненных операций. 292 Часть III. Объекты документа
<html> <head> <title>title Property</title> <script type="text/javascript"> var count = 0; function setToolTip(elem) { elem.title = "You have previously rolled atop this paragraph " + count + " time(s)."; } function incrementcount(elem) { count++; setToolTip(elem); } . </script> </head> <body> <hl>title Property Lab</hl> <hr /> <p id="myP" title="First Time!" onmouseover= "incrementCount(this)">Roll the mouse over this paragraph a few times.<br /> Then pause atop it to view the tooltip.</p> </body> </html> См. также свойство window, status. uniquelD Значение: строка Только для чтения Совместимость: WinIE5+, МасШ5-, NN-, Moz-, Safari- С помощью свойства uniquelD браузер WinIE5+ позволяет генерировать идентификатор (свойство id) элемента, создаваемого на странице динамически. Это свойство следует ис- пользовать с осторожностью, так как идентификатор, созданный в определенный момент времени, может отличаться от идентификатора, генерируемого при последующем создании элемента на странице. Поэтому к свойству uniquelD обращаются тогда, когда в сценарии неизвестный элемент должен иметь свойство id, но сами алгоритмы не могут зависеть от конкретного идентификатора. Чтобы элемент получил только один идентификатор (пока объект существует в памяти), при- свойте значение свойства uniquelD одного н того же объекта. Получение свойства uniquelD не влияет на его значение. Таким образом, значение свойства uniquelD присваивается свойству id объекта для выполнения других видов обработки. (Например, метод getElementByld () требует, чтобы свойству id объекта было присвоено значение.) Пример Листинг 15.18 демонстрирует синтаксис получения сгенерированного браузером иденти- фикатора объекта. После ввода определенного текста в поле щелкните на кнопке — функция addRowO вставит в таблицу новую строку. В левом столбце приведен идентификатор, Глава 15. Основные объекты HTML-элементов 293
сгенерированный с помощью свойства uniquelD. ВIE5+ идентификаторы создаются в форма- те "ms_idn", где п представляет собой целое число текущего сеанса работы в браузере. По- скольку функция addRow () назначает идентификатор строке и ячейкам каждой строки, то це- лое число для каждой строки на трн больше, чем для предыдущей. Нет никакой гарантии, что будущие версии браузеров наследуют этот формат и последовательность именования объектов. Лирпшг 15.11. Нсяольэомиме свойства uni «ив ID <html> <head> <title>Inserting an WinIE5+ Table Row</title> <script type=,,text/javascript"> function addRow(iteml) { if (iteml) { 11 сохранение длинной ссылки в переменной var theTable = document.getElementByld("myTable"); // добавление новой строки в конец таблицы var newRow = theTable.insertRow(theTable.rows.length); 11 назначение строке идентификатора newRow.id = newRow.uniquelD; I/ объявление переменной строки var newCell;' 11 вставленная строка изначально не имеет ячеек newCell = newRow.insertCell(0); // назначение идентификатора ячейке newCell.id = newCell.uniquelD; // отображение идентификатора ячейки в качестве текста newCell.irinerText = newRow.id; newCell.bgColor = "yellow" 11 повторное использование переменной newCell = newRow.insertcell(1); newCell.id = newCell.uniquelD; newCell.innerText = iteml; } } </script> </head> <body> «table id="myTable" border="l"> <tr> <th>Row ID</th> <th>Data</th> </tr> 1 <tr id="firstDataRow"> <td>firstDataRow«/td> <td>Fred«/td> 1 </tr> <tr id="secondDataRow"> ,| <td>secondDataRow</td> 1 <td>Jane</td> </tr> </table> .1 <hr /> 4 <form> i 294 Часть III. Объекты докуме/
Enter text to be added to the table:<br I> <input type="text" name="input" size="25" /xbr /> «input type='button' value='Insert Row' onclick='addRow(this.form.input.value)' /> </form> </body> </html> См. также: свойство id; метод getElementByld (). Методы addBehavior (" URL") Возвращаемое значение: целочисленный идентификатор Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод addBehavior () импортирует внешнее поведение Internet Explorer и присоединя- ет его к текущему объекту, расширяя, таким образом, его свойства и/или методы. Подробно о поведениях IE (новое свойство IE5 для Windows) рассказывается в главе 48. Единственным параметром метода addBehavior () является ссылка URL на код компоненты поведения. Эта компонента может располагаться во внешнем файле (с расширением . htc). В этом слу- чае URL является либо абсолютным, либо относительным. IE включает библиотеку встроен- ных (по умолчанию) поведений, URL которых имеют следующий формат. #6е£аи1£#имяПоведения В данном случае имяПов едения представляет одно из поведений по умолчанию (глава 48). Если поведение импортируется в документ с помощью дескриптора object, то параметром метода addBehavior () является идентификатор элемента в следующем формате. ЪидентификаторОбъекта При добавлении поведения загрузка внешнего кода происходит асинхронно. Несмотря на то, что метод быстро возвращает значение, поведение не всегда готово к работе. Только по- сле полной загрузки поведение может отзываться на события и предоставлять доступ к своим свойствами н методам. К поведениям, загружаемым из внешних файлов, применяются прави- ла безопасности доменов. Пример В листинге 15.19а показано, как выглядит файл поведения. Данное поведение предназна- чено для демонстрации возможностей метода addBehavior (). Поведение и HTML-стра- ница, с которой оно загружается, должны располагаться на одном сервере и в одном домене (также они должны загружать по одному протоколу). «PUBLIC:ATTACH EVENT="onmousedown" ONEVENT="makeHot()" /> «PUBLIC:ATTACH EVENT="onmouseup" ONEVENT="makeNormal()" /> «PUBLIC:PROPERTY NAME="hotColor" /> «PUBLIC:METHOD NAME="setHotColor" /> «SCRIPT LANGUAGES'JScript"> var oldColor var hotColor = "red" Глава 15. Основные объекты HTML-элементов 295
function setHotColor(color) { hotColor = color } function makeHotO { if (event.srcElement == element) { oldColor = style.color runtimestyle.color = hotColor } } function makeNormaK) { if (event.srcElement == element) { runtimestyle.color = oldColor } } </SCRIPT> Поведение присоединено в объекту текстового абзаца, который приведен в листинге 15.196. При загрузке страницы поведение к объекту автоматически не присоединяется, поэтому щел- чок на тексте абзаца ни к чему не приводит. При включении поведения с помощью функции turnOn () метод addBehavior () при- соединяет код makeHot. htc к объекту туР. Начиная с этого момента, объект myP располагает дополнительными свойством, методом и двумя обработчиками событий. Если необходимо присоединить данное поведение к другим абзацам документа, то потребуется выполнить ме- тод addBehavior () по отношению к им всем. После распоряжения о загрузке файлу поведения в сценарии вызывается функция setinitialcolor (), с помощью которой новый цвет (выбранный в списке) назначается абзацу. Но это происходит только после полной загрузки поведения. Именно поэтому функ- ция проверят значение свойства readyState объекта myP. Если IE все еще загружает пове- дение, то функция будет запущена повторно через 500 миллисекунд В процессе загрузки поведения вы можете изменить цвет выделения абзаца. Функция сна- чала проверяет, загружено ли поведение полностью, анализируя для этого' свойство цвета для объекта. Если цвет новый, то вызывается метод добавления поведения. Вы также можете просто установить значение свойства. <html> <head> <title>addBehavior() and removeBehavior() Methods«/title> «script type=,,text/javascript"> var myPBehaviorlD; function turnOn() { myPBehaviorlD =' document.getElementByld("туР"). addBehavior("makeHot.htc"); setlnitialColor(); } function setlnitialColor() { if (document.getElementByld("туР").readyState == "complete") { 296 Часть III. Объекты документа
var select = document.forms[0].colorchoice; var color = select.options[select.selectedlndex].value; document.getElementByld("myP").setHotColor(color); } else { setTimeout("setlnitialColor()", 500) ; function turnOff() { document.getElementByld("my₽").removeBehavior(myPBehaviorlD); } function setColor(select, color) { if (document.getElementByld("myP").hotColor) { document.getElementByld("myP").setHotColor(color); } else { alert("This feature is not available. Turn on the Behavior first."); select.selectedlndex = 0; function showBehaviorCount() { var num = document.getElementByld("туР").behaviorUrns.length; var msg = "The myP element has " + num + " behavior(s). "; if (num > 0) { msg += "Name(s): \r\n"; for (var i = 0; i < num; i++) { msg += document.getElementByld("myP").behaviorUrns[ij + "\r\n"; } } alert(msg); } «/script> </head> <body> «hl>addBehavior() and removeBehavior() Method Lab</hl> «hr /> «p id="myP">This is a sample paragraph. After turning on the behavior, it will turn your selected color when you mouse down anywhere in this paragraph.«/p> «form> <input type="button" value="Switch On Behavior" onclick="tumOn() " /> Choose a 'hot' color: «select name="colorchoice” onchange="setColor(this, this.value)"> «option value="red">red«/option> «option value="blue">blue«/option> «option value="cyan">cyan«/option> «/selects <br /> «input type="button" value="Switch Off Behavior" onclick="turnOff()" /> <p>«input type="button" value="Count the URNs" onclick="showBehaviorCount()" />«/p> «/form> </body> «/html> Глава IS. Основные объекты HTML-элементов 297
Для отключения поведения выполняется метод removeBehavior (). Обратите внимание, что он связан с объектом тур н в качестве аргумента принимает идентификатор загруженно- го ранее поведения. Если с объектом связно несколько поведений, то вы можете удалить ка- ждый из них отдельно от остальных (поскольку все они имеют разные идентификаторы). См. также: свойство readyState; метод removeBehavior (); поведения (глава 48). addEventListener (11 типСобытия", функцияПолучателяСобытия, захват) removeEventListener("типСобытия", функцияПолучателяСобытия, захват) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Механизм событий W3C DOM включает в себя способы возникновения н перемещения событий (главу 25). Хотя новый метод обеспечивает привязку события к элементу с помощью атрибутов HTML (например, всем известный обработчик события one lick), все же рекомен- дуется определять события с помощью приемника события для элемента. (В браузерах, поддер- живающих модель событий W3C, происходит внутреннее преобразование методов привязыва- ния событий — например, обработчиков событий в атрибутах — в приемники событий.) Чтобы сообщить объектной модели документа, что элемент должен принимать опреде- ленный тип события, необходимо воспользоваться методом addEventListener (). Он имеет три параметра. Первый является строкой с типом события, который должен приниматься элементом. Строки с типами событий не включают префикс on, который имеют обработчики событий. Имена состоят только из названий событий, как правило, включающих только сим- волы нижнего регистра (за исключением специальных системных событий, имена которых начинаются с префикса DOM). Все события, заданные спецификацией W3C DOM (хотя не все они поддерживаются NN6), приведены в табл. 15.7. abort error blur focus change load click mousedown DOMActivate mousemove DOMAt t rMod i f i ed mouseout DOMCharacterDataModified mouseover DOMFocusIn mouseup DOMFocusOut reset DOMNodelnserted resize DOMNodelnsertedlntoDocument scroll DOMNodeRemoved select DOMNodeRemovedFromDocument submit DOMSubtreeModif ied unload 298 Часть III. Объекты документа
Обратите внимание, что количество событий, определяемых DOM 2, является более ог- раниченным по сравнению с числом событий в IE4+. Кроме того, консорциум W3C вре- менно приостановил решение вопроса о событиях клавиатуры до выхода DOM 3. К сча- стью, такие события поддерживаются в NN в той же форме, в которой они, вероятно, будут реализованы в W3C DOM. Вторым параметром метода addEventListener () является ссылка на функцию JavaScript. Структурно это напоминает ситуацию присвоения функции свойству объекта '(например objReference.onclick = Функция). Кроме того, имя функции не должно помещаться в кавычки. Такой подход означает, что в вызове функции нельзя указать пара- метры. Поэтому функции, которым необходим доступ к формам или их элементам управле- ния, должны использовать собственные ссылки (в результате чтения свойства объекта собы- тия, определяющего, какой объект является целью). По умолчанию модель событий W3C DOM заставляет события всплывать вверх по иерархии элементов-контейнеров, начиная с объекта, являющегося целью события (например по щелчку на кнопке). Однако если третий параметр метода addEventListener О имеет значение true, то захват определенного типа события разрешен всякий раз, когда текущий объект явля- ется целевым. Это значит, что событие любого другого типа, целью которого является текущий объект, переместится по иерархии (если только событие также не имеет приемника события, связанного с объектом, третий параметр метода которого установлен в значение true). Использование метода addEventListener О требует, прежде всего, наличия объекта, к которому присоединен метод. Поэтому данный метод лучше вызывать внутри функции инициализации, запускаемой обработчиком события onload для всей страницы. (Объект document может вызвать метод addEventListener О сразу, поскольку этот объект су- ществует с самого начала процесса загрузки.) Сценарий обладает возможностью удалить приемник события, который ранее был добав- лен сценарием. Метод removeEventListener () имеет те же параметры, что и addEvent- Listener (), а это значит, что отключение одного приемника не влияет на остальные. Ис- ходя из того, что для одного события можно назначить два приемника (один — предназна- ченный, а второй — не предназначенный для захвата, хотя это очень редкая ситуация), трн параметра метода removeEventListener О позволяют точно указать, какой приемник события из объекта следует удалить. В отличие от метода захвата в NN4, модель событий W3C DOM не имеет “глобального” механизма захвата событий независимо от цели. Метод addEventListener () очень бли- зок по функциональности к методу attachEvent () в IE5. Кроме того, захват событий в IE5 можно разрешить с помощью метода setcapture (). Обе модели событий W3C н IE5 ис- пользуют свои типы синтаксиса для привязки объектов к функциям-обработчикам, поэтому реальные функции могут служить обеим моделям, а различие в версии браузера проявляется только прн привязке событий. В главе 25 вопрос обработки событий в этих двух моделях ос- вещен более подробно. Пример В листинге 15.20 приведен простой пример управления базовой моделью событий W3C DOM. При загрузке страницы приемником событий выступает браузер (за исключением кнопок). Но вы всегда можете указать приемник для события click объекта body или объекта р, кото- рый окружает элемент span (содержащий текст), причем сделать это можно двумя способа- ми: всплывания и захвата. После добавления приемника события щелкните в тексте — в ре- зультате вы увидите процесс обработки события н узнаете о том, каким из двух методов передается событие. Обратите внимание на последовательность обработки событий. Удалите передатчики событий по одному, прн этом следите за реакций браузера. Глава 15. Основные объекты HTML-элементов 299
«html> «head> «title>W3C Event Model Lab«/title> «style type="text/css"> td {text-align:center} </style> «script type="text/javascript"> I/ добавление приемников событий function addBubbleListener(elemID) { document.getElementByld(elemID).addEventListener("click", reportEvent, false),- } function addCaptureListener(elemID) { document.getElementByld(elemID).addEventListener("click", reportEvent, true); } 11 удаление приемников событий function removeBubbleListener(elemID) { document.getElementByld(elemID).removeEventListener("click", reportEvent, false); } function removeCaptureListener(elemID) { document.getElementByld(elemID).removeEventListener("click", reportEvent, true); } 11 отображение сведений о событии function reportEvent(evt) { var elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target; if (elem.id == "mySPAN") { var msg = "Event processed at " + evt.currentTarget.tagName + " element (event phase = " + evt.eventPhase + ").\n";_ document.controls.output.value += msg; } } 11 очистка сведений о событиях function clearTextArea() { document. controls. output. value = " " ,- «/script> «/head> «body id="myBODY"> «hl>W3C Event Model Lab«/hl> «hr /> «p id="myP">«span id="mySPAN">This paragraph (a SPAN element nested inside a P element) can be set to listen for "click" events.«/span>«/p> «hr /> «form name="controls" id="controls"> «p>Examine click event characteristics:&nbsp;«input type="button" value="Clear" onclick="clearTextArea()" /> «br /> «textarea name="output" cols="80" rows="6" wrap="virtual"> «/textarea>«/p> 300 Часть III. Объекты fit
«table cellpadding="5" border="l"> «caption style="font-weight:bold">Control ₽anel«/caption> <tr style="background-color:#ffff99"> <td rowspan="2">"Bubble"-type click listener:«/td> «td>«input type="button" value="Add to BODY" onclick= "addBubbleListener('myBODY')" />«/td> <td>«input type="button" value="Remove from BODY" onclick="removeBubbleListener('myBODY')" />«/td> «/tr> «tr style="background-color:#ffff99"> «td>«input type="button" value="Add to ₽" onclick= "addBubbleListener('myP')" /></td> «tdxinput type="button" value="Remove from P" onclick= "removeBubbleListener('myP')" />«/td> «/tr> <tr style="background-color:#ff9999"> «td rowspan="2">"Capture"-type click listener:«/td> «tdxinput type= "button" value="Add to BODY" onclick= "addCaptureListener ('myBODY') " /x/td> «tdxinput type="button" value="Remove from BODY" onclick= "removeCapturefljistener('myBODY')" />«/td> </tr> «tr style="background-color:#ff9999"> «tdxinput type="button" value="Add to P" onclick= "addCaptureListener (' myP') " /x/td> «tdxinput type="button" value="Remove from P" onclick=”removeCaptureListener('myP')" /></td> </tr> «/table> «/form> «/body> </html> См. также методы attachEvent (), detachEvent (), dispatchEvent (), fireEvent (), removeEventListener(). appendChild (объектЭлемента) Возвращаемое значение: ссылка на объект узла Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Метод appendChild () вставляет элемент или текстовый узел (определенный в предыдущем коде) в качестве нового, последнего дочернего объекта текущего элемента. Кроме очевидного применения (добавления нового дочернего элемента к последовательности дочерних узлов), метод appendChild () полезен при создании объектов, предназначенных для добавления, замены или вставки в существующий документ новых данных. Метод document. createElement (), параметром которого является имя дескриптора, возвращает ссылку на элемент. Метод appendChild () возвращает ссылку на добавленный объект узла. Эта ссылка от- личается от объекта, переданного методу в качестве параметра, так как возвращаемое значе- ние представляет объект как часть документа, а не отдельный объект, созданный в памяти. Пример В листинге 15.21 приведен пример использования метода appendChild() совместно сметодами removeChildO н replacechild() для изменения в документе дочерних эле- ментов. Поскольку браузеры W3C DOM рассматривают символ возврата каретки в исходном Глава 15. Основные объекты HTML-элементов 301
коде как текстовый (дочерний) узел, в листинге 15.21 HTML-код не содержит символов воз- врата каретки между элементами. Функция append () создает новый элемент li, а затем использует метод appendchild () для присоединения текста, введенного в текстовое поле, в качестве отображаемого текста эле- мента. Вложенное выражение document. createTextNode (form, input .value) выпол- няется, чтобы “узаконить” операцию создания узла, добавляемого к элементу li. Все описан- ные выше операции выполняются до добавления элемента li в документ. В последнем операторе функции из элемента 1и вызывается метод appendChi ld(), чтобы добавить эле- мент Ив элемент 1и. При вызове метода replaceChild () в функции replace () во многом используется та- кой же код. Разница состоит в методе двух аргументов. Второй аргумент представляет ссылку на заменяемый дочерний элемент. В этом случае заменяется последний дочерний узел элемента lu. Чтобы получить ссылку на него в коде функции, используется свойство lastchild. Полу- ченная ссылка подставляется в качестве второго элемента метода replaceChild (). <html> <head> <title>appendChild(), removeChild() , and replaceChild() Methods</title> «script type="text/javascript"> function append(form) { if (form.input.value) { var newltem = document.createElement("LI"); newltem.appendchild(document.createTextNode(form. input .value) ) ; document.getElementByld("myUL").appendchild(newltem); function replace(form) { if (form.input.value) { var newltem = document.createElement("LI"); var lastchild = document.getElementByld("myUL"). lastchild; newltem.appendchild(document.createTextNode(form, input.value)); document.getElementByld("myUL").replaceChild(newltem, lastchild); } } function restore() { var oneChild; var mainObj = document.getElementByld(“myUL"); while (mainObj.childNodes.length >2) { oneChild = mainObj.lastchild; mainObj.removechild(oneChild); } } </script> </head> <body> <hl>Child Methods</hl> 302 Часть III. Объекты документа
<hr I > Here is a list of items: <ul id="myUL"xli>First Item</lixli>Second Item</lix/ul> <form> Enter some text to add/replace in the list: cinput type="text" name="input" size="30" /xbr /> cinput type="button" value="Append to List" onclick="append(this.form)" /> cinput type="button" value="Replace Final Item" onclick="replace(this.form)" /> cinput type="button" value="Restore List" onclick="restore()" /> c/form> c/body> </html> В последних операторах сценария используется метод removechild () для удаления всех дочерних элементов узла ul. Эта операция выполняется до тех пор, пока элемент ul содержит более двух исходных узлов. Для решения данной задачи используется свойство lastchild. См. также: методы removechild О , replaceChild (); узлы и дочерние объекты (глава 14). applyElement (объектЭлемеита [, тип]) Возвращаемое значение: отсутствует Совместимость: WinEE5+, MacIE-, NN-, Moz-, Safari- Метод applyElement О (не реализованный в Мас1Е5) позволяет вставить новый эле- мент в качестве родительского или дочернего элемента текущего объекта. Важным свойством данного метода является то, что новый объект заключает в себя текущий (если новый элемент является родительским) или наоборот (если новый элемент является дочерним). Когда новый элемент становится дочерним, все предыдущие дочерние объекты становятся вложенными в него (смещаются на один уровень). Легко догадаться, как действие метода влияет на уро- вень текущего элемента, поэтому applyElement () следует применять с осторожностью. Один из параметров — ссылка на объект — является обязательным. Этот объект создает- ся операторами типа document. createElement () или же одним из методов дочерних уз- лов, которые возвращают объект. Второй (дополнительный) параметр может принимать одно из следующих значений. Значение параметра Описание outside Новый элемент становится родительским для текущего inside Новый элемент становится первым дочерним узлом текущего Если параметр опущен, по умолчанию подразумевается значение outside. В листинге 15.22 показано, как используется метод applyElement () для решения практических задач. Пример Листинг 15.22 поможет вам детальнее изучить метод applyElement (). В коде этого лис- тинга в элемент span абзаца вставляется новый элемент em. В любой момент вы можете про- смотреть HTML-код всего элемента р, чтобы проверить, вставлен ли в него элемент em, а также проверить влияние вставленного элемента на иерархическую структуру объектов документа. Глава 15. Основные объекты HTML-элементов 303
После загрузки страницы внимательно изучите HTML-код элемента абзаца. Только по- сле этого можете приступать к выполнению следующих операций. Обратите внимание на элемент span и вложенный в него элемент font, которые содержат всего одно слово. Ес- ли вы вставите элемент ет в элемент span (щелкните на средней кнопке), то элемент ет станет первым (единственным) дочерним элементом span. При этом элемент font станет дочерним у элемента ет. <html> <head> <title>applyElement() Method</title> «script type="text/javascript"> function applyOutside() { var newltem = document.createElement("EM"); newltem.id = newltem.uniquelD; document.getElementByld("mySpan").applyElement(newltem); } function applylnside() { var newltem = document.createElement("EM"); newltem.id = newltem.uniquelD; document.getElementByld("mySpan").applyElement(newltem, "inside"); } function showHTMLO { alert(document.getElementByld("myP").outerHTML); } </script> </head> <body> <hl>applyElement() Method«/hl> «hr /> <p id="myP">A simple paragraph with a «span id= "mySpan" xfont size="+l">special«/fontx/span> word in it.«/p> <form> «input type="button" value="Apply &lt;EM&gt; Outside" onclick="applyOutside()" /> «input type="button" value="Apply &lt;EM&gt; Insidd" onclick="applylnside()" /> «input type="button" value="Show &lt;P&gt; HTML..." onclick="showHTML() " /xbr /> «input type="button" value="Restore Paragraph" onclick="location.reload()" /> </form> </body> </html> Результаты вставки и удаления элемента ет визуально проявляются в изменении начерта- ния всего одного слова на странице. Тем не менее, в приведенном примере видно, насколько сильно влияние всего одного элемента на общую иерархическую структуру HTML-документа. См. также методы insertBefore (), appendchild(), insertAdjacentElement (). 304 Часть III. Объекты документа
attachEvent (11 имяСобытия", ссылкаНаФуякщао) detachEvent (" имяСобытия", ссылкаНаФункцию) Возвращаемое значение: булевого типа Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод attachEvent () используется в коде, который определяет поведения Е (глава 48). Его можно также применить как еще один способ привязки обработчика событий к объекту. В следующем примере приведен типичный подход для назначения обработчика события. myObject.onmousedown = setHilite; С помощью метода attachEvent () эта операция выполняется следующим образом. myObject.attachEvent("onmousedown", setHilite); Оба параметра являются обязательными. Первый из них представляет собой строку с име- нем элемента (регистр учитывается). Второй — ссылку на функцию, запускаемую при возник- новении события. Эта ссылка представляет собой идентификатор функции с учетом регистра без кавычек и скобок (а это значит, что при таком вызове функции ей нельзя передать параметры). Использование метода attachEvent () имеет небольшое преимущество по сравнению Л привязкой событий к атрибутам элемента. В первом случае метод возвращает значение true, если привязка события прошла успешно. IE сообщает об ошибке, если функция указа- на неверно, поэтому при обработке ошибок не стоит полагаться на значение false. Кроме того, метод не дает подтверждения, что объект распознал имя события. Если для привязки обработчика к событию объекта использовался метод attachEvent (), ТО обратное действие можно произвести с помощью метода detachEvent (). Параметры последнего совпадают с параметрами метода attachEvent (). Метод detachEvent () не может отключить события, привязка которых была выполнена в атрибутах дескриптора или установкой свойств событий. > В модель событий W3C DOM включены функции, подобные этим методам в IE: addEvent- Listener () и removeEventListener (). Пример Используйте приложение The Evaluator (глава 13) для создания функции, которая вызыва- ется при возникновении события onmousedown для объекта первого абзаца страницы. Нач- ните с назначения функции глобальной переменной а (уже инициализированной в The Evaluator) в верхнем поле. а = new Function("alert('Function created at " + (new Date(J) + "')") Кавычки и скобки делают выражение весьма запутанным, поэтому будьте внимательны при его вводе. Если вы все ввели правильно, то в области результатов будет представлен текст функции. Теперь назначьте эту функцию в качестве обработчика события onmousedown элемента туР, введя в верхнем поле следующее выражение. document.getElementByld("туР").attachEvent("onmousedown", а) Если оно будет выполнено успешно, в области результатов выводится значение true. При наведении указателя мыши на первый абзац в окне сообщения будут указаны дата и вре- мя создания функции обработки события (выполняется выражение newData () ). Чтобы отменить связь между объектом и обработчиком событий, введите в верхнее поле •следующее выражение. document.getElementByld("myP").detachEvent("onmousedown", a) См. также: методы addEventListener О , detachEvent О , dispatchEvent(), fireEvent (), removeEventListener (); привязка событий (глава 14). Глава 15. Основные объекты HTML-элементов 305
blur () focus() Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Метод blur () делает элемент неактивным, а метод focus — наоборот, активизирует элемент. Хотя методы blur () и focus () поддерживались уже самыми ранними версиями браузеров, не все объекты можно активизировать. Браузеры до IE4 и NN6 имеют ограничен- ную поддержку этих методов в объекте window и элементах управления форм. Окна Метод blur () (NN3+, IE4+) размещает указанное окно за всеми открытыми на экране ок- нами. Если открыты окна других программ (например почтовых клиентов или приложений за- грузки новостей), окно, в котором выполнялся метод blur (), размещается позади других окон. .j ' “х В браузерах Mozilla метод window. blur (), не корректирует порядок расположения текущего окна в стеке (таким образом в этих браузерах кнопка Put Me in Back лис- тинга 15.23 не работает). В сценарии можно воспользоваться следующим спосо- ТУ бом: с помощью метода focus () окажите воздействие на другое окно и перемес- тите его на передний план (мы говорим о связи, возникающей при использовании свойства window. opener, которая должна существовать между двумя окнами). Открывая новое окно, уделите особое внимание его размещению на экране. При быстром отображении окна после щелчка мышью пользователь может скрыть меньшее окнб за большим. Как правило, неопытные пользователи не обращают внимания на панель задач Windows или меню браузера (если оно есть), не проверяют, открыто ли еще меньшее окно, и, таким образом, не акти- визируют его. Если вспомогательное окно является важным, то в каждом окне следует разместить кнопку или другой элемент, позволяющий пользователю легко переходить от окна к окну. Ме- тод window. focus () размещает текущее окно поверх всех остальных окон (т.е. в начале стека). Вы можете не размещать на странице кнопку, активизирующую скрытое окно, — по- стройте функции открытия окон так, чтобы открываемое окно автоматически выводилось на передний план (как показано в листинге 15.23). Это упрощает навигацию по Web-узлу. Чтобы достичь успеха, проверьте правильность всех ссылок на окна. Будьте внимательны при использовании свойства window. opener для обращения к главному окну в случае, ко- гда вспомогательное окно его активизирует. Элементы форм Методы blur () и focus () применяются, прежде всего, к элементам управления форм: 1 текстовым полям, элементам select и textarea. » Подобно тому, как изображение с камеры становится нечетким при изменении фокуса,! текстовый объект становится “нечетким”, отдаленным при его деактивизации — когда кто-то I активизирует другое поле. В сценарии метод blur() снимает выделение с поля и удаляет! курсор введения текста. При этом курсор не переходит к следующему полю, как это происхо-1 дит при нажатии клавиши <ТаЬ> вручную. , 1 Для текстового объекта активность обозначает наличие курсора, ожидающего введения! текста в поле объекта. Активизация означает “открытие” поля для редактирования его значе-1 ния пользователем. ' Активизация текстового поля или элемента textarea сама по себе не позволяет размес-1 тить курсор в определенной части поля. Курсор, как правило, появляется в начале текста. Для! подготовки поля к замене существующего текста необходимо последовательно воспользоваться! 306 Часть III. Объекты д(
методами focus () и select (). Помните, что метод focus () работает ненадежно в брау- зере NN3 для UNIX: хотя метод select () и позволяет выделить текст в поле, однако поле чаще всего не активизируется. Еще одна проблема в совместном применении методов focus () и select () для пред- варительного выделения содержимого поля заключается в следующем: многие версии Internet Explorer не позволяют получить желаемых результатов из-за внутренних проблем с синхро- низацией. Эту проблему можно обойти (и обеспечить совместимость с NN), инициируя дей- ствия активизации и выделения с помощью метода setTimeout (). Соответствующий при- мер приведен в главе 43. Распространенным требованием к документу является размещение курсора в конце тек- стового поля или элемента textarea, чтобы пользователь мог добавить текст к уже сущест- ; вующему содержимому. В IE4+ это достигается в результате применения объекта TextRange. Следующий сценарий перемещает текстовый курсор в конец элемента textarea, идентифи- катором которого является myTextarea. var range = document.all.myTextarea.createTextRange(); range.move ("textedit") ; „ range.select(); При совместном использовании методов blur () или focus (), а также обработчиков событий onblur и onf ocus необходимо проявлять осторожность (особенно если обработ- ’ чики выводят на экран окна с предупреждениями). Многие комбинации таких событий и ме- ; годов могут создать бесконечный цикл, в результате чего закрыть диалоговое окно будет не- возможно. С другой стороны, существует комбинация этих методов и обработчиков, полезная для старых версий браузеров, в которых текстовые поля не обладают свойством disabled. Следующий обработчик события для текстового поля предотвращает ввод информации в него. onfocus = "this.blur()"; Некоторые операционные системы и браузеры позволяют активизировать такие элементы, как кнопки (включая флажки и переключатели) и гиперссылки (включая элементы а и area). ‘-Когда такой элемент активизируется, вместо щелчка кнопкой мыши нажимается клавиша про- бела на клавиатуре. Это свойство может быть полезным тем, кому трудно пользоваться мышью, ц Нежелательным сторонним эффектом в отдельных ОС является то, что признак активно- сти элемента (пунктирный прямоугольник) остается вокруг кнопки и после щелчка на ней мышью (причем до тех пор, пока активным не станет другой элемент). Чтобы избежать этого, . включите следующий обработчик события onmouseup в атрибутах кнопок. onmouseup = "this.blur()"; В IE5.5 установка свойства hideFocus в значение true позволяет устранить эффект вы- деления пунктиром элемента при его активизации. Однако пользователь уже не сможет визу- ально определить, какой элемент на странице в данный момент активен. Другие элементы При управлении другими элементами методом focus () можно воспользоваться вместо метода scrollIntoView (). Ссылки (а) и элементы area в версии IE для Windows после активизации будут окружены пунктирным прямоугольником. Если этот эффект нежелателен, следует применить тот же обработчик события onmouseup = "this.blur()”; (или свойство hideFocus в IE5.5+), о котором было рассказано в разделе “Элементы форм”. Компания Microsoft в браузере IE5 расширила количество объектов, поддерживающих мето- ды blur () и focus (). Глава 15. Основные объекты HTML-элементов 307
Пример В листинге 15.23 приведен пример использования методов focus () и blur () для акти- визации окон браузера. В рассматриваемом примере рабочая среда состоит из двух окон. Из каждого из окон можно активизировать другое окно. Для создания ссылки на новое окно в главном окне используется метод window. open (). Во вложенном окне (его содержимое создается динамически с помощью JavaScript-кода) для доступа к исходному окну использу- ется свойство self .opener. При этом к самому вложенному окну применяется метод self .blur (). Активизация одного окна и деактивизация другого приводит к тому же ре- зультату, что и отображение одного окна поверх другого на рабочем столе. <html> <head> <title>Window Focus() and Blur()</title> «script type="text/javascript"> // объявление глобальной переменной var newWindow = null; function makeNewWindow() { // проверка существования окна if (InewWindow || newWindow.closed) { I/ сохранение нового объекта окна в глобальной переменной newWindow = window.open"width=250,height=250"); // небольшая пауза для завершения открытия окна в IE3 setTimeout("fillwindow()”,100); } else { // окно существует, вывод его на передний план newWindow.focus(); // компоновка нового содержимого и вывод его в подокне function fillwindow() { var newContent = "<htmlxheadxtitle>Another Sub Window <\/titlex\/head>" ; newContent += "<body bgColor=1 salmon’>"; newContent += "<hl>A Salmon-Colored Subwindow. <\/hl>" newContent += "<formxinput type='button' value='Bring Main to Front1 onclick='self.opener.focus()’>"; newContent += "<formxinput type='button' value=’Put Me in Back' onclick='self.blur()’>"; newContent += "<\/formx\/bodyx\/html>" ; // написание HTML-кода в окно нового документа newWindow.document.write(newContent); newWindow.document.close(); </script> </head> <body> <hl>Window focus() and blur() Methods</hl> <hr /> <form> <input type="button" name="newOne" value="Show New Window" onclick="makeNewWindow()" /> </form> </body> </html> 308 Часть III. Объекты доку
Ключевой оператор в функции makeNewWindow () в этом листинге — это первое услов- ное выражение. Поскольку переменная newWind при загрузке страницы инициализируется значением null, то это же значение она принимает сначала и в функции. Но после отобра- жения второго окна'в переменной newWind сохраняется объект этого (вложенного) окна; та- кое значение сохраняется в переменной даже после закрытия окна. Таким образом, перемен- ная newWind не принимает значение null. Чтобы проверить закрыл ли пользователь вложенное окно, используется условное выражение в начале функции. В главе 25 речь пойдет о методе focus () для текстовых объектов. См. также методы window. open (), document. f ormObj ect. textObj ect. select (). clearAttributes () Возвращаемое значение: отсутствует Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод clearAttributes () удаляет все атрибуты элемента, за исключением name и id. Таким образом, удаляются параметры стилевого форматирования, обработчики событий, а также атрибуты, присвоенные в исходном HTML-коде или в сценарии. Помните, что метод clearAttributes () не изменяет длину набора атрибутов элемента, так как этот набор всегда содержит все возможные атрибуты элемента. (Вернитесь к свойству attributes, рассмотренному ранее в этой главе.) Этот метод удобен тогда, когда нужно создать абсолютно новый набор атрибутов элемен- та и начать отображение элемента “с чистого листа”. Помните: если в сценарии атрибутам не присвоить новые значения, элемент будет отображаться в первичном состоянии до тех пор, пока новые значения не будут установлены. Это значит, что даже позиционируемые элементы окажутся в неупорядоченном состоянии (до тех пор, пока не будет задан новый стиль пози- ционирования). Если вам нужно лишь изменить значение одного или нескольких атрибутов, воспользуйтесь методом setAttribute () или определите соответствующее свойство. Чтобы получить тот же результат в NN6+/Mozl+, необходимо в цикле очистить значения всех атрибутов (методом removeAttribute ()), кроме id и name. Пример Используйте приложение The Evaluator (глава 13) для изучения атрибутов элемента до и после применения метода clearAttributes (). Для начала отобразите HTML-код для элемента'таблицы, введя в вверхнее текстовое поле следующее выражение. myTable.outerHTML Обратите внимание на атрибуты дескриптора <table>. Взгляните на отображенную в до- кументе таблицу, чтобы оценить влияние на нее атрибутов border и width. Введите в верх- нее поле приложения следующее выражение для удаления из элемента всех подлежащих этой операции атрибутов. myTable.clearAttributes() Еще раз взгляните на таблицу. Границы таблицы исчезли, а ее ширина определяется ис- ключительно ее содержимым. Наконец, ознакомьтесь с HTML-кодом таблицы после удаления атрибутов, воспользовавшись свойством outerHTML. myTable.outerHTML Файл с исходным кодом не изменился, хотя объектная модель в памяти браузера все еше отражает выполненные над атрибутами операции. См. также свойство attributes; методы getAttribute (), setAttribute (), removeAttribute (), mergeAttributes () и setAttributeNode (). Глава 15. Основные объекты HTML-элементов 309
click () Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN2+, Mozl+, Safari 1+ Метод click () позволяет сценарию произвести действие, равнозначное щелчку на эле- менте. Данный метод существовал с момента появления языка сценариев, однако он был дос- тупен только для таких элементов input, как кнопки (командные кнопки, кнопки восстанов- ления, отправления, переключатели и флажки). В ранних версиях браузеров операторы обработчиков событий необходимо было указывать напрямую. Кроме того, не на всех плат- формах кнопки реагируют в ответ на “щелчок” из сценария. Например, NN4 для Мас не из- меняет состояния флажка из сценария. Если вам требуется, чтобы сценарий “щелкал” на кнопке, проще всего напрямую запус- тить обработчик события. Если элемент является переключателем или флажком, то его со- стояние придется изменять вручную (например установить свойство checked флажка), а не ящать, что это сделает браузер. Пример Используйте приложение The Evaluator для изучения метода click (). В нижней части страницы приложения содержится несколько разных типов элементов управления. Чтобы “щелкнуть”, например, на флажке, выполните следующее выражение, введя его в верхнее поле. document.myForm2.myCheckbox.click() Если вы используете браузер одной из последних версий, то флажок изменит свое состояние с установленного на сброшенный при каждом следующем выполнении последнего выражения. См. также обработчик события one lick. cloneNode(булевоЗначение) Возвращаемое значение: ссылка на объект узла Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Метод cloneNode () создает точную копию объекта узла. Эта копия не имеет родитель- ского узла и не обладает другими типами взаимосвязей с остальными элементами (конечно же, исходный узел остается на своем месте). Копия не становится частью объектной модели документа, если только явно не вставить и не добавить узел где-либо на странице. Копия включает все атрибуты исходного элемента, в том числе и атрибут ID. Так как значение, воз- вращаемое методом cloneNode (), является самым настоящим объектом Node, к нему можно применить любой из методов Node, хотя объект и не является частью документа. Значение логического типа, являющееся аргументом метода cloneNode () управляет тем, что включает копия узла: все его дочерние узлы (true) или только сам узел (false). Например, если создать только копию элемента абзаца, она будет содержать лишь элемент (т.е. пару дескрипторов и атрибуты открывающего дескриптора), исключая его содержимое. Включение дочерних узлов делает все содержимое элемента частью копии. Этот параметр явля ется необязательным в IE5 (имея по умолчанию значение false) и обязательным в W3C DOM. Пример Используйте приложение The Evaluator (глава 13) для клонирования, переименования и пр. соединения элементов, управляемых в исходном коде приложения. Начните с дублировяня элемента абзаца туР вместе с его содержимым. Введите в верхнее поле следующее выражение. а = document.getElementByld("myP").cloneNode(true) 310 Часть III. Объекты a
F Переменная а теперь содержит исходный узел, поэтому вы можете изменить ее атрибут id, [ введя следующее выражение. I a.setAttribute("id", "Dolly") Е Если вы хотите ознакомиться со свойствами клонированного узла, то введите в нижнее | поле переменную а. Точный список свойств зависит от используемого браузера и его версии. 1. В любом случае вы должны ознакомиться со свойством id, которое теперь имеет значение Dolly. 1 На последнем этапе присоедините новый переименованный узел в конец элемента body, •7 введя в верхнее поле такое выражение. document.body.appendChild(а) ! Теперь вы можете прокрутить страницу вниз и увидеть добавленный в него абзац. По- li скольку два узла имеют разные идентификаторы, то в сценарии не возникает путаницы с их F управлением. [- См. также: объект Node (глава 14); методы appendChild (), removechild (), t removeNode (), replaceChild() и replaceNode (). f componentFromPoint (x, y). L Возвращаемое значение: строка L Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- г Метод componentFromPoint () помогает решать некоторые задачи По управлению со- г бытиями. Его используют для “поиска” событий (другими словами, для определения того, где F произошло событие: внутри или снаружи определенного элемента). Если элемент имеет по- Г лосы прокрутки, метод возвращает дополнительную информацию о событии, например, ка- [ кую компоненту полосы прокрутки активизировал пользователь. t Ключевым аспектом этого метода является то, что его применяют для элемента, исполь- k зуемого в качестве ссылки. Например, если нужно проверить, произошло ли событие mouseup [ для элемента с идентификатором myTable, метод запускается следующим образом. ь , var result = document.all.myTable.componentFromPoint(event.clientX, !' event.clientY) ; Г'к Параметрами метода являются координаты х и у. Они не поступают от события, но, как [- правило, привязывают метод к определенному событию. События мыши (кроме onclick) [ подходят лучше всего. [ Строка, возвращаемая методом, характеризует точку, в которой произошло событие. Если f Она находится внутри элемента, метод возвращает пустую строку. Если точка находится за ! пределами элемента, строка содержит значение "outside". Для полос прокрутки список [ возвращаемых значений несколько шире (как показано в табл. 15.8). Компания Microsoft оп- ределяет дополнительные значения, соответствующие изменению размеров элемента (это происходит в специальном режиме, называемом авторизованным режимом DHTML в Windows). ' Указанный режим требует наличия специального элемента ActiveX, который не рассматрива- • ется в этой книге. Такие значения также перечислены в табл. 15.8. Возвращаемая строка Компонента элемента в указанной точке scrol IbarDown scrol IbarHThumb scrollbarLeft Кнопка прокрутки вниз Бегунок на горизонтальной полосе прокрутки Кнопка прокрутки влево у Глава 15. Основные объекты HTML-элементов 311
Окончание табл. 15.8 Возвращаемая строка Компонента элемента в указанной точке scrollbarPageDown scrollbarPageLeft scrollbarPageRight scrolIbarPageUp scrollbarRight scrollbarUp scrolIbarVThumb handleBottom handleBottomLeft handleBottomRight handleLeft handleRight handleTop handleTopLef t handleTopRight Область постраничной прокрутки вниз Область постраничной прокрутки влево Область постраничной прокрутки вправо Область постраничной прокрутки вверх Кнопка прокрутки вправо Кнопка прокрутки вверх Бегунок на вертикальной полосе прокрутки Нижний элемент изменения размера Нижний левый элемент изменения размера Нижний правый элемент изменения размера Левый элемент изменения размера Правый элемент изменения размера Верхний элемент изменения размера Верхний левый элемент изменения размера Верхний правый элемент изменения размера Однако для большинства событий этот метод использовать не нужно. Свойство srcElement объекта события возвращает ссылку всегда, когда происходит событие. Пример Листинг 15.24 демонстрирует метод componentFromPoint (), используемый для опре- деления места возникновения события. Таким образом, метод связывается с объектом textarea, размер которого специально изменялся, чтобы на экране отобразились полосы прокрутке. После щелчка в произвольной области объекта textarea или другом месте документа в строке состояния не без помощи метода componentFromPoint () отобразится информация о месте возникновения события. В сценарии комбинация свойства event.srcElement и метода componentFromPointО, используется для определения способа обработки событий. Свойство srcElement применяется как фильтр, определяющий будет ли отображаться в строке состояния информация о событиях. ; Обработчик события onmousedown элемента body выполняет все действия по управле-, нию событиями. В IE используется метод всплывания событий (на странице не отменяется та одно событие), поэтому все события mousedown достигают элемента body. Таким образов) функция wherelnWorld () может определить, где произошло событие mousedown: в пре- делах текстовой области или в остальной части страницы. ,1 <html> <head> <title>componentFromPoint() Method</title> «script type=" t,ext/javascript11 > function wherelnWorld(elem) { var x = event.clientX; 312 Часть III. Объекты д<
var у = event.clientY; var component = document.getElementByld("myTextarea"). componentFromPoint(x,y); if (window.event.srcElement == document. getElementByld("myTextarea")) { if (component == "") { status = "mouseDown event occurred inside the element"; } else { status = "mouseDown occurred on the element\'s " + component; } } else { status = "mouseDown occurred " + component + " of the element"; } } </script> ' </head> <body onmousedown="whereInWorld()"> <hl>componentFromPoint() Method</hl> <hr /> <p>Tracking the mouseDown event relative to the textarea object. View results in status bar.</p> <form> <textarea name="myTextarea" wrap="off" cols="12" rows="4"> This is Line 1 This is Line 2 This is Line 3 This is Line 4 This is Line 5 This is Line 6 </textarea> </form> .< </body> </html> См. также объект event. contains (ссБхлкаНаОб'ъектЭлеме.нта) Возвращаемое значение: булевого типа Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Метод contains () сообщает, содержит ли текущий объект другой известный объект в иерархии контейнера HTML. Обратите внимание на то, что это не определение физически закладывающихся элементов, а анализ того, вложен ли один элемент в другой. Метод contains () просматривает всю иерархию текущего объекта в поисках вложенно- го объекта. По существу, метод contains () проверяет все элементы, входящие в массив all. Потому указанный метод можно использовать вместо цикла, с помощью которого обычно осуществляют поиск вложенного элемента. Параметром метода contains () является ссылка на объект. Если задается только стро- ка— идентификатор объекта, то для поиска ссылки на вложенный элемент можно использо- вать метод document, al 1. item (). Если одним идентификатором обладает несколько объектов, то браузер выдаст ошибку сценария, так как ссылка на такие элементы является ссылкой на массив, а не на один объект. Глава 15. Основные объекты HTML-элементов 313
На заметку Элемент всегда содержит самого себя. Пример Используя приложение The Evaluator, определите, как метод contains () определяет на- личие одного объекта в другом объекте. Для этого введите следующие выражения в верхнее поле страницы приложения. document.body.contains(document.all.myP) document.all.myP.contains(document.all.item("myEM")) document.all.myEM.contains(document.all.myEM) document.all.myEM.contains(document.all.myP) Экспериментируйте с другими комбинациями объектов документа. См. также методы item (), document. getElementByld (). detachEvent() См. attachEvent (). dispatchEvent(объектеобытия) Возвращаемое значение: булевого типа Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Метод dispatchEvent () позволяет сценарию эмулировать событие для любого; объекта, который его поддерживает. Это обобщенный метод модели событий W3C, кото- рый был частично реализован в более ранних версиях браузеров с помощью таких мето- дов, как click() и focus(). 1 Процесс генерирования одного из событий с помощью этого метода подобен созданию в сце- нарии нового узла и вставке в объектную модель документа. Однако для событий создаваемый объект является объектом Event, который генерируется методом document. createEventQ. Событие, генерируемое таким способом, является просто его экземпляром. Для задания парамет- ров экземпляров события (например указания координат или кнопки мыши) необходимо использо- вать свойства объекта события. Запустите событие с помощью метода dispatchEvent() и передайте в него новосозданный объект Event как единственный параметр. Интерпретация значения булевого типа, которое возвращает dispatchEvent (), нет проста. Браузер отслеживает запущенное событие согласно типу установленного способа о работки событий (всплывание или захват). Если определенная функция приемника собыъ запускает метод preventDef ault (), то метод dispatchEvent)) возвращает fals указывая на то, что событие не вызывает естественного действия для объекта; иначе мет возвращает значение true. Обратите внимание, что возвращаемое значение ничего не сое щает о типе обработки события или о том, сколько функций-приемников события вызывает, при запуске события. Несмотря на то, что метод dispatchEvent() реализован в NN6, браузер! обеспечивает способ генерирования новых событий. Если попытаться перенапра»; существующее событие другому объекту с помощью метода dispatchEvent (i V ? r’w' браузер сможет аварийно завершить работу. 314 Часть III. Объекты
Пример В листинге 15.25 показано, как в W3C DOM с помощью метода dispatchEvent () со- бытия генерируются программным образом. Обратите внимание на синтаксис функции doDispatch (), которая используется для создания и инициализации нового события, свя- занного с мышью в Mozilla-совместимых браузерах. Поведение этой страницы идентично по- ведению страницы листинга 15.26, в которой используется эквивалентная функция fireEvent () (она поддерживается в IE5.5+). <html> <head> <titlex/title> <style type="text/css"> #mySPAN {font-style:italic} </style> «script type="text/javascript"> I/ установка нескольких свойств объекта события function getEventProps(evt) { var msg = ""; var elem = evt.target; msg += "event.target.nodeName: " + elem.nodeName + "\n"; msg += "event.target.parentNode: " + elem.parentNode.id + "\n" msg += "event button: " + evt.button; return msg; } // обработчик события onclick для объектов body, myP и mySPAN function bodyClick(evt) { var msg = "Click event processed in BODY\n\n"; msg += getEventProps(evt); alert(msg); checkCancelBubble(evt); } function pClick(evt) { var msg = "Click event processed in P\n\n"; msg += getEventProps(evt); alert(msg); checkCancelBubble(evt); } function spanClick(evt) { var msg = "Click event processed in SPAN\n\n"; msg += getEventProps(evt); alert(msg); checkCancelBubble(evt) ; } 11 отмена всплывания события при установке флажка function checkCancelBubble(evt) { if (document.controls.bubbleOn.checked) { evt.stopPropagation(); } } Глава 75. Основные объекты НГМ1-элементов 315
// назначение обработчиков события onclick для трех элементов function init() { document.body.onclick = bodyclick; document.getElementByld("myP").onclick = pClick; document.getElementByld("mySPAN").onclick = spanclick; } // вызов метода dispatchEvent (') для объекта c ID, // подставляемым в качестве параметра function doDispatch(objID, evt) { // создание пустого события мыши var newEvt = document.createEvent("MouseEvents"); // инициализация щелчка кнопкой с ID 3 newEvt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 3, null); // передача события элементы, подставленному как параметр document.getElementByld(objID).dispatchEvent(newEvt); // запрет всплывания событий щелчков evt.stopPropagation(); } </script> </head> <body id="myBODY" onload="init()"> <hl>dispatchEvent() Method«/hl> «hr /> <p id="myP">This is a paragraph <span id="mySPAN"> (with a nested SPAN)</span> that receives click events.</p> <hr /> <pxb>Control Panel</bx/p> «form name="controls"> «pxinput type= "checkbox" name="bubbleOn" onclick="event.stopPropagation()" />Cancel event bubbling.</p> «pxinput type="button" value="Fire Click Event on BODY" onclick="doDispatch(’myBODY', event)" />«/p> «pxinput type="button" value="Fire Click Event on myP" onclick="doDispatch('myP', event)" /x/p> «pxinput type= "button" value="Fire Click Event on mySPAN" onclick="doDispatch('mySPAN', event)" />«/p> </form> </body> «/html> См. также метод f i reEvent (). f i reEvent (" типСобытия" [, ссылкаНаСобытие]) Возвращаемое значение: булевого типа Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Несмотря на то, что некоторые объекты имеют методы эмуляции физических событий (например методы click () и focus ()), IE5.5 обобщает механизм, позволяя сценарн направить любое подходящее событие любому объекту. Его переносчиком является мет-, fireEvent(). Один из требуемых параметров — тип события; он задается как строка. Типы событий в 1 называются так же, как и свойства для обработчиков (например onclick, onmouseover ит.д.). 316 Часть III. Объекты
Второй дополнительный параметр представляет собой ссылку на существующий объект event. Этот объект может быть событием, вызываемым пользователем или системой (подразумевается, что метод fireEvent () является функцией, запускаемой обработчиком события). Существующее событие может быть также объектом, созданным методом document.createEventObject () в IE5.5. В любом случае существующий объект event указывается с целью задания свойств объекта event, создаваемого методом fireEvent (). Тип события определяется первым параметром метода, но если необходимо установить дру- гие свойства (например координаты указателя или код клавиши), они выбираются у сущест- • вующего объекта. Ниже приведен пример кода, который создает новое событие mouse down, устанавливающее некоторые свойства, а затем запускающее событие для элемента на странице. var newEvent = document.createEventObj ect(); newEvent.clientX = 100; newEvent.clientY = 30; newEvent.canceIBubble = false; newEvent.button = 1; document.all.myElement.fireEvent("onmousedown", newEvent); События, генерируемые методом fireEvent (), совпадают с обычными объектами window, event в IE и имеют несколько важных свойств объекта event, предварительную установку которых производит браузер. Важно, что свойство cancelBubble имеет значение false, a returnvalue— значение true (как это происходит, когда событие генерируется пользователем или системой). Таким образом, если требуется предотвратить всплывание собы- тий и/или действие исходного элемента события по умолчанию, то функции обработчиков со- бытий должны устанавливать эти события объекта event так, как это обычно происходит в IE. Метод fireEvent () возвращает значение булевого типа, которое определяется свойст- вом returnvalue. Если свойство returnvalue имеет значение false во время обработ- ки события, метод fireEvent () также возвращает значение false. При обычной обработ- ке метод возвращает значение true. , Несмотря на то, что модель событий W3C DOM 2 включает метод dispatchEvent () для обработки событий, генерируемых в сценарии (и методы объекта Event для создания объектов событий), Microsoft не следует рекомендациям стандарта. В базовых операциях ме- тоды fireEvent () и dispatchEvent () похожи, однако в серьезных приложениях между ними возникает существенная разница (например в том, как распространяются события, или как объект Event представлен в модели W3C). Пример Листинг 15.26 содержит код сценария, в котором события генерируются программным образом с помощью метода fireEvent (). Три кнопки на представленной странице позво- ляют сгенерировать событие щелчка для каждого из трех элементов, которым назначены об- работчики событий. Возникающие таким образом события искусственные, поскольку созда- ются с помощью метода createEventObject (). В демонстрационных целях свойство button этих событий устанавливается в значение 3. Обычно свойство с таким значением за- дается для объектов event, которые в конечном счете указывают на элемент. При включен- ном всплывании событий, те из них, которые сгенерированы методом fireEvent (), подоб- ны событию щелчка на реальных объектах. Таким образом, если отключить всплывание событий, то первый же обработчик событий предотвратит всплывание события, и дальней- шая обработка события будет прекращена. Учтите, что всплывание события отменяется в об- . работниках событий, которые управляют событиями. Глава 15. Основные объекты HTML-элементов 317
<html> <head> <titlex/title> «style type="text/css"> #mySPAN {font-style:italic} </style> «script type="text/javascript"> // назначение свойств объекта события function getEventProps() { var msg = ""; var elem = event.srcElement; msg += "event.srcElement.tagName: " + elem.tagName + "\n"; msg += "event.srcElement.id: " + elem.id + "\n"; msg += "event button: " + event.button; return msg; } // обработчики события onClick для объектов body, myP и mySPAN function bodyClickO { var msg = "Click event processed in BODY\n\n"; msg += getEventProps(); alert(msg); checkCancelBubble(); } function pClickO { var msg = "Click event processed in P\n\n"; msg += getEventProps(); alert(msg); checkCancelBubble(); function spanClick() { var msg = "Click event processed in SPAN\n\n"; msg += getEventProps(); alert(msg); checkCancelBubble(); } ч // отмена всплывания события при установке флажка function checkCancelBubble() { event.cancelBubble = document.controls.bubbleOn.checked; } // назначение обработчиков onclick трем элементам function init() { document.body.onclick = bodyclick; document.getElementByld("myP").onclick = pClick; document.getElementByld("mySPAN").onclick = spanClick; } // вызов метода fireEventO для объекта, // ID которого подставляется как параметр function doFire(objID) { var newEvt = document.createEventObjectO; newEvt.button = 3; document.all(objID).fireEvent("onclick", newEvt); 318 Часть III. Объекты flot]
11 предотвращение всплывания события щелчка event.cancelBubble = true; } </script> </head> <body id="myBODY" onload="init()"> <hl>fireEvent() Method</hl> <hr /> <p id="myP">This is a paragraph <span id="mySPAN"> (with a nested SPAN)</span> that receives click events.</p> <hr /> <pxb>Control Panel</bx/p> <form name="controls"> <pxinput type="checkbox" name="bubbleOn" onelick="event.cancelBubble=true" />Cancel event bubbling.</p> <pxinput type="button" value="Fire Click Event on BODY" onclick="doFire('myBODY')" /></p> <pxinput type="button" value="Fire Click Event on myP" onclick="doFire('myP')" /></p> <pxinput type="button" value="Fire Click Event on mySPAN" onclick="doFire ('mySPAN') " /x/p> </form> </body> </html> См. также метод dispatchEvent (). focus ( ) Cm. blur (). get Ad j acentText ("позшщя") Возвращаемое значение: строка Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод getAdj acentText () позволяет извлечь текстовые компоненты объекта элемента (другими словами, без какой-либо информации о дескрипторах HTML). Единственным его па- раметром является одна из четырех строковых (с учетом регистра) констант, указывающая откуда гй> отношению к текущему объекту следует извлекать текст. Значения констант приведены ниже. Значение параметра Описание beforeBegin Текст от открывающего дескриптора текущего элемента до дескриптора предыдущего элемента afterBegin Текст после открывающего дескриптора элемента до следующего дескриптора (им может быть закрывающий дескриптор данного элемента или открывающий дескриптор вложенного элемента) beforeEnd Текст от закрывающего дескриптора текущего элемента до предыдущего дескриптора (им может быт^ открывающий дескриптор данного элемента или закрывающий дескриптор вложенного элемента) afterEnd Текст от закрывающего дескриптора текущего элемента до дескриптора следующего элемента Глава 15. Основные объекты HTML-элементов 319
Если текущий объект не содержит вложенных элементов, метод с параметром afterBegin или beforeEnd возвращает то же значение, что и свойство объекта innerText. Если те- кущий объект вложен непосредственно в другой элемент (например, элемент td внутри эле- мента tr), перед открывающим дескриптором элемента и после закрывающего дескриптора не будет текста, поэтому вызов метода с такими параметрами возвратит пустую строку. Строки, возвращаемые данным методом, эквивалентны значениям текстовых фрагментов узлов в W3C DOM, однако IE5+ рассматривает эти блоки данных только как строковые зна- чения, а не текстовые узлы. Не зависящие от браузера DOM-версии данного метода выглядят следующим образом. document.getElementByld("objName").previousSibling.nodeValue document.getElementByld("objName").firstChild.nodeValue document.getElementByld("objName").lastchild.nodeValue document.getElementByld("objName").nextSibling.nodeValue Пример Используйте приложение The Evaluator для изучения всех четырех констант, определяю- щих извлекаемый из элемента myP или туЕт текстовый фрагмент. Поочередно введите в верх- нее текстовое поле каждое из следующих выражений. document.getElementByld("myP").getAdj acentText("beforeBegin") document.getElementByld("myP").getAdj acentText("afterBegin") document.getElementByld("myP").getAdjacentText("beforeEnd") document.getElementByld("myP").getAdjacentText("afterEnd") Первый и последний операторы возвращают пустую строку, поскольку элемент myP не окружен текстовыми данными. Константа afterBegin указывает возвратить текстовый! фрагмент внутри элемента myP до элемента туЕМ (не включая его). Константа beforeEnd указывает возвратить текстовый фрагмент, начинающийся с конца элемента туЕМ и закаляй-’ вающийся правой границей элемента myP. 1 Теперь мы можем узнать, что же возвращается в случае применения элемента туЕМ. document.getElementByld("туЕМ").getAdj acentText("beforeBegin") document .getElementByld ("myEM") .getAdjacentText ( "afterBegin1') document.getElementByld("myEM").getAdjacentText("beforeEnd") document.getElementByld("myEM").getAdjacentText("afterEnd") Поскольку данный элемент не имеет вложенных элементов, то второй и третий варианты воз ' вращают одинаковые результаты. Они совпадают со значением свойства innerText элемента. ! См. также свойства childNodes, data, firstChild, lastchild, nextSibling,] nodeValueиpreviousSibling. -J getAttribute("имяАтрибута"[, I ЧувствительностьКРегистру]) j Возвращаемое значение: см. текст ] Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- > Метод getAttribute () возвращает значение, присвоенное определенному атрибут текущего объекта. Этим методом можно воспользоваться как альтернативным вариантом пм лучения свойств объекта, особенно если в сценарии имя атрибута задано в строковом в-« (вместо ссылки на объект или его свойства). Поэтому следующие операторы возвращал| одинаковые значения. я var mult = document.all.mySelect.multiple; Я var mult = document.all.mySelect.getAttribute("multiple"); 320 Часть III. Объекты fit
; Тип значений, возвращаемых методом getAttribute (), является или строковым включая значения атрибутов, присвоенных как числовые значения без кавычек) или булевым ;мер, свойство multiple объекта элемента select). K-jfcar Стандарт W3C DOM 2 рекомендует использовать методы getAttribute () ''Якммту и setAttribute О для чтения и записи значений атрибутов объекта элемента вместо применения соответствующих свойств объекта. Использовать эти мето- ды рекомендуется для элементов XML, однако стандарт DOM приводит к некото- рому конфликту, определяя все свойства для объектов элементов HTML. Брау- зеры, конечно же, будут поддерживать доступ к атрибутам с помощью свойств и в будущем, поэтому вы вполне можете пользоваться разными методами доступа. Все браузеры, поддерживающие метод getAttribute (), требуют одного параметра — строки с именем атрибута. По умолчанию он не учитывает регистр. Обратите внимание, что это может повлиять на специальные атрибуты, присвоенные элементам HTML или XML. При присвоении свойствам объекта имена атрибутов автоматически преобразуются к нижнему ре- гистру. Поэтому необходимо избегать повторного использования имен атрибутов, даже если. -» исходном коде они включают символы разного регистра. Е позволяет использовать дополнительный параметр, при указании которого в первом аргу- менте учитывается регистр. По умолчанию он имеет значение false, т.е. в первом параметре ре- гистр не учитывается. Значение true меняет ситуацию. Все это имеет значение лишь тогда, ко- гда для добавления параметра к существующему объекту используется метод setAttribute () и версия IE этого метода требует учета регистра. По умолчанию метод setAttribute () учи- тывает регистр в имени атрибута (см. также описание метода setAttribute () далее в этой пиве, где рассказывается о влиянии setAttribute () на свойство attributes в IE). Пример Приложение The Evaluator (глава 13) может использоваться для изучения метода getAttri- bute () элементов страницы. В ЕЕ4 применяется синтаксис формата document .all. Брау- зеры Ш5+ и W3C распознают метод getElementByld () обращения к элементам. Чтобы возвратить значения атрибутов, введите в верхнее поле страницы следующие выражения. Е4 document.all.myTable.getAttribute("width") document.all.myTable.getAttribute("border") E5+/W3C document.getElementByld("myTable").getAttribute("width") document.getElementByld("myTable").getAttribute("border") См. также: свойство attributes; методы document. createAttribute (), setAttribute (). getAttributeNode ("имяАтрибута") Возвращаемое значение: атрибут объекта узла Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- B W3C DOM атрибут является объектом, наследующим все свойства объекта Node (главу 14). Как следует из его названия, объект атрибута представляет собой пару “имя-значение” для атри- бута, заданного явно в дескрипторе элемента. Возможность обработки атрибутов как объектов узлов важнее в XML, чем в HTML, но в любом случае она важна для представления узлов атри- бутов в контексте объектно-ориентированного взгляда на документы W3C DOM. Обратите внимание, что узлы атрибутов не рассматриваются как узлы в иерархии документа. Поэтому узел атрибута не является дочерним узлом элемента, в котором он определен. Глава 15. Основные объекты HTML-элементов 321
Такое поведение атрибутов учитывается прй сравнении содержимого свойства attributes объекта в IE и W3C DOM. В IE5+ свойство attributes возвращает массив всех атрибутов элемента (даже те, которые не включены в дескриптор явно). В модели W3C свойство attributes возвращает объект, (внутренне) называемый картой именованных узлов. Как и массив, карта именованных узлов имеет свойство length (предназначенное для просмотра карты в цикле), а также несколько методов, позволяющих вставлять, удалять, читать или за- писывать пары “имя-значение” в карту узлов. Объект атрибута выглядит сложным, в первую очередь, потому что он наследует все свойства объекта Node. В табл. 15.9 приведены свойства объекта атрибута. ОжЛст* ответа и4Е5 1 attributes childNodes firstChild lastchild name nextsibling nodeName nodeType nodeValue ownerDocument parentNode previousSibling specified value Все выше изложенное является объяснением метода getAttributeNode () который воз- вращает объект атрибута в W3C DOM. Его единственным параметром является строка с имене>| атрибута (без учета регистра). Для получения или установки значений атрибутов можно юс пользоваться любым свойством из табл. 15.9. Конечно же, атрибуты HTML являются свойств! ми элементов HTML, поэтому иногда проще читать или устанавливать их напрямую. Пример В приложении The Evaluator предусмотрены все необходимые инструменты для изуче метода getAttributeNode () в NN6. Текстовая область вывода результатов имеет сколько атрибутов, подлежащих проверке. Поскольку метод возвращает объект, ввел? в нижнее поле следующие выражения, которые позволяют ознакомиться со свойствами екта узла атрибута. document.getElementByld("output").getAttributeNode("cols") document.getElementByld("output").getAttributeNode("rows") document.getElementByld("output").getAttributeNode("wrap") document.getElementByld("output").getAttributeNode("style") 322 Часть III. Объекты да
Все (кроме последнего) выражения выводят список свойств для каждого объекта узла ат- рибутов. Последнее выражение, тем не менее, ничего не возвращает, поскольку атрибут . style в элементе не определен. См. также: свойство attributes; методы getAttribute (), removeAttribute- Node (), setAttributeNode (). getAttributeNodeNS (" иШпространстваИмен", ’локальноеИмя") Возвращаемое значение: атрибут объекта узла Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ » Этот метод возвращает объект атрибута в W3C DOM. Первый параметр метода задает строку URI (Uniform Resource Identifier — универсальный идентификатор ресурса), которая совпадает с URI, назначенным в подписи документа. Второй параметр определяет локальную часть имени получаемого атрибута. См. также: свойства attributes, namespaceURI; методы getAttributeNode(), BetAttributeNodeNS (). getAttributeNS (" иКТпространстваИмен", 'локальноеИмя") Возвращаемое значение: см. описание Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ Этот метод возвращает значение, назначенное определенному атрибуту текущего объекта, ' если этот атрибут определен в пространстве имен XML документа. Первый параметр метода представляет собой строку URI, которая совпадает с URI, назначенным в подписи простран- ства имен ранее в документе. Второй параметр определяет локальную часть имени атрибута, значение которого возвращает метод. Возвращаемые значения имеют строковый (в том числе числовые значения, не заключае- ма* в кавычки) или булев тип (например, свойство multiple объекта элемента select). См. также: свойства attributes, namespaceURI, localName; методы getAttribute (), .getAttributeNodeNS(), BetAttributeNodeNS(). getBoundingClientRect() Возвращаемое значение: объект TextRectangle Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- BIE5+ каждому элементу, имеющему содержимое, поставлен в соответствие прямоуголь- ник, который указывает, сколько места объект занимает на странице. Этот прямоугольник на- зывается ограничивающим', в объектной модели WinIE5 он является объектом TextRectangle (даже если содержимым является изображение или объект другого типа). Он имеет четыре свойства (top, left, bottom и right)— координаты точек, определяющих прямоуголь- ник. Метод getBoundingClientRect () возвращает объект TextRectangle, отвечаю- щий текущему объекту. Доступ к координатам ограничивающего прямоугольника осуществ- ляется следующим образом. var parTop = document.all.myP.getBoundingClientRect().top; Для элементов, состоящих из текста (например абзацев), размеры объектов TextRectangles отдельных строк текста влияют на размеры результирующего ограничивающего прямоугольника. Например, если абзац содержит две строки, и вторая строка достигает лишь половины ширины Глава 15. Основные объекты HTML-элементов 323
первой, то так же соотносятся и значения объектов TextRectangle этих строк. Ширина ре-1 зультирующего прямоугольника, очевидно, совпадает с шириной объекта TextRectangle j большей (первой) строки. Таким образом, ширина ограничивающего прямоугольника равна ши- ] рине самой длинной строки, а высота — сумме высот всех объектов TextRectangle в абзаце. 1 Метод getClientRects () позволяет получить построчный набор объектов Text-1 Rectangle элемента. Пример В листинге 15.27 приведен пример использования обоих методов: getBoundingClient-1 Rect () и getClientRects (). Он демонстрирует разницу в использовании этих методов j в одном документе. В документе содержится набор элементов, сгруппированных в элементе span, I который называется main. Группа состоит из двух абзацев и неупорядоченного списка. Элементы управления страницы позволяют расположить желтый прямоугольник под лю-1 бым из указанных объектов группы для его выделения. При этом выделяющий прямоуголь- ] ник может иметь ширину как выделяемого элемента, так и ширину элемента span, содержа- J щего всю группу объектов. j Код, выполняющий все необходимые операции, включен в функцию hi lite (), котора»! управляет элементом select и флажком. В начале функции с помощью метода getClient-J RectsO элемента main создается массив объектов TextRectangle для всех текстовых! строк. Этот массив используется при определении координат углов выделяющего строку (за-1 данную элементом select) желтого прямоугольника. } Если пользователь указывает номер выделяемой строки в списке select (и если этот но-1 мер меньше общего количества объектов TextRectangle), функция вычисляет размер! и расположение выделяющего желтого прямоугольника. При установке на странице единственное 1 флажка левая и правая границы задаются с помощью метода getBoundingClientRect ОJ поскольку ширина прямоугольника будет равна ширине элемента span. В противном случи i границы задаются свойствами left и right указанного объекта TextRectangle в маа»4 ве clientRects. Я Далее в свойстве style объекта hi liter устанавливается расположение и размер тр*Я моугольника. Верхняя и нижняя границы зависит от выбранной строки, поэтому использукгЛ ся свойства top и bottom соответствующего элемента. Уже упомянутые ранее значеЯ left и right приравниваются к свойствам pixelLeft и pixelRight объекта hi liters Обратите внимание, что в свойствах top и left учитывается прокрутка страницы в омД браузера. Если уменьшить размер окна браузера, то размер строк и их количество будут май няться (текст перетекает, чтобы не “выходить” за пределы окна). Таким образом, изменяв Л и общая нумерация строк. С помощью обработчика события onresize в функции hiliter (Я всегда применяется текущий порядок нумерации строк, независимо от их количества. д <html> j <head> j <title>getClientRects() and getBoundClientRect() Methods</title>; «script type="text/javascript"> I function hiliteO { ( var hTop, hLeft, hRight, hBottom, hWidth; var select = document.forms [0] .choice,- var n = parselnt(select.options[select.selectedlndex].value) 4 - 1; -I var clientRects = document.getElementByld("main"). 32‘ Часть III. Объекты д(
getClientRects() ; var mainElem = document.getElementByld("main"); if (n >= 0 && n < clientRects.length) { if (document.forms[0].fullwidth.checked) { hLeft = mainElem.getBoundingClientRect().left; hRight = mainElem.getBoundingClientRect().right; } else { hLeft = clientRects[n].left; hRight = clientRects[n].right; } document.getElementByld("hiliter").style.pixelTop = clientRects[n].top + document.body.scrolITop; document.getElementByld("hiliter").style.pixelBottom = clientRects[n].bottom; document.getElementByld("hiliter").style.pixelLeft = hLeft + document.body.scrollLeft; document.getElementByld("hiliter").style.pixelwidth = hRight - hLeft; document.getElementByld("hiliter").style.visibility = "visible"; } else if (n > 0) { alert("The content does not have that many lines."); document.getElementByld("hiliter").style.visibility = "hidden"; } } </script» </head> «body onresize="hilite()"> «hl»getClientRects() and getBoundClientRect() Methods</hl> «hr /> <form> Choose a line to highlight: «select name="choice" onchange= "hilite()"> «option value="l"»l«/option» «option value="2">2«/option> «option value="3"»3«/option> «option value="4">4«/option> «option value="5">5«/option> «option value="6"»6«/option» «option value="7">7«/option> «option value="8"»8«/option» «option value="9">9«/option> «option value="10"»10«/option» «option value="11"»11«/option» «option value="12"»12</option» «option value="13"»13«/option» «option value="14"»14«/option» «option value="15"»15</option» «/select»«br /» «input name="fullWidth" type="checkbox" onclick="hilite()" /> Full Width (bounding rectangle) «/form» «span id="main"> <p»Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aligua. Ut enim adminim veniam, quis nostrud exercitation ullamco:«/p> Глава 15. Основные объекты HTML-элементов 325
<ul> <li>laboris</li> <li>nisi</li> <li>aliguip ex ea commodo</li> </ul> <p>Duis aute irure dolor in reprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa gui officia deseruntmollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. </px/span> <div id="hiliter" style="position:absolute; background-color:yellow; z-index:-1; visibility:hidden"> </div> </body> </html> Поскольку свойство z-index стиля для элемента hiliter устанавливается в значение -1, то выделяющий элемент всегда располагается под текстом. Если пользователь выберет номер строки, больший количества строк в окне браузера, то элемент hiliter будет скрыт. См. также: метод getClientRects (); объект TextRectangle (глава 35). getClientRects О Возвращаемое значение: массив объектов TextRectangle Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод getClientRects () возвращает массив всех объектов TextRectangle, нахо- дящихся внутри текущего объекта в момент вызова метода. Каждый объект TextRectangle имеет свои собственные свойства top, left, bottom и right. Поэтому можно, например, в цикле просмотреть все значения массива и подсчитать ширину каждой строки в пикселях, Если необходимо найти суммарную высоту и/или ширину всего набора, используйте метод getBoundingClientRect(). Пример В листинге 15.27 продемонстрирована разница между методами getBoundingClient- Rect () иgetClientRects(). См. также: метод getBoundingClientRect (); объект TextRectangle (глава35). getElementsByTagName (" имяДескриптора") Возвращаемое значение: массив объектов элементов Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Метод getElementsByTagName () возвращает массив всех элементов текущего объекта,1 дескрипторы которых соответствуют имени, указанному как единственный аргумент этого метода. Аргумент представляет собой строку без учета регистра. Группа элементов, возвр щаемая как массив, включает лишь элементы, находящиеся в области определения текуще: объекта. Поэтому, если в документе две таблицы и для одной из них выполняется мете getElementsByTagName ("td"), то список элементов ячеек таблицы будет содержать да» те из них, которые относятся к текущему объекту. Сам текущий элемент в массив не включен. 326 Часть III. Объекты доку/
Параметром метода getElementsByTagName () может служить символ 11 * ". Результи- рующий массив элементов в этом случае совпадает с тем, что IE4+ возвращает как набор .document .all. Пример Приложение The Evaluator (глава 13) позволяет детально изучить метод getElement- ByTagName (). Введите следующие выражения в верхнее текстовое поле и внимательно изу- чите полученные результаты. document.body.getElementsByTagName("div") document.body.getElementsByTagName("div").length document.getElementByld("myTable").getElementsByTagName("td").length Поскольку метод getElementByTagName () возвращает массив объектов, вы можете : использовать возвращаемые-значения в качестве корректной ссылки на элемент. document.getElementsByTagName("form")[0].getElementsByTagName ("input").length См. также: методы getElementByld (), getElementByTagNameNS () tags (). getElementsByTagNameNS (" UR 1пространства.Имен", "локальноеИмя") Возвращаемое значение: массив объектов элементов Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Этот метод возвращает массив элементов, который содержится в текущем объекте (в XML-документе), определенном параметрами. Первый параметр метода определяет строку URI (она совпадает с URI, назначенным подписи к документу). Второй параметр задает часть с локальным именем атрибута, значение которого определяется. Этот метод возвращает значения строкового (включая незаключенные в кавычки число- вые данные) или булевого типа (например, свойство multiple объекта элемента select). См. также: свойства attributes, namespaceURI, localName; методы getElement- T3yld (), getElementByTagName () tags (). getExpression (" имяАтрибута") Возвращаемое значение: строка Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод getExpression () возвращает текст выражения, присвоенного атрибуту элемен- та методом setExpression (). Возвращаемое значение является не значением выражения, а са- мим выражением. Если требуется найти значение выражения (предполагая, что все переменные находятся в области определения сценария), необходимо вызвать метод getExpression () внутри функции eval (). Эта операция преобразует строку в выражение JavaScript и возвра- тит его результат. Метод имеет один аргумент — строку с именем атрибута. Пример В листинге 15.32 приведен пример использования метода setExpressions (). В нем используются значения, возвращаемые методом getExpressions (). См. также: методы document. recalc (), removeExpression (), setExpression (). Глава 15. Основные объекты HTML-элементов 327
hasAt tribute (" имяАтрибута") Возвращаемое значение: булевою типа Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Метод hasAttribute () возвращает значение true, если текущий объект имеет атри- бут, имя которого совпадает с единственным параметром. В противном случае возвращается значение false. См. также: методы hasAttributeNS (), hasAttribute () hasAttributeNS (11 иШпространстваИмен", "локальноеИмя") Возвращаемое значение: булевою типа Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Метод hasAttributeNS () возвращает значение true, если текущий объект имеет ат- рибут, определенный двумя параметрами. В противном случае возвращается значение false. Первый параметр метода определяет строку URI, которая совпадает с URI, назначен- < ным подписи к документу. Второй параметр задает часть с локальным именем атрибута, зна- J чение которого определяется. См. также: свойства attributes, namespaceURl, localName; методы hasAttribute О, hasAttributes(). hasAttributes() Возвращаемое значение: булевою типа Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Этот метод возвращает true, если текущий объект имеет атрибуты, полностью опреде- ленные в дескрипторе элемента. В противном случае метод возвращает значение false. См. также: методы hasAttributeNS (), hasAttribute (). hasChildNodes() Возвращаемое значение: булевою типа Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safari 1 + Метод hasChildNodes () возвращает значение true, если текущий объект имеет вло- женные узлы; в ином случае он возвращает значение false. Вложенный узел не всегда явля- ется тем же, что и дочерний элемент, поэтому следующие два выражения возвращают true, лишь в том случае, когда текущий объект имеет, по крайней мере, один дочерний узел. document.getElementByld("myObj ect").hasChildNodes() document.getElementByld("myObject").childNodes.length > 0 Второе выражение не взаимозаменяемо со следующим оператором (в котором использу- ется свойство children, поддерживаемое только в IE). document.getElementByld("myObject").children.length > 0 Метод hasChildNodes (), как правило, используется в условных выражениях для щв-’ верки существования узла перед выполнением операций с ним. if (document.getElementByld("myObject").hasChildNodes() { операторы, применяемые к узлу } 328 Часть III. Объекты доки
Пример Приложение The Evaluator позволяет детально изучить метод has Chi IdNodes (). Если вы введете в верхнее поле следующее выражение document.getElementByld("myP").hasChildNodes() to будет возвращено значение true. Чтобы определить количество дочерних узлов элемента, достаточно узнать свойство length массива childNodes. document.getElementByld("myP").childNodes.length Это выражение определяет количество узлов как сумму двух текстовых узлов и элемента em между ними. Проверим, имеет ли первый текстовый узел дочерние узлы. document.getElementByld("myP").childNodes[0].hasChildNodes() Возвращается значение false, поскольку текстовый узел не имеет вложенных узлов. Те- перь выполним то же с элементом em. document.getElementByld("myP").childNodes[1].hasChildNodes() Возвращаемый ответ — true, поскольку в этот элемент вложен текстовый узел. В завер- шение выполните еще одно выражение. document.getElementByld("myP").childNodes[1].childNodes.length Вы получите результат 1. Непосредственно к элементу em можно также обратиться с по- мощью следующих ссылок. document.getElementByld("myEM").hasChildNodes() document.getElementByld("myEM").childNodes.length Если вы хотите ознакомиться со свойствами текстового фрагмента, расположенного внутри элемента em, то введите в нижнее поле следующее выражение. document.getElementByld("myEM").childNodes[0] См. также: свойство childNodes; методы appendChild (). removeChild (). replaceChild(). insertAdj acentElement ("расположение ", объект Элемент a) Возвращаемое значение: объект Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод insertAdj acentElement () (не поддерживаемый в Мас1Е5) вставляет объект элемента (полученный из различных источников) в определенном месте по отношению к те- кущему объекту. Оба аргумента являются обязательными. Первый должен быть одним из че- тырех возможных параметров (регистр не учитывается), приведенных в таблице. Положение Описание beforeBegin Перед открывающим дескриптором текущего элемента afterBegin После открывающего дескриптора перед любым вложенным содержимым beforeEnd Перед закрывающим дескриптором после любого вложенного содержимого afterEnd После закрывающего дескриптора Положение рассматривается относительно текущего объекта. Тип текущего элемента (блоковый или внутритекстовый) во многом влияет на отображение на экране вставляемого Глава 15. Основные объекты HTML-элементов 329
элемента. Предположим, что создается элемент b (с использованием метода document. createElement ()), которому присваивается некоторый текст. С помощью метода insert- Ad j acentElement () элемент b вставляется перед элементом р. Так как элемент р является блоковым, аргумент beforeBegin размещает элемент b перед открывающим дескриптором элемента р. Это значит, что полужирный текст появится в строке текста над элементом р, тая как дескриптор <р> начинает новый блок, выравниваемый по левому краю (если в стилях не' указано иначе). В результате HTML-код будет иметь такой вид. <Ь>Новый элемент. </Ьхр>Исходный элемент.</р> Чтобы сделать элемент b частью р и вставить его перед существующим содержимым, ис- пользуйте параметр afterBegin. В результате вы получите следующий HTML-код. <р><Ь>Новый элемент.</Ь>Исходный элемент.</р> Результат использования параметра beforeEnd будет таким <р>Исходный элемент. <Ь>Новый элемент. </Ьх/р> a afterEnd — следующим • ‘ <р>Исходный элемент.</р><Ь>Новый элемент.</Ь> Вставляемый объект представлен ссылкой на объект элемента. Ее можно получить с по-, мощью любого оператора, который возвращает ссылку на объект, или, скорее всего, в резрм тате выполнения метода document. createElement (). Помните, что объект, созданный ме-j тодом document. createElement (), изначально является пустым, а все атрибуты имем значения по умолчанию. Более того, объект передается методу insertAdj acentElement ()] по ссылке, т.е. существует всего одна копия объекта. При попытке вставить объект в дв}| местах (двумя операторами) он будет просто перемещен с первой позиции во вторую. Есм] необходимо скопировать объект, ничего не изменяя в исходном положении, следует воспоия зеваться методом cloneNode (), указав аргумент' true (тем самым вы скопируете вам внутреннюю структуру узла). i Пример : Приложение The Evaluator поможет вам разобраться и с использованием метода insert-1 Adj acentElement (). Вы должны научиться вставлять новый элемент hl над элементом myEl От вас потребуется всего лишь ввести несколько операторов в верхнее текстовое пос! Начните с сохранения нового элемента в глобальной переменной а. I, а = document.createElement ("hl") Далее введите в новый объект текст. Г a.innerText = "New Header" ’ Вставьте этот элемент непосредственно перед объектом myP. J myP.insertAdjacentElement("beforeBegin", а) Л Обратите внимание, что новому элементу не было назначено свойство id. ПоскольЛ элемент вставлялся по ссылке, вы можете изменить его, воспользовавшись переменной и сохраненным в нем объектом. 2 a.style.color = "red" -д Вставленный элемент становится частью иерархической структуры документа, поэтмВ к нему можно обратиться с помощью оператора myP. previousSibling. X Родительским для нового вставленного объекта является элемент body. Вы можете чить текущее состояние HTML-кода отображенной страницы, введя в верхнее поле следуЛ щее выражение. Л document.body.innerHTML fl 330 Часть III. Объекты да
Если вы прокрутите страницу ниже первой формы, то сможете увидеть элемент hl, вставленный в документ с атрибутом style. См. также: методы document. createElement (), applyElement (). insertAdjacentHTML("расположение", "текстНТМЪ") insertAdj acentText ("расположение", " текст") Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Два этих метода вставляют код HTML или просто текст в текущий элемент. Они исполь- зуются после, а не во время загрузки страницы (в последнем случае следует применить метод document. write () ). Первый параметр должен быть одним из четырех возможных аргументов (регистр не учи- тывается), приведенных в таблице. Положение Описание beforeBegin afterBegin beforeEnd Перед открывающим дескриптором текущего элемента После открывающего дескриптора перед любым вложенным содержимым Перед закрывающим дескриптором после любого вложенного содержимого ; afterEnd После закрывающего дескриптора Приведенные параметры дают те же результаты, что и для метода insertAdj acent - Element (), о котором было рассказано выше. Применение метода insertAdj acentHTML () или insertAdj acentText () зависит ’’ от природы содержимого, а также от выполняемых браузером задач. Если элемент содержит дескрипторы HTML, которые должны интерпретироваться и отображаться браузером как часть исходного кода страницы, воспользуйтесь методом insertAdj acentHTML (). В этом случае все дескрипторы станут членами объектной модели документа. Если же требуется просто отобразить текст (включая и дескрипторы HTML в неинтерпретированном виде), ис- ‘ пользуйте метод insertAdj acentText (). В результате обычного отображения дескрип- торы, включенные в строку (она передается во втором аргументе), не интерпретируются. Все дескрипторы отображаются как обычные символы на странице. Такое различие напоминает разницу между свойствами innerHTML и innerText. Отличие метода insertAdj acentHTML () от insertAdj acentElement () связано с природой вставляемого содержимого. Первый позволяет вставить строку как HTML-код, последний требует создания объекта элемента. Оба метода работают в IE4+ (включая версии для Мас), тогда как insertAdj acentElement () требует новой объектной модели IE5 и выше. Если HTML-код, передаваемый как второй параметр insertAdj acentHTML (), содер- жит дескрипторы <script>, необходимо установить атрибут defer в открывающем деск- рипторе. Таким образом, запуск операторов сценария непосредственно после вставки в доку- мент будет невозможен. Пример Приложение The Evaluator (глава 13) применяется для изучения этих двух методов. Чтобы на реальном примере ознакомиться с результатом выполнения этих методов, перед элемен- том туР вставим HTML-код. Глава 15. Основные объекты HTML-элементов 331
Вначале назначьте глобальной переменной а следующий HTML-код. > а = "<b id='myB1>Important News!</b>" Поскольку этот HTML-код вводится в той же строке, что и код начала элемента myP, то в методе вставки используйте параметр afterBegin. myP.insertAdj acentHTML("afterBegin", a) Обратите внимание, что после восклицательного знака в HTML-коде пробел отсутствует. Чтобы доказать принадлежность вставленного HTML-элемента объектной модели документа, добавьте пробел после элемента Ь с идентификатором ту В. myB.insertAdjacentText(“afterEnd", " ") Каждый раз при выполнении этого выражения (повторного щелчка на кнопке Evaluate или нажатия <Enter>) на страницу добавляется новый пробел. Далее мы разберемся, что же происходит при вставке с помощью метода insertAdj acent- Text () строки, содержащей HTML-код. Перезагрузите приложение The Evaluator и введите следующие два выражения в верхнее поле, выполнив их совместно. а = "<b id=’myB'>Important News!</b>" myP.insertAdjacentText("afterBegin", a) Как видно, HTML-код не вставляется, хотя и отображается в виде простого текста. После выполнения последнего метода вы не найдете в документе элемента myB. См. также: свойства innerText, innerHTML, outerText, outerHTML; методы: insertAdj acentElement (), replaceAdj acentText (). insertBef ore (новыйОбъектДочернегоУзла [, i ссылкаНаДочернийУзел]) -i Возвращаемое значение: объект Node Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Метод insertBef ore () относится к синтаксису W3C DOM, используемому для вставки дочернего узла в существующий элемент. Ссылки на узлы в обоих аргументах должны быт» объектами Node (включая и генерируемые методом document. createElement ()). Поведение метода может показаться неочевидным. Если указать второй параметр (ссылку ш! существующий дочерний узел текущего элемента), то новый дочерний узел будет вставлен пе-1 ред существующим. Если опустить второй параметр (или указать null), новый дочерний узел бу- j дет вставлен как последний в текущем элементе— в этой ситуации данный метод совпадает по 1 действию с методом appendChild (). Преимущества метода проявляются, очевидно, при указа-] нии второго аргумента — новый дочерний узел можно вставить в любом месте внутри элемента,] Помните, что метод insertBef ore () выполняется с точки зрения родительского обь-1 екта. Internet Explorer содержит несколько дополнительных методов, например insert-1 Adj acentElement (), в которых указывается дочерний элемент. J Пример । В листинге 15.28 продемонстрирована операция вставки дочерних элементов (li) в роды тельский элемент (ol) с помощью метода insertBef ore (). При этом элементы встянм ются в разные части документа (в зависимости от значения второго параметра). В текстоыя поле указывается текст или HTML-код, добавляемый в документ. Если не указать в следш| щем списке расположение вставляемого элемента, то второй параметр метода примет знамЛ ние null. В последнем случае элемент добавляется после остальных дочерних элементов! В списке select указывается порядковый номер одного из дочерних элементов объекта о1Л 332 Часть III. Объекты д<
<html> <head> <title>insertBefore() Method</title> «script type="text/javascript"> function dolnsert(form) { if (form.newText) { var newChild = document.createElement("LI"); newChiId.innerHTML = form.newText.value; var choice = form.itemindex.options[form, itemindex.selectedlndex].value; var insertPoint = (isNaN(choice)) ? null : document.getElementByld("myUL"). childNodes[choice]; document.getElementByld("myUL").insertBefore(newChild, insertPoint); } } </script> </head> i <body> <hl>insertBefore() Method«/hl> «hr /> <form onsubmit="return false"> <p>Enter text or HTML for a new list item: «input type="text" name="newText" size="40" value="" /></p> <p>Before which existing item? «select name="itemindex"> «option value="null">None specified«/option> «option value="O">l«/option> «option value="l">2«/option> «option value="2">3</option> </select>«/p> «input type="button" value="Insert Item" onclick="dolnsert(this.form)" /> «/form> «ol id="myUL"> <li>Originally the First Item«/li> <li>Originally the Second Item«/li> <li>Originally the Third Item«/li> «/ol> </body> </html> См. также: методы appendChild(), replaceChild(), removechild(), insert- AdjacentElement (). isSupported (11 спецификация", 11 версия") Возвращаемое значение: булевого типа Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 14- Метод isSupported () определяет, поддерживается ли текущий узел в указанной спе- цификации и версии W3C DOM. Если нет, то возвращается значение false. Первый пара- метр принимает имена следующих модулей (имена чувствительны к регистру символов): Core, XML, HTML, Views, Stylesheets, CSS, CSS2, Events, UIEvents, MouseEvents, MutationEvents, HTMLEvents, Range, Traversal. Второй параметр задает версию мо- дуля в строковом формате, например "2.0". Слава 15. Основные объекты HTML-элементов 333
Пример Приложение The Evaluator может использоваться для выполнения метода isSupported!). Если в вашем компьютере установлено несколько браузеров NN или Mozilla, то попробуйте выполнить в них (на странице приложения) следующие выражения (а также многие другие). document.body.isSupported("CSS", "2.0") document.body.isSupported("CSS2", "2.0") document.body.isSupported!"Traversal", "2.0") Если у вас установлен браузер Safari, то обязательно выполните эти же выражения и в нем, чтобы увидеть разницу в поддерживаемых технологиях. Item(index | "индекс" [, подиндекс]) Возвращаемое значение: объект Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Метод item () работает с такими объектами, которые представляют собой наборы (массивы) других объектов. В контексте W3C D0M такие объекты называются списками именованных узлов (узлы и атрибуты) или HTML-наборами (HTML-массивами) (элементы формы). В W3C DOM метод item () определен с одним числовым параметром — индексом объекта в массиве. В NN6 этот метод реализован именно так. Если известен индекс элемента в массиве, то можно обратиться к массиву непосредственно с помощью JavaScript. Два сле- дующих оператора указывают на один и тот же объект. document.getElementByld("myTable").childNodes.item(2) document.getElementByld("myTable").childNodes[2] Возможности метода расширены строковым идентификатором объекта в наборе. (Однако для доступа к объектам attributes, rules и TextRectangle требуются все же целочис- ленные значения.) Кроме того, если в набор входит несколько объектов с одним идентифика- тором (их стоит использовать лишь в случае необходимости), второй числовой параметр по- зволит выбрать конкретный объект из группы (в подгруппе индекс начинается с нуля). Очевидно, что эго неприменимо к таким наборам, как attributes и rules, поскольку им не присваивается идентификатор. Метод возвращает ссылку на объект, заданный аргументами метода. Пример Приложение The Evaluator (глава 13) используется также для анализа метода item(). Введите в верхнее текстовое поле следующие выражения. В W3C и IE5: document.getElementByld("myP").childNodes.length document.getElementByld("myP").childNodes.item(0).data document.getElementByld("myP").childNodes.item(1).nodeName В W3C, IE4 и IE5: document.forms[1].elements.item(0).type В IE4 и IE5: document.all.item("myP").outerHTML myP.outerHTML В последних двух примерах оба оператора возвращают одну и ту же строку. Первый при- < мер применяется при управлении в сценарии строковым вариантом имени объекта. Если' в сценарии известна ссылка на объект, то второй подход более эффективен. См. также: все свойства объектов элементов, которые возвращают наборы (массивы)! других объектов. 334 Часть III. Объекты документ»
mergeAttributes (" исходныйОб'ьект") Возвращаемое значение: отсутствует Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод mergeAttributes () представляет собой удобный способ присвоения атрибутов новосозданным объектам (вместо их добавления по одному). Если в наличии есть объект, ат- рибуты которого могут послужить прототипом для других элементов (кроме атрибута id), эти атрибуты можно присвоить новосозданному объекту. Пример В листинге 15.29 продемонстрировано использование метода mergeAttributes () в процессе репликации текстового поля формы. Каждой новой копии текстового поля при этом назначается собственный идентификатор. Функция doMerge () начинает свою работу с создания двух новых элементов: р и input. Поскольку новые элементы еще не имеют свойств, то элементу input назначается уникаль- ный идентификатор с помощью идентификатора uniquelD. Далее атрибуты исходного поля из HTML-кода передаются в новый элемент input. Таким образом в созданный элемент ко- пируются все атрибуты, за исключением name и id. После этого элемент input вставляется в элемент р, который, в свою очередь, присоединяется к элементу формы. Наконец, в новом поле отображается значение свойства outerHTML копии элемента. Удостоверьтесь, что в элемент скопированы все атрибуты, за исключением name и id (в том числе атрибуты сти- лей и обработчики событий). Чтобы проверить работоспособность обработчиков событий в новом элементе, добавьте в него пробел и нажмите <ТаЬ> для вызова обработчика onchange, изменяющего регистр символов. jjbCnWT 15.29. ИсП0ЛЬ30ВаНИ*ЖТ*Д>ялгд«в1* tri tut* о V *,j <html> <head> <title>mergeAttributes() Method</title> <script type="text/javascript"> function doMerge(form) { var newPElem = document.createElement("p"); var newInputElem = document.createElement("input"); newInputElem.id = newInputElem.uniquelD; newInputElem.mergeAttributes(form.fieldl); newPElem.appendChild(newInputElem); form.appendchi1d(newPE1em); newInputElem.value = newInputElem.outerHTML; } // вызывается обработчиком onchange полей function upperMe(field) { field.value = field.value.toUpperCase(); } </script> </head> <body onload="document.expandable.fieldl.value = document.expandable.fieldl.outerHTML"> <hl>mergeAttributes() Method</hl> <hr /> Глава 15. Основные объекты HTML-элементов 335
<form name="expandable" onsubmit="return false"> «pxinput type= "button" value="Append Field ’Clone'" onclick="doMerge(this.form)" /></p> «pxinput type="text" name="fieldl" id="FIELDl" size="120" value="" style="font-size:9pt" onchange="upperMe(this)" </form> </body> </html> См. также: методы clearAttributes (), cloneNode (), removeAttributes (). normalize () Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- | В случае добавления, вставки, удаления и замещения дочернего узла элемента вполне возможно, что два текстовых узла станут соседними. Зачастую это не влияет на графическое j представление содержимого, однако некоторые XML-приложения имеют жесткие ограниче»! ния на расположение узлов в иерархической структуре документа, в соответствии с которым] два текстовых узла соседними быть не могут. “Правильная” иерархическая структура узлом предполагает, что текстовый узел окружен узлами других типов. Метод normalize () про*! сматривает дочерние узлы текущего объекта и комбинирует соседние текстовые узлы в один.j Это влияет на общее количество дочерних узлов элемента, а также изменяет иерархическим отношения вложенных узлов. | Пример 1 Используйте приложение The Evaluator для изучения метода normalize () в Mozilla*.] совместимых браузерах. В следующей последовательности действий показано, каким обра*1 зом можно добавить текстовый узел, соседний с уже имеющимся в элементе myP. С помо-1 щью метода normalized в приведенном примере удаляется граница между соседним! текстовыми узлами. , I Для начала определите количество дочерних узлов элемента туР. ' document.getElementByld("туР").childNodes.length ; Как видите, исходно в этом элементе присутствует три дочерних узла. Далее создайте тем стовый узел и присоедините его к элементу туР после последнего дочернего узла. 1 а = document.createTextNode("This means you!“) | document.getElementByld("myP").appendChild(a) j Теперь количество дочерних узлов элемента myP увеличится до четырех. 1 document.getElementByld("myP").childNodes.length j -J Легко можно удостовериться, что последний текстовый узел — именно тот, который вы! создали ранее. i document.getElementByld("myP").lastchild.nodeValue ] После выполнения метода normalize () элемента myP все соседние текстовые узлы бу] дут объединены в один большой текстовый узел. document.getElementByld("myP").normalize() Теперь элемент myP (как и раньше) состоит из трех текстовых узлов, хотя последний них содержит исходный текст, а также текст добавленного ранее на страницу узла. 1 5 Xfi : 1 1 336 Часть III. Объекты док
document.getElementByld("myP").childNodes.length document.getElementByld("myP").lastchild.nodeValue См. также: методы document. createTextNode (), appendChild (), insertBefore (), removeChild(), replaceChild(). releasecapture() se tCap tur e (булевКонтейнер) Возвращаемое значение: отсутствует Совместимость: WinDE5+, MacIE-, NN-, Moz-, Safari- C помощью метода s et Capture () можно указать объект, который будет перехваты- вать все события мыши (onmousedown, onmouseup, onmousemove, onmouseout, onmouseover, onclick и ondblclick). В IE перехват событий мыши, обычно, применя- ется в следующей ситуации: на странице появляется некоторый элемент, который является генератором действия пользователя (например, раскрывающиеся, контекстные меню или ак- тивные области). После отображения такого элемента на экране необходимо будет блокиро- вать все события мыши, кроме тех, которые относятся к текущему объекту. Когда этот эле- мент исчезнет с экрана, события мыши освободятся: т.е. остальные объекты (кнопки или ссылки на странице) вновь будут откликаться на них. Захват не блокирует события — они лишь перенаправляются к указанному объекту. Со- бытия возникают, если только они не отменены явно (см. главу 25). Предположим, что деск- риптор <body> содержит обработчик события onclick, управляющий всем документом. Если включить захват событий элементом div, содержащимся в документе, то все события вначале будут перенаправляться последнему. Элемент div может иметь обработчик события onclick, выполняющий действия в том случае, когда события относятся к какому-либо из его дочерних элементов. Если в обработчике событий элемента div не отменен переход со- бытия вверх по структуре, то обработчик события onclick элемента body также обработает его, хотя изначально оно получено (захвачено) элементом div. Определение того, какой объект должен захватывать события, является серьезным вопро- сом в разработке документа. При захвате все события мыши (независимо от того, где они происходят) перенаправляются указанному объекту. Поэтому при разработке приложения, интерфейс которого предполагает щелчок на объектах и перетаскивание позиционируемых элементов, обязательно укажите, какой из элементов (или даже объект document) должен производить захват событий. Для всплывающих областей логично и более удобно при про- граммировании назначить механизм захвата событий элементу, содержащему всплывающее содержимое (как правило, позиционируемый элемент div). Метод setcapture () имеет дополнительный аргумент логического типа. Он управляет тем, подчиняются ли события дочерних элементов захватывающего объекта описанному механизму захвата. Значение по умолчанию (true) означает, что все события мыши, опреде- ленные для дочерних элементов текущего объекта, направляются последнему, а не в исход- ную точку назначения (так, метод setcapture () чаще всего используется для всплываю- щих и контекстных меню). Параметр false соответствует ситуации, когда дочерние элементы обрабатывают события самостоятельно. Затем происходит обычное перемещение событий вверх по структуре (см. главу 25). Поведение метода может стать непредсказуемым, если элемент, перехватывающий собы- тия, содержит элементы форм (например, текстовые поля или списки). Этим элементам со- бытия требуются для активизации и дальнейшего взаимодействия со сценарием, а механизм захвата событий предотвращает возможность доступа к ним. Чтобы обойти такое поведение, следует проверить свойство srcElement. В случае, если щелчок выполнен на одном из та- ких элементов, активизируйте его (или же проинформируйте пользователя о необходимости перехода к нужному элементу с помощью клавиши <ТаЪ>). Глава 15. Основные объекты HTML-элементов 337
После указания перехватывающего события объекта, необходимо определить, какие со- бытия будут обрабатываться, а также будут ли они перемещаться вверх по иерархической структуре. О всплывании необходимо беспокоиться лишь в том случае, если обработчики со- бытий находятся в элементах-контейнерах, расположенных выше в структуре. Если после за- хвата события не требуется, чтобы запускался вышерасположенный обработчик, всплывание для него следует отменить. Если дизайн страницы требует, чтобы всплывающий на экране элемент скрывался, а об- работка событий вновь приобретала привычный характер (например после того, как поль- зователь сделает выбор во всплывающем меню), необходимо воспользоваться методом releasecapture (). Так как захват событий возможен лишь для одного элемента, отмените его, запустив метод releasecapture () для элемента-контейнера или объекта document. Захват событий автоматически отменяется, когда пользователь производит одно из сле- дующих действий. Активизирует другое окно. Выводит системное диалоговое окно (например, предупреждение). Прокручивает страницу. Открывает контекстное меню браузера (щелчком правой кнопкой мыши). Активизирует строку адреса браузера или нажимает клавишу <ТаЬ>. С помощью обработчика события onlosecapture объекта document можно “скрыть” элемент-контейнер, отображаемый при обработке события. Помните, что для предотвращения доступа к элементам страницы возможен захват событий мыши, но не клавиатуры! Поэтому механизм захвата событий, используемый для эмуляции окон или элементов меню и предотвращающий доступ к остальной части страницы, не является самЬ- достаточным — пользователь может перейти к любому элементу формы или ссылке после нажа- тия клавиши <ТаЬ>, а затем активизировать элемент нажатием клавиши пробела или <Enter>. Захват событий в W3C DOM отличается от механизма, поддерживаемого в IE. В W3C DOM браузер имеет возможность заменить захват события любого типа на обычное всплыва- ние события В иерархической структуре. Например, приемник события может помещаться в дескрипторе body и проверять все события, относящиеся к элементам body, до их поступ- ления к соответствующим элементам. (Подробнее о модели обработки событий в W3C DOM и том, как создать приложения, выполняемые в разных браузерах, речь идет в главах 14 и 25.) Пример В листинге 15.30 продемонстрированы особенности использования методов setCapture() и releasecapture () при создании контекстного меню в IE5+. Назначение этого контекстного меню весьма простое— определить способ нумерации списка упорядоченных элементов страницы. Как только пользователь щелкнет на элементе о1 правой кнопкой мыши, на экране появится контекстное меню. Захват событий происходит таким образом, что щелчок за пре- делами контекстного меню не вызывает никаких действий. При этом само контекстное меню скрывается. При выборе одного из вариантов контекстного меню изменяется значение свой- ства listStyleType объекта ol. Как только контекстное меню скрывается с экрана, захват событий отключается — любой щелчок на странице обрабатывается стандартным образом. В рассматриваемом примере используются обработчики событий onclick, onmouseover и onmouseout элемента div, который содержит контекстное меню. Чтобы отобразить кон- текстное меню, на экране задействуется обработчик события oncontextmenu элемента ol. Все действия в этом обработчике событий выполняет функция showContextMenu (). Дан- ная функция указывает захватывать события для объекта div. Более того, элемент div' рас- полагается в месте щелчка еще до отображения на экране. Чтобы предотвратить появление на 338 Часть III. Объекты документа
экране стандартного контекстного меню, свойство returnValue объекта event устанавли- вается в значение false. Как мы выяснили ранее, все события мыши теперь происходят в объекте div. Посмот- рим, что же происходит при использовании мыши. В результате перемещения указателя мы- ши возникают события mouseover и mouseout, которыми управляют обработчики, назна- ченные объекту div. Обратите внимание, что два обработчика событий— highlight () и unhighlight () — выполняются только тогда, когда свойство srcElement объекта event приравнивается к одному из элементов объекта div. Поскольку на странице не обрабатываются события onmouseover или onmouseout других элементов, даже расположенные на более высоких уровнях иерархической структуры, то всплывание событий для них не отменяют. Когда пользователь нажимает кнопку мыши, выполняются самые разные действия, свя- занные с включением или отключением захвата событий в сценарии. При отключении захвата событие click всплывает от места возникновения к обработчику событий onclick элемен- та body (на экране отображается сообщение, когда событие достигает элемента body). При включении захвата событий (отображение контекстного меню на экране) обработчик события handleclick () применяет выбранный тип нумерации. Для всех событий щелчка, обрабаты- ваемых этой функцией, контекстное меню скрывается, а всплывания событий не происходит (предупреждающее сообщение не отображается). Подобное происходит, когда пользователь выбирает элемент меню или щелкает в другом месте страницы. В последнем случае контек- стное меню должно скрываться, за что и отвечает обработчик событий onlosecapture. <html> <head> <titlex/title> <style type="text/css"> #contextMenu {position:absolute; background-color:#cfcfcf; border-style:solid; border-width:Ipx; border-color:#EFEFEF #505050 #505050 #EFEFEF; padding:3px lOpx; font-size:8pt; font-family:Arial, Helvetica; line-height:150%; visibility:hidden} .menuitem {color:black} .menuItemOn {color:white} ol {list-style-position:inside; font-weight:bold; cursor:hand} li {font-weight:normal} </style> <script type="text/javascript"> function showContextMenu() { contextMenu.setcapture(); contextMenu.style.pixelTop = event.clientY + document.body.s crolITop; contextMenu.style.pixelLeft = event.clientX + document.body.scrollLeft; contextMenu.style.visibility = "visible"; event.returnvalue = false; } function revert() { document.releasecapture(); hideMenu(); } function hideMenu() { Глава 15. Основные объекты HTML-элементов 339
contextMenu.style.visibility = "hidden"; function handleclick() { var elem = window.event.srcElement; if (elem.id.indexOf("menultem") == 0) { document.getElementByld("shapesList").style. listStyleType = elem.listtype; } revert(); event.cancelBubble = true; } function highlight() { var elem = event.srcElement; if (elem.className == "menuitem") { elem.className = "menuItemOn"; function unhighlight() { var elem = event.srcElement if (elem.className == "menuItemOn") { elem.className = "menuitem"; </script> </head> <body onclick="alert(’You reached the document object.')"> <ol id="shapesList" oncontextmenu="showContextMenu()"> <li style="list-style: none"xa href="javascript: alert(’A%20sample%201ink.’)">Three-Dimensional Shapes</ax/li> <li value="l">Circular Cylinder</li> <li>Cube</li> <li>Rectangular Prism</li> <li>Regular Right Pyramid</li> <li>Right Circular Cone</li> <li>Sphere</li> </ol> <div id="contextMenu" onlosecapture="hideMenu()" onclick="handleclick()" onmouseover="highlight()" onmouseout="unhighlight()"> <span id="menulteml" class="menuitem" listtype="upper-alpha">A,B,C, . . .«/spanxbr /> <span id="menultem2" class="menuitem" listtype="lower-alpha">a,b, c, . . .«/spanxbr /> <span id="menultem3" class="menuitem" listtype="upper-roman">1, II, III, . . .«/spanxbr /> <span id="menultem4" class="menuitem" listtype="lower-roman">i,ii,iii, . . .«/spanxbr /> <span id="menultem5" class="menultem" listtype="decimal">1,2,3,...</span> </div> </body> </html> См. также: методы addEventListener (), dispatchEvent (), fireEventO, removeEventListener (); событие onlosecapture; объект Event (глава 25). 340 Часть III. Объекты документа
removeAttribute ("имяАтрибута" [, чувствительностьКРегистру]) Возвращаемое значение: булевого типа (IE); отсутствует (NN) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Атрибут, созданный с помощью метода setAttribute (), можно удалить методом removeAttribute (). Обязательным параметром является имя атрибута. IE4+ позволяет устанавливать и удалять атрибуты, в именах которых учитывается регистр. По умолчанию в методе removeAttribute () в IE второй аргумент (булевого типа) имеет значение false. Если при вызове метода setAttribute () параметр имел значение true, метод removeAttribute () должен вызываться таким же образом. В W3C DOM (NN/Moz/Safari) метод removeAttribute () имеет только один параметр (имя атрибута без учета регистра) и не возвращает никакого значения. В IE метод возвращает true, если процесс удаления завершился успешно, и false — в ином случае (в том числе, если атрибут был установлен другим способом). Пример Приложение The Evaluator (глава 13) позволяет изучить метод removeAttribute () для элементов страницы (просмотрите примеры для метода setAttribute () далее в этой гла- ве и введите соответствующие операторы removeAttribute () в верхнее поле). С помо- щью метода getAttribute () проверьте наличие или отсутствие каждого атрибута. См. также: свойство attributes; методы document. createAttribute (), getAttribute() иsetAttribute(). removeAttributeNode (узелАтрибута) se t At tribut eNode (узелАтрибута) Возвращаемое значение: объект Attribute Совместимость: WinIE6+, MacIE-, NN6+, Mozl+, Safari 14- Как отмечалось при описании метода getAttributeNode () ранее в этой главе, в W3C DOM пара “имя-значение” является объектом атрибута. Объект атрибута представляет собой отдельный узел в карте именованных узлов — наборе объектов атрибутов, принадлежащих эле- менту. Карта именованных узлов и объектов атрибутов часто используется в среде XML, где ат- рибуты могут не только содержать ценные данные, но и не рассматриваются в объектной моде- ли документа как свойства, к которым возможен доступ из сценария. Вместо обращения к свойствам объекта в XML-сценарии возможен доступ только к реальными объектам атрибутов. Если вам требуется вставить атрибут согласно формальной спецификации W3C, то вос- пользуйтесь методом document.createAttribute (), генерирующим новый объект атри- бута. Затем в последующих операторах сценария присвойте значения свойствам nodeName и nodeValue, указав, таким образом, атрибуту пару “имя-значение”. После этого с помощью метода setAttributeNode () новый объект атрибута можно будет добавить в список ат- рибутов текущего объекта. Единственным параметром метода является объект атрибута, а воз- вращаемым значением — новый, вставленный в документ, объект. Метод removeAttributeNode () позволяет выполнить обратное действие— удалить атрибут элемента, используя тот же синтаксис. И вновь его единственным параметром явля- ется объект атрибута. Если в сценарии известно только имя атрибута, для получения кор- ректной ссылки на объект необходимо воспользоваться методом getAttributeNode (). Метод removeAttributeNode () возвращает ссылку на удаленный объект атрибута. Этот Глава 15. Основные объекты HTML-элементов 341
объект остается в памяти браузера, но перестает быть частью иерархической структуры до- кумента. Такой подход позволяет присвоить удаленный объект атрибута переменной, изме- нить его, а затем присвоить любому другому объекту документа. На практике работать с атрибутами как с узлами приходится крайне редко. Методы getAttribute (), removeAttribute () и setAttribute () выполняют те же опера- ции, когда известно только имя атрибута (в строковом представлении текущего элемента). Пример Приложение The Evaluator (глава 13) также используется для изучения методов setAttributeNade() и removeAttributeNode () элемента р страницы. Ваша зада- ча — создать и добавить атрибут style в элемент р. Начните с создания нового атрибута и сохранения его во временной глобальной переменной а. а = document.createAttribute("style") Далее назначьте значение объекту attribute. a.nodeValue = "color:red” Вставьте новый атрибут в элемент р. document.getElementByld("myP").setAttributeNode(a) Абзац с текстом изменит свой цвет в соответствии с новым добавленным атрибутом. Несмотря на то, что в NN6 этот метод не возвращает ссылку на новый добавленный узел атрибута, вы можете получить ее косвенно. b = document.getElementByld("myP").getAttributeNode("style") Наконец, используйте ссылку на новый добавленный атрибут, чтобы удалить его из иерар- хической структуры. document.getElementByld("myP").removeAttribute(b) После удаления атрибута абзац примет свой исходный цвет (см. пример использования метода setAttribute () далее в этой главе, чтобы узнать, как выполнить те же действия с помощью метода setAttribute ()). См. также: свойство attributes; методы document. createAttribute (), getAttribute (),getAttributeNode(), setAttribute(). removeAttributeNS (11 ШНпространстваИмен" , "локальноеИмя") Возвращаемое значение: ничего Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод удаляет атрибут, определенный двумя параметрами. Первый параметр метода определяет строку URI, которая совпадает с URI, назначенного подписи к документу. Второй параметр задает часть с локальным именем атрибута, значение которого определяется. См. также: свойства attributes, namespaceURI, localName; методы remove- Attribute (),getAttributeNS() и setAttributeNS(). removeBehavior(идентификатор) Возвращаемое значение: булевого типа Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод removeBehavior () отсоединяет поведение от объекта. Подразумевается, что оно добавлено методом addBehavior (). Значение, возвращаемое методом addBehaviord, представляет собой уникальный идентификатор поведения. Этот идентификатор является обяза- 342 Часть III. Объекты документа
тельным аргументом метода removeBehavior (). Таким образом, объекту, например, можно присвоить два поведения, а затем удалить только одно из них. Если процесс удаления завер- шается успешно, метод removeBehavior () возвращает true; в ином случае — false. Пример Обратитесь к листингам 15.19а и 15.196 (ранее в этой главе), чтобы детальнее ознако- миться с методами addBehavior () и removeBehavior (). См. также: метод addBehavior (). removeChild (объекагУзла) Возвращаемое значение: ссылка на объект Node Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Метод removeChild () удаляет дочерний элемент текущего узла. Содержимое дочер- него элемента не отображается на странице, а сам объект перестает быть частью иерархи- ческой структуры. Тем не менее, объект не удаляется полностью. Метод removeChild () возвращает ссыл- ку на удаленный узел. Присвойте его переменной, и объект можно будет сохранить для по- следующей вставки. Переменной можно воспользоваться как аргументом следующих мето- дов: appendChild(), replaceChild(), swapNode() и insertBefore(). Помните, что метод removeChild () вызывается относительно родительского элемента. Если требуется просто удалить элемент, это можно сделать напрямую (в IE5+) с помощью метода removeNode (). Пример Пример использования метода removeChild () приведен в листинге 15.21 ранее в этой главе. См. также: методы appendChild (), replaceChild (), removeNode (). removeEventListener() См. addEventListener(). removeExpression("имяСвойства") Возвращаемое значение: булевоготипа Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Если свойству объекта (включая объект style) значение присваивается с помощью ме- тода setExpression (), удалить его можно методом removeExpression (). Его единст- венным параметром является строка с именем свойства (с учетом регистра). В случае успешного удаления метод возвращает значение true, и false — в ином слу- чае. Помните, что удаление выражения не изменяет значения, присвоенного свойству. Дру- гими словами, методом setExpression () можно установить значение свойства, а затем удалить выражение, чтобы далее (когда документ пересчитает выражения) не последовало никаких изменений. Если вы преследуете именно такую цель, то проще задать свойство пу- тем присвоения значения в сценарии. Пример ‘Вы можете смело экспериментировать со всеми тремя методами в приложении The Evaluator (глава 13). Следующая последовательность действий позволяет добавить выражение в свойство style элемента туР страницы, а затем удалить его. Глава 15. Основные объекты HTML-элементов 343
Для начала введите в нижнее текстовое поле значение 24 (но не нажимайте <Enter> и не щелкайте на кнопке List Properties). Тем самым вы ограничите свойство fontsize объекта тур. Далее назначьте объекту style объекта тур выражение, введя в верхнее поле следую- щий оператор. myP.style.setExpression("fontsize","document.forms[0].inspector. , value","JScript") Теперь вы можете вводить в нижнее текстовое поле различные размеры шрифта; при этом изменения немедленно вступят в силу. (События клавиатуры указывают на обновление фор- матирования.) По умолчанию размер шрифта отображается в пунктах (рх), хотя при желании можно добавить к числовому значению суффикс pt, чтобы указать размер в точках. Перед тем, как перейти к следующему этапу, введите значение, отличное от 16 (именно это значение задается для свойства fontsize по умолчанию). Далее введите в верхнее поле следующий оператор, чтобы отсоединить выражение от свойства. myP.style.removeExpression("fontsize") Теперь вы не сможете изменить размер шрифта с помощью нижнего текстового поля, од- нако элемент будет отображаться шрифтом с последним указанным размером. Чтобы прове- рить это, в верхнее поле введите следующий оператор. myP.style.fontsize . См. также: методы document. recalc (), getExpression () и setExpression (). removeNode (флаг) Возвращаемое значение: ссылка на объект Node Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод removeNode () применяется для удаления текущего узла из иерархии элементов в IE5+. Единственным его аргументом является значение булевого типа, с помощью которого можно удалить либо сам объект (без дочерних узлов), либо узел вместе со всеми его дочерними элементами (значение true). При использовании по умолчанию параметра false следует про- явить осторожность: если текущий узел имеет дочерние узлы (например, при попытке удалить только элемент TABLE, но не его дочерние элементы), то IE5 может вызвать сбой и внезапно за- вершить свою работу. Более безопасно удалять узел вместе со всеми его дочерними элементами. Метод возвращает ссылку на удаляемый узел. Этот объект перестает быть частью объект- ной модели документа. Но возвращаемое значение содержит все свойства объекта (включая outerHTML и указанные явно стилевые спецификации). Поэтому им можно воспользоваться для вставки узла в любом другом месте документа. В объектных моделях документа W3C и NN6 метод removeNode () не поддерживается. Аналогичным методом, определенным для всех браузеров, является removechild(). Об- ласть применения метода removechild () задается в иерархической структуре объектов на один уровень выше объекта, задаваемого в методе removeNode (). Пример В листинге 15.21 показана разница между методами appendChild () и removechild(). В функции restore () вы можете заменить выражение mainObj.removechild(oneChild); на следующий оператор (в IE5+). oneChild.removeNode(true); 344 Часть III. Объекты документа
Разница в этих двух вариантах синтаксиса на первый взгляд незначительна, однако она весьма существенна. В листинге 15.31 далее в этой главе приведен еще один пример исполь- зования метода removechild (). См. также: объект Node; методы appendChild (), cloneChild (), removechild (), replaceChild(), replaceNode (). replaceAdj acentText ("расположение", " текст") Возвращаемое значение: строка Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод replaceAdjacentTextО позволяет заменить один фрагмент текста другим; расположение фрагмента отсчитывается относительно текущего объекта. Обратите внимание, что этот метод применяется только для текстовых элементов и неприменим к дескрипторам HTML. Метод возвращает строку, которая была заменена. Оба аргумента являются обязательными. Первый задает один из четырех возможных пара- метров расположения текстового фрагмента (регистр не учитывается), приведенных в таблице. Положение Описание beforeBegin Перед открывающим дескриптором текущего элемента afterBegin После открывающего дескриптора перед вложенным содержимым beforeEnd Перед закрывающим дескриптором после вложенного содержимого afterEnd После закрывающего дескриптора текущего элемента С параметрами beforeBegin и afterEnd этот метод предпочтительнее применять для элементов внутритекстовых фрагментов (а не блоковых). Например, если воспользоваться методом replaceAdj acentText О с аргументом beforeBegin для второго из последо- вательно заданных абзацев, то текст-заместитель будет вставлен после первого абзаца. Метод replaceAdj acentText () нужно рассматривать относительно узлов текстовых фрагмен- тов (хотя IE5 и не полностью поддерживает свойства W3C DOM). Метод заменяет узел тек- стового фрагмента (при указании одного из четырех возможных параметров) новым текстом. Замена текста простого элемента с помощью параметра afterBegin или beforeEnd ана- логична присвоению текста свойству innerText объекта. Пример Используйте приложение The Evaluator для всестороннего изучения метода replace- Adj acentText О. Введите каждое из следующих выражений в верхнее текстовое поле, а результат их выполнения просмотрите в элементе тур (и вложенном элементе туЕ). document.getElementByld("туЕМ").replaceAdjacentText("afterBegin", "twenty") Обратите внимание, что новый текст элемента туЕ наследует поведение своего контейне- ра (т.е. элемента). Как правило, заменяемый текст (all) возвращается методом в качестве ре- зультата и выводится в поле Results. document.getElementByld("туЕМ").replaceAdj acentText("beforeBegin", "We need ") Заменяются все символы текстового фрагмента, включая пробелы. Если заменяемый фрагмент содержит пробелы, то вам придется добавить в заменяющую строку дополнитель- ный пробел. document.getElementByld("myP").replaceAdj acentText("beforeEnd", " good people.") Глава 15. Основные объекты HTML-элементов 345
Существует еще один способ вставки текстового фрагмента после элемента myEm. Если вы попробуете заменить текст после элемента туР следующим образом document.getElementByld("туР").replaceAdjacentText("afterEnd", ' "Hooray!") то текст будет вставлен после закрывающего дескриптора элемента туР. В дальнейшем этот текстовый фрагмент будет восприниматься как плавающий текстовый узел в объектной мо- дели документа. См. также: свойства innerText, outerText; методы getAdj acentText (), insert- Adj acentHTML(), insertAdj acentText(). replaceChiId(объектНовогоУзла, объектСтарогоУзла) Возвращаемое значение: ссылка на объект Node Совместимость: WinIE5+, MacIE5+, NN-, Mozl+, Safaril+ Метод replaceChild () позволяет заменить существующий объект дочернего узла но- вым элементом. Параметрами метода служат объекты узлов (вначале указывается заменяю- щий объект, а после него — заменяемый). “Старый” объект должен быть дочерним по отно- шению к тому родительскому элементу, для которого запускается метод, а новый— его правильным дочерним элементом в иерархической структуре документа. Метод возвращает ссылку на объект дочернего узла, замененного новым объектом. Этой ссылкой можно воспользоваться как параметром в любом из методов вставки или замены узлов. Помните, что метод replaceChild () вызывается из родительского элемента. Если требу- ется просто изменить элемент, это можно сделать напрямую с помощью метода swapNode () или replaceNode (). Пример Пример использования этого метода приведен в листинге 15.21 ранее в этой главе. См.также: методы appendChild (), removeChild (), replaceNode О , swapNode (). replaceNode (11 объектНовогоУзла”) Возвращаемое значение: ссылка на объект Node Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод replaceNode () подобен replaceChild (), но запускается он для заменяемого узла (а не родительского объекта). Аргументом метода является ссылка на объект узла, кото- рый можно создать с помощью метода document. createElement () или скопировать. Возвращаемое значение является ссылкой на заменяемый узел. Таким образом, его можно со- хранить в переменной для последующего использования. Если заменяемый узел содержит дочерние элементы, метод replaceNode () удаляет их из документа. Поэтому, если требуется заменить только “внешний” узел, сохранив все внут- ренние дочерние узлы, необходимо скопировать и вставить их в новый узел (как показано в примере на компакт-диске). Пример В листинге 15.31 продемонстрирован пример использования трех методов управления уз- лами: removeNode (), replaceNode () и swapNode (). Все они выполняются только в ГЕ5+. Страница, которая отображается после выполнения кода листинга 15.31 в браузере, начи- нается со списка типа ul, содержащего четыре элемента. С помощью кнопок в нижней части 346 Часть III. Объекты документа
страницы вы можете изменить структуру узлов документа. Первая кнопка запускает функцию replace(), которая изменяет элемент ul на ol. Чтобы выполнить эту задачу, функция должна временно отсоединить все дочерние узлы исходного элемента ul (впоследствии они будут присоединены к новому элементу ol). В то же время старый элемент ul сохраняется в глобальной переменной oldNode (он восстанавливается в следующей функции). Чтобы заменить узел ul на ol, в функции replace () создается новый, пустой элемент ol с идентификатором myOl. Далее все дочерние элементы (li) сохраняются в виде массива, представленного отдельной переменной. После этого дочерние элементы вставляются в но- вый элемент ol с помощью метода insertBef ore (). Обратите внимание, что каждый до- черний элемент после вставки в новый элемент ol удаляется из массива innards. Наконец, с помощью метода replaceNode () новый элемент ol заменяет старый элемент ul. При этом последний сохраняется в переменной oldNode. Функция restore О выполняет действия, противоположные задаваемым функцией replace (). При этом также сохраняется обратный порядок управления дочерними элементами. Третья кнопка вызывает функцию swap (). Эта функция меняет местами первый и по- следний узлы. Метод swapNode () задается для одного из узлов, а второй узел указывается в качестве атрибута. Исходя из природы элемента ol, тип нумерации остается прежним; за- меняется только текст элементов li. Чтобы продемонстрировать возможности метода removeNode (), в код страницы была добавлена четвертая функция, используемая для удаления последнего дочернего узла элемен- та списка. При каждом вызове метода в него подставляется атрибут true, указывающий на удаление вместе с элементом li всех вложенных в него текстовых узлов. Поэксперименти- руйте с этим методом, задав в качестве параметра значение false. Обратите внимание, что после удаления элемента li родительско-дочерние отношения в документе нарушаются. <html> <head> <title>removeNode(), replaceNodeО, and swapNode() Methods</title> «script type="text/javascript"> // сохранение исходного узла между изменениями var oldNode; // замена узла UL на узел OL function replace() { if (document.getElementByld("myUL")) { var newNode = document.createElement("OL"); newNode.id = "myOL"; var innards = document.getElementByld("myUL").children; while (innards.length >0) { newNode.insertBefore(innards[0]); } oldNode = document.getElementByld("myUL"). replaceNode(newNode); // восстановление узла OL из узла UL function restore() { if (document.getElementByld("myOL") && oldNode) { var innards = document.getElementByld("myOL").children; Глава 15. Основные объекты HTML-элементов 347
while (innards.length >0) { oldNode.insertBefore(innards[0]); } document .getElementByld ("myOL").replaceNode(oldNode); } } // взаимозамена первого и последнего узлов function swap() { if (document.getElementByld("myUL")) { document.getElementByld("myUL").firstChild.swapNode( document.getElementByld("myUL").lastChild); } if (document.getElementByld("myOL")) { document.getElementByld("myOL").firstChild.swapNode( document.getElementByld("myOL").lastchild); } } // удаление последнего узла function remove() { if (document.getElementByld("myUL")) { document.getElementByld("myUL").lastchild. removeNode(true); } if (document.getElementByld("myOL")) { document.getElementByld("myOL").lastChild. removeNode(true); } } </script> </head> <body> <hl>Node Methods</hl> <hr /> Here is a list of items: <ul id="myUL"> <li>First Item</li> <li>Second Item</li> <li>Third Item</li> <li>Fourth Item</li> </ul> <form> <input type="button" value="Change to OL List" onclick="replace()" />&nbsp;&nbsp; «input type="button" value="Restore LI List" onclick="restore()" />&nbsp;&nbsp; «input type="button" value="Swap First/Last" onelick="swap()" />&nbsp;&nbsp; «input type="button" value="Remove Last" onclick="remove()" /> </form> </body> «/html> Вы можете выполнить все действия, запрограммированные в коде листинга 15.31, поддер- живая стандарт W3C DOM. Для этого вместо методов removeNode () и replaceNode () ис- пользуйте методы removechild () и replaceChild (). Вам также нужно изменить ссыл- ку document.all на document.getElementByld(). См. также: методы removechild (), removeNode (), replaceChild (), swapNode (). 348 Часть III. Объекты документа
scroll IntoView (флаг) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN7+-, Mozl+, Safaril+ Метод scrollIntoView () прокручивает страницу (по вертикали или горизонтали) таким образом, чтобы текущий объект попал в видимую область окна или фрейма. Параметр булевого типа управляет расположением элемента в видимой области. Значение true (по умолчанию) выравнивает верхнюю часть элемента по верхнему краю окна или фрейма (подразумевается, что документ достаточно велик, чтобы позволить такую прокрутку). Значение false выравнивает нижнюю часть элемента по нижнему краю видимой области. Как правило, используется пер- вое значение, но в некоторых случаях применяется и значение false (когда, например, не- желательно, чтобы пользователь видел информацию ниже определенного элемента). Для элементов форм используется обычная ссылка (document.имяФормы.element- Name.scrollIntoView()), но можно пользоваться и идентификатором элемента, если он предварительно задан (document.getElementByld("идентификаторЭлемента") .scroll- IntoView ()). Пример Приложение The Evaluator применяется также и для изучения метода scroll IntoView (). Измените высоту окна браузера так, чтобы в нем отображались только верхнее поле и об- ласть Results. Введите в верхнее поле следующие выражения и ознакомьтесь с видом эле- мента туР на странице. myP.scrollIntoView() туР.scrollIntoView(false) Увеличьте высоту окна браузера так, чтобы в нем отображалась нижняя часть страницы. Если ввести в верхнее поле выражение myTable.scrollIntoView(false) то страница будет прокручена таким образом, что ее нижний край совпадет с нижним краем окна. Если же использовать параметр по умолчанию (true или не задавать) myTable.scrollIntoView() то страница будет прокручена таким образом, что ее верхний элемент окажется максимально приближенным к верхнему краю окна. При этом страницу нельзя прокрутить в области, рас- положенные вне данных страницы (хотя при динамическом изменении расположения эле- мент может располагаться и за пределами страницы). Если вы попытаетесь прокрутить доку- мент так, чтобы в верхней части окна оказалось начало страницы, то помните, что элемент table имеет подпись (элемент caption), которая расположена в начале таблицы. См. также: методы window. scroll (), window. scrollBy (), window. scrollTo (). setActive () Возвращаемое значение: отсутствует Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Метод setActive () позволяет сценарию сделать объект элемента активным. Однако при этом, в отличие от метода focus (), окно не прокручивается так, чтобы элемент по- пал в видимую область. При вызове метода setActive () запускается обработчик события onf ocus, определенный для элемента; при этом браузер не переходит к этому объекту. Глава 15. Основные объекты HTML-элементов 349
Пример Используйте приложение The Evaluator, чтобы сравнить методы setAct ive () и setFocus(). Прокрутите страницу вверх и увеличьте окно браузера так, чтобы скрыть в нижней части до- кумента флажок; затем введите в верхнее текстовое поле следующее выражение. document.forms[1].myCheckbox.setActive() Прокутите страницу вниз и удостоверьтесь, что флажок активизирован (нажмите <пробел>). Вернитесь к верхнему текстовому полю и введите следующий оператор. document.forms[1].myCheckbox.focus() Тем самым вы активизируете флажок и прокрутите страницу так, чтобы он отображался на экране. См. также: метод focus (). setAttribute(11 имяАтрибута", значение[, ЧувствительностьКРегистру]) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Метод setAttribute () присваивает новое значение существующему атрибуту текуще- го объекта или вставляет совершенно новую пару “имя-значение” в набор атрибутов объекта. Этот метод позволяет способом, отличным от непосредственного назначения, установить значение свойства. 'На заметку Стандарт W3C DOM2 рекомендует использовать методы getAttribute О и setAttribute () для получения и задания значений атрибутов объекта эле- мента вместо применения соответствующих свойств объекта. Если использова- ние этих методов вполне оправдано для элементов XML, стандарт DOM приво- дит к некоторым проблемам, т.к. поддерживает все свойства объектов элементов HTML. Браузеры, конечно же, будут обеспечивать доступ к атрибутам с помощью свойств и в будущем, поэтому вы вполне можете пользоваться раз- ными методами доступа. Два первых аргумента метода setAttribute () являются обязательными. Первый пред- ставляет собой имя атрибута. По умолчанию в нем учитывается регистр. Поэтому, когда ме- тод setAttribute () используется для изменения существующего атрибута в режиме по умолчанию, необходимо корректно указать имя с учетом регистра. Помните, что имена всех атрибутов, присвоенных в исходном коде, автоматически преобразуются в нижний регистр. Значение, присвоенное атрибуту, является вторым параметром метода. Для совместимо- сти разных браузеров значение должно принадлежать или строковому, или булевому типу. IE обеспечивает дополнительный третий аргумент, управляющий регистром символов в имени атрибута. Значение по умолчанию (true) обеспечивает разные результаты, что зави- сит от того, используется ли метод setAttribute () для присвоения нового атрибута или изменения значения существующего. В первом случае значение третьего параметра true оз-' начает, что в первом параметре учитывается регистр. Во втором случае оно указывает, что новое значение присваивается атрибуту лишь в том случае, если первый аргумент в точности; (с учетом регистра) совпадает с существующим именем атрибута. Иначе создается новый ат- рибут, именем которого служит первый параметр. Применять зависимые от регистра имена новых атрибутов не рекомендуется, если исполь-1 зуются имена, отличающиеся только регистром символов. В методах setAttribute!) и getAttribute () используйте установки по умолчанию. 350 Часть III. Объекты документ»)
ВIE4+ существуют некоторые ограничения на действия метода setAttribute (); атри- бут, который добавляется этим методом не становится частью набора attributes, присое- диненного к элементу. Несмотря на то, что значение нового атрибута можно получить с по- мощью метода getAttribute (), его невозможно извлечь из набора attributes. Если новый атрибут создается оператором document.getElementByld("myTable").setAttribute(“currYear", (new Date()).getFullYear()) к нему можно получить доступ с помощью одного из двух следующих выражений. var tableYear = document.getElementByld("myTable”). getAttribute("curryear"); var tableYear = document.getElementByld("myTable").currYear; Оператор var tableYear = document.getElementByld("myTable"). attributes["currYear"]; не позволяет получить значение нового атрибута. Возможности W3C DOM по управлению атрибутами как объектами узлов рассматриваются в разделах, посвященных методам getAttributeNode () и removeAttributeNode () (ранее в этой главе). Пример Используйте приложение The Evaluator для детального изучения метода setAttribute () элементов страницы. В IE4 в ссылках используется выражение document. all, а в IE5+ поддерживается W3C-CTamjapT — метод getElementByld (). Установка атрибутов влечет за собой немедленное изменение макета страницы (равно как и изменение свойств объектов). Введите в верхнее текстовое поле следующие выражения, чтобы ознакомиться со значениями атрибутов. IE4+ document.all.myTable.setAttribute("width", "8 0%") document.all.myTable.setAttribute("border", "5") E5+/W3C document.getElementByld("myTable").setAttribute("width", "80%") document.getElementByld("myTable").setAttribute("border", "5") См. также: свойство attributes; методы document. createAttribute О , getAttribute (), getAttributeNode (), removeAttribute (), removeAttribute- Node (), setAttributeNode (). setAttributeNode () Cm. removeAttributeNode(). setAttributeNodeNS (" узелАтрибуиа") Возвращаемое значение: объект Attribute Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод вставляет или заменяет атрибут в текущем элементе. Единственный параметр представляет объект атрибута, а возвращаемое значение — это ссыпка на новый вставленный объект атрибута. При вызове этого метода браузер просматривает локальные имена и URI пространства имен в поисках указанного узла. Если совпадение найдено, то узел заменяется; если нет, то вставляется. См. также: свойства attributes, namespaceURI, localName; методы getAttributeNS (), removeAttributeNS(), setAttributeNS(). Глава 15. Основные объекты HTML-элементов 351
setAttributeNS(" иШпространстваИмен", 11 локальяоеЯмя" , " значение") Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод вставляет или заменяет атрибут в текущем элементе, заданном тремя парамет- рами. Первый параметр указывает строку URI, совпадающую с соответствующей подписью в документе. Второй параметр задает локальное имя атрибута, значение которого необходимо получить. Если атрибут, заданный первыми двумя параметрами, найден, то его значение из- менится на указанное в третьем параметре. В противном случае значение будет вставлено в виде отдельного атрибута. См. также: свойства attributes, namespaceURI, localName; методыgetAttributeNS О, removeAttributeNS(), setAttributeNS(). se t Cap tur e (булевКонтейнер) См. releasecapture (). setExpression("имяСвойства", "выражение*, "язык*) Возвращаемое значение: отсутствует Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод setExpression () применяется для присвоения результата выполнения выраже-. ния свойству объекта элемента. Метод позволяет присваивать значения объектам HTML- элементов и объектам стилей. Метод setExpression () — это способ присвоения значений атрибутам в сценарии. Од- нако для присвоения напрямую значений стилям, определенным в дескрипторе HTML, можно воспользоваться синтаксисом метода expression (), как показано в следующем примере. <р style="width:expression(document.body.style.width * 0.75)"> Метод setExpression () принимает три параметра. Первым из них является строка с именем свойства (учитывается регистр), которому присваивается выражение. Второй — строка с выражением, значение которого вычисляется. В выражениях могут использоваться глобальные переменные или другие объекты текущего документа (при условии, что свойство не является массивом). Выражение может также содержать математические операторы. Обратите внимание на тип данных выражения. Тип значения должен совпадать с типом свойства, которому оно присваивается. Например, URL фонового изображения страницы дол- жен быть строкой. Для числовых значений можно использовать и числовой, и строковый тип, поскольку значения преобразуются автоматически в соответствии с типом свойства. Даже вы- ражения, результатом которых является число, следует заключать в кавычки. Они нужны далеко не во всех случаях, но если вы выработаете привычку использовать кавычки, то сможете из- бежать проблем в строковых или более сложных выражениях, в которых без них не обойтись. Третий параметр метода позволяет указать используемый язык написания сценариев. Он принимает такие значения. Jscript VBScript JavaScript Во всех проявлениях JScript и JavaScript совпадают. Оба языка совместимы со стандартом ЕСМА-262. J 352 Часть III. Объекты документа]
v Одна из причин использования метода setExpression () заключается в том, чтобы ди- намические свойства всегда отвечали текущему состоянию страницы. Например, если свой- ство зависит от текущей ширины документа, его необходимо изменить при изменении поль- зователем размеров окна. Браузер автоматически реагирует на многие события и обновляет некоторые динамические свойства. По существу, браузер пересчитывает и присваивает свой- ствам новые значения. В частности, такой автоматический пересчет выполняется при поступ- лении событий клавиатуры. Однако в том случае, когда сценарий сам выполняет действия (другими словами, не связанные с предопределенными событиями), потребуется вычислить выражения явно. Данную задачу выполняет метод document. re cal с () — его необходимо вызвать для пересчета значений динамических свойств. Пример В коде листинга 15.32 используются методы setExpression (), recalc () и getExpres- sion () для создания своеобразных цифровых часов. Текущее время обозначается тремя по- лосами (часы, минуты, секунды), длина которых увеличивается с течением времени. В то же время с помощью элементов innerHTML и span справа от каждой полосы указывается чи- словое значение показателей. Динамически пересчитываемые значения в этом примере создаются на основе нового объекта даты (сохраняется в переменной now), данные которого заимствуются из системных часов компьютера. Для преобразования часов, минут и секунд в длины соответствующих по- лос необходимо выполнить дополнительные вычисления. Полосы делятся на 24 (часы) и 60 (минуты и секунды) частей. В двух последних полосах каждая часть имеет длину 5 пикселей (сохраняется в переменной shortwidth). Часть полосы часов равна значению shortwidth, умноженному на 2,5. Рис. 15.1. Графические цифровые часы с необычным интерфейсом Глава 15. Основные объекты HTML-элементов 353
При загрузке документа элементам span, представляющим цветные полосы часов, длина не задается. После полной загрузки страницы, обработчик события onload запускает функ- цию init (). Эта функция устанавливает начальные длины всех полос и подписи к ним. По- сле этого в функции init () вызывается функция updatedock (). Последняя функция создает объект даты для текущего времени. В ией вызывается метод document, recalc О, который указывает пересчитать документ, соответственно выраже- ниям в функции init (), а также назначить свойствам новые значения. При динамическом отображении на странице времени функция updatedock () вызывается каждую секунду. Чтобы увидеть результат выполнения метода getExpression (), щелкните на кнопке страницы. При этом будет возвращено значение одного из атрибутов, назначенных с помо- щью метода setExpression (). <html> <head> <title>getExpression() , setExpression() , and recalc() Methods</title> <style type="text/css"> th {text-align:right} span {vertical-align:bottom} </style> «script type="text/javascript"> var now = new Date(); var shortwidth = 5,- var multiple = 2.5; function init() { with (document.all) { hoursBlock.style.setExpression("width","now.getHours() * shortwidth * multiple","jscriptH); hoursLabel.setExpression("innerHTML","now.getHours()", "j script"); minutesBlock.style.setExpression("width", "now.getMinutes() * shortwidth","j script"); minutesLabel.setExpression("innerHTML", "now.getMinutes()","j script"); secondsBlock.style.setExpression("width", "now.getSeconds() * shortwidth","jscript"); secondsLabel.setExpression("innerHTML", "now.getSeconds()","j script"); } updateClock(),- } function updateClock() { now = new Date(); document.recalc(); setTimeout("updateClock()",1000); } function showExpr() { alert("Expression for the \’Hours\' innerHTML property is:\r\n" + document.getElementByld("hoursLabel"). getExpression("innerHTML") + ".") ; 354 Часть III. Объекты Д1
} «/script> </head> «body onload="init()"> «hl>getExpression(), setExpression(), recalc() Methods«/hl> «hr /> <p>This clock uses Dynamic Properties to calculate bar width and time numbers:</p> «table border="0”> «tr> «th>Hours:«/th> «td>«span id="hoursBlock" style="background-color:red”> </span> &nbsp;«span id="hoursLabel">«/span>«/td> «/tr> «tr> «th>Minutes:</th> «td>«span id="minutesBlock" style= "background-color:yellow">«/span>&nbsp; «span id="minutesLabel">«/span>«/td> </tr> «tr> «th>Seconds:«/th> > <td>«span id="secondsBlock" style= "background-color:green">«/span>&nbsp; < span id="secondsLabel"> «/span> </td> </tr> «/table> «hr /> «form> «input type="button" value="Show 'Hours' number innerHTML Expres s ion" one1i ck="showExpr()" /> «/form> </body> </html> См. также: методы document. recalc (), removeExpression (), setExpression (). swapNode (объктДругогоУзла) Возвращаемое значение: ссылка на объект Node Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Метод swapNode () меняет местами в иерархии элементов два узла. При этом содержи- мое узлов полностью сохраняется. Аргументом выступает объект узла (созданный методом document. createElement () или скопированный). Возвращаемое значение — это ссылка на объект, метод swapNode () которого был вызван. Пример Пример использования swapNode () приведен в листинге 15.31. См. также: методы removeChild (), removeNode (), replaceChild (), replace- Node (). tags(" имяДескриптора") Возвращаемое значение: массив объектов элементов Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Глава 15. Основные объекты HTML-элементов 355
Метод tags () имеют не все элементы, однако он включен во все наборы элементов (например all, forms или elements). Его можно представить как фильтр, отбирающий определенные элементы из набора. Например, для получения массива всех элементов Р доку- мента используется выражение. document.all.tags("Р") Аргументом является строка с именем дескриптора, который нужно извлечь. Регистр в данном случае не учитывается. Возвращаемое значение представляет собой массив ссылок на объекты текущего набора, имена которого совпадают с заданным параметром. Если совпадений нет, результирующий массив имеет нулевую длину. Для обеспечения совместимости с другими браузерами предпоч- тительнее пользоваться методом getElementsByTagName (), описанным ранее в этой главе.' Пример Приложение The Evaluator позволяет детально изучить метод tags (). Поочередно вве- дите в верхнее поле каждое из приведенных ниже выражений. document.all.tags("div") document.all.tags("div").length myTable.all.tags("td").length Поскольку метод tags () возвращает массив объектов, вы можете использовать люб возвращенное значение в качестве корректной ссылки на элемент. document.all.tags("form")[1].elements.tags("input").length См. также: метод getElementsByTagName (). urns (" ШШповедения”) Возвращаемое значение: массив объектов элементов Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- "Методом urns () обладают не все элементы, однако он включен во все наборы объект» Аргументом является строка, которая содержит URN (Uniform Resource Name— У нив» сальное имя ресурса) поведения (как правило, . htc в IE5), присвоенного одному или I скольким элементам набора. Параметр не включает расширение имени файла. Если для уч занного параметра не найдено URN, метод urns () возвращает массив нулевой дач» Данный метод связан со свойством behaviorUrns, которое содержит массив URN-no дений, присвоенных объекту элемента. Пример Чтобы иметь возможность переназначения поведения в будущем с помощью мел urns (), на страницу можно добавить кнопку и функцию (листинг 15.196), которая бу. проверять, присоединено ли поведение makeHot .htc к элементу myP. Эта функция выг дит следующим образом. function behaviorAttachedO { i f (document.all.urns("makeHot")) { alert ("There is at least one element set to \'makeHot\’ . } } См. также: свойство behaviorUrns. 356 Часть III. Объекты д
Обработчики событий onactivate onbeforedeactivate ondeactivate Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Обработчики событий onactivate и ondeactivate появились в IE5.5. При опреде- ленных обстоятельствах они похожи на обработчики событий onf ocus и onblur, соответ- ственно. Если элемент активизируется, то событие onactivate запускается перед onfocus; и наоборот, до деактивизации элемента события запускаются в следующей после- довательности: onbeforedeactivate, ondeactivate, onblur. Только элементы, кото- рые по своей природе могут активизироваться (например, ссылки или элементы управления форм) или для которых установлен атрибут tabindex, могут запустить эти события. В IE5.5+ поддерживаются исходные обработчики событий onfocus и onblur. Но по- скольку их поведение подобно onactivate и ondeactivate, не рекомендуется использо- вать старые и новые обработчики событий в одном приложении. Если сценарий создается только для IE5.5+, воспользуйтесь новой терминологией. Пример Вы можете изменить листинг 15.34 так, чтобы вместо обработчиков onfocus и onblur в нем использовались обработчики onactivate и ondeactivate. Используйте приложение The Evaluator для изучения обработчика события onbeforedeactivate. Для начала определите активный элемент туР. туР.tabindex = 1 Несколько раз нажмите клавишу <ТаЬ>, и вы активизируете элемент туР, на что укажет пунктирная рамка вокруг него. Чтобы не допустить деактивизацию элемента, назначьте обра- ботчику событий onbeforedeactivate безымянную функцию, как показано в следующем выражении. myP.onbeforedeactivate = new Function("event.returnValue=false") Теперь, когда вы нажмете клавишу <ТаЬ>, элемент туР будет оставаться активным до тех пор, пока вы не перезагрузите документ. Не стоит увлекаться этим приемом, если вы не пла- нируете заблокировать доступ к их содержимому. См. также: обработчики событий onblur, onfocus. onbeforecopy Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Обработчик события onbeforecopy запускается до того, как происходит копирование, инициированное пользователем в результате вызова опции меню Edit (включая и комбина- цию клавиш <Ctrl+C>) или контекстного меню. Если пользователь выполняет команду Сору из меню Edit или контекстного меню, событие onbeforecopy запускается до того, как ото- бражаются элементы меню. На практике событие иногда запускается повторно. Запуск собы- тия onbeforecopy не гарантирует, что пользователь завершит операцию копирования (например, он может закрыть контекстное меню до выбора соответствующего пункта). В отличие от событий вставки, обработчик события onbeforecopy не работает с эле- ментами ввода текста на формах. Глава 15. Основные объекты HTML-элементов 357
Пример Вы можете использовать обработчик onbef огесору для обработки данных перед их ко- пированием. В листинге 15.33 показано, как с помощью обработчика onbeforecopy эле- мента второго абзаца можно скопировать только выделенные текстовые фрагменты. Скопи- рованные данные вставляются в текстовую область, чтобы наглядно представить результат выполненного действия. Если бы в данном случае использовался обработчик опсору, то вы- деление создавалось бы после выбора команды копирования, а не до этого. <html> <heads <titlesonbeforecopy event handler</title> <script type=”text/javascript"s function selectwhole() { var obj = window.event.srcelement; var range = document.body.createtextrange(); range.movetoelementtext(obj); range.select (); event.returnvalue = false; } </scripts </heads <bodys chlsonbeforecopy event handler</hls <hr /s <psselect one or more characters in the following paragraph. Then execute a copy command via edit or context menu.</ps <p id="myp" onbeforecopy="selectwhole()"slorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aligua. Ut enim adminim veniam, guis nostrud exercitation ullamco laboris nisi ut aliguip ex ea commodo conseguat.</ps <forms <pspaste results here:<br /> <textarea name="output" cols="60" rows="5"s </textareas</ps </forms </bodys </htmls См. также: обработчики событий onbef orecut, oncopy. onbeforecut Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Обработчик события onbef orecut запускается до того, как лроисходит вырезка, ини- циированная пользователем в результате выбора опции меню Edit (включая и комбинацию клавиш <Ctrl+X>) или контекстного меню. Если пользователь выполняет команду Cut из ме- ню Edit или контекстного меню, событие onbef orecut запускается до того, как отобража- ется меню. На практике событие иногда запускается дважды. Запуск события onbef orecut не гарантирует, что пользователь завершит операцию вырезки (например, он может закрыть контекстное меню до выбора соответствующего пункта). Если добавить обработчик события onbeforecut в элемент HTML, в контекстном меню операция Cut будет запрещена. Однако присвоение вызова функции JavaScript этому обработчику делает активным данный пункт меню. 358 Часть III. Объекты документа
Пример Вы можете истуэльзовать обработчик событий onbeforecut для выполнения операций до того, как выделенные данные будут вырезаны в буфер обмена. Чтобы ознакомиться с этим обработчиком, в листинге 15.33 измените onbeforecopy на onbeforecut. В исходном случае операция вырезания и вставки текстового фрагмента в текстовую область не выполня- лась. После изменения листинга команда вырезания становится активной для выполнения. См. также: обработчики событий onbeforecopy, oncut. onbeforedeactivate См. обработчик событий onactivate. onbeforeedit focus Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Обработчик события onbeforeeditfocus (не поддерживаемый в MacIE5) запускается при редактировании элемента на странице в такой среде DHTML, как элемент управления ActiveX или при редактировании содержимого страницы в IE5.5+. В данном случае рассмат- ривается второй сценарий, поскольку он полностью реализуется на клиентской стороне сред- ствами JavaScript. Событие onbeforeeditfocus запускается до того, как элемент активи- зируется. (При этом на экране процесс редактирования может никак не отобразиться, если только это не запрограммировано в сценарии напрямую.) Событие запускается каждый раз, когда пользователь щелкает мышью на элементе, даже если этот элемент уже активен. Пример Приложение The Evaluator применяется и для изучения обработчика onbef oreeditf ocus в IE5.5+. Следующее выражение назначает этому обработчику события объекта myP безы- мянную функцию. Данная функция изменяет цвет текста на красный. myP.onbeforeeditfocus = new Function("myP.style.color=’red'”) Далее разрешите редактировать содержимое с помощью следующего оператора. myP.contentEditable = true По щелчку на элементе myP его текст будет окрашиваться в красный цвет непосредствен- но перед редактированием данных. Если вы хотите реализовать подобную функциональность в собственных приложениях, то обязательно включите в сценарии функцию блокировки ре- дактирования данных и возврата исходного цвета текста. См. также: свойства document .designMode, contentEditable, isContent- Editable. onbeforepaste Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Как и события onbeforecopy и onbeforecut, событие onbeforepaste происходит до отображения контекстного меню или меню Edit (пока текущий объект или его часть выде- лены). Это событие оказывается полезным, когда сценарий проводит копирование и вставку сложного объекта. Управляемый объект может соответствовать нескольким типам данных, однако сценарий обработает только один из них. Или же в буфер обмена помещаются допол- нительные данные (например, свойство id элемента). Использование обработчика события onbeforepaste для установки свойства event. returnvalue в значение false гаран- тирует, что вставляемым элементом можно будет управлять из контекстного меню или меню Edit (при условии, что элемент содержится в буфере обмена). Обработчик события onpaste позволяет переносить содержимое из буфера обмена в текущий выделенный элемент. Глава 15. Основные объекты HTML-элементов 359
Пример В листинге 15.45 (далее в этой главе) приведен пример использования обработчиков опЬеforepaste и onpaste. См. также: обработчики событий oncopy, oncut, onpaste. onblur Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Событие onblur происходит тогда, когда изменяется активный элемент документа. На- пример, элемент текстового поля генерирует событие onblur, когда пользователь переходит к следующему элементу формы с помощью клавиши <ТаЬ>. Событие onblur первого эле- мента происходит раньше события onfocus второго. Свойства события onblur расширяются, так как появляются новые поколения браузеров, поддерживающих языки сценариев. В ранних версиях деактивизация (blur) и активизация (focus) задавались лишь для элементов ввода текста (включая и элемент select). Поэтому их можно использовать для активизации подобных элементов управления в браузерах любых типов и версий. У объекта window обработчик события onblur появился, начиная с NN3 и IE4. В IE4 обларть его применения стала охватывать и другие элементы форм, в основном, в операционной системе Windows, поскольку в пользовательском интерфейсе именно этой- ОС пунктирным прямоугольником выделяются такие активные элементы, как кнопки и ссыл- ки (после чего их можно активизировать нажатием клавиши пробела). В IE5 обработчик со- бытия onblur задается почти для каждого элемента HTML. Тем не менее, для большинства из них активизация и деактивизация невозможны, если в дескрипторе элемента не задан ат- рибут tabindex. Например, если присвоить tabindex=" 1" в дескрипторе <р>, то пользо- ватель сможет сделать активным этот абзац (выделить пунктирным прямоугольником в Windows), только если щелкнет на нем или последовательно нажмет клавишу <ТаЬ>. Если вы собираетесь использовать обработчик события onblur для окна или элементов, предназначенных для ввода текста, помните, что при программировании функции- обработчика возможны неожиданные или нежелательные эффекты. Например, в IE активный объект window может стать неактивным (или сгенерировать событие onblur), когда поль- зователь сделает активным другой элемент страницы (или просто щелкнет в пустой области страницы). Подобным образом взаимодействие между onblur, onfocus и диалоговой функцией alert () может оказаться проблематичным для элементов текстовых полей. По- этому для запуска процедуры проверки правильности заполнения формы рекомендуется исполь- зовать обработчик события onchange. Если один и тот же элемент имеет два обработчика (onblur и onchange), то onchange происходит перед onblur. Подробно о применении обработчиков событий для проверки правильности данных рассказано в главе 43. В IE5.54- добавлен обработчик события ondeactivate, который запускается непосредст-! венно перед onblur. События onblur и ondeactivate блокируются, если функция обра- j ботчика события onbeforedeactivate устанавливает свойство event. returnvalue рав-' ным false. Пример Чаще всего разработчики страниц используют обработчик события onblur для отслежи-1 вания выполняемых пользователем действий. Например, можно остановить деактивизацию I из текстового поля до тех пор, пока в нем не будут введены корректные данные. Такой под-] ход используется редко, поскольку существуют более дружественные способы принуждения 1 пользователей вводить все необходимые данных (см. главу 43). В следующем листинге пока-J зано влияние атрибута tabindex элемента (в WinIE5) на выполнение обработчиков событий! onblur и onfocus. Обратите внимание, что события обрабатываются только для второго! абзаца, хотя заданы они для всех трех абзацев. J 380 Часть III. Объекты документ»!
<html> <head> <title>onblur and onblur Event Handlers</title> <script type="text/javascript"> function showBlur() { var id = event.srcElement.id; alert("Element \"" + id + "\" has blurred."); } function showFocus() { var id = event.srcElement.id; alert("Element \"" + id + "\" has received focus."); } </script> </head> <body> < hl id="Hl" tabindex="2">onblur and onblur Event Handlers</hl> <hr /> < p id="Pl" onblur="showBlur()" onfocus="showFocus()">Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aligua. Ut enim adminim veniam, guis nostrud exercitation ullamco laboris nisi ut aliguip ex ea commodo conseguat.</p> < p id="P2" tabindex="l" onblur="showBlur()" onfocus="showFocus()">Bis nostrud exercitation ullam mmodo conseguet. Duis aute involuptate velit esse cilium dolore eu fugiat nulla pariatur. At wer eos et accusam dignissum gui blandit est praesent luptatum delenit aigueexcepteur s int occae.</p> < p id="P3" onblur="showBlur()" onfocus="showFocus()">Unte af phen neigepheings atoot Prexs eis phat eit sakem eit very gast te Plok peish ba useing phen roxas. Eslo idaffaegad gef trenz beynoeguon guiel ba trenzSpraadshaag ent trenz dreek wire procassidt program.</p> </body> </html> См. также: методы blur(), focus (); обработчики событий ondeactivate, onbeforedeactivate, onfocus, onactivate. onclick Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Событие onclick происходит в том случае, когда пользователь нажимает и отпускает основную кнопку мыши в области одного элемента. Кроме того, такое событие может вы- зваться не только щелчком кнопки мыши (в системах Windows 95 и выше). С помощью кла- виатуры можно сделать активным элемент, а затем нажать клавишу пробела или <Enter> — это действие эквивалентно щелчку мыши. Если объект элемента поддерживает метод click (), то в IE событие onclick запускается до вызова метода (обратите внимание, что в браузере NN это не происходит). Свойства события onclick расширялись по мере появления новых поколений браузеров, поддерживающих языки написания сценариев. Важно знать последовательность событий, происходящих в результате однократного или двукратного нажатия пользователем кнопки Глава 15. Основные объекты HTML-элементов №1
мыши. Похожими событиями являются onmousedown, onmouseup и ondoubleclick Событие onmousedown запускается, когда пользователь нажимает кнопку мыши (замыкает, контакт). Затем (когда контакт разрывается) запускается событие onmouseup. Лишь nfa еле этого происходит событие onclick; оно подтверждает, что события onmousedown! и onmouseup уже произошли. События onmousedown и onmouseup с примерами их менения рассматриваются далее в этой главе. Взаимодействие с событием ondblclick выглядит достаточно просто: вначале (noewj первого нажатия) происходит событие onclick, за ним (после второго нажатия) следуетсоч бытие ondblclick. О событии ondblclick подробнее рассказано далее в этой главе. < При использовании объектов, которые вызывают в сценарии внутренние операции при щелчке на них (в частности, ссылки и области), обработчик события onclick способен полнить все действия самостоятельно (включая переход к другой странице, обычно реализуй мый атрибутом href элемента). Например, для совместимости со всеми браузерами, поддержи вающими языки написания сценариев, можно реализовать поддержку щелчка на изображении заключив его в дескриптор <а>. Обработчик события onclick размещается в дескрипт^ <а> (что невозможно в дескрипторах <img> ранних версий браузеров). Если настроить ом работник события onclick, не предприняв специальных мер, то вначале будет вызван oW ботчик, а затем будут выполнены внутренние действие элемента. Предположим, вам необ»4 димо блокировать выполнение внутреннего действия элемента. Для этого обработай события должен возвращать значение false. Добиться такого эффекта можно двумя cih*«g бами. Первый из них заключается в добавлении оператора return false к обработчику. 1 <а href="#" onclick="yourFunction() return false"ximg. . .></а> i Другой способ позволяет перенести оператор return false внутрь функции, рвкяи зующей обработку события (как показано ниже). м function yourFunction() { ' [операторы, выполняющие действия] return false,- .1 <а href="#" onclick="return yourFunction() "ximg. . .x/a> Используются оба способа. Можно применить и третий — вообще не использовать обрм ботчик события onclick, а присвоить атрибуту href значение javascript :псевдо-иК1 (см. объект ссылки в главе 19). i Модель событий в IE4+ позволяет предотвратить выполнение внутренних действий л щелчке на объекте: достаточно, чтобы функция обработчика события onclick устанавлтм ла свойство returnvalue объекта события в значение false. Для этого в функцию еле .-«J включить такой код. , event.returnvalue = false; ' Модель событий W3C DOM предлагает совсем другой подход к отмене действий предпринимаемых по умолчанию: в функции обработчика события, следует вызвать мет J eventObj.cancelDefault(). Ч Распространенной ошибкой начинающих программистов является использование кжв ки отправки данных формы (Submit) для выполнения сценария, а не своего первонаш ла ного действия. Обычно элементу input типа submit присваивается обработчик собитш onclick для выполнения некоторых локальных операций. Кнопка отправки данных фо, UH (Submit) имеет встроенное внутреннее поведение, подобно ссылкам и областям. Если это « ведение блокируется так, как это было описано выше, то рекомендуется использовать ьи мент input типа button. fl 362 Часть III. Объекты догуммя
Если вы испытываете трудности с реализацией обработчика события onclick (например при определении используемой кнопки мыши), может оказаться, что программированию сце- нария мешает поведение операционной системы или браузера по умолчанию. Как правило, добиться желаемого результата позволяет обработчик события onmousedown. (Событие onmouseup может не генерироваться при нажатии второй кнопки мыши.) При взаимодейст- вии с пользователем предпочтительно использовать обработчик события onclick, посколь- ку поведение браузера в этом случае похоже на то, к чему он привык в повседневной практи- ке. В экстренных случаях можно прибегнуть к событию onmousedown. Пример Обработчик события onclick проше всего использовать в создаваемых сценариях. В листинге 15.35 приведен пример обработки событий щелчка и двойного щелчка. При щелчке и/или двойном щелчке на ссылке в строке состояния отображаются сообщения, свя- занные с событием. Обратите внимание на то, что при двойном щелчке сначала возникает со- бытие одинарного щелчка, а сообщение двойного щелчка в строке состояния сразу же заме- няет сообщение обычного щелчка. <html> <head> <title>onclick and ondblclick Event Handlers</title> «script type="text/javascript"> var timeout; function clearOutput() { document.getElementBy!d("clickType").innerHTML = ""; } function showClick() { document.getElementByld("clickType").innerHTML = "single"; clearTimeout(timeout); timeout = setTimeout("clearOutput()", 3000); } function showDblClickO { document.getElementByld("clickType").innerHTML = "double"; clearTimeout(timeout); timeout = setTimeout("clearOutput()", 3000); } </script> </head> <body> <hl>onclick and ondblclick Event Handlers</hl> <hr /> <a href="#" onclick="showClick() .-return false" ondblclick="return showDblClickO">A sample link.</a> (Click type: «span id="clickType">«/span>) «/body> </html> См. также: метод click (); обработчики событий oncontextmenu, ondblclick, onmousedown, onmouseup. Глава 15. Основные объекты HTML-элементов 363
oncontextmenu Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Событие oncontextmenu происходит, когда пользователь щелкает на объекте второй (как правило, правой) кнопкой мыши. Этот щелчок вызывает лишь два события: onmousedown и oncontextmenu. Для блокировки отображения меню при щелчке правой кнопкой мыши необходимо ис- пользовать один из трех методов, доступных в IE5+ (как отмечалось при описании обработ- чика события onclick: два варианта с возвращаемым значением false и присвоение зна- чения false свойству event. returnvalue). Часто разработчики пытаются заблокировать появление контекстного меню с целью предотвращения загрузки изображений или просмотра исходного кода фреймов. Однако помните: если пользователь отключит опцию Active Scripting в IE5+, то обработчик события не сможет помешать появлению контекстного меню. Другая возможность использования события заключается в отображении специального контекстного меню, созданного средствами DHTML. В этом случае необходимо запретить вызов исходного контекстного меню, чтобы два меню не могли появиться одновременно. Пример Пример использования обработчика oncontextmenu приведен ранее в этой главе в лис- тинге 15.30 (при рассмотрении способов управления контекстным меню). См. также: методы releasecapture (), setcapture (). oncontrolselect Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Событие oncontrolselect происходит до того, как пользователь выделяет область, называемую разработчиками Microsoft управляющим выделением. Из документации Microsoft не совсем понятно, что же такое управляющее выделение, но, кажется, оно непосредственно связано с режимом пользовательского редактирования. См. также: обработчики событий onresizeend, onresizestart. oncopy oncut Совместимость: WinIE5+, MacIE4+, NN-, Moz-, Safari- События oncopy и oncut происходят после того, как пользователь или сценарий ини- циируют действие копирования или вырезки текущего объекта. Каждому событию предшест- вует соответствующее событие before, которое происходит перед выбором опции меню Edit или появлением контекстного меню (а также перед операциями копирования, вырезки, инициированных комбинациями клавиш). Данные обработчики позволяют добавить возможность редактирования к тем элементам, которые обычно невозможно скопировать или вырезать. В таких ситуациях следует сделать доступными опции Сору или Cut в контекстном меню или меню Edit, установив свойство event. returnvalue для обработчика onbefогесору или onbeforecut в значение false. Затем обработчики событий oncopy или oncut должны поместить содержимое объекта в буфер обмена, применив метод setData () для объекта clipboardData. В этом случае в функции обработчика необходимо установить свойство event. returnvalue рав- ным false — это предотвратит обработку содержимого буфера обмена методами копирова- ния или вырезки по умолчанию. 364 Часть III. Объекты документа .
Поскольку вы сами распоряжаетесь данными, помещаемыми в буфер обмена, то можете выполнять не только их непосредственное копирование. Например, вы вправе сохранить зна- чение свойства src объекта изображения, чтобы пользователь имел возможность вставить его в произвольном месте страницы. В случае использования обработчика события oncut сценарий отвечает также и за удале- ние элемента или выделенного содержимого со страницы. Для удаления всего содержимого эле- мента достаточно просто установить его свойство innerHTML или innerText равным пустой строке. Для выделенной области следует использовать метод selection.createRange (), генерирующий объект TextRange. Содержимое последнего можно затем обработать мето- дами, соответствующими данному объекту. Пример В листинге 15.36 продемонстрирован пример совместного использования обработчиков onbeforecut и oncut (а также обработчиков onbeforepaste и onpaste). Как видите, функция handleCut () не только заносит выделенное слово в объект clipboarddataData, но и удаляет исходный элемент ячейки таблицы. Если же заменить обработчик onbeforecut и oncut на onbeforecopy и опсору (и отменить удаление исходного элемента в таблице), то будет выполняться операция копирования-вставки, а не вырезания-вставки. Этот вариант рассматривается в листинге 15.45 далее в этой главе. ИНМмг 15.36. Вырезание и «стами данных <httnl> <head> <title>onbeforecut and oncut Event Handlers</title> «style type="text/css"> td {text-align:center} th {text-decoration:underline} .blanks {text-decorat ion:under1ine} «/style> «script type="text/javascript"> function selectwhole() { var obj = window.event.srcElement; var range = document.body.createTextRange(); range.moveloElementText(obj); range.select(); event. retumValue = false; } function handleCut() { var rng = document.selection.createRangeO; clipboardData.setData("Text",mg.text); var elem = event.srcElement; elem.innerText = event.returnvalue = false; } function handlePaste() { var elem = window.event.srcElement; if (elem.className == "blanks") { elem.innerHTML = clipboardData.getData("Text"); } event. retumValue = false; } Глава 15. Основные объекты HTML-элементов 365
function handleBeforepaste() { var elem = window, event. srcElement; if (elem.className == "blanks") { event.returnvalue = false; } } </script> </head> <body> <hl>onbeforecut and oncut Event Handlers</hl> <hr / > <p>Your goal is to cut and paste one noun and one adjective from the following table into the blanks of the sentence. Select a word from the table and use the Edit or context menu to cut it from the table. Select one or more spaces of the blanks in the sentence and choose Paste to replace the blank with the clipboard contents.</p> <t£ble cellpadding="5" onbeforecut="selectwhole()" oncut="handleCut()"> <tr> <th>Nouns</th> <th>Adjectives</th> </tr> <td>truck</td> <td>round</td> </tr> < td>dol1</td> <td>red</td> </tr> < td>ba11</td> <td>pretty</td> </tr> </table> <p id="myP" onbeforepaste="handleBeforepaste()" onpaste="handlePaste()"> Pat said, "Oh my, the <span id="blankl" class="blanks">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp,-</span> is so <span id="blank2" class= "blanks">&nbsp; &nbsp;&nbsp;&nbsp;fcribsp;</span>!"</p> <button onclick="location.reload()">Reset</button> </body> </html> См. также: обработчики событий onbeforecopy, onbeforecut, onbeforepaste и onpaste. ondblclick Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Событие ondblclick происходит после второго быстрого щелчка мышью. Время между нажатиями зависит от настроек в папке Панель управления (Control Panel) компьютера конечного пользователя. Событие one lick происходит после первого из двух щелчков. Не стоит разрабатывать страницу, на которой элемент выполняет одно действие по одинар- ному щелчку и другое — по двойному. Учитывая, как в современных браузерах реализуется последовательность событий, нецелесообразно использовать это событие (событие onclick все равно происходит даже при двойном щелчке). Часто по щелчку кнопки мыши выдается 366 Часть III. Объекты документа
некоторая справка. Такая схема реализована в большинстве менеджеров файлов, использую- щих графические средства: по щелчку на значке файл выделяется, а двойной щелчок его вы- полняет. В любом случае, одно действие не мешает другому и не запутывает пользователя. Пример Пример использования обработчика ondblclick приведен в листинге 15.35 ранее в этой главе. См. также: обработчики событий onclick, onmousedown, onmouseup. ondrag, ondragend, ondragstart Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Событие ondrag происходит после события ondragstart и затем продолжает постоянно запускаться, пока пользователь “перетаскивает” по экрану выделенную область или объект. В отличие от onmousetnove, которое происходит лишь при движении указателя мыши, собы- тие ondrag продолжает происходить и тогда, когда указатель остается неподвижным. В IE5+ пользователи имеют возможность “перетащить” объект в другие окна браузера или другие при- ложения. Событие продолжает запускаться, пока указатель находится в пределах окна браузера. Поскольку событие происходит независимо от того, что находится под объектом, им можно воспользоваться в играх или тренажерах, когда пользователь выполняет операцию “перетаскивания” за ограниченное время (например при сравнении пар объектов). Если в следующих версиях браузеров появится возможность загружать указатели, с помощью со- бытия ondrag можно будет эмулировать анимированный указатель. Четкое понимание последовательности событий, связанных с “перетаскиванием” объекта, необходимо в случаях, когда в сценарии реализуется управление внутренними действиями (в основных операциях “перетаскивания” этого обычно не требуется). Рассмотрим обычную операцию “перетаскивания” (рис. 15.2). Представим, что названия ячеек таблицы совпадают с содержимым ячеек: “truck” в ячейке А1; .“round” в Bl; “doll” в А2 и т.д. Во время операции “перетаскивания” многие объекты способ- ны генерировать события, связанные с ней. Последовательность событий, а также цели их на- значения представлены в табл. 15.10. На практике некоторые события, приведенные в табл. 15.10, могут и не происходить. Это связано с тем, сколько обработчиков событий используется в сценарии. Еще одним важным фактором является скорость, с которой пользователь выполняет операцию “перетаскивания” (а также производительность процессора). Чаще всего опускаются такие события, как ondragenter и ondragleave, а также некоторые из событий ondragover, если пользо- ватель “проходит” по объекту быстрее, чем может произойти событие ondragover. Несмотря на указанную неопределенность, существует несколько событий, которые про- исходят всегда. События ondragstart, ondrop (для целевого объекта) и ondragend, а также промежуточные события ondrag происходят всегда при “перетаскивании” объекта по экрану. Все события, кроме ondrop, запускаются для исходного элемента, a ondrop — для целевого элемента. Пример Пример использования обработчиков событий операций “перетаскивания” приведен в листинге 15.37. Эта страница основана на примере, представленном в листинге 15.36, но в ней применены несколько, другие программные конструкции. В данном случае пользовате- лю предлагается выбрать отдельные слова в столбцах Nouns и Adjectives, а затем перета- щить их в пустые места предложений. Зачастую на операцию перетаскивания пользователю отводится всего несколько секунд. Глава 15. Основные объекты HTML-элементов 367
Рис. 15.2. Стандартная операция “перетаскивания ” Событие Цель Описание ondragstart ячейка А1 Первое событие, запускаемое при операции “перетаскивания’’ ondrag ячейка А1 Продолжает запускаться во время всей операции. В промежутках могут происходить и другие события ondragenter ячейка А1 Несмотря на то, что указатель еще не покинул ячейку А1, событие ondragenter происходит при первом движении в пределах исходного элемента ondragover ячейка А1 Запускается во время операции для элементов, над которыми перемещается указатель. Если пользователь просто удерживает кнопку мыши и не перемещает указатель, то события ondrag и ondragover постоянно запускаются одно за другим (повторение) ячейка А1 События ondrag и ondragover запускаются попеременно, пока указатель находится в ячейке А1 ondragenter table Элемент table, заданный границей и/или областью между ячейками, получает событие ondragenter, когда в эту область попадает указатель ondragleave ячейка А1 Событие ondragleave запускается после того, как для другого элемента происходит событие ondragenter ondrag ячейка А1 Событие продолжает происходить 368 Часть III. Объекты документа
Окончание табл. 10.15 Событие Цель Описание ondragover table Исходным элементом этого события становится элемент table, поскольку указатель перемещается в его область. Если указатель остается в ней неподвижным, ТО события ondrag (ячейка А1) и ondragover (table) продолжают генерироваться попеременно ondragenter ячейка B1 В результате “перетаскивания" указатель смещается с границы таблицы в область ячейки В1 ondragleave table ondrag ячейка A1 Событие ondrag продолжает происходить для объекта ячейки А1 ondragover ячейка B1 Указатель находится в ячейке В1, поэтому событие ondragover происходит для этого объекта. Оно запускается несколько раз (в зависимости от производительности компьютера и действий пользователя) попеременно с событием ondrag ondragenter body “Перетаскивание” выходит за пределы элемента table и происходит теперь внутри элемента body ondragleave table Событие происходит после того, как указатель покидает элемент table ondrag ячейка A1 Событие продолжает происходить ondragover body Указатель находится внутри элемента body. Событие запускается несколько раз (в зависимости от производительности компьютера и действий пользователя) попеременно с событием ondrag , ondragenter blankl Указатель достигает элемента span, идентификатором которого является blankl и где находятся области вставки, выделенные подчеркиванием ondragleave body Указатель покидает элемент body ondrag ячейка A1 Продолжает запускаться ondragover blankl Указатель находится на элементе blankl. Событие запускается несколько раз (в зависимости от производительности компьютера и действий пользователя) попеременно с событием ondrag ondrop blankl Элемент span информируется о текущем “перетаскивании” ondragend ячейка A1 Исходный элемент получает событие, указывающее на завершение процесса перетаскивания. Это событие происходит даже в том случае, если процесс завершается не совсем успешно по причине того, что элемент не дошел до объекта назначения Обработчики событий ondragstart и ondrag помещены в теле страницы, поскольку соответствующие события всплывают от перетаскиваемого пользователем элемента. Дейст- вия, выполняемые этими обработчиками, выполняются только в том случае, когда “перетаскивается” элемент таблицы. Этот метод обработки событий весьма эффективен, по- скольку исключает повторный вызов обработчиков событий для одних и тех же ячеек таблицы. Обработчик события ondragstart вызывает функцию setupDrag (). Эта функция от- меняет обработку события (за исключением случаев, когда перетаскиваемый элемент пред- ставлен объектом td таблицы). Чтобы сделать приложение более эффективным при перетас- кивании слов в выбранные части приложения, в пустое место вставляется не только слово, но и дополнительные сведения. Таким образом, другой обработчик события может определить, что в первое пустое место предложения перетаскивается существительное, а во второе — Глава 15. Основные объекты HTML-элементов 369
прилагательное. Чтобы выполнить подобную задачу, мы отнесли слова из первого и второго столбцов к разным классам. Функция setupDrag () генерирует массив, каждый элемент ко- торого состоит из свойства innerText исходных элементов событий, а также имени его класса. Но объект event.dataTransfer не поддерживает массивы, поэтому с помощью метода Array. join () массив преобразуется в строку, в которой отдельные записи разделе- ны точкой с запятой. Эта строка и сохраняется в объекте event .dataTransfer. Предна- значение данного объекта простое — отображать на экране в процессе перетаскивания кур- сор правильного вида. Поскольку функция setupDrag() выполняется в этом сценарии первая, то таймер в ней устанавливается в значение текущего времени (это время считается началом операции перетаскивания). Обработчик событий ondrag (в теле страницы) перехватывает все события перетаскива- ния, происходящие с элементами таблицы. Как только возникает событие, вызывается функ- ция timerlt(), которая сравнивает текущее время с начальным временем (сохраненное в переменной timer). Если разница во времени превышает 2 секунды, то на экране появляется извещающее сообщение. Для его закрытия, пользователю необходимо отпустить кнопку мыши. Чтобы использовать в качестве целевых элементов пустые объекты span, их обработчики событий ondragend, ondragover и ondrop должны устанавливать свойство event. return- value в значение false. Кроме того, свойство event.dataTransfer.droppEffeet должно указывать тип выполняемого действия (в нашем случае сору). Указанные обработ- чики событий помещаются в элемент р, содержащий пустые элементы span (опять-таки для простоты). Обратите внимание, что функция cancelDef aults () выполняется только то- гда, когда целевой элемент представлен пустым объектом span с идентификатором, начи- нающимся со слова blank. При отпускании пользователем кнопки мыши вызывается обработчик события ondrop, который вызывает функцию handleDrop (). Эта функция получает данные объекта event .dataTransfer и создает на их основе исходный массив (с помощью метода String, split ()). В результате простого тестирования в сценарии можно легко опреде- лить, что слово соответствующего типа вставляется в необходимую часть предложения. «html> <head> <title>Dragging Event Handlers</title> «style type="text/css"> td {text-align:center} th {text-decoration:underline} .blanks {text-decorat ion:under1ine} </style> «script type="text/javascript"> var timer; function setupDrag() { if (event.srcElement.tagName != "TD") { // запрет перетаскивания других элементов event. retumValue = false; } else { // настройка массива данных, перетаскиваемых в цель var passedData = [event.srcElement.innerText, event.srcElement.className]; // сохранение массива в строке event.dataTransfer.setData("Text", passedData.joint":")); 370 Часть III. Объекты документа
event.dataTransfer.effectAllowed = "copy"; timer = new DateO; } } function timelt() { if (event.srcElement.tagName == "TD" && timer) { if ((new DateO) - timer > 2000) { alert("Sorry, time is up. Try again."); timer = 0; } } } function handleDropO { var elem = event.srcElement; var passedData = event.dataTransfer.getData("Text"); var errMsg = ""; if (passedData) { // извлечение массива из строки passedData = passedData.split(":"); if (elem.id == "blankl") { if (passedData[1] == "noun") { event.dataTransfer.dropEffeet = "copy"; event.srcElement.innerText = passedData[0]; } else { errMsg = "You can't put an adjective into the noun placeholder. ";’ } else if (elem.id == "blank2") { if (passedData[1] == "adjective") { event.dataTransfer.dropEffeet = "copy"; event.srcElement.innerText = passedData[0]; } else { errMsg = "You can't put an noun into the adjective placeholder."; } } if (errMsg) { alert(errMsg); } } } function cancelDefault () { if (event.srcElement.id.indexOf("blank") == 0) { event.dataTransfer.dropEf feet = "copy"; event.returnvalue = false; } } </script> </head> cbody ondragstart="setupDrag()" ondrag="timelt()"> <hl>Dragging Event Handlers</hl> <hr / > <p>Your goal is to drag one noun and one adjective from the following table into the blanks of the sentence. Select a word from the table and drag it to the desired blank. Глава 15. Основные объекты HTML-элементов 371
When you release the mouse, the word will appear in the blank.You have two seconds to complete each blank.</p> <table cellpadding="5"> <tr> <th>Nouns</th> <th>Adjectives</th> </tr> <tr> <td class="noun">truck</td> <td class="adj ective">round</td> </tr> <tr> <td class="noun">doll</td> <td class="adjective">red</td> </tr> <tr> <td class="noun">ball</td> <td class="adjective">pretty</td> </tr> </table> <p id="myP" ondragenter="cancelDefault()" ondragover="cancelDefault()" ondrop="handleDrop()"> Pat said, "Oh my, the «span id="blankl" class="blanks"> &nbsp;&nbsp;&nbsp,-&nbsp;&nbsp;</span> is so <span id="blanks" class="blanks">&nbsp;&nbsp;&nbsp,-&nbsp;&nbsp; </span>!"</p> <button onclick="location.reload()">Reset</button> </body> </html> См. также: объект event. dataTransfer; обработчики событий ondragenter, ondragleave,ondragover, ondrop. ondragenter ondragleave ondragover Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Эти события происходят во время операции “перетаскивания”. Когда указатель помеща- ется в прямоугольную область, ограничивающую элемент на странице, для последнего про- исходит событие ondragenter. После этого для элемента, который только что покинул ука- затель мыши, происходит событие ondragleave. События всегда запускаются в таком порядке (обратном по отношению к физическому действию). В зависимости от производи- тельности компьютера и скорости, с которой пользователь “перетаскивает” объект, одно из событий может не произойти, особенно если физическая скорость действий пользователя превышает возможности компьютера запускать события вовремя. Событие ondragover происходит постоянно, пока указатель находится поверх элемен- та. При “перетаскивании” объекта из одной точки страницы в другую событие ondragover происходит для всех объектов, по которым “проходит” указатель. Если какие-либо другие со- бытия, связанные с “перетаскиванием”, не запускаются (т.е. кнопка мыши остается нажатой, но указатель не движется), то события ondrag и ondragover происходят по очереди. Обработчик события ondragover объекта, на котором завершается процесс “перетаскивания”, должен устанавливать свойство event. returnvalue в значение false (см. описание обработчика события ondrag ранее в этой главе). 372 Часть III. Объекты документа
Пример Пример использования обработчиков ondragenter и ondragleave приведен в лис- тинге 15.38. На этой простой странице отображается (в строке состояния) время возникнове- ния события перетаскивания. Событие отпускания элемента не происходит, поэтому указа- тель не изменяет своего вида. При стаскивании указателя с верхнего заголовка обработчик ondragleave удаляет сообщение в строке состояния. <html> <head> <title>ondragenter and ondragleave Event Handlers</title> «script type="text/javascript"> function showEnterO { status = "Entered at: " + new Date(); ‘event.returnvalue = false; function clearMsgO { status = " " ; event.returnvalue = false; } </script> </head> <body> <hl ondragenter="showEnter()" ondragleave="clearMsg()"> ondragenter and ondragleave Event Handlers</hl> <hr /> <p>Select any character(s) from this paragraph, and slowly drag it around the page. When the dragging action enters the large header above, the status bar displays when the onDragEnter event handler fires. When you leave the header, the message is cleared via the onDragLeave event handler.«/p> </body> </html> См. также: обработчики событий ondrag, ondragend, ondragover, ondragstart, ondrop. ondragstart Cm. ondrag ondrop Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Событйе ondrop (не поддерживаемое в MacIE5) происходит тогда, когда пользователь отпускает кнопку мыши, завершая, тем самым, операцию “перетаскивания”. Компания Micro- soft рекомендует применять к элементу назначения обработчики событий ondragenter, ondragover и ondrop. В каждом из них необходимо установить свойство data- Transfer .dropEffeet равным тому эффекту, который изображается во время операции “перетаскивания” (о чем свидетельствует различный вид указателя). Эти настройки должны соответствовать свойству dataTransfer. ef fectAllowed, устанавливаемому в обработчике события ondragstart. В каждом из трех обработчиков событий свойство event.returnvalue должно быть установлено в значение false (см. описание обработ- чика события ondrag ранее в этой главе). Глава 15. Основные объекты HTML-элементов 373
Пример В листинге 15.37 приведен пример использования обработчика ondrop. См. также: объект event.dataTransfer; обработчики событий ondrag, ondragend, ondragenter, ondragleave, ondragover, dndragstart. onf11terchange Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Событие onf ilterchange происходит тогда, когда фильтр переводит элемент в новое со- стояние, или преобразование объекта завершается (преобразование иногда изменяется со време- нем). Событие может происходить только для объектов, к которым применимы фильтры и эффек- ты преобразования в IE (в первую очередь, блоковые элементы и элементы управления форм). Событие onf ilterchange часто применяется для запуска следующего преобразования в последовательности из нескольких подобных операций. В результате может получиться бесконечный цикл, когда объект, получающий событие, переключается между двумя состоя- ниями преобразования. Если вам не требуется такой цикл, разместите два различных типа со- держимого в отдельные позиционируемые элементы и используйте обработчик события onf ilterchange для “перехода” от одного элемента к другому. Пример Ознакомиться с обработчиком onf ilterchange вы можете в листинге 15.39. В этом при- мере данный обработчик события позволяет выполнить второй эффект преобразования сразу после завершения первого. Несмотря на то, что обработчик события onf ilterchange поддерживается в IE4 и IE5 практически одними и теми же объектами, свойства объекта фильт- ра трактуются в браузерах весьма неоднозначно. В коде, приведенном в листинге 15.39, активно используются элементы управления ActiveX, представленные в IE5.5 (описываются в главе 30). <html> <head> <title>onfilterchange Event Handler</title> <script type="text/javascript"> function init() { imagel.filters[0].apply(); image2.filters[0].apply(); start(); } function start() { imagel.style.visibility = "hidden"; imagel.filters[0].play(); } function finish() { if (imagel.filters[0].status == 0) { image2.style.visibility = "visible"; image2 . filters [0] .playO ; } } </script> </head> 374 Часть III. Объекты документа
<body onload="init()"> <hl>onfilterchange Event Handler</hl> <hr /> <p>The completion of the first transition ("circle-in") triggers the second ("circle-out"). cbutton onclick= "location.reload()">Play It Again</buttonx/p> <div id="imagel" style="visibility:visible; position:absolute; top:150px; left:150px,- filter:progID:DXImageTransform.Microsoft. Iris(irisstyle='CIRCLE1, motion='in')" onfilterchange= “finish()"> <img alt="image" src="deskl.gif" height="90" width="120" /> </div> <div id="images" style="visibility:hidden,- position:absolute; top:150px; left:150px; filter:progID:DXImageTransform.Microsoft. Iris(irisstyle='CIRCLE’, motion=1 out1)> <img"alt="image" src="desk3.gif" height="90" width="120" /> </div> </body> </html> См. также: объект filter. onfocus Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Событие onfocus происходит тогда, когда элемент активизируется; как правило, в этот момент деактивизируется другой элемент. (Элемент, который становится неактивным, полу- чает событие onblur до того, как текущий элемент получает событие onfocus.) Например, элемент ввода текста запускает событие onfocus, когда пользователь переходит к этому эле- менту с помощью клавиши <ТаЬ>. К такому же эффекту приводит щелчок мышью на элементе. Свойства события onfocus были расширены в связи с появлением новых поколений браузеров, поддерживающих языки написания сценариев. В ранних версиях деактивизация и активизация были ограничены лишь элементами ввода текста (включая и элемент select). У объекта window обработчик события onfocus появился, начиная с NN3 и IE4. В IE4 об- ласть его применения стала охватывать и другие элементы форм, в основном, в операци- онной системе Windows, поскольку пользовательский интерфейс именно этой ОС позволя- ет выделять пунктирным прямоугольником такие элементы, как кнопки и ссылки (после чего их можно активизировать нажатием клавиши пробела). В IE5 обработчик события onfocus имеют почти все элементы HTML. Тем не менее, для большинства из них акти- визация и деактивизация не выполняется, если в дескрипторе элемента не установлен ат- рибут tabindex. Например, если присвоить значение tabindex="l" в дескрипторе <р>, то пользователь сможет активизировать этот абзац (выделение пунктирным прямо- угольником в Windows), щелкнув мышью или нажав клавишу <ТаЬ>. В IE5.5 добавлен обработчик события onactivate, который запускается непосредственно перед onfocus. Можно использовать любой из них, но нет смысла включать в сценарий оба обработчика, если только вы не преследуете цель заблокировать активизацию определенных элементов. Для этого в IE5.5 в обработчик события onactivate необходимо включить опера- тор event.retumValue=false. В ранних версиях браузеров достаточно создать следую- щий обработчик события для элементов управления форм: onfocus="this.blur() ". Одна- ко этого недостаточно, чтобы не допустить изменения управляющих настроек пользователем. * К сожалению, альтернативы этому нет. Глава 15. Основные объекты HTML-элементов 375
Пример Пример использования обработчика onfocus приведен в листинге 15.34 ранее в этой главе (при рассмотрении обработчика onblur). См. также: обработчики событий onactivate, onblur, ondeactivate. onhelp Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Обработчик события onhe Ip в Windows запускается для активного элемента, когда поль- зователь нажимает на клавиатуре функциональную клавишу. В Мас1Е5 это событие происхо- дит только для окна (другими словами, обработчик события должен быть указан в дескрипто- ре <BODY>) при нажатии клавиши <Не1р> на клавиатуре компьютера Macintosh. Опции меню Help в браузере не активизируют этого события. Чтобы не допустить появления на экране окна справочной системы браузера, обработчик события должен возвратить значение false (в IE4+) или установить свойство event. returnvalue равным false (ti IE5+). Поскольку обработчик события в версии для Windows можно включить в любой отдельный элемент страницы, он часто используется для создания контекстной справочной системы. Если же ак- тивно поле адреса или само окно браузера, то сценарий не может перехватить событие — в таких случаях появляется стандартное окно справочной системы браузера. Пример В листинге 15.40 продемонстрирован пример контекстно-зависимой справочной системы. В этом приложении справочные сведения приводятся для данных, вводимых в текстовые по- ля. При установке курсора в поле над ним появляется надпись-подсказка, которая указывает на то, что справочные сведения отображаются при нажатии клавиши <F1>. <html> <head> <title>onhelp Event Handler</title> <script type="text/javascript"> function showNaraeHelp() { alert("Enter your first and last names."); event.cancelBubble = true; return false; } function showYOBHelp() { alert("Enter the four-digit year of your birth. For example: 1972"); event.cancelBubble = true; return false; } function showGenericHelp() { alert("All fields are required."); event.cancelBubble = true; return false; } function showLegendO { document.getElementByld("legend").style.visibility = "visible"; } function hideLegendO { 376 Часть III. Объекты документа
document.getElementByld("legend").style.visibility = "hidden"; } function init() { var msg = ""; if (navigator.userAgent.indexOf("Mac") != -1) { msg = "Press \'help\’ key for help."; } else if (navigator.userAgent.indexOf("Win") != -1) { msg = "Press Fl for help."; } document.getElementByld("legend").style.visibility = "hidden"; document.getElementByld("legend").innerHTML = msg; } </script> </head> <body onload="init()" onhelp="return showGenericHelp()"> <hl>onhelp Event Handler</hl> <hr /> <p id="legend" style="visibility:hidden; font-size:10px"> &nbsp;</p> <form> Name: <input type="text" name="name" size="30" onfocus="showLegend()" onblur="hideLegend()" onhelp="return showNameHelp()" /><br /> Year of Birth: «input type="text" name="YOB" size="30" onfocus="showLegend()" onblur="hideLegend()" onhelp="return showYOBHelp()" /> </form> </body> </html> См. также: методы window. showHelp (), window. showModalDialog (). onkeydown onkeypress onkeyup Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ При нажатии клавиши на клавиатуре происходит последовательность трех событий. При нажатии клавиши происходит событие onkeydown; за ним следует onkeypress, а при от- пускании клавиши — событие onkeyup. Если клавиша остается нажатой и символ вводится повторно автоматически, события onkeydown и onkeypress происходят при вводе каждо- го последующего символа. Последовательность событий имеет важное значение при обработке некоторых событий клавиатуры. Рассмотрим сценарий, в котором автоматически и последовательно активизиру- ются текстовые поля в процессе введения пользователем заданного количества символов (например, числа, месяца и года). К моменту, когда происходит событие onkeyup, символ уже добавляется к содержимому поля — это позволяет гарантировано узнать длину текста в нем. <html> <head> «script type="text/javascript"> function jumpNext(fromFld, toFld) { if (fromFld.value.length == 2) { document.forms[0] .elements[toFld] .focus 0; Глава 15. Основные объекты HTML-элементов 377
document.forms[0].elements[toFld].select(); </script> </head> <body> <form> Month: <input name="month" type="text" size="3" value="" onkeyup="jumpNext(this, day)" maxlength="2" /> Day: cinput name ="day" type="text" size="3" value="" onkeyup ="jumpNext(this, year)" maxlength="2" /> Year: cinput name="year" type="text" size="3" value="" onkeyup ="jumpNext(this, month)" maxlength="2" /> c/form> </body> </html> Три этих события происходят не для всех клавиш на обычной клавиатуре в браузерах, поддерживающих события клавиатуры. Клавиши, для которых такие события происходят во всех браузерах, — это буквенно-цифровые клавиши, имеющие ASCII-коды (пробел и <Enter>), к ним не относятся функциональные клавиши, клавиши со стрелками и другие средства нави- гации. Клавиши-модификаторы— <Shift>, <Ctrl>, <Alt>— генерируют свои собственные события (в зависимости от типа и версии браузера). Состояние этих клавиш-модификаторов можно проверить в функциях, запускаемых для других событий клавиш. Обработчик onkeydown поддерживается Mozilla-совместимыми браузерами (поколения стврше Mozilla 1.4 (NN7.1)). Программирование обработки событий клавиатуры, как правило, означает проверку на- жатия клавиши. Ситуация усложняется, если сценарий должен выполняться в различных ти- пах браузеров. В некоторых случаях написание сценариев только для браузера Internet Explorer может оказаться непростой задачей, поскольку небуквенно-цифровые клавиши гене- рир^тот только события onkeydown и onkeyup. Чтобы полностью обрабатывать события клавиатуры, необходимо различать коды клавиш и коды символов. Каждая клавиша на клавиатуре имеет свой код. Этот код постоянный, он не зависит от одновременно нажатых клавиш. Буквенно-цифровые клавиши (буквы, цифры, пробел и т.д.) генерируют также и коды символов. Эти коды представляют символы, связан-' ные с клавишами. Их значение изменяется при нажатии клавиши-модификатора. Например, если отдельно нажать клавишу <А>, то она сгенерирует символ нижнего регистра “а” (код 97); если при этом держать нажатой клавишу <Shift>, она сгенерирует символ “А” (код 65). Код самой клавиши (65 для клавиатур западных языков (Western)) остается постоянным. Информация о кодах клавиш сохраняется в свойствах объекта event. Объект event в IE имеет только одно такое свойство — keyCode. Оно содержит код клавиши для событий onkeydown и onkeyup, а также код символа для события onkeypress. Объект event в NN6 имеет два отдельных свойства: charCode (код символа) и keycode (код клавиши) (примеры использования этих свойств объекта event см. в главе 25). Если требуется обработать не буквенно-цифровые клавиши (например, функциональные клавиши, клавиши навигации и т.д.), следует использовать обработчик события onkeydown или onkeyup. Для обработки тех символов, которые отображаются в текстовых полях, дос- таточно применить обработчик события onkeypress. Поэкспериментировать с событиями и кодами можно в листинге 15.41, а также примерах из главы 25. 378 Часть III. Объекты документа
Распространенные задачи по обработке событий клавиатуры IE4+ (но не NN) позволяет изменить символ, вводимый пользователем в текстовом поле. Обработчик события onkeypress модифицирует свойство event. keyCode, причем собы- тие продолжается дальше обычным образом (другими словами, обработчик не возвращает , false и не устанавливает свойство event.returnvalue равным false). Следующая функция IE (вызываемая обработчиком события onkeypress) проверяет, чтобы текст, вво- димый в поле, принадлежал верхнему регистру, даже если пользователь пытается ввести сим- вол нижнего регистра. function assureUpper() { if (event.charCode >= 97 && event.charCode <= 122) { event.charCode = event.charCode — 32; } J Подобная операция может запугать пользователей, поэтому тщательно проанализируйте ее. Чтобы символ, введенный с помощью клавиатуры, не появлялся сразу же в текстовом по- ле, обработчик события onkeypress должен отменить действие по умолчанию. Например, следующий HTML-код (NN4+, IE4+) позволяет вводить в текстовое поле только цифры. <html> <head> «title>Keyboard Capture«/title> «script language="JavaScript"> function checklt(evt) { var charCode = (evt.which) ? evt.which : event.keyCode if (charCode > 31 && (charCode < 48 || charCode > 57)) { alert("Please make sure entries are numbers only."); return false,- } return true; } </script> </head> <body> <form> Enter any positive integer: «input type="text" name="numeric" onKeyPress="return checklt(event)"> </form> </body> </html> При попытке ввести нецифровой символ пользователь получает предупреждение, а сам символ не появляется в текстовом поле. События клавиатуры позволяют сценарию отправить форму по нажатию клавиши <Entei>, когда курсор находится в текстовом поле. ASCT-код клавиши <Enter> равен 13. Поэтому доста- точно просто проверить код каждой клавиши и отправить форму, когда появится значение 13. function checkForEnter(evt) { evt = (evt) ? evt : event; var charCode = (evt.charCode) ? evt.charCode : (( evt.which) ? evt.which : evt.keyCode); if (charCode ==13) { document.forms[0].submit(); return false; } return true; } Глава 15. Основные объекты HTML-элементов 379
Присвоение функции checkForEnter () в обработчике события onkeypress каждого текстового поля добавляет новые возможности обычной HTML-форме. В браузере Internet Explorer можно перехватывать некоторые комбинации <С1г1+клавиша (только буквы)>, но лишь в том случае, если их не использует сам браузер. Значение свой- ства keyCode события onkeypress для комбинаций <С1г1+клавиша> находится в диапа- зоне от 1 до 26 Для букв от А до Z (для комбинаций, используемых браузером, никаких со- бытий не происходит). Пример Приложение, приведенное в листинге 15.41, представляет собой лабораторию по исследо- ванию обработчиков событий клавиатуры и изучению кодов клавиш в браузерах IE5+ и W3C. Сам код приложения не столь важен, как выполняемые им функции. Для каждой нажимаемой комбинации клавиш отображается значение свойства keyCode, представляемое для событий onkeydown, onkeypress, onkeyup. Если в комбинации используется модифицирующая клавиша, то ее название выделяется для всех трех событий. При запуске этого приложения в NN6+ свойство keyCode не содержит код символа (хотя строка для его отображения пре- дусмотрена, и в самом приложении об ошибке ничего не сказано). Лучший способ увидеть, как происходят события клавиатуры, — понажимать клавиши, (включая модифицирующие) и понаблюдать за выводимыми в таблице значениями. Не забудьте понажимать клавиши со стрелками. Как видите, для события onkeypress коды символов не отображаются, хотя для двух остальных событий они успешно генерируются. <html> <head> <title>Keyboard Event Handler Lab</title> <style type="text/css"> td {text-align:center} </style> <script type="text/javascript"> , function init() { } document. onkeydown = showKeyDown; document.onkeyup = showKeyUp; document.onkeypress = showKeyPress; } function showKeyDown(evt) { evt = (evt) ? evt : window.event; document.getElementByld("pressKeyCode").innerHTML = 0; document.getElementById("upKeyCode").innerHTML = 0; document.getElementByld("pressCharCode").innerHTML = 0; document. getElementByld ("upCharCode ") •. innerHTML = 0 ; restoreModifiers(""); >1 restoreModifiers("Down"); , restoreModifiers("Up"); document.getElementByld("downKeyCode").innerHTML = j evt.keyCode; if (evt.charCode) { j document.getElementByld("downCharCode").innerHTML = f evt.charCode; } 1 showModifiers("Down", evt); i 380 Часть III. Объекты д<
} function showKeyUp(evt) { evt = (evt) ? evt : window. event ; document.getElementByld("upKeyCode").innerHTML = evt. keyCode if (evt.charCode) { document.getElementByld("upCharCode").innerHTML = evt.charCode; } showModifiers("Up", evt); return false } function showKeyPress(evt) { evt = (evt) ? evt : window.event; document.getElementById("pressKeyCode").innerHTML = evt.keyCode; if (evt.charCode) { document.getElementByld("pressCharCode").innerHTML = evt. charCode ; } showModifiers("", evt); return false; } function showModifiers(ext, evt) { restoreModifiers(ext); if (evt.shiftKey) { document.getElementByld("shift" + ext).style, backgroundcolor = "ttffOOOO"; } if (evt.ctrlKey) { document.getElementByld("Ctrl" + ext).style, backgroundcolor = "#00ff00"; } if (evt.altKey) { document.getElementByld("alt" + ext).style, backgroundcolor = "#OOOOff"; } } function restoreModifiers(ext) { document.getElementByld("shift" + ext).style. backgroundcolor = "#ffffff"; document.getElementByld("ctrl" + ext).style, backgroundcolor = "#ffffff"; document.getElementByld("alt" + ext).style, backgroundcolor = "#ffffff"; } </script> </head> <body onload="init()"> <hl>Keyboard Event Handler Lab</hl> <hr /> <form> ctable border="2" cellpadding="2"> <tr> Глава 15. Основные объекты HTML-элементов 381
<thx/th> <th>onKeyDown</th> <th>onKeyPress</th> <th>onKeyUp</th> </tr> <tr> <th>Key Codes</th> <td id="downKeyCode">0</td> <td id="pressKeyCode">0</td> <td id="upKeyCode”>0</td> </tr> <tr> <th>Char Codes (IE5/Mac; NN6)</th> <td id="downCharCode">Oc/td> <td id="pressCharCode">0</td> <td id="upCharCode">0</td> </tr> <tr> < th rowspan="3">Modifier Keys</th> ctdxspan id="shiftDown">Shift</spanx/td> _ ctdxspan id="shift">Shift</spanx/td> ctdxspan id="shiftUp">Shiftc/span>c/td> </tr> <tr> ctdxspan id="ctrlDown">Ctrlc/span>c/td> < tdx span id= "Ctrl" >Ctrl</spanx/ td> < tdxspan id= "ctrlUp">Ctrl< /spanx/td> </tr> ctr> «tdxspan id="altDown">Alt</spanx/td> ctdxspan id="alt">Alt</spanx/td> ctdxspan id="altUp">Alt</spanx/td> </tr> </table> c/form> c/body> </html> См. также: метод String. fromCharCode (). onlosecapture Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Обработчик события onlosecapture запускается тогда, когда отключается захват со- бытий для данного объекта. Это происходит, если пользователь выполняет одно из следую- щих действий: активизирует другое окно; выводит любое системное диалоговое окно (например окно предупреждения); прокручивает страницу; открывает контекстное меню браузера (щелкнув правой кнопкой мыши); активизирует поле адреса окна браузера, нажав клавишу <ТаЪ>. Функция, добавленная в обработчик события onlosecapture, должна производить всю необходимую “очистку данных” после отключения объектом захвата событий. 382 Часть III. Объекты документа
Пример Пример использования onlosecapture приведен ранее в листинге 15.30 (при рассмот- рении сценария управления контекстным меню). С помощью этого обработчика в сценарии скрывалось контекстное меню. См. также: методы releasecapture (), setcapture (). onmousedown onmouseup Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Обработчик события onmousedown запускается тогда, когда пользователь щелкает одной из кнопок мыши. Событие onmouseup происходит при отпускании кнопки мыши, причем объ- ект, получивший такое событие, до этого получил также и событие onmousedown. Когда пользователь щелкает мышью на объекте, события происходят в такой последовательности: onmousedown, onmouseup, onclick. Если же пользователь нажимает кнопку, а затем переме- щает указатель за пределы объекта, то происходит только событие onmousedown. В NN4 эти два события ограничены объектами button, radio button, checkbox, 1 ink и area. Данные события позволяют дизайнерам использовать широкие возможности по управле- нию изображениями и пиктограммами. В большинстве случаев кнопки в приложениях рабо- тают следующим образом: при нажатии кнопки мыши внешний вид кнопки на странице из- меняется, а при отпускании (или перемещении указателя)— возвращается к исходному состоянию. Описанные события мыши позволяют эмулировать именно такое поведение эле- ментов на странице. Объект события, созданный для каждого действия, имеет свойство, которое показывает, какая кнопка мыши была нажата. В модели событий NN4 это свойство называется which, ав!Е4+ и NN6/Mozl+— button (для разных кнопок оно принимает различные значения). Проверять номер кнопки мыши надежнее для событий onmousedown или onmouseup, но не для onclick, так как объект события onclick не всегда содержит информацию о нажа- той кнопке мыши. Пример Для демонстрации типичного сценария ролловера (изменяющегося при наведении указа- теля мыши изображения) ниже приведен листинг 15.42. На соответствующей странице ото- бражаются две небольшие навигационные кнопки (в виде стрелок). Поскольку в IE3 и NN2 объект изображения не включается в объектную модель документа, то далеко не все браузеры корректно отображают кнопки на экране. Только браузеры, поддерживающие предваритель- ное кэширование изображений (создающие массив document. images), можно смело ис- пользовать для выполнения этого приложения. <html> <head> <title>onmousedown and onmouseup Event Handlers</title> «script type="text/javascript"> if (document.images) { var RightNormlmg = new Image(16,16); var RightUpImg = new Image(16,16); var RightDownlmg = new Image(16,16); Глава 15. Основные объекты HTML-элементов 383
var LeftNormlmg = new Image(16,16); var LeftUpImg = new Image(16,16); var LeftDownlmg = new Image(16,16); RightNormlmg.src = "RightNorm. gif "; RightUpImg.src = "RightUp.gif"; RightDownlmg.src = "RightDown.gif"; LeftNormlmg.src = "LeftNorm.gif"; LeftUpImg.src = "LeftUp.gif"; LeftDownlmg.src = "LeftDown.gif"; } function setimage(imgName, type) { if (document.images) { var imgFile = eval(imgName + type + "Img.src"); document.images[imgName].src = imgFile; return false; } } </script> </head> <body> <hl>onmousedown and onmouseup Event Handlers</hl> <hr / > <p>Roll atop and click on the buttons to see how the link event handlers swap images:</p> <center> <a href="javascript:void(0)" onmouseover="return setimage('Left','Up')" onmousedown="return setimage('Left','Down')" onmouseup="return setlmagef'Left','Up')" orimouseout="return setimage('Left','Norm')"><img alt="image" name="Left" src="LeftNorm.gif" height="16" width="16" border="0" /></a> &nbsp,-&nbsp; <a href ="javascript:void(0) " onmouseover="return setImage('Right','Up')" onmousedown="return setimage('Right','Down')" onmouseup="return setImage('Right','Up')" onmouseout="return setimage ('Right' , 'Norm') "ximg alt="image" name="Right" src="RightNorm.gif" height="16" width="16" border="0" /></a> </center> </body> </html> См. также: обработчик события onclick. onmouseenter onmouseleave Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- B IE5.5 появилось два новых обработчика событий: onmouseenter и onmouseleave. Оба они работают так же, как onmouseover и onmouseout, соответственно. Компания Microsoft предложила лишь альтернативную терминологию. В IE5.5 происходят и старые, и новые события (старые перед новыми). В сценариях, создаваемых сугубо для IE5.5+, можно воспользоваться новой терминологией, в иных случаях необходимо придерживаться старых типов событий. 384 Часть III. Объекты документ»
Пример ►. Вы можете изменить листинг 15.43 так, чтобы в нем вместо onmouseover и onmouseout использовались обработчики onmouseenter и onmouseleave. См. также: обработчики событий onmouseover, onmouseout. onmousemove Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Событие onmousemove происходит тогда, когда указатель мыши перемешается по теку- щему объекту. При этом кнопка мьпшгйе обязательно должна быть нажатой, хотя данное событие в большинстве случаев используется при “перетаскивании” элемента, особенно в NN/Mozilla, где не поддерживается обработчик события ondrag. Несмотря на то, что степень детализации этого события находится на уровне пикселей, не стоит использовать количество событий как средство измерения пройденного расстояния. В зависимости от скорости движения указателя, а также от быстродействия компьютера, со- бытие происходит не в каждой точке, через которую проходит указатель. В NN4 обработчик события onmousemove нельзя присвоить атрибуту дескриптора эле- мента. Вместо этого необходимо использовать механизм захвата событий (в сценарии) для та- ких объектов, как window, document или layer. Такой подход позволяет “перетаскивать” по- зиционируемые элементы в NN4. В IE4+ и NN6+ обработчик события onmousemove можно присвоить любому элементу (хотя “перетаскивать” можно только позиционируемые элемен- ты). При разработке страницы, где пользователи могут “перетащить” несколько элементов, обработчик события onmousemove, чаще всего присваивают объекту document, что позво- ляет событиям всплывать для последующей обработки. Пример В главах 39 и 56 приведены примеры использования обработчика onmousemove. См. также: обработчики событий ondrag, onmousedown, onmouseup. onmouseout onmouseover Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Событие onmouseover происходит тогда, когда указатель попадает в прямоугольную об- ласть, содержащую объект (при этом выполняется только одно событие— кроме ошибки eWinNN4, где оно происходит постоянно во время движения указателя). Событие onmouseout происходит тогда, когда указатель покидает пределы описанной области. Обычно эти события применяются для вывода вспомогательного текста об объекте в строке состояния окна, а также при смене изображений (эффект перетекания). Для изменения изображения используется обра- ботчик события onmouseover; для возврата к обычному состоянию — onmouseout. Такие события присутствовали в объектных моделях браузеров с самого начала их воз- никновения, однако в ранних версиях они доступны не для всех объектов. В IE4+ и W3C DOM данные события поддерживаются всеми объектами, отображаемыми на экране. В IE5.5 существуют дополнительные обработчики событий— onmouseenter и onmouseleave, дублирующие onmouseover и onmouseout. Старые версии событий запускаются непо- средственно перед новыми. / Обработчик события onmouseout обычно не запускается, если событие добав- ’нм* > лено к элементу, находящемуся у края фрейма или окна, а пользователь доста- • точно быстро перемещает указатель за пределы текущего фрейма. Глава 75. Основные объекты HTML-элементов 385
Пример На странице, представленной листингом 15.43, приведено предложение с четырьмя ссыл- ками, на примере которых рассматриваются обработчики onmouseover и onmouseout. Каждая ссылка при активизации запускает функцию общего назначения, которая отображает сообщение в строке состояния. <html> <head> <title>onmouseover and onmouseout Event Handlers</title> «script type="text/javascript"> function setstatus(msg) { status = msg; return true; } function emulate() { alert("Not going there in this demo."); } </script> </head> <body> <hl>onmouseover and onmouseout Event Handlers</hl> <hr /> <hl>Pledge of Allegiance</hl> <hr /> I pledge <a href="javascript:emulate()" onmouseover^"return setstatus('View dictionary definition')" onmouseout="return setstatus('')">allegiance</a> to the <a href="javascript:emulate()" onmouseover="return setstatus('Learn about the U.S. flag (http://lcweb.loc.gov)')" onmouseout="return setstatus('')">flag</a> of the <a href="javascript:emulate()" onmouseover^'return setstatus('View info about the U.S. government')" onmouseout="return setstatus('')">United States of America</a>, and to the Republic for which it stands, one nation <a href= "javascript:emulate()" onmouseover="return setstatus('Read about the history of this phrase in the Pledge')" 1 onmouseout="return setstatus('')">under God</a>, indivisible, with liberty and justice for all. </body> </html> См. также: обработчики событий onmouseenter, onmouseleave, onmousemove. onpaste Совместимость: WihIE5+, MacIE-, NN-, Moz-, Safari- Возникает сразу же после того, как пользователь или сценарий инициирует операцию вег ки для текущего объекта. Ему предшествует событие onbef orepaste, которое запускается 386 Часть III. Объекты
того, как выбирается опция Paste меню Edit или соответствующий пункт контекстного меню (а также непосредственно до вставки, если она осуществляется нажатием комбинации клавиш). Обработчик события используется для добавления новых возможностей редактирования тем элементам, которые обычно не позволяют производить вставку. В этом случае необходи- мо сделать активной опцию Paste контекстного меню или меню Edit, установив свойство event.returnvalue для обработчика события oribeforepaste равным false. Затем обработчик события onpaste должен извлечь данные из буфера обмена (методом . getData () объекта с 1 ipboardData) и вставить в текущий объект. Поскольку за то, какие данные сохраняются в буфере обмена, отвечает сценарий, вы не ограничены прямым копированием данных. Поэтому можно, например, сохранить значение свойства src объекта изображения для его последующей вставки в указанном месте страницы. Пример В листинге 15.44 продемонстрировано использование обработчиков onmouseout и onmouseover (совместно с обработчиками onbeforecopy и опсору) для управления опе- рацией передачи данных при копировании и вставке информации. В таблице страницы содер- жатся копируемые данные (столбец существительных и столбец прилагательных). Скопирован- ные данные вставляются в пустые части приложения. Обработчики onbeforecopy и опсору назначены элементу table, поскольку события элемента td всплывают к контейнеру table. Нижнее предложение содержит два пустых элемента span. Чтобы вставить в них текст, пользователь должен сначала выделить хотя бы один символ “пустого” места. (В лис- тинге 15.37 приведена версия этого приложения для событий перетаскивания.) Обработчик onbeforepaste предложения устанавливает свойство event. returnvalue в значение false. Таким образом команда вставки становится доступной для выполнения (по умолча- нию она отключена). При вставке свойство innerHTML целевого объекта span приравнива- ется к текстовым данным, которые сохранены в буфере обмена. <html> <head> <title>onbeforepaste and onpaste Event Handlers</title> «style type="text/css"> td {text-align:center} th {text-decoration:underline} .blanks {text-decoration:underline} </style> «script type="text/javascript"> function select-whole () { var obj = window.event.srcElement; var range = document.body.createTextRange(); range.moveToElementText(obj); range.select(); event.returnvalue = false; } function handleCopyO { var rng = document.selection.createRange(); clipboardData.setData("Text",rng.text); event. retumValue = false; } function handlePaste() { var elem = window.event.srcElement; Глава 15. Основные объекты HTML-элементов 387
if (elem.className == "blanks") { elem.innerHTML = clipboardData.getData("Text"); } event.returnvalue = false; function handleBeforePaste() { var elem = window.event.srcElement; if (elem.className == "blanks") { event.returnvalue = false; «/script> </head> <body> <hl>onbeforepaste and onpaste Event Handlers«/hl> <hr /> <p>Your goal is to copy and paste one noun and one adjective from the following table into the blanks of the sentence. Select a word from the table and copy it to the clipboard. Select one or more spaces of the blanks in the sentence and choose Paste to replace the blank with the clipboard contents.</p> «table cellpadding="5" onbeforecopy="selectWhole()" oncopy="handleCopy()"> <tr> <th>Nouns</th> <th>Adjectives</th> </tr> <tr> <td>truck</td> <td>round</td> </tr> <tr> <td>doll</td> <td>red</td> </tr> <tr> <td>ball</td> <td>pretty</td> </tr> </table> <p id="myP" onbeforepaste="handleBeforePaste()" onpaste="handlePaste()"> Pat said, "Oh my, the «span id="blankl" class="blanks">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;«/span> is so «span id="blank2" class= "blanks">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;«/span>!"</p> «button one1ick="location.reload()">Reset«/button> «/body> «/html> См. также: обработчики событий oncopy, oncut, onbef orepaste. onpropertychange Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Событие onpropertychange происходит в IE5+ для Windows, когда сценарий изменяет какое-либо свойство объекта. Это относится и к стилю объекта. Изменение свойств методом setAttribute () также запускает данное событие. 388 Часть III. Объекты д<
Свойство event.propertyName содержит имя (в строковом формате) свойства, которое было изменено. В случае изменения объекта style текущего объекта значение event.propertyName начинается с префикса "style.", например style.backg- roundcolor. Обработчик данного события применяется для последующей обработки измененных свойств объекта. Вместо того, чтобы вносить операторы внутрь функции, изменяющей свой- ства, их можно вынести в отдельную функцию общего характера (например, для изменения свойств нескольких объектов). Пример В листинге 15.45 приведен пример использования обработчика onpropertychange. В нем показано, как запрограммировать ответную реакцию на изменение свойств объекта. Соответст- вующая страница содержит четыре переключателя, которые изменяют свойства innerHTML и style. color абзаца. Обработчик onpropertychange вызывает функцию showchange (), которая извлекает информацию о событии и отображает сведения в строке состояния окна. <html> <head> <title>onpropertychange Event Handler</title> «script type="text/javascript"> function normalText() { myP.innerText = "This is a sample paragraph."; } function shortTextO { myP.innerText = "Short stuff."; } function normalcolor() { myP.style.color = "black"; } function hotColorO { myP.style.color = "red"; } function showChangeO { var objID = event.srcElement.id; var propName = event.propertyName; var newValue = eval(objID + "." + propName); status = "The " + propName + " property of the " +-objID; status += " object has changed to \"" + newValue + "\"." ; } </script> «/head> «body> <hl>onpropertychange Event Handler</hl> <hr I > <p id="myP" onpropertychange="showChange()">This is a sample paragraph.</p > <form> Text: «input type="radio" name="btnl" checked="checked" onclick="normalText()" />Normal «input type="radio" name="btnl" onclick="shortText()" />Short«br /> Color: «input type="radio" name="btn2" checked="checked" onclick="normalcolor()" />Black «input type="radio" Глава 15. Основные объекты HTML-элементов 389
name="btn2" onclick="hotColor()" />Red </form> </body> </html> См. также: свойство style; метод setAttribute (). onreadystatechange Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Обработчик события onreadystatechange запускается тогда, когда изменяется со- стояние загрузки элемента. Подробнее об этом рассказывалось при обсуждении свойства readyState ранее в этой главе (обратите внимание на ограничения для IE4). Изменение со- стояния еще не гарантирует, что сценарий может прочесть свойства объекта. В каждом сце- нарии, где используется обработчик события onreadystatechange, необходимо всегда проверять свойство readyState объекта. Событие происходит для объектов, способных загружать данные: applet, document, frame, frameset, iframe, img, link, object, script и xml. Для других типов объек- тов событие происходит только в том случае, если им определено поведение DHTML. Собы- тие onreadystatechange не всплывает, и его нельзя отменить. См. также: свойство readyState. onresize Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Обработчик события onresize запускается при изменении размеров объекта в ответ на действия пользователя или сценария. Почти все элементы, обладающие содержимым, имеют данный обработчик события при условии, что нобъекте существуют пространственные атри- буты (например, высота, ширина или координаты положения). В IE4+ и NN6+/Mozl+ событие onresize не всплывает. Изменение размеров окна брау- зера или фрейма не запускает обработчик события onload. Пример При желании вы можете захватывать события изменения пользователем размера окна (фрейма) браузера. Обработчику событий в сценарии обычно назначается функция. window.onresize = handleResize; Эта же операция выполняется и в коде HTML. <body onresize="handleResize()"> См. также: метод window, resize (). onresizeend onresizestart Совместимость: WinIE5.5+, MacfE-, NN-, Moz-, Safari- Обработчики событий onresizeend и onresizestart запускаются в режиме редак- тирования Windows только для тех объектов, изменение которых возможно. Как отмечалось при обсуждении обработчика события oncontrolselect, компания Microsoft еще не пре- доставила подходящего описания или примера. См. также: обработчик события oncontrolselect. 390 Часть III. Объекты документа
onselectstart Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Обработчик события onselectstart запускается тогда, когда пользователь начинает выделять содержимое страницы. Последним может быть текст страницы, изображение или текст внутри поля. Если пользователь выделяет несколько объектов, то событие происходит для первого из них. Пример Используйте страницу из листинга 15.46 изучения обработчика onselectstart. Как только пользователь начнет выделять данные на странице, в строке состояния отобразится идентификатор объекта, принимающего событие. Обратите внимание на то, что событие не возникает до тех пор, пока вы полностью не выделите элемент. Если ни один объект не рас- полагается под указателем, то событие принимает объект body. <html> <head> <title>onselectstart Event Handler</title> «style type="text/css"s td {text-align:center} </style> «script type="text/javascript"> function showObj() { var objID = event.srcElement.id; status = "Selection started with object: " + objID; } «/script> «/heads «body id="myBody" onselectstart="showObj()"s <hl id="myHl"s onselectstart Event Handler «/his «hr id="myHR" /s «p id="myP"sThis is a sample paragraph.</ps «table border="l"s <tr id="rowl"s «th id="headerl"sColumn A«/ths «th id="header?"sColumn B«/ths «th id="header!"sColumn C«/ths </trs <tr id="row2"s <td id="cellA2"stext«/tds «td id="cellB2"stext«/tds <td id="cellC2"stext«/tds </trs «tr id="row3"s «td id="cellA3"stext«/tds «td id="cellB3"stext«/tds «td id="cellC3"stext«/tds «/trs «/tables «/bodys </htmls См. также: обработчик события onselect для различных объектов. Глава 15. Основные объекты HTML-элементов 391
Объекты window и frame Диаграмма объектной модели документа в главе 14 (рис. 14.1) показывает, что объект window является внешним глобальным контейнером всех объектов документа, используемых в сценариях JavaScript. Все операции HTML и JavaScript осуществляются в пределах окна. Им может быть стандартное окно приложения Windows, Мас или XWindows, содержащее полосы прокрутки, панели инструментов и другие элементы; или же созданное вами окно без некоторых обыч- ных средств. Фрейм также является окном, хотя он и не имеет дополнительных элементов, кроме полос прокрутки. Все ссылки JavaScript начинаются с объекта window. Браузеры IE4+, NN6+ и W3C трактуют набор фреймов как специальный тип объекта window, поэтому о нем тоже рассказано в этой главе. Из всех объектов браузера, доступных при создании сце- нариев, не только window, но все связанные с ним элементы обладают объектно-специфическими средствами. Чтобы ра- бота с такими объектами стала более понятной, в этой главе приведено немало вспомогательной информации. Терминология При первом знакомстве с объектной моделью документа объект window кажется очень странным и непонятным. Чего стоит только количество синонимов объектов window: top, self, parent и frame. Ухудшает ситуацию еще и то, что эти термины являются свойствами объекта window. В неко- торых случаях окно является родительским для самого себя, но если определить набор из двух фреймов, то из трех объек- тов window только один будет родительским. При работе с такими объектами несложно и запутаться. Если вы не используете фреймы, то никогда не столкне- тесь с большинством проблем, однако, если они составляют часть дизайна вашего проекта, то вы должны знать, как они влияют на объектную модель документа.
Фреймы Вопрос применения является неоднозначным среди Web-дизайнеров: одни разработчики го- рячо выступают за их применение, другие — так же горячо против. Я считаю, что иногда без фреймов просто не обойтись. Например, если документ достаточно велик и требует прокрутки при просмотре его содержимого, желательно, чтобы элементы навигации все время находились в видимой области окна. Размещение таких элементов (ссылок или карт изображений) в отдель- ном фрейме делает их всегда доступными, независимо от состояния основного документа. Создание фреймов На создание фреймов в документе не влияет использование JavaScript. Простейший доку- мент с набором фреймов выглядит следующим образом. <html> <head> «title>My Frameset«/title> </head> «frameset> , «frame name="Framel" src="document1.html"> «frame name-"Frames" src="document2.html"> </frameset> </html> Приведенный HTML-документ (он не отображается для пользователя) определяет набор фреймов. Каждый из них должен содержать URL (заданный атрибутом src) документа, за- гружаемого во фрейм. Присвоение имени каждому фрейму с помощью атрибута name упро- щает написание сценариев. Объектная модель фрейма Возможно, ключом к успешному созданию сценариев, работающих с фреймами, является понимание того, как объектная модель документа выглядит в памяти, отведенной для браузе- ра, в определенный момент времени. Схематические структуры, приведенные в этой книге (рис. 16.1), не отображают точную объектную модель документа или набора документов. Для одного документа без фреймов объектная модель состоит из един- ственного объекта window, в котором содержится документ (рис. 16.1). В такой простой структуре объект window является начальной точкой для ссылок на любой загруженный объект. Поскольку окно всегда присутст- вует (чтобы мог быть загружен и представлен документ), в ссылках на объекты в документе объект текущего окна можно не указывать. В простой модели с двумя фреймами (рис. 16.2) браузер трактует кон- тейнер исходного документа как родительское окно. Единственным сви- детельством того, что документ, задающий набор фреймов, существует, служит его заголовок, отображаемый в строке заголовка браузера. Каждый дескриптор <frame> внутри набора < frameset > создает свой объект window, в который загружается соответствующий документ. Каж- Window Document Рис. 16.1. Прос- тейшее взаимоот- ношение “окно-до- кумент” дому фрейму соответствует свой объект document. Документ сам по себе имеет единственный контейнер, как и в модели, приведенной на рис. 16.1. Родительский объект не виден пользовате- лю, однако он все равно присутствует в объектной модели. Его удобно использовать для хра- нения данных, применяемых в дочерних фреймах, или загрузки различных документов в них. Глава 16. Объекты window и frame 393
<frame> Рис. 16.2. Родительское окно и фреймы являют- ся частью объектной модели В более сложных конструкциях, как, например, на рис. 16.3, дочерний фрейм сам может содержать документ с набором фреймов. В таких случаях проявляется разница между объек- тами parent и top. Верхнее (top) окно является общим для всех фреймов на рис. 16.3. Как мы скоро увидим, при взаимодействии одних фреймов с другими (и документов в них), ссыл- ки на дальние объекты начинаются с общего для всех фреймов объекта window. <frame> Рис. 16.3. Три поколения объектов окон Ссылки на фреймы Ссылки на объекты необходимы JavaScript, чтобы найти требуемый объект в объектной модели, находящейся в данный момент в памяти браузера. Ссылка представляет собой “карту”, в соответствии с которой браузер ведет поиск (например, чтобы узнать значение не- которого текстового поля в определенном документе). Поэтому при создании ссылки необхо- димо четко представлять, где в объектной модели находится сценарий и как ссылка опреде- ляет самый далекий от исходного объект. В случае объектов двух поколений (рис. 16.2) возможны три типа отношений. 394 Часть III. Объекты документа
Родительско-дочерние. Дочерне-родительские. Дочерне-дочерние. Для доступа к объекту, функции или переменной используются следующие ссылки. имяФрейма.имяОбъектаПеременнойФункции parent.имяОбъектаПеременнойФункции parent.имяФрейма.имяОбъектаПеременнойФункции Помните: если ссылка указывает на другой фрейм, она должна начинаться с объекта window, общего для обоих фреймов. Рассмотрим этот принцип на примере сложной модели (рис. 16.3): если документ из левого дочернего фрейма ссылается на правый нижний фрейм, то структура ссылки будет следующей. top.имяФрейма.имяФрейма.документ. ... Ссылка начинается с верхнего (top) объекта window через два фрейма к искомому доку- менту. JavaScript следует именно по такому маршруту. Объект top против объекта parent У читателей может возникнуть вопрос: почему бы не использовать объект top для всех ссылок? Для объектной модели, такой подход вполне оправдан: родительским объектом в структуре из двух поколений является также и верхнее окно. Тем не менее, документ, за- дающий набор фреймов, не всегда является объектом top в “чужом” браузере. Представь- те, например, Web-узел, загружающий другие Web-узлы в свои фреймы. В такой ситуации объект top является другим. Ссылки, построенные через него, или не будут работать, или приведут к ошибкам в сценарии. Поэтому рекомендуется использовать объект parent, когда речь идет о поколении, предыдущем по отношению к текущему документу. Предотвращение использования фреймов Ссылками top и parent можно воспользоваться для того, чтобы не допустить отобра- жение вашего Web-узла внутри набора фреймов другого узла. Для этого необходимо, чтобы документ верхнего уровня просто проверял, в какое окно он загружен (это должно быть верх- нее (top) или родительское (parent) окно). Когда документ находится в таком окне, ссылка на свойство top совпадает со ссылкой на текущее окно (в данном случае используется сино- ним объекта window— self). Если два значения не совпадают, то сценарий загружает до- кумент заново, но уже в окно верхнего уровня. Сценарий, выполняющий эти действия, при- веден в 16.1 (его следует разместить в начале документа). «script type="text/javascript"> if (top != self) { top.location = location; } «/script> В начале документ может загружаться внутрь фрейма, но затем (после выполнения сцена- рия) он станет документом самого верхнего уровня в окне браузера. Глава 16. Объекты window и frame 395
Проверка загрузки фреймов При разработке Web-приложения иногда необходимо убедиться, что страница загружает полный набор фреймов. Рассмотрим, например, следующую возможность: посетитель Web-узла добавляет в список закладок только один из фреймов. При следующем посещении в браузере отображается документ только из одного фрейма. Вполне вероятно, что меню навигации при этом находится в другом фрейме набора, который в данной ситуации загружается не полностью. Сценарий может проверить, загружается ли страница в своем наборе фреймов (сравни- вается URL окон top и self). Если они совпадают, для страницы необходимо загрузить на- бор фреймов. Простая версия этого сценария, загружающая необходимый набор фреймов, показана в листинге 16.2. В сценарий включен специальный код для NN4, не допускающий отображение отдельного фрейма (NN4 для Windows и Unix загружает страницу в отдельном скрытом окне и запускает ее сценарии.) Чтобы получить более полную реализацию этого сцена- рия, в котором набору передается параметр, определяющий открытие страницы в одном из фреймов, обратитесь к свойству location. search, описанному в главе 17. «script type="text/javascript"> var isNav4 = (navigator.appName == "Netscape” && parselnt(navigator.appVersion) == 4); if (top.location.href == window.location.href) { if (isNav4) { if (window.innerWidth != 0) { top.location.href = "myFrameset.html"; } } else { top.location.href = " myFrameset.html"; </script> Включение и отключение фреймов Некоторые Web-узлы по умолчанию загружают свое содержимое в набор фреймов, но предлагают пользователю возможность их отключения. Только браузеры IE4+ и W3C позво- ляют на ходу изменять свойства cols и rows набора, эмулируя этим добавление или удале- ние фреймов в текущем окне (см. объект элемента frameset далее в этой главе). В других браузерах нельзя динамически изменить структуру набора фреймов после загрузки страницы, но можно загрузить содержимое начальной страницы в основное окно. Для этого следует до- бавить кнопку или ссылку, загружающую документ в окно объекта top. top.location.href = "mainBody.html"; Переход обратно к многофреймовой версии реализуется только в результате перезагрузки' исходного документа (набора фреймов). Наследование Разработчики сценариев, имеющие опыт в объектно-ориентированном программирова- нии, вероятно, ожидают, что фреймы наследуют свойства, методы, функции и переменные' родительского объекта. Тем не менее, именно этого и не обеспечивают браузеры. Доступ 396 Часть III. Объекты документа
к элементам родительского объекта все же возможен, но по полной ссылке. Например, вирту- альная функция из родительского документа доступна всем фреймам по следующей ссылке. parent.myFunc() Ей можно передать аргументы и получить возвращаемое значение. Синхронизация фреймов Серьезной проблемой при написании сценариев становится то, что включение сценариев в многофреймовый документ опасно и даже приводит к сбоям в отдельных браузерах. Такие сценарии полагаются на наличие документов во фреймах, однако, если фреймы предварительно не созданы, а их документы — не загружены, сценарии приведут или к ошибкам, или к сбою. Один из способов обойти проблему заключается в запуске всех сценариев в обработчике события onload. Теоретически этот обработчик не запускается, если все документы не были успешно загружены во все фреймы набора. К сожалению, IE4+ для Windows содержит ошиб- ку— событие onload запускается даже в том случае, если загрузка была прервана щелчком на кнопке Stop или нажатием клавиши <Esc>. В то же время необходимо проявить особую осторожность, задавая обработчик события onload в документах отдельных фреймов. Если сценарий полагается на присутствие документа в другом фрейме (например сестринском), он, скорее всего, будет выполняться с ошибками. Многие причины (начиная с низкопроизводи- тельной Сети или сервера и заканчивая ненадежным модемом) могут привести к неверному порядку загрузки документов во фреймах. Одним из способов обойти проблемы является создание переменной логического типа вредительском документе, состояние которой отражает состояние необходимого фрейма. После загрузки документа его обработчик события onload устанавливает флажок в значение true. Все сценарии, обрабатывающие содержимое фрейма, должны использовать оператор if для проверки значения этой переменной. Несмотря на серьезную ошибку в IE4+, описанную выше, рекомендуется запрограммировать запуск всех сценариев по событию onload родительского документа. Зависимость от других фреймов — достаточно сложная проблема, однако чем старше версия браузера, тем меньше риск. Пустые фреймы Вы часто будете создавать фреймы в наборе, не помещая в них каких-либо документов до тех пор, пока пользователь не начнет взаимодействовать с элементами управления в других фреймах. NN и последние версии IE поддерживают элемент пустого документа, имеющий внутренний URL (about: blank). Но в NN2 и NN3 для Macintosh при его “отображении” выводится специальное сообщение. Кроме того, этот URL доступен не во всех браузерах. По- этому, когда требуется создать пустой фрейм, необходимо включить HTML-документ общего вида непосредственно во фрейм, используя атрибут src, как показано в листинге 16.3. За- грузка “пустого” HTML-документа не требует никаких дополнительных операций. Зйистик W.3. Издание пустого фрейма <html> <head> <script type="text/javascript"> function blank() { return "<html></html>"; } Глава 16. Объекты window и frame 397
</script> </head> <frameset> <frame name="Framel" src="someURL.html"> «frame name="Frames" src="javascript:parent.blank()"> </frameset> </html> Просмотр исходного кода фрейма Знакомство с работами других программистов — одно из лучших средств изучения JavaScript (и любого другого языка программирования). В большинстве браузеров, поддерживающих сценарии, можно легко просмотреть исходный код документа фрейма, даже если он частично или полностью генерируется на JavaScript. Щелкните на фрейме, чтобы активизировать его (в некоторых браузерах он выделяется рамкой, в других — нет). Затем выберите пункт Frame Source (Исходный код фрейма) (или его эквивалент) в меню View (Вид) (или в контекстном меню, вызываемом щелчком правой кнопкой мыши). Выбранный фрейм можно также распе- чатать или сохранить в виде отдельного файла. Фреймы и элементы frame С расширением объектных моделей, когда почти все элементы HTML стали доступны сценариям (браузеры IE4+ и W3C DOM), возникло несоответствие в терминологии. Все, что рассказывалось о фреймах в этой главе, относится к исходной объектной модели, где фрейм является отдельным типом окна, причем разница заключается лишь в создании ссылок на объекты. Это справедливо даже для последних версий браузеров. Тем не менее, элемент frame отличается от объекта фрейма исходной модели. Элемент frame представляет собой объект, свойства которого определяются атрибутами дескриптора <frame>. Они предоставляют доступ в сценарии к таким параметрам, как границы фрейма и полосы прокрутки, — свойствам, не присущим исходному объекту фрейма. Ссылки на фрейм и элемент frame также различны. Ранее в этой главе было приведено немало примеров того, как необходимо создавать ссылки на фреймы старым способом. Дос- туп к объекту элемента frame осуществляется с помощью атрибута id или родительско- дочерних ссылок в элементе frameset (свойством parentNode для перехода к элементу frame, содержащему документ, воспользоваться нельзя). Я предпочитаю присваивать значе- ние атрибуту ID дескриптора <f rame> и осуществлять доступ к элементу frame с помощью объекта document, находящегося в родительском (parent) (или верхнем (top)) окне ие- рархической структуры набора фреймов. Поэтому для доступа к свойству frameBorder элемента frame используется следующий синтаксис parent.document.all.идентификаторФрейма!.frameBorder или в IE5+, NN6+ и W3C DOM. parent.document.getElementByld("идентификаторфрейма1").frameBorder Когда ссылка задается с помощью элемента frame, доступ к документу, содержащемуся во фрейме, невозможен. 398 Часть III. Объекты документа
Объект window Свойства Методы Обработчики событий аррСоге alert() onabort** clientInformation attachEvent()* onafterprint clipboardData back() onbeforeprint closed blur()* onbeforeunload components [] captureEvents() onblur* controllers [] clearinterval() onchange** crypto clearTimeout() onclick** defaultstatus close () enclose** dialogArgument s confirm() ondragdrop dialogHeight createPopupO onerror dialogLeft detachEvent()* onfocus* dialogTop disableExternalCapture() onhelp dialogwidth execScript() onkeydown* * directories find() onkeypress** . document fi reEvent () * onkeyup** event focus ()* onload external forward() onmousedown* * frameElement handleEvent() onmousemove * * frames [] home() onmouseout** history moveBy() onmouseover * * innerHeight moveTo() onmouseup** innerWidth navigate() onmove length open() onreset** loading print() onresize location prompt() onscroll locationbar releaseEvents() onselect** menubar resizeBy() onsubmit** name navigator of fscreenBuffering opener outerHeight outerwidth pageXOffset pageYOffset parent personalbar resizeTo() routeEvent() scroll() scrollBy() scrollTo() setActive()* setCursor() setinterval() setTimeout() showHelp() onunload Глава 16. Объекты window и frame 399
Окончание таблицы Свойства Методы " Обработчики событий pkcsll prompter returnvalue showModalDialog() showModelessDialog() sizeToContent() screen screenLeft screenTop screenX screenY scrollbars scrollMaxX scrolIMaxY self sidebar stop() Status toolbar top window * См. главу 15. * * Для обработки захватываемых или всплывающих событий других объектов в браузерах IE4+ UW3CDOM. Синтаксис Создание окна. var windowobject = window.open([параметры] ); Доступ к свойствам и методам окна. window. свойсвтво | метод ( [параметры] ) self.свойство|метод([параметры]) объектОкна.свойство|метод([параметры] ) Описание объекта Объект window находится на вершине иерархии, включая даже объект document. Это высокое положение наделяет объект window рядом свойств, не доступных другим объектам. Поскольку, как правило, все происходит внутри окна, ссылку на объект window можно опус- тить. В предыдущих главах методы объекта document вызывались так: document .write О. Полная ссылка выглядит следующим образом: window.document .write (). Поскольку действие происходит в окне, содержащем документ, частью которого является сценарий, ок- но считается частью ссылки. Для окон с одним фреймом эта концепция сильно упрощается. Как отмечалось выше, в списке свойств объекта window присутствует атрибут self. Он яв- ляется синонимом самого объекта (поэтому в иерархической структуре отображается как объект). 400 Часть III. Объекты документа
Применение свойства, имя которого совпадает с самим объектом, может быть не совсем понят- ным, но такая ситуация распространена в объектно-ориентированных средах. Причины, по которым свойство self используется вместо ссылки на объект окна, обсуждаются далее. Как было показано при определении синтаксиса, в коде JavaScript не обязательно специ- ально создавать объект window. После запуска браузер, как правило, открывает окно. Оно является полноценным объектом (даже если является пустым). Поэтому после загрузки поль- зователем страницы, объект window автоматически создается как часть документа, доступ- ная для управления в сценарии. И тут мы сталкиваемся с потенциальной ловушкой: часто разработчики предполагают, что обработчики событий объекта window или значения свойств, присвоенные в сценарии, могут “пережить” документ, в котором выполняется сценарий. За исключением очевидных физических свойств окна, каждый новый документ, загружаемый в окно, обновляет свойства н обработчики окна в исходное состояние. Управление в сценарии элементами пользовательского интерфейса существующего (уже открытого) окна во многом зависит от типа и версии браузера. В браузерах до версии 4 мож- но изменить только строку состояния (внизу окна браузера). В IE4+ и NN4+ в режиме реаль- ного времени можно управлять такими свойствами, как размер, расположение и (в защищен- ных сценариях NN) отображение отдельных элементов (например, панелей инструментов н полос прокрутки). Многие свойства можно изменять только в специальных безопасных диапазонах, если сценарии криптографически защищены (см. главу 46) и/или пользователь разрешает сценариям производить такие операции. Во всех браузерах свойства окон более гибкие, когда в сценарии создается новое окно (методом window. open ()): для него изменяются размеры окна, отображаются панели ин- струментов, полосы прокрутки и определяются дополнительные элементы окна. Последние версии браузеров поддерживают такие настройки окна, как его положение на экране и скры- тие строки заголовка. И вновь, если определенная опция может использоваться для извлече- ния личных данных пользователя (например, попытка скрыть окно, которое отображает дей- ствия, производимые в другом окне), то используйте защищенные сценарии. На уровне объекта window сценарий умеет отображать диалоговое окно одного из трех возможных типов (окно предупреждения, окно подтверждения типа ОК/Отмена и окно за- проса данных). Несмотря на то, что диалоговые окна очень удобны для проведения отладки (см. главу 45), они могут показаться непрактичными и непривлекательным для пользователей Web-узла. Поскольку большинство диалоговых окон JavaScript являются модальными (т.е. они не позволяют производить никаких действий в основном окне браузера, а на платформе Macintosh — вообще никаких действий, пока окно не будет закрыто), попытайтесь избежать их использования. Помните, что некоторые пользователи создают макросы для посещения Web-узлов. Если при таком автоматизированном доступе появится диалоговое окно, процесс потребует обязательного вмешательства пользователя. Все диалоговые окна, генерируемые JavaScript, идентифицируют себя как “генерируемые JavaScript” (менее навязчиво в браузерах версии 4 и выше). Такое поведение, в первую оче- редь, вызвано необходимостью защиты данных системы: чтобы скрытые сценарии не могли создавать диалоговые окна, подобные системным, и запрашивать у пользователя личные дан- ные. Кроме того, такой подход направлен на сокращение использования диалоговых окон в Web-дизайне. И это правильно, поскольку они обычно лишь раздражают пользователей. За исключением имеющихся только в IE модальных и безрежимных диалоговых окон (см. методы window. showModalDialog () и window. showModeless ()), обычные диа- логовые окна JavaScript не позволяют использовать в них текстовые или графические элемен- ты. В них нельзя даже изменить текст кнопок или добавить новую кнопку. В браузерах, под- держивающих DHTML, допускается использовать позиционируемые элементы div или iframe для эмуляции диалогового окна (не зависящего от типа браузера). Глава 16. Объекты window и frame 401
Свойства аррСоге Components[] controllers[] prompter sidebar Значения: см. текст Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Браузеры NN6+/Mozilla обеспечивают сценариям доступ к различным службам из пакета xpconnect (“хр” означает “cross-platform”— не зависящий от платформы, или межплат- форменный). Такие службы позволяют сценариям работать со свойствами СОМ-объектов и языка mozilla.org XUL (XML-based User Interface Language— язык пользовательского интерфейса на основе XML). Обсуждение этого вопроса выходит за рамки данной книги. Советуем обратиться к документаций по NN6 и проанализировать сценарии по адресу . http://www.mozilla.org/scriptable/. clientinformation Значение: объект navigator Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Чтобы обеспечить сценариям доступ к свойствам на уровне браузера и в то же время из- бежать упоминания конкурирующей торговой марки (Navigator), компания Microsoft разрабо- тала свойство clientinformation. Его значение идентично объекту navigator (онтак- же доступен в IE). Для совместимости различных типов браузеров следует использовать объект navigator (см. главу 38). См. также: объект navigator. clipboardData Значение: объект Чтение/Запись Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Объект clipboardData (не поддерживаемый в Мас1Е5) используется для передачи данных в таких операциях, как вырезка, копирование и вставка данных под управлением сценария. Объект содержит данные одного или нескольких типов, которые связаны с вы- полнением операции. Этим свойством следует пользоваться только при редактировании данных с помощью меню Edit (или комбинаций клавиш, соответствующих его опциям), а также контекстного меню, управляемого сценарием (обычно в сочетании с обработчиками событий редактирования объектов). Работа с объектом clipboardData требует знания трех методов, приведенных в табл. 16.1. Советуем также ознакомиться с обработчиками событий редактирования объектов (версиями before и after событий вырезки, копирования и вставки) (см. главу 15). Объект clipboardData нельзя использовать для обмена данными между страницами, источником которых послужили разные домены или протоколы (например http и https). 402 Часть III. Объекты документа
Метод Возвращаемое значение Описание clearData ( [format] ) Отсутствует Удаляет данные из буфера обмена. Если параметр формата не указан, происходит очистка всех данных. Формат данных может включать одну или несколько ОПЦИЙ: Text, URL, File, HTML, Image GetData (format) Строка Извлекает данные указанного формата из буфера обмена. Формат имеет одно из следующих значений: Text, URL, File, HTML, Image. При получении данных очистка буфера не происходит, поэтому их можно извлекать несколькими последовательными операциями SetData(format, data) Булевого типа Сохраняет данные а буфере обмена. Формат принимает следующие значения: Text, url, File, html, image. Для нетекстовых форматов данные должны представлять собой путь или URL, указывающий на содержимое. Метод возвращает значение true, если запись данных в буфер обмена произошла успешно Пример В листинге 15.30 приведен пример использования объекта clipboardData совместно с несколькими обработчиками событий. См. также: свойство event .datalransfer; обработчики событий onbeforecopy, onbeforecut, onbeforepaste, oncopy, oncut, onpaste. closed Значение: булевого типа Только для чтения Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ При создании нового окна методом window.open() часто возникает необходимость дос- тупа к свойствам его объектов (например, для установки значения текстового поля). Доступ к новому окну осуществляется с помощью ссылки, возвращаемой методом window. open (), как показано в следующем фрагменте кода. var newWind = window.open("someURL.html","subWind”); newWind.document.entryForm.ZIP.value = "00000"; В данном примере переменная newWind не связана с окном “напрямую”, а является лишь ссылкой на него. Если пользователь закроет окно, она все равно будет содержать ссылку на него. Поэтому любая попытка в сценарии обратиться к объекту отсутствующего окна приве- дет, скорее всего, к ошибке. Перед работой с элементами нового окна необходимо убедиться в том, что оно все еще открыто. Свойство closed возвращает значение true, если объект window был закрыт сценарием или пользователем. Всякий раз, когда оператор сценария выполняется после того, как у пользо- вателя была возможность закрыть окно, обязательно проверяйте значение свойства closed. Глава 16. Объекты window и frame 403
Пример В листинге 16.4 приведен код, с помощью которого открывается и закрывается окно брау- зера. Сценарий начинается с инициализации глобальной переменной newWind, в которой со- храняется ссылка на объект второго окна. Эта переменная имеет глобальную область дейст- вия, поскольку доступ к ней должны иметь другие функции, выполняющие операции по управлению окном. Например, новое окно содержит HTML-код, вставляемый в него динамическим образом, а не в результате загрузки отдельного HTML-файла. Тем не менее, параметр URL метода window.open () приравнивается к пустой строке (по умолчанию). Далее следует код пре- доставления IE (особенно версий 3 и 4) возможности динамического ввода в окно содержи- мого. После задержки (задается с помощью метода setTimeout (), описанного далее в этой главе) вызывается функция f inishNewWindows (), которая обращается к окну с помощью переменной newWind. Метод document .close () закрывает сеанс записи данных в новое окно браузера, а отдельная функция closewindow () отвечает за закрытие подокна В конце примера с помощью оператора if проверяется выполнение двух условий: объект window инициализирован значением null (пользователь успел щелкнуть на кнопке закры- тия окна до создания его содержимого) и свойство closed окна установлено в значение null или false. Если хотя бы одно из условий выполняется, то по отношению ко второму окну выполняется метод close (). <html> <head> <title>window.closed Property«/title> «script type="text/javascript"> // инициализация глобальной переменной для объекта нового окна // этот объект доступен для всех функций страницы var newWind; // создание окна и добавление в него содержимого function newWindow() { newWind = window.open("","subwindow","height=200,width=200"); setTimeout("finishNewWindowO", 100); } function finishNewWindowO { var output = ""; output += "<html><bodyxhl>A Sub-window«/hl>"; output += "«fornixinput type=’button’ value='Close Main Window'"; output +="onclick='window.opener.close()' x/formx/body> </html>"; newWind.document.write(output); newWind.document.close(); } // закрытие по'докна function closewindow() { if (newWind && !newWind.closed) { newWind.close(); </script> </head> 404 Часть III. Объекты документа
<body> <form> cinput type="button" value="Open Window" onclick= "newWindow () " /xbr /> cinput type="button" value="Close it if Still Open" onclick="closewindow()" /> c/form> c/body> , c/html> Чтобы завершить пример закрытия и открытия окна, в подокно была добавлена кнопка, с помощью которой можно закрыть основное окна. В современных браузерах перед выпол- нением последней операции на экране появится запрос на подтверждение действия. См. также: методы window. open (), window. close (). components См. appCore. Controllers Cm. appCore crypto pkcsll Значения: ссылка на объекты Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ Свойства crypto и pkcsll содержат ссылки на объекты браузера, связанные с внутренни- ми механизмами криптографии с открытым ключом (мы не будем их рассматривать в данной книге; чтобы узнать о них подробнее, обратитесь по адресу http://www.mozilla.org/ projects/security/). defaultstatus Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Когда документ будет загружен в окно или фрейм, строка состояния может отображать сообщение, за исключением случаев, когда указатель мыши находится на объекте, задаю- щем содержимое строки состояния (например, ссылка или карта изображения). Свойство window.defaultstatus обычно содержит пустую строку, однако его можно установить равным определенному значению. Любая указанная опция временно заменяется другим зна- чением, когда пользователь наводит указатель мыши на ссылку (о том, как установить вре- менное сообщение в строке состояния, вы узнаете из описания свойства window. status). Чаще всего свойство window.defaultstatus устанавливают после загрузки докумен- та в окно. Сценарий располагается непосредственно в разделе head или body документа или же запускается обработчиком события onload. Пример За исключением случаев изменения содержимого строки состояния при перемещении пользователя по Web-странице, рекомендуется выводить сообщения в нижней части окна при загрузке в нем документа. В листинге 16.5 приведен пример использования свойства Глава 16. Объекты window и frame 405
defaultstatus для восстановления содержимого строки состояния при выполнении обра- ботчика onmouseout. Изменение в строке состояния также выполняется при задании друго- го значения свойства status. Листинг 16.5. Сообщениепо <html> <head> <title>window.defaultstatus property</title> <script type="text/javascript"> window.defaultstatus = "Welcome to my Web site."; </script> </head> <body> <a href="http://www.microsoft.com" onmouseover="window.status = 'Visit Microsoft\'s Home page.'; return true" onmouseout="window.status = '';return true">Microsoft</a> <pxa href = "http://mozilla.org" onmouseover="window.status = 'Visit Mozilla\'s Home page.'; return true" onmouseout="window.status = window.defaultstatus; return true">Mozilla</ax/p> </body> </html> Если вам необходимо отобразить в строке состояния двойные или одинарные кавычки (как во второй ссылке листинга 16.5), то введите перед ними обратную косую черту (\' или \"). См. также: свойство window. status. dialogArguments Значение: различное Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство dialogArguments доступно только для окон, открытых специфическими для IE методами showModalDialogO или showModelessDialogO. Последние позволяют передать диалоговому окну параметр, а свойство dialogArguments обеспечивает доступ к нему сценариям диалогового окна. Значение может быть строкой, числом или массивом JavaScript (массив удобен для передачи нескольких значений). Пример Пример использования свойства dialogArguments приведен в листинге 16.39. С его помощью подставляются и извлекаются аргументы диалогового окна, отображаемого мето- дом window.showModalDialog(). См. также: методы window. showModalDialog (), window. showModelessDialog О. dialogHeight dialogwidth Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- 406 Часть III. Объекты документа
Сценарии документа, размещаемые внутри модального или безрежимного диалогово- го окна (генерируемого специфическими для IE методами showModalDialogO или showModelessDialogO), обладают возможностью получать или изменять высоту и ши- рину окна с помощью свойств dialogHeight и dialogwidth. Доступ к этим свойствам из сценариев основного окна возможен только для безрежимных диалоговых окон, которые ос- таются отображаемыми, когда пользователь работает в главном окне. Значения свойств задаются в виде строк и включают сокращение (рх) для единиц измере- ния пикселей. Пример В диалоговых окнах часто содержатся кнопки или значки, предоставляющие заинтересо- ванным пользователям больше детальных сведений или дополнительные параметры для на- стройки приложения. Вы можете создать функцию переключения окна с одного размера на другой. Следующая функция предполагает использование в диалоговом окне кнопки с назва- нием Show Details (Больше) или Hide Details (Меньше). К обработчику onclick кнопки и привязывается текущая функция. function toggleDetails(btn) { if (dialogHeight == "200px") { dialogHeight = "350px"; btn.value = "Hide Details"; } else { dialogHeight = "200px"; btn.value = "Show Details"; } } На практике вы также можете изменить свойство display со значения попе на block, чтобы убедиться в сокрытии полос прокрутки в меньшей версии диалогового окна. См. также: свойства window. dialogLef t, window. dialogTop. dialogLeft dialogTop Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Сценарии документа, размещаемые внутри модального или безрежимного диалогово- го окна (генерируемого специфическими для IE методами showModalDialogO или showModelessDialog ()), имеют возможность получать или изменять координаты левого верхнего угла окна с помощью свойств dialogLeft и dialogTop. Доступ к этим свойст- вам из сценариев основного окна возможен только для безрежимных диалоговых окон, кото- рые остаются отображаемыми, когда пользователь работает в главном окне. Значения свойств задаются в виде строковых данных и включают сокращение (рх) для единиц измерения пикселей. Если попытаться изменить значения так, чтобы часть окна вы- шла за пределы видимой области экрана, браузер автоматически откорректирует значения. Пример Хотя изменять расположение окна, размер которого был изменен с помощью сценария (или пользователем, если им предоставляется подобная возможность) не рекомендуется, хотя программно эту задачу выполнить не сложно. Следующие операторы в документе, из которо- го вызывается диалоговое окно, располагают последнее по центру окна. Глава 16. Объекты window и frame 407
dialogLeft = (screen.availWidth/2) - (parselnt(dialogwidth)/2) + "px"; dialogHeight = (screen.availHeight/2) - (parselnt(dialogHeight)/2) + "px"; Обратите внимание, что функция parselnt О используется для получения числовой части значений dialogwidth и dialogHeight. См. также: свойства window. dialogHeight, window. dialogTopWidth. directories locationbar menubar personalbar scrollbars statusbar toolbar Значение: объект Чтение/Запись (для защищенных сценариев) Совместимость: WinlE-, MacIE-, NN4+, Mozl+, Safaril+ За пределами области содержимого окна, где непосредственно размещается документ, браузер Netscape Navigator отображает целый набор панелей инструментов и других средств, называемых элементами управления окна. Все браузеры позволяют отображать эти элементы при создании нового окна (третий параметр метода window. open ()), но до появления в NN4 защищенных сценариев эти элементы нельзя было добавить или удалить в главном или лю- бом другом окне. В NN4 эти элементы являются основными объектами в объекте window. В NN6 преду- смотрено дополнительное свойство — панель каталогов (часть окна, подобная фрейму, кото-, рая может быть отображена или скрыта в левой части окна). В то же время браузеры NN6/W3C не позволяют отображать или скрывать полосы прокрутки окна браузера. Изменение состояния отображения этих элементов на ходу влияет на взаимоотношение между внутренними и внешними размерами окна браузера. Если для представления содержи- мого требуется настроить размер окна, то откорректировать элементы управления следует раньше. Все же тщательно обдумайте возможность изменения отображаемых элементов управления окна. Опытные пользователи, как правило, настраивают вид окон своих браузе- ров так, как они привыкли, поэтому любые изменения лишь раздражают их. К счастью, эти' изменения не сохраняются в настройках пользователя, но остаются после выгрузки страницы. Если ваш сценарий изменяет эти настройки, сначала сохраните исходные параметры, а затем, в обработчике события onunload восстановите их. Строка меню на платформе Macintosh не является элементом управления ок браузера. Поэтому состояние ее отображения нельзя изменить средства; сценария. Совет Пример В листинге 16.6 показан пример изменения внешнего вида окна браузера с помощь; свойств directories, locatioribar, menubar, personalbar, scrollbars, statusbar, toolbar. Чтобы запустить этот сценарий, вам необходимо подписать его или настроить до- верителя (см. главу 16). Для выполнения операторов подписанного сценария необхо; включить поддержку Java. 408 Часть III. Объекты д<
После загрузки страницы в сценарии сохраняется состояние каждого элемента окна. Каж- цая кнопка страницы позволяет отобразить или скрыть определенный элемент окна. Функция инвертирует состояние элемента, указанного в качестве аргумента. Обратите внимание, что функция restore О вызывается обработчиком onunload документа. Кроме того, если вы запустите этот сценарий в NN6+, то возникнет некритическая ошибка при отображении или сокрытии полос прокрутки. <html> «head> <title>Bars Bars Bars«/title> ' «script type="text/javascript"> // сохранение исходных внешних размеров при загрузке страницы var originalLocationbar = window.locationbar.visible; var originalMenubar = window.menubar.visible; var originalPersonalbar = window.personalbar.visible; var originalScrollbars = window.scrollbars.visible; var originalStatusbar = window.statusbar.visible; var originalToolbar = window.toolbar.visible; // общая функция установки внутренних размеров function toggleBar(bar) { netscape.security.PrivilegeManager. enablePrivilege("UniversalBrowserWrite"); bar.visible = !bar.visible; netscape.security.PrivilegeManager. revertPrivilege("UniversalBrowserWrite"); } // восстановление установок function, restore() { netscape.security.PrivilegeManager. enablePrivilege("UniversalBrowserWrite"); window.locationbar.visible = originalLocationbar; window.menubar.visible = originalMenubar; window.personalbar.visible = originalPersonalbar; window.scrollbars.visible = originalScrollbars; window.statusbar.visible = originalStatusbar; window.toolbar.visible = originalToolbar; netscape.security.PrivilegeManager. revertPrivilege("UniversalBrowserWrite"); } </script> </head> cbody onunload="restore()"> <form> «b>Toggle Window Bars</bxbr /> <input type="button" value="Location Bar" onclick="toggleBar(window.locationbar)" /xbr /> cinput type="button" value="Menu Bar" onclick="toggleBar(window.menubar)" /xbr /> «input type="button" value="Personal Bar" onclick="toggleBar (window.personalbar) " /xbr /> «input type= "button" value="Scrollba'rs" onclick="toggleBar(window.scrollbars)" />«br /> Глава 16. Объекты window и frame 409
«input type="button" value="Status Bar" onclick="toggleBar(window.statusbar)" /xbr /> «input type="button" value="Tool Bar" onclick="toggleBar(window.toolbar)" /xbr /> «hr /> «input type="button" value="Restore Original Settings" onclick= "restore () " /xbr /> </form> </body> </html> См. также: метод window. open (). document Значение: объект Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство document приведено в данном случае лишь для полноты. Каждый объект window содержит один объект document (хотя в NN4 окно может содержать слои, каждый из которых имеет свой объект document; см. главу 39). В качестве значения свойства document, которое не отображается, выступает объект document. Вместо этого свойство document при- меняется при задании ссылок на свойства и методы документа или других объектов (например форм), содержащихся в нем. Для загрузки в окно другого документа используется объект location (см. главу 17). Подробное описание объекта document приведено в главе 18. См. также: объект document. event Значение: объект Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safaril+ Объект event рассматривается как свойство объекта window только в браузерах IE4+. В объектной модели NN4+ и W3C DOM копия объекта event передается как аргумент функции) обработчика события. Связь с объектом window в IE достаточно непоследовательна, поскольку все действия с объектом event происходят в функциях обработчиков событий-. Единствен- ное отличие состоит в том, что объект может рассматриваться как глобальный, когда одна функция обработчика вызывает другую. Вместо передачи объекта event как параметра,1 функции в IE могут обращаться к нему напрямую (с или без префикса window. в ссылке). За полной информацией о применении объекта event во всех браузерах обратитесь к главе 25. | См. также: объект event. external Значение: объект Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- I . Свойство external (не поддерживаемое в Мас1Е5) применяется лишь тогда, когда окно < браузера выступает компонентой другого приложения. Это свойство обеспечивает своего ро-1 да шлюз между текущим окном браузера и приложением, действующим как хост для него. | Когда WinIE4+ действует как компонент операционной системы-хоста, свойством external I можно воспользоваться для доступа к методам, управляющим поведением документа за преде-1 лами браузера. Три самых полезных метода управления компонентами для разработчиков Web-1 410 Часть III. Объекты документ»
страниц— это AddDesktopComponent (), AddFavorite () и NavigateAndFind (). Два первых метода отображают такое же диалоговое окно предупреждения, как и при выборе ко- манды из меню браузера или контекстного меню рабочего стола, которое не позволяет создате- лям Web-узлов добавлять документы на рабочий стол или в список Избранное (Favorites) без разрешения на то пользователя. Параметры всех трех методов приведены в табл. 16.2. -5 1 МЙЙКШ tedcw. ttU mal .V,» 1 ‘ > v Метод Описание AddDesktopComponent ("URL", "type"[, left, top, width, height]) AddFavorite (“URL"[, "title"]) NavigateAndFind (“URL", "findstring", "target") Добавляет Web-узел или изображение на активный рабочий стол (Active Desktop) (если он включен в системе Windows пользователя). Параметр value имеет значение website или image. (Не обязательно.) Параметры размера окна являются целочисленными Добавляет заданный URL в список Избранное (Favorites). Необязательный параметр для строки заголовка определяет запись в списке меню (если он опущен, то отображается один URL) Переходит к заданному в первом аргументе URL и открывает страницу в указанном целевом объекте (в текущем фрейме открывается пустая строка). Параметр findstring задает текст, поиск которого осуществляется на странице. После нахождения текстовый фрагмент выделяется Пример Первый пример запрашивает у пользователя разрешения на добавление Web-узла на ак- тивный рабочий стол Windows. Если активный рабочий стол не доступен, то пользователю предоставляется возможность активизировать его. external .AddDesktopComponent ("http://www.nytimes.com" , "website" , 200, 100,400, 400); В следующем примере у пользователя спрашивается разрешение на добавление адреса URL в список избранного. Пользователь может придерживаться стандартной процедуры до- бавления Web-страницы в папку Избранное. external.AddFavorite("http://www.dannyg.com/updatell.html", "JSBible 5 Support Center"); Последний пример предполагает, что пользователь выбирает один из вариантов в списке select. Обработчик onchange объекта select вызывает следующую функцию, которая отображает в окне необходимую страницу и прокручивает ее к указанному разделу. function locate(list) { var choice = list.options[list.selectedlndex].value; external.NavigateAndFind("http://www.collegesports.net/ scores.html", choice, "scores"); } frame Element Значения: ссылка на объект f rame или i f rame Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Глава 16. Объекты window и frame 411
Если текущее окно задается дескриптором <frame> или <iframe>, его свойство f rameElement содержит ссылку на элемент, содержащийся в нем. Как вы узнаете из знаком- ства с объектом элемента frame (далее в этой главе), ссылка на объект frame или i frame обеспечивает доступ к свойствам, повторяющим атрибуты объекта элемента HTML. Для окна, не являющегося частью набора фреймов, свойство f rameElement имеет значение null. Преимущества этого свойства становятся очевидными, когда один и тот же документ загружается в несколько наборов фреймов. Сценарий в документе может ссылаться на внешний элемент frame, даже если элемент имеет различные идентификаторы в разных набо- рах. К элементу frameset возможен доступ также и с помощью свойства parentElement свойства f rameElement. var frameSetObj = self.frameElement.parentElement; Ссылка на элемент frameset предоставляет возможность изменять размеры фреймов. См. также: объекты frame, iframe. frames Значение: массив Только для чтения Совместимость: WinE3+, МасЕЗ+, NN2+, Mozl+, Safaril+ В многофреймовом окне верхнее (или родительское) окно может содержать любое коли- чество отдельных фреймов, каждый из которых представляет собой полноценный объект window. Свойство frames применяется тогда, когда оператор ссылается на объект, располо- женный в другом фрейме. Например, если по щелчку на кнопке в одном фрейме в другом за- гружается документ, его обработчик события должен содержать ссылку; указывающую точно, куда следует поместить новый HTML-документ. Данную задачу выполняет свойство frames. Полная ссылка, использующая свойство frames, начинается с объекта parent или top. Последнее требование позволяет JavaScript правильно переместиться по иерархии всех за- груженных на данный момент объектов к требуемому элементу. Узнать текущее количество активных фреймов в окне позволяет следующее выражение. parent.frames.length Это выражение возвращает количество фреймов, определенных в родительском окне. Од- нако оно не учитывает фреймы более высокой степени вложенности (третьего уровня и больше). Другими словами, при наличии таких фреймов не существует свойства, позво- ляющего определить точное количество всех фреймов в окне браузера. Браузер сохраняет информацию о всех отображаемых фреймах в массиве, причем пер- вый фрейм (т.е. первый определенный дескриптором <f rame> элемент в наборе фреймов) имеет индекс 0. parent.frames[0] Если в окне находится три фрейма (с индексами frames [0], frames [1] и frames [2], соответственно), то ссылка на свойство title документа во втором из них выглядит сле- дующим образом. parent.frames[1].document.title Эта ссылка рассматривается подобно пути следования транспортного средства: она начи- нается в родительском окне и ведет через документ второго фрейма к свойству title. В браузерах, предшествующих Е4 и NN6, кроме количества фреймов, определенных в роди- тельском окне, и их имен (top. frames [i] .name), другие свойства напрямую недоступны (см. элемент frame далее в этой главе). В следующих версиях браузеров элементы frame отдельных фреймов имеют несколько свойств, отражающих дополнительные значения атри- бутов дескриптора <f rame>. 412 Часть III. Объекты документа
Использование индексов для задания фреймов — небезопасный метод, поскольку струк- тура набора фреймов может измениться, что приведет и к изменению индексов. Поэтому лучше воспользоваться преимуществами, предоставляемыми атрибутом паше дескриптора «frame >, и присвоить каждому фрейму уникальное описательное имя. Значение name ис- пользуется в атрибутах target ссылок, когда страница загружается во фрейм, отличный от содержащего ссылку. Имя фрейма представляет собой альтернативу индексу при задании ссылок. Например, в листинге 16.7 двум фреймам присвоены различные имена. Для доступа к заголовку документа во фрейме Just AKid2 используется следующая ссылка. parent.JustAKid2.document.title где имя фрейма (с учетом регистра) заменяет frames [1]. Для обеспечения гибкости в JavaScript имя объекта можно использовать вместо индекса массива. parent.frames["JustAKid2”].document.title Основным преимуществом применения имен является их постоянство: как бы ни изменилась структура набора фреймов (а значит, и индексы отдельных фреймов), имена останутся теми же. Пример В листингах 16.7-16.8 приведен пример того, как JavaScript обращается к объектам внут- ри фреймов. Во все кадры загружается один и тот же документ. Сценарий извлекает сведения о текущем фрейме и всем наборе фреймов. На рис. 16.4 показан результат загрузки докумен- та, представленного листингом 16.7. <html> <head> <title>window.frames property</title> </head> «frameset cols="50%,50%"> «frame name="JustAKidl" src="lstl6-08.htm" /> «frame name="JustAKid2" src="lstl6-08.htm" /> </frameset> </html> Определив количество фреймов в наборе (длину набора фреймов), вы получите ноль. Этот результат вполне закономерен, поскольку все фреймы представлены отдельными окнами, и ни один из них не вложен в другое окно. Если же добавить в ссылку свойство parent, то в область учета попадут все фреймы, сгенерированные основным окном документа. <html> «head> <title>Window Revealer II«/title> «script type="text/javascript"> function gatherWindowData() { var msg = "" msg += "<p>«b>From the point of view of this frame: </bxbr />" ; msg += "window.frames.length: " + window.frames.length + "<br />"; msg += "window.name: " + window.name + "</p>"; msg += "«p>«b>From the point of view of the framesetting Глава 16. Объекты window и frame 413
document:</bxbr />"; msg += "parent.frames.length: " + parent.frames.length + "<br / > "; msg += "parent.frames[0].name: " + parent.frames[0].name + "</p>"; return msg; } </script> </head> <body> <script type="text/javascript"> document.write(gatherWindowData()); </script> </body> </html> Последний оператор в этом примере демонстрирует, как правильно использовать син- таксис массивов (скобки) для обращения к определенному фрейму. Индексация массивов фреймов начинается с нуля. Поскольку документ запрашивает имя первого фрейм (parent. frames [ 0 ]), то будет возвращен результат JustAKidl для обоих фреймов. См. также: объекты frame, frameset; свойства window, parent, window, top. Рис. 16.4. Возвращение свойств из двух фреймов, созданных с помощью кода листинга 16.7 history Значение: объект Только для чтения Совместимость: WinIE3+, МасЕЗ+, NN2+, Mozl+, Safaril+ См. описание объекта history в главе 17. 414 Часть III. Объекты документ
innerHeight innerWidth outerHeight , outerwidth Значение: целочисленное Чтение/Запись Совместимость: WinlE-, MacIE-, NN4+, Mozl+, Safaril+ Браузеры NN4+ позволяют сценариям корректировать высоту и ширину любого окна (включая главное окно браузера), благодаря установке соответствующих свойств. Такое из- менение размеров необходимо проводить для страниц, дизайн которых предопределяет высо- ту и ширину окна. Благодаря им, размер окна можно установить, не полагаясь на пользовате- ля (хотя он в любой ситуации имеет возможность вручную изменить размеры главного окна). Поскольку объект navigator (см. главу 38) позволяет установить тип операционной систе- мы, размеры окна можно делать разными в зависимости от используемых шрифтов и пред- ставления элементов управления форм на разных платформах. Современные браузеры обеспечивают две метода указания высоты и ширины окна: внеш- ний (outer) и внутренний (inner). В обоих методах размеры вычисляются в пикселях. Внутренние размеры относятся к области содержимого документа (иногда ее называют ак- тивной областью окна). Если оптимальный способ отображения документа зависит от внут- ренней области, тогда следует установить значения innerHeight и innerWidth. В отличие от этого, внешние размеры относятся к окну целиком, включая все элементы управления (полосы прокрутки, строку состояния и т.д.). Установка свойств outerHeight и outerwidth обычно выполняется совместно с определением параметров объекта screen (глава 38). Как правило, внешние свойства используют для заполнения окном области, дос- тупной на мониторе пользователя. Более эффективным способом изменения этих двух размеров окна является метод window. resizeTo (), поддерживаемый браузерами IE4+. Параметрами метода служат шири- на и высота в пикселях (целочисленные значения). Таким образом, изменение размеров произ- водится в одном операторе. Помните, что этот метод не задает расположения окна. Таким обра- зом, для заполнения окном доступной на мониторе области требуется выполнить еще и метод window. moveTo (), размещающий левый верхний угол окна в точке с указанными координатами. В отличие от тех преимуществ, которые эти свойства предоставляют авторам страниц, в поддерживаемых браузерах существуют ограничения на минимально задаваемый размер в тех сценариях, которые не защищены криптографически. Поэтому внешние размеры окна нельзя установить меньшими 100 пикселей. Это ограничение не допускает использования ок- на малого размера (практически невидимого), чтобы следить за действиями, производимыми в других окнах. В защищенных сценариях окна могут иметь высоту или ширину меньше 100 пикселей, но только с разрешения разработчика. Пример В листинге 16.9 представлен пример, в котором с помощью кнопок изменяются свойства innerHeight, innerWidth, outerHeight, outerwidth (в NN4 и NN6). Все остальные браузеры попросту игнорируют операцию настройки этих свойств. <html> <head> <title>Window Sizer</title> Глава 16, Объекты window и frame 415
«script type="text/javascript"> // сохранение исходный внешних размеров при загрузке страницы var originalwidth = window.outerwidth; var originalHeight = window.outerHeight; // общая функция установки внутренних размеров function setlnner(width, height) { window.innerWidth = width; window.innerHeight = height; } // общая функция установки внешних размеров function setouter(width, height) { window.outerwidth = width; window.outerHeight = height; } // восстановление исходных размеров окна function restore() { window.outerwidth = originalwidth; window.outerHeight = originalHeight; } </script> </head> <body> <form> <b>Setting Inner Sizesc/bxbr /> «input type="button" value="600 Pixels Square" onclick="setlnner (600,600) " /xbr /> «input type="button" value="300 Pixels Square" onclick="setlnner (300,300) " /xbr /> «input type="button" value="Available Screen Space" onclick="setlnner(screen.availwidth, screen.availHeight)" /xbr /xhr /> <b>Setting Outer Sizes«/b>«br /> «input type="button" value="'600 Pixels Square" onclick="setOuter (600,600) " /xbr /> «input type="button" value="300 Pixels Square" onclick="setOuter (300,300) " /xbr /> «input type="button" value="Available Screen Space" onclick="setOuter(screen.availwidth, screen.availHeight)" /xbr /xhr /> «input type="button" value="Cinch up for Win95" onclick="setlnner(273,304)" /xbr /> «input type="button" value="Cinch up for Mac" onclick="setlnner(273,304)" /xbr /> «input type="button" value="Restore Original" onclick="restore () " /xbr /> </form> </body> «/html> См. также: методы window. resizeTo (), window.moveTo (); объект screen; объект navigator. loading Значение: булево Только для чтения Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- 476 Часть III. Объекты документа -
Это свойство, уникальное для браузера NN4, позволяет узнать, загружает ли окно содер- жимое. Если да, то оно имеет значение true или false после завершения загрузки содер- жимого страницы. location Значение: объект Чтение/Запись Совместимость: WinE3+, МасЕЗ+, NN2+, Mozl+, Safaril+ См. обсуждение объекта location в главе 17. locationbar См. directories. name Значение: строка Чтение/Запись Совместимость: WinE3+, МасЕЗ+, NN2+, Mozl+, Safaril+ Всем объектам window можно присвоить имена. Их следует использовать при работе с фреймами, особенно в многофреймовой среде. Главное окно браузера по умолчанию в качестве имени содержит пустую строку. Этому окну присваивать имя нет необходимости, так как в JavaScript и HTML существует немало способов обращения к главному объекту window (свойство top, константа _top для атрибу- та target и свойство opener для открываемых окон). Если необходимо присвоить имя главному окну, то для этого используется свойство window.name. Помните, что свойство окна сохраняется независимо от состояния загрузки или выгрузки документов в нем, поэтому может оказаться, что все сценарии обращаются к одному и тому же документу или набору фреймов. Если не восстановить исходное значение свойства (пустая строка), имя окна будет сохранено при загрузке всех последующих докумен- тов. Я предлагаю в таких ситуациях присвоить имя окну в обработчике события onload, азатем обнулить его в обработчике onunload. <body onload="self.name = 'Main'" onunload="self.name = 1'" > Пример приведен в листинге 16.16 (установка имени родительского окна поможет при изучении взаимоотношений между родительским и дочерним окном). См. также: свойство top; методы window. open (), window. sizeToContent (). navigator Значение: объект Только для чтения Совместимость: WinE4+, МасЕ4+, NN6+, Mozl+, Safaril+ Несмотря на то, что объект navigator является свойством объекта window только в последних версиях браузеров, сам этот объект появился довольно давно (см. главу 38). В предыдущих версиях браузеров он рассматривался как полностью отдельный объект. По- скольку ссылку на объект window при доступе к его свойствам можно опустить, для совмес- тимости со всеми версиями браузеров (по крайней мере с теми, в которых поддерживается объект navigator) можно использовать старый вариант синтаксиса. В ссылках на объект navigator рекомендуется поступать именно таким образом. См. также объект navigator. Глава 16. Объекты window и frame 417
offscreenBuffering Значение: булево или строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Браузеры Internet Explorer 4+ (на платформах Win32) по умолчанию заносят страницу в буфер (фрагмент памяти) до ее представления на экране. Этим поведением можно управ- лять явно с помощью свойства window. offscreenBuf fering. По умолчанию свойство содержит строку auto. Чтобы отменить автоматическое поведе- ние IE по умолчанию, свойству можно присвоить значение булевого типа true или false. Пример Если вы хотите отключить буферизацию всей страницы, то в начале сценария разместите следующую строку кода. window.offscreenBuffering = false; onerror Значение: функция Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Свойство onerror представляет собой исключение из правила этой книги: не описывать обработчики событий как свойства объектов. Причина заключается в том, что с событием onerror связаны некоторые специальные свойства, полезные при настройке обработчиков событий в сценариях. Современные браузеры (IE5+, NN4+ и W3C) разработаны таким образом, чтобы предот- вратить навязчивый вывод сообщений об ошибках, встречающихся при загрузке страницы или навигации по ней. Даже самые простые извещения о возникших проблемах (сообщения или значки в строке состояния) могут оказаться сложными для пользователей, не знакомых с JavaScript. JavaScript позволяет отключить вывод предупреждений об ошибках или сообще- ний о них при запуске сценариев на странице. Вопрос заключается в следующем: в каких слу- чаях необходимо отключать вывод этих сообщений? Обычно ошибки свидетельствуют о неполадках в сценарии. Ошибка может быть резуль- татом неправильного программирования действия или несовместимости определенных средств JavaScript (например, отсутствие поддержки объекта текущей версией браузера дм используемой платформы, в которой сценарий при отладке не был протестирован). При воз- никновении таких ошибок сценарий обычно не может продолжить работу и выполнить свою задачу. Отменять вывод ошибок выполнения сценария в процессе его разработки не имеет смысла, поскольку так вы вряд ли узнаете о скрытых ошибках. Так же опасно скрывать диа- логовые окна ошибок от пользователей, которые будут считать, что страница загружается нормально, тогда как это может быть не так. В такой ситуации некоторые данные иногда об- рабатываются или отображаются некорректно. Тем не менее, существуют такие ситуации, когда можно отключить вывод диалоговых окон с сообщениями об ошибках. Например, если известно, что версия браузера для опреде- ленной платформы сообщает об ошибке, но сценарий при этом выполняется правильно, мож-' но не допустить появления такого сообщения. Однако сделать это можно лишь после тща-. тельного тестирования, убедившись, что сценарий выполняется абсолютно корректж несмотря на возникающие ошибки. 418 Часть III. Объекты докумы
IE запускает обработчик события onerror только для ошибок, появляющихся во *Н» twenty время выполнения сценария. Это означает следующее: если сценарий содержит синтаксическую ошибку, которая возникает на этапе загрузки страницы, обра- ботчик события onerror не запускается, и перехватить сообщение о ней нельзя. Более того, если в IE установлен отладчик сценариев, любой код, предназначен- ный для отключения вывода сообщений об ошибках, работать не будет. При запуске браузера свойство window.onerror имеет значение <undefined>. В та- ком состоянии обо всех ошибках JavaScript браузер докладывает обычным образом — выво- дом окна или сообщения. Чтобы не допустить отображение сообщений об ошибках, свойству window. onerror необходимо присвоить функцию, которая не выполняет никаких действий. function doNothingO {return true;} window.onerror = doNothing; Для восстановления сообщений об ошибках потребуется заново загрузить страницу. Свойству window. onerror можно присвоить и более полезную функцию, которая управляет ошибками. Когда сообщения об ошибках отображаются (по умолчанию), ошибка сценария (а также Java-аплета или исключения класса) вызывает функцию, присвоенную свойству onerror, и передает ей три параметра: сообщение об ошибке; URL документа, вызвавшего ее; номер строки с ошибкой. Важно, что все ошибки можно обработать созданными собственноручно средствами (или вообще не сообщать пользователю о них). Последним оператором функции должен быть return true — он обеспечивает вывод стандартного сообщения об ошибке JavaScript. Вы можете перехватывать все ошибки и управлять ими с помощью специально разрабо- танного интерфейса (не требующего вывода предупреждающих сообщений пользователю). Последний оператор подобной функции должен содержать оператор return true, если вы не хотите, чтобы сообщения об ошибках отображались на экране. Если для вызова Java-аплетов или методов Java-класса напрямую из сценариев использу- ется LiveConnect, то для обработки прерываний, генерируемых языком Java, подойдет та же схема. Прерывание Java необязательно свидетельствует об ошибке в коде: в некоторых мето- дах предполагается, что Java-код перехватывает определенные типы прерываний (например, действие в ответ на запрет доступа в диалоговом окне защищенного сценария). Пример пере- храта прерываний Java приведен в главе 44. Кроме того, в главе 31 описана модель обработки прерываний JavaScript, которая представлена в браузерах, совместимых с W3C DOM. Пример В листинге 16.10 приведен сценарий, содержащий ошибку. В него добавлена функция обработ- ки ошибки, которая отображает на экране отдельное окно, содержащее текстовую область (рис. 16.5). Кнопка Submit обеспечивает отправку сообщения об ошибке по указанному почтовому адре- су — это один из вариантов сообщения о возникновении неполадок в готовых приложениях. <html> <head> <title>Error Dialog Control</title> <script type="text/javascript"> Глава 16. Объекты window и frame 419
// функция с неправильным значением переменной function goWrongO { var х = fred; } // отключение окон с ошибками function errOffO { window.onerror = doNothing; } // включение окон с ошибками function errOn() { window.onerror = handleError; } // назначение обработчика ошибок по умолчанию window.onerror = handleError; \ // обработчик при выключении ошибок предотвращает появление окон function doNothing() { return true; } function handleError(msg, URL, lineNum) { var errWind = window.open("","errors","height=270,width=400") ; var wintxt = "chtmlxbody bgcolor=red>"; wintxt += "cb>An error has occurred on this page. Please report it to Tech Support.</b>"; wintxt += "<form method=POST enctype='text/plain' action=mailTo:Support4@dannyg.com >"; wintxt += "ctextarea name=1errMsg' cols=45 rows=8 wrap=VIRTUAL>"; wintxt += "Error: " + msg + " \n"; wintxt += "URL: " + URL + "\n"; wintxt += "Line: " + lineNum + "\n"; wintxt += "Client: " + navigator.userAgent + "\n"; wintxt += "------------------------------------------\n" ; wintxt += "Please describe what you were doing when the error occurred:"; wintxt += "</textareaxbr />" ; wintxt += "cinput type=SUBMIT value='Send Error Report'»"; wintxt += "cinput type=button value='Close1 onclick= 'self.close()'>"; wintxt += "c/formx/bodyx/html>"; errWind.document.write(wintxt); errWind.document.close(); return true,- } </script> </head> <body> cform name="myform"> cinput type="button" value="Cause an Error" one1i ck ="goWrong()" /> cpxinput type="button" value="Turn Off Error Dialogs" onclick="errOff()" /> cinput type="button" value="Turn On Error Dialogs" onclick="errOn()" /x/p> c/form> c/body> c/html> 420 Часть III. Объекты документ*
Я добавил на страницу кнопку, выполняющую “принудительную” перезагрузку, в резуль- тате которой восстанавливается значение свойства window.onerror. Если отключить отобра- жение сообщений об ошибках, то функция управления ошибками выполняться не будет. См. также: метод location.reload(); обработка прерываний JavaScript (глава 31); отладка сценариев (глава 45). Рис. 16.5. Пример “автоматического” вывода сооб- щения об ошибке opener , Значение: ссылка на объект окна Чтение/Запись Совместимость: WinIE3+, МасЕЗ+, NN3+, Mozl+, Safaril+ Многие авторы сценариев ошибочно считают, что окно браузера, созданное методом window.open (), имеет с главным окном взаимоотношения типа “дочерний-родительский” (как это происходит в случае с фреймами). Но подобная связь не устанавливается! Вновь соз- данное окно браузера имеет очень слабую связь с породившим его окном: посредством свой- ства opener. Его цель — обеспечить сценариям в новом окне ссылку на исходное окно. На- пример, исходное окно может содержать значения переменных или функции общего назначения, которые используются в новом окне. Кроме того, исходное окно иногда содер- жит элементы форм, настройки которых или являются значениями нового окна, или устанав- ливаются при взаимодействии пользователя с ним. Поскольку значение свойства opener — это ссылка на объект window, начинать ссылки можно непосредственно с него. Можно также использовать и более полную ссылку вида window.opener или self .opener. Ссылка должна включать определенный объект или свойство исходного окна. Если новое окно открывает следующее новое окно, то цепочка остается в силе; она лишь становится на один шаг длиннее. Третье порожденное окно может запросить объекты в глав- ном окне с помощью следующей ссылки. opener.opener.... Правильная методика построения сценариев для третьего окна заключается в том, чтобы сохранить значение opener .opener в глобальной переменной. Если пользователь закроет второе окно, переменной можно будет воспользоваться как ссылкой на главное окно. Если сценарий, генерирующий новое окно, находится во фрейме, свойство opener ука- зывает на этот фрейм. Чтобы новое окно взаимодействовало с родительским или каким-либо другим фреймом исходного окна, следует с особой тщательностью создать ссылку на такой Глава 16. Объекты window и frame 421
объект. Например, если новому окну требуется установить свойство checked флажка во фрейме, сестринском по отношению к исходному окну, полная ссылка будет выглядеть так. opener.parent.sisterFrameName.document.formName.checkboxName.checked При создании ссылки будьте предельно внимательны, шаг за шагом отслеживая, как сце- нарий “проходит” из исходной точки в точку назначения. Пример Чтобы продемонстрировать важность свойства opener, рассмотрим, как новое окно соз- дается в основном окне браузера (листинг 16.11). Функция doNewO генерирует небольшое подокно и загружает в него файл, представленный листингом 16.12. Обратите внимание на первый условный оператор этой функции, с помощью которого окно активизируется (используется метод focus ()), если оно уже существует. Листинг Главное окно браузера, в котором генерируется подокно «html> «head> «title>Master of all Windows«/title> «script type="text/javascript"> var myWind; function doNew() { if (ImyWind || myWind.closed) { myWind = window.open("lstl6-12.htm","subWindow", "height=200,width=350,resizable"); } else { // вывод на передний план существующего подокна myWind.focus(); } } «/script» </head> <body> «form name="input"> Select a color for a new window: «input type="radio" name="color" value="red" checked^"checked" />Red «input type="radio" name="color" value="yellow" />Yellow «input type="radio" name="color" value="blue" />Blue «input type= "button" name="storage" value="Make a Window" onclick= "doNewO" /xhr /> This field will be filled from an entry in another window: «input type="text" name="entry" size="25" /> «/form> </body> «/html> Листинг 16.12. Ссылка на свойство пр «html> «head> «title>New Window on the Block«/title> «script type="text/javascript"> function getColorO { 422 Часть III. Объекты документ»,
11 сокращение ссылки colorButtons = self.opener.document.forms[0].color; I/ проверка установленного переключателя for (var i = 0; i < colorButtons.length; i++) { if (colorButtons[i] .checked) { return colorButtons[i].value; } } return "white"; } </script> <script type="text/javascript"> document.write("cbody bgcolor=’" + getColorO + "'>") </script> </head> <body> <hl>This is a new window.</hl> <form> cinput type="button" value="Who's in the Main window?" onclick="alert(self.opener.document.title)" /> <p>Type text here for the main window: cinput type="text" size="25" onchange="self.opener.document.forms[0]. entry.value = this.value" />c/p> c/form> c/body> </html> В функции getColor О многочисленные ссылки на массив переключателей могут вы- глядеть длинными. Чтобы упростить ссылки, в этой функции массив переключателей сохра- няется в переменной с именем colorButtons. Данная переменная фигурирует во всех ссылках на объекты переключателей, включая операторы проверки их установки. Кнопка во втором окне выводит на экран сообщение о том, кто открыл это окно. Даже ес- ли в основном окне загружена другая страница, свойство opener второго окна будет указы- вать на первое. Но при этом свойство document основного окна изменится. Наконец, второе окно содержит объект ввода текстовых данных. Введите в него опреде- ленный текст, предварительно активизировав поле. Обработчик onchange обновляет тек- стовое поле в основном окне (предполагается, что в последнем открыт исходный документ). См. также: методы window. open (), window. focus (). outerHeight outerwidth Cm. innerHeight и innerWidth выше. pageXOffset pageYOffset Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Mozl+, Safaril+ Левый верхний угол (внутренней) области содержимого окна браузера является точкой от- счета при прокрутке документов. Когда документ прокручен до самого верха и выровнен по ле- вому краю (или же он достаточно мал, чтобы полностью поместиться в окне браузера), его рас- положение считается равным 0,0, т.е. документ находится на нулевом расстоянии от левого Глава 16. Объекты window и frame 423
верхнего угла. Если прокрутить документ, то его расположение будет задано другим значением. Это расстояние называется смещением страницы, а свойства pageXOf f set и pageYOffset позволяют определить, соответственно, горизонтальное и вертикальное смещение в пикселях. Master ot ail Windows Mierfsseft internet ExpterorС file ‘ •-!*( Vie л ! «ivonfes Help . 0®** ” !.*) 1*1 jsearch ^Favortw g ~ Q Ш Select a color for a new window ©Red О Yellow QBlue This field will be filled from an entry m another wmdow Hello from the subwindow <jDo My Compute Puc. 16.6. Основное окно и подокно, связанные свойством opener Область использования этих значений становится очевидной при разработке, например, кнопок навигации, тщательно управляющих содержимым страницы, отображаемым в окне. Например, страница может состоять из двух фреймов, в одном из которых находятся элемен- ты навигации, а в другом — непосредственно содержимое. К элементам управления относят- ся полосы прокрутки, которые из эстетических соображений при отображении фрейма от- ключены. Сценарии, использующие созданные вручную кнопки прокрутки, определяют значение свойства pageYOf f set, а затем с помощью метода window, scrolITo () про- кручивают документ до следующего логического раздела. В IE4+ похожими свойствами обладает объект body: body, scrolILeft и body, scrolITop (см. главу 18). Пример Сценарий листинга 16.13 представляет собой необычную программную конструкцию, соз- дающую набор фреймов и добавляющую в каждый из двух фреймов одного документа опреде- ленную информацию. Цель данного примера (обычно открывается в Safari) — продемонстриро- вать возможности свойств pageXOf f set и pageYOf f set в прокручивающихся документах. В левом фрейме содержится два поля, в которых представлены значения свойств pageXOf f set и pageYOf f set правого фрейма. В правом фрейме вы увидите тридцатист- роковую таблицу фиксированной ширины (800 пикселей). События мыши захватываются на уровне документа (глава 18), что позволяет для запуска функции showOffsets () выпол- нить щелчок в любой части таблицы и за ее пределами. Эта функция выводит в соответст- вующих полях значения смещения страницы текущего фрейма. 424 Часть III. Объекты докупи
16.13. Свойства pageXOffeet ИpageYOffeet <html> «head> , «title>Master of all Windows«/title> «script type="text/javascript"> function leftFrameO { var output = ”«html>«body«h3>Page Offset Values«\/h3> «hr \/>\n"; output += "<form>PageXOffset:«input type='text' name='xOffset1 size='4' \/>«br \/>\n"; output += "PageYOffset:«input type='text’ name='yOffset' size='4' \/>«br \/>\n"; output += "«\/formx\/bodyx\/html>"; return output; } function rightFrame() { var output = "«htmlxheadxscript type='text/javascript’>\n"; output += "function showOffsets() {\n"; output += "parent.readout.document.forms[0].xOffset.value = self.pageXOffset;\n"; output += "parent.readout.document.forms[0].yOffset.value = self.pageYOffset;\n}\n"; output += "document.captureEvents(Event.CLICK);\n"; output += "document.onclick = showOffsets;\n"; output += "<\/script>«\/head>«body>«h3>Content Page«\/h3>\n"; output += "Scroll this frame and click on a table border " + " to view page offset values.«br \/>«hr \/>\n"; output += "«table border='5' width='8001>"; var oneRow - "«td>Cell l«\/td>«td>Cell 2«\/tdxtd>Cell 3 <\/tdxtd>Cell 4«\/td>" + "<td>Cell 5«\/td>"; for (var i = 1; i «= 30; i++) { output += "<tr>«tdxb>Row " + i + ”«\/b>«\/td>" + oneRow + ”«\/tr>"; } output += "<\/tablex\/bodyx\/html>” return output; } «/script> «/head> «frameset cols="30%,70%"> «frame name="readout" src="javascript:parent.leftFrame()" /> «frame name="display" src="javascript:parent.rightFrame()" /> </frameset> </html> Чтобы понять, как свойствам смещения задаются значения, прокрутите окно в горизон- тальном направлении. Свойство pageXOffset несколько увеличится. То же происходит и со свойством pageYOf fset при прокрутке документа в вертикальном направлении. Помни- те, что эти свойства указывают координаты левого верхнего угла документа. В листинге 18.20 приведена версия этого документа для IE4+. См. также: свойства window. innerHeight, window. innerWidth, body. scrollLeft, body.scrollTop; методы window.scrollBy(), window.scrollTo (). Глава 16. Объекты window и frame 425
parent Значение: ссылка на объект окна Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство parent (а также свойство top, о котором рассказано далее в этом разделе) вступает в действие, как правило, тогда, когда отображаемый документ является частью мно- гофреймового окна. HTML-документы, отображаемые во фреймах, отличаются от того доку- мента, который содержит сам набор фреймов. Этот документ хранится в памяти браузера (причем именно его URL отображается в строке адреса) и не виден пользователю (кроме ис- ходного вида при выборе опции Source View (Просмотр исходного кода)). Если сценариям в отображаемых документах необходимо сослаться на объекты или свой- ства окна, содержащего набор фреймов, используется свойство parent (в ссылке не следует указывать объект window, например window.parent .propertyName, поскольку это вы- зывает ошибки в ранних версиях браузеров). На первый взгляд, свойство parent нарушает ие- рархию объектов, поскольку в документе с одним фреймом оно указывает на уровень, находя- щийся выше. Если не указать свойство parent или вместо него использовать свойство self, то ссылка будет указывать на фрейм, а не на внешний объект window с набором фреймов. Нетрадиционный, но вполне приемлемый способ использования объекта parent заклю- чается в хранении временных переменных или даже массивов данных. Эти значения доступ- ны всем документам, загруженным во фреймы, включая ситуацию, когда документы изменя- ются. При сохранении данных в родительском фрейме “на ходу” (т.е. в ответ на действие пользователя) следует проявлять осторожность. В ранних версиях браузеров переменные воз- вращались к значениям по умолчанию (т.е. настраиваемым сценарием родительского окна) при изменении размеров окна. В дочернем окне можно вызвать функцию, определенную в родительском окне. Ссылка на функцию выглядит следующим образом. parent.functionName([parameters]) С первого взгляда, свойства parent и top могут показаться идентичными. В среде, ко- торая состоит из одного окна, содержащего набор фреймов, и его непосредственных дочер- них окон, так и есть. Но если одно из них само содержит набор фреймов, то общая иерархия объектов включает три поколения окон. С точки зрения самого “младшего” дочернего окна (например определенного во втором наборе фреймов), свойство parent указывает на его не- посредственно родительское окно, тогда как top указывает на первое окно с основным набо- ром фреймов в этой последовательности. С другой стороны, новое окно, созданное методом window. open (), не имеет взаимоотно- шений типа “родительский-дочерний” с исходным окном. Поэтому его свойства top и parent указывают на само новое окно (об эти! взаимоотношениях см. ранее в настоящей главе). Пример Чтобы продемонстрировать, как различные свойства объекта windows задаются в мно- гофреймовых документах, загрузите в браузере листинг 16.14. Отобразите в каждом фрейме один и тот же документ (листинги 16.15). Этот документ представляет несколько важных свойств окна, включая свойство document .title. Листинг ЖН Мжгофрвймовый wrpeffl из листинг! 16.11 <html> <head> i <title>The Parent Property Example</title> 426 Часть III. Объекты документа
«script type="text/javascript"s self.name = "Framesetter"; </script> «/heads «frameset cols="50%,50%" onunload="self.name = ' «frame name="JustAKidl" src="lstl6-15.htm" /> «frame name="JustAKid2" src="lstl6-15.htm" /> «/framesets </html> * ГИНГ 16.15. Отображение нескольких с? а объекта window <html> «heads «titlesWindow Revealer II«/titles «script type="text/javascript"s function gatherWindowData() { var msg = ""; msg = msg + "top name: " + top.name + "<br /s"; msg = msg + "parent name: " + parent.name + "«br />"; msg = msg + "parent.document.title: " + parent.document.title + "«br /s"; msg = msg + "window name: " + window.name + "«br /s"; msg = msg + "self name: " + self.name + "«br /s"; msg = msg + "self.document.title: " + self.document.title; return msg; } «/scripts «/heads «bodys «script type="text/javascript"s document.write(gatherWindowData()); «/scripts• «/bodys «/htrnls В двух кадрах этого примера (рис. 16.7) содержатся ссылки на объекты window и self. Они возвращают имя фрейма в наборе (JustAKlidl для левого фрейма и JustAKid2 для пра- вого фрейма). Другими словами, для каждого фрейма объект window представлен по- разному. Ссылка self. document. title соответствует документу, загруженному только в текущий фрейм. При этом ссылки top и parent (в настоящем примере они одинаковые) определяют свойства, общие для обоих фреймов. Причина такого поведения очень проста. Стоит обратить внимание на несколько других моментов. Первое: имя окна с набором кадров назначается при загрузке кода листинга 16.14, а не по обработчику события onload дескриптора «framesets. Причина такого поведения очень проста— имя должно назна- чаться фрейму до того, как в него будет вставлено содержимое. Если же ожидать возникно- вения события onload, то имя фрейму будет назначаться после его заполнения данными. Второе: я восстановил пустое имя родительского окна при выгрузке документов набора фреймов. В результате будут предотвращены возможные конфликты, возникающие при за- грузке в основное окно последующих документов. См. также: свойства window, frames, window, self, window, top. Глава 16. Объекты window и frame 427
Рис. 16.7. Свойства top и parent одинаковы для обоих кадров personalbar См. directories. returnvalue Значение: любого типа Чтение/Запись Совместимость: WinIE4+, MacIE5+, NN-, Moz-, Safari- Сценарии используют свойство returnvalue в документах, загружаемых в необычное для IE модальное диалоговое окно. Последнее генерируется методом showModalDialog (), который возвращает те данные, которые были присвоены свойству returnvalue диалого- вого окна до его закрытия. Такое поведение возможно по следующей причине: обработка сценариев в главном окне приостанавливается, пока открыто модальное диалоговое окно. Ес- ли его закрыть, сценарию в главном окне можно возвратить значение, причем выполнение продолжится с той точки, в которой было вызвано модальное окно. Пример Пример использования свойства returnvalue приведен в листинге 16.39, в котором вы ознакомитесь также с методом showModalDialog () (в IE4+). См. также: метод showModalDialog (). screen Значение: объект screen Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Несмотря на то, что объект screen является свойством объекта window только в по- следних версиях браузеров, сам этот объект появился еще в NN4 (см. главу 38), но как от- дельный элемент. Поскольку ссылку на объект window можно опустить при доступе к его 428 Часть III. Объекты документа
свойствам, для совместимости со всеми версиями браузеров (по крайней мере с теми, кото- рые поддерживает объект screen) можно использовать старый вариант синтаксиса. В ссыл- ках на объект screen рекомендуем поступать именно таким образом. Пример Примеры использования объекта screen для определения характеристик монитора ком- пьютера, в котором запущен браузер, приведены в главе 38. См. также: объект screen. screenLeft screenTop Значение: целочисленное Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Браузеры IE5+ поддерживают свойства screenLef t и screenTop объекта window, по- зволяющие получить положение в пикселях (относительно левого верхнего угла (0,0) мони- тора) элемента, который в терминологии Microsoft имеет название клиентской области окна браузера. Клиентская область исключает многие элементы управления окна (заголовок, ад- ресную строку и панель изменения размеров окна). Поэтому, когда окно браузера IE5+ от- крыто во весь экран (т.е. панели изменения размеров окна не отображаются), свойство screenLef t имеет значение 0, a screenTop зависит от панелей управления, отображенных пользователем. Для окон, открытых не во весь экран (причем размещенных так, что их левая и верхняя части выходят за пределы экрана), значения свойств могут быть отрицательными. Два этих свойства предназначены только для чтения. Изменить положение всего окна браузера (а не только клиентской области) позволяют методы window. moveTo () и window. moveBy (). Браузеры IE вплоть до версии 5.5 не поддерживают свойств, задающих положение всего окна браузера. Пример Приложение The Evaluator (глава 13) позволяет детально изучить свойства использования screenLef t и screenTop. Запустите браузер и максимально расширьте его окно (в Windows). Введите в первое текстовое поле следующее выражение. window.screenLeft Щелкните на кнопке Evaluate для просмотра текущих установок. Уменьшите размер окна браузера и перетащите его по экрану. При каждом перетаскивании щелкайте на кнопке Evaluate для ознакомления с изменениями. Эти же операции выполните и для свойства window.screenTop. См. также методы window. moveTo (), window. moveBy (). screenX screenY Значение: целочисленное Чтение/Запись Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ NN6+/Moz/Safari используют свойства screenX и screenY, чтобы расположить внеш- нюю границу окна относительно левой верхней координаты (0,0) монитора. Окно браузера включает панели изменения размеров окна шириной четыре пикселя, которые имеют все окна на платформе Win32. Поэтому, когда окно браузера NN6+ открыто во весь экран, значения свойств screenX и screenY равны -4. Netscape Navigator не поддерживает свойств, которые Глава 16. Объекты window и frame 429
эквивалентны свойствам screenLeft и screenTop, используемым в IE5 (они отвечают клиентской области окна). В NN можно только проверить, какие панели инструментов ото- бражаются в окне браузера (см. window, directories). Оба свойства можно изменить средствами сценария, что приведет к перемещению окна, однако более удобными являются все же методы window. moveTo () и window. moveBy (), поскольку обе координаты в последнем случае можно указать в одном операторе. Пример Приложение The Evaluator позволяет экспериментировать со свойствами screenX и screenY. Разверните окно браузера во весь экран (в Windows) и введите в верхнее тексто- вое поле следующее выражение. window.screenY Щелкните на кнопке Evaluate для просмотра текущих установок. Уменьшите размер окна браузера и перетащите его по экрану. При каждом перетаскивании щелкайте на кнопке Evaluate для ознакомления с изменениями. Эти же операции выполните для свойства window.screenY. См. также: методы window. moveTo (), window. moveBy (). scrollbars См. directories. scrolIMaxX scrolIMaxY Значение: целочисленное Чтение/Запись Совместимость: WinlE-, MacIE-, NN7.1+, Mozl.4+, Safaril- B указанных браузерах эти свойства позволяют определить максимальные границы про- крутки документа в окне. Прокрутка выполняется только в случае добавления в окно полос прокрутки. Значения этих свойств указываются в пикселях. См. также: свойства scrollX, scrollY scrollX scrollY Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN7.1+, Mozl+, Safaril+ Свойства scrollX и scrollY в NN6+/Moz/Safari позволяют определить положение го- ризонтальной и вертикальной полос прокрутки окна. Прокрутка возможна только тогда, когда окно отображает полосы прокрутки. Целочисленные значения задаются в пикселях. Объектная модель IE не поддерживает этих свойств окна, однако аналогичную информа- цию содержат свойства body. scrollLef t и body. scrollTop. Пример В приложении The Evaluator предусмотрено достаточно возможностей для детального изучения свойства scrollX и scrollY. Введите в верхнее поле следующее выражение. window.scrollY Теперь вручную прокрутите страницу вниз и щелкните на кнопке Evaluate. Узнайте, на- сколько страница сместилась вниз при прокрутке. См. также: свойства body. scrollLeft, body. scrollTop. 430 Часть III. Объекты документа
self Значение: ссылка на объект окна Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Так же, как ссылка на объект window не является обязательной, свойство self можно опустить, если ссылка задается на объект в том же окне. Кажется необычным, что свойство self представляет тот же объект, что и window. Например, чтобы обратиться к заголовку окна с одним фреймом, можно использовать любую из трех следующих конструкций. window.document.title self.document.title document.title Несмотря на то, что self является свойством окна, не следует сочетать различные типы ссылок в сценарии страницы с одним фреймом (например, начинать ссылки с конструкции window, self — известно, что такой синтаксис вызывает многочисленные проблемы в сце- нариях). Однако указание свойства self, необязательное в окнах с одним фреймом, делает код понятным для чтения. В окнах с несколькими фреймами необходимо использовать это свойство очень внимательно. В JavaScript ссылки в пределах одного окна обрабатываются достаточно логично. Поэто- му, обычно часть self в них можно опустить. Однако, когда документ находится в много- фреймовом окне, полные ссылки (включая префикс self) делают чтение и отладку кода более простыми. Свойство self имеют все окна, поэтому оно содержит ссылку на объект window. Пример В листинге 16.16 выполняются те же операции, что и в листинге 16.5, но в первом в ссыл- ках на объект окна применено свойство self. Подобные ссылки использовать совсем не обя- зательно, хотя в многофреймовых документах они играют важную роль при обращении одно- го фрейма к объектам в других фреймах. Свойство self позволяет быстро указать текущий фрейм, из которого вызываются элементы других фреймов. ЦЫсажг Мй. Использование свойстве **if <html> <head> <title>self Property</title> <script type="text/javascript"> self.defaultstatus = "Welcome to my Web site."; </script> </head> <body> <a href="http://www.microsoft.com" onmouseover="self.status = 'Visit Microsoft\'s Home page.'; return true;" onmouseout="self.status = 1’;return true;">Microsoft</a> <pxa href="http://mozilla.org" onmouseover="self.status = 'Visit Mozilla\'s Home page.'; return true;" onmouseout = "self . status = self .defaultstatus return true; ">Mozilla</ax/p> </body> </html> См. также: свойства window, frames, window, parent, window, top. Глава 16. Объекты window и frame 431
sidebar См. appCore. status Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ B нижней части окна браузера находится строка состояния. Часть строки занимает область, в которой обычно отображается состояние загрузки документа или URL ссылки, на которую на- веден указатель мыши. Временное содержимое этой строки можно изменить, присвоив строку с текстом свойству status объекта window. Корректировать свойство status необходимо лишь в ответ на события, дающие временный эффект (например, обработчик onmouseover объекта ссылки или карты изображения). Установка этого свойства отменяет другие его значе- ния. Когда пользователь сводит указатель мыши с объекта, изменяющего содержимое строки состояния, последняя возвращается к значению по умолчанию (на некоторых страницах она может быть пустой). Safari 1.0 не всегда отображает в строке состояния новый текст. Это свойство окна используется как наиболее дружественный пользователю вариант ото- бражения URL ссылки, когда пользователь перемещает указатель мыши по странице. Напри- мер, в строке состояния можно описать тему страницы, на которую указывает ссылка (текст размещается в ответ на возникновение события onmouseover). Следует также помнить, что опытные пользователи привыкли видеть в этой строке URL. Поэтому можно создавать, на- пример, комбинированные сообщения (при этом строка состояния будет включать описание страницы, за которым в скобках следует URL). В средах с несколькими фреймами можно ус- тановить свойство window. status, не заботясь об указании адреса отдельного фрейма. Пример В листинге 16.17 свойство status устанавливается в обработчике onmouseover. Оно приравнивается к ссылкам, заданным в дескрипторах HTML-ссылки. Обратите внимание, что в последней строке обработчика должно возвращаться значение return true, или сооб- щение не будет отображаться в строке состояния всех указанных браузеров. Л»сл1нг16Л 7. j <html> <head> <title>window.status Property</title> </head> <body> <a href="http://www.dannyg.com" onmouseover="window.status = 'Go to my Home page. (www.dannyg.com)’; return true"> Home</a> <pxa href = "http://mozilla.org" onmouseover="window.status = 'Visit Mozilla Home page. (mozilla.org)'; return true"> Mozilla</ax/p> '< /body> </html> 432 Часть III. Объекты документа
Чтобы избежать непредвиденного поведения межплатформенных браузеров при обработ- ке события onmouseover и свойства window. status, добавьте в код обработчик событий onmouseout для ссылок и клиентских карт изображений. Подобные обработчики onmouseout должны устанавливать свойство status равным пустой строке. Таким образом, при наведе- нии указателя мыши на объект ссылки в строке состояние будет выводиться сообщение, за- данное в свойстве defaultstatus. Если вы собираетесь написать общую функцию, кото- рая управляет сообщениями в строке состояния, то используйте в ней обработчик onmouseover очень аккуратно, не забывая об операторе return true. В листинге 16.18 приведен альтернативный вариант. <html> <head> <title>Generalizable window.status Property</title> <script type="text/javascript"> function showstatus(msg) { window.status = msg; return true; } </script> </head> <body> <a href="http://home.netscape.com" onmouseover="return showstatus('Go to my Home page.')" onmouseout="return showstatus('1)">Home</a> <pxa href = "http: //mozilla.org" onmouseover="return showstatus('Visit Mozilla Home page.’)" onmouseout="return showstatus('')">Mozilla</a></p> </body> </html> Обратите внимание, как обработчики событий возвращают результат выполнения метода showStatus (). В последнем примере управления строкой состояния (листинг 16.19) показано, как в ниж- нюю часть окна браузера добавить бегущий текст. ЛктрГ СоэдМм 6егущ8*ст>ов» <html> <head> <title>Message Scroller</title> <script type="text/javascript"> var msg = "Welcome to my world..."; var delay = 150; var timerId; var maxCount = 0; var currCount = 1; function scrollMsgO { // Установка количества прокруток сообщения if (maxCount == 0) { maxCount = 3 * msg.length; } Глава 16. Объекты window и frame 433
window.status = msg; // отслеживание количества прокрученных символов curгCount++; I/ смещение первого символа сообщения в конец сообщения msg = msg.substring (1, msg.length) + msg.substring (0, 1); // проверка достижения последнего символа строки if (currCount >= maxCount) { timerID =0; // zero out the timer window.status = // clear the status bar return; // break out of function } else { // рекурсивный вызов функции timerld = setTimeout("scrollMsg()", delay); } } </script> </head> cbody onload=scrollMsg()"> </body> </html> Поскольку строка состояния управляется с помощью отдельной функции (а не обработчи- ка события onmouseover), то вам нет необходимости добавлять в ее конец оператор return true, чтобы установить свойство status. Функция scrollMsg () использует сложные конструкции JavaScript (метод window. setTimeout ()) и методы управления строками (глава 27). Чтобы изменить скорость прокрутки текста в строке состояния, введите другое значение переменной delay. Установка свойства status в обработчике события onmouseover в NN выпол- С0®81 няется несколько некорректно. Сценарий постоянно “конфликтует” с браузером v за право заполнить данными строку состояния. Если ссылка, на которую наво- дится указатель мыши, находится на границе фрейма, то событие onmouseover вызвать практически невозможно. Таким образом запрограммированое сообще- ние в строке сообщения не отображается. Тестировать подобные документы Web-разработчикам довольно сложно. См. также: свойство window.defaultstatus; обработчики событий onmouseover, onmouseout; объект link. statusbar toolbar См. locationbar. top Значение: ссылка на объект окна Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство top объекта window указывает на самое верхнее окно в иерархии объектов до- кумента. Для окна с одним фреймом оно указывает на тот же объект, что и window (а также его свойства self и parent), поэтому в ссылку нельзя включать префикс window. В мно- гофреймовом окне самым верхним окном является то, в котором определен первый набор фреймов (в случае вложенных наборов). В такой среде пользователи никогда не видят самого верхнего окна, однако оно хранится в памяти браузера как объект. Причина заключается 434 Часть III. Объекты документа
в том, что это окно является “перевалочным пунктом” для других фреймов, которые могут обращаться к любым дочерним фреймам (если, например, в одном фрейме понадобится за- дать ссылку на дочерний объект другого). Ссылка выглядит так. top.имяФункции([параметры]) Об отличиях между свойствами top и parent подробно рассказывалось в начале этой главы, когда описывалась общая методика разработки сценариев для фреймов. Кроме того, обратитесь К описанию свойства parent в примере, демонстрирующем назначение свойства top. См. также: свойства window, frames, window, self, window.parent. window Значение: объект окна Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Использование свойства window как отдельного элемента, скорее, запутывает работу, чем оказывается полезным. Значение свойства window совпадает с объектом window. Одна- ко нет необходимости использовать ссылки вида window. window. Несмотря на то, что объект window подразумевается во многих ссылках, его можно использовать или не использовать в ссылках на объекты из одного и того же окна. Но его точно не допускается применять в ссылках на элементы, находящиеся выше данного окна в иерархической структуре (top или parent). Методы alert("сообщение") Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Диалоговое окно предупреждения является модальным: в нем представлено сообщение и кнопка ОК, щелчок на которой закрывает окно. Пока на экране присутствует диалоговое окно предупреждения, другое приложение или окно нельзя сделать активным. Прежде чем продолжить работу, пользователю необходимо закрыть это окно. Единственный параметр метода alert () представляется значением любого типа данных, в том числе и некоторых необычных типов, редко применяемых в JavaScript (например от- дельные объекты^. Это делает диалоговое окно предупреждения довольно удобным средст- вом отладки сценариев JavaScript. Если необходимо проверить значение выражения, запусти- те метод alert (), подставив первое в качестве параметра. Сценарий будет выполнен до этой точки, а затем выведет значение. (Советы по отладке сценариев приведены в главе 45.) Разработчиков приложений часто беспокоит то, что все модальные диалоговые окна, соз- данные в JavaScript (методами alert (), confirm () и prompt ()), идентифицируют себя как генерированные JavaScript или браузером. В старых браузерах это выглядит не очень эс- тетично, поскольку ключевая фраза находится даже не в заголовке окна, а внутри окна. Это сделано преднамеренно, чтобы предотвратить действия тех разработчиков сценариев, кото- рые пытаются имитировать диалоговые окна предупреждений системы или браузера, предла- гая пользователю ввести пароль или другие важные данные. Идентифицирующую сообщение фризу нельзя исключить или заменить средствами сценария. Модальное диалоговое окно эмулируют независимо от версии браузера, но оно не является таким гибким, как настоящее модальное окно, создаваемое в браузерах IE4+ методом window. showModalDialog (). Поскольку метод alert () имеет глобальную природу (т.е. в многофреймовой среде не имеет значения, из какого фрейма он вызывается), ссылку на объект window обычно опуска- ют. По возможности следует воздержаться от использования диалоговых окон предупреждений Глава 16. Объекты window и frame 435
в HTML-документах и при разработке Web-страниц. Модальность этих окон затрудняет поль- зовательскую навигацию по страницам. Взаимодействие с пользователем рекомендуется осуществлять с Помощью форм или отдельных фреймов. Пример Параметр в примере листинга 16.20 представлен конкатенированной строкой. Он содер- жит две фиксированные строки, а также значение свойства navigator. appName. После за- грузки этого окна на экране появляется окно с предупреждением (рис. 16.8). chtml> <head> <title>win,dow. alert () Method</title> </head> <body> «script type="text/javascript"> alert("You are running the " + navigator.appName + " browser.") </script> </body> </html> Puc. 16.8. Результат выполнения метода alert () в Internet Explorer и Netscape Navigator См. также: методк window. conf i rm (), window. prompt (). back() forward() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Цель методов window. back () и window. forward () в браузере NN4 состоит в том, чтобы добавить в сценарий унифицированную версию кнопок навигации Back (Назад) и Forward (Вперед) и позволить объекту history управлять навигацией в пределах опреде- ленного окна или фрейма— как и должно быть. Эти методы не поддерживаются в IE (и не вклю- чены в объект window в W3C DOM 2), поэтому при навигации рекомендуется ограничиться 436 Часть III. Объекты документа
методами объекта history. Более подробная информация о совместимости версий, а также навигации приведена в описании объекта history в главе 17. См. также: методы history, back (), history. forward (), history, go (). captureEvents (списокСобытий) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- B NN4 событие проходит через объект window и лишь затем достигает точки назначения. Например, по щелчку на кнопке событие достигает вначале объекта window, затем объекта document и лишь после этого— кнопки, в которой обработчик onclick выполняет задан- ные в нем операции. Механизм “перемещения” события в NN4 позволяет объектам окна, документа и слоя пе- рехватить события и обработать их до того, как они достигнут своих целей (или полностью предотвратить последнее). Для того чтобы этот подход сработал, сценарий должен проин- формировать внешний контейнер о том, какой тип событий следует перехватывать. Чтобы объект window перехватывал все события определенного типа, необходимо вызвать метод window.captureEvents(). t Браузеры NN6+ и W3C обеспечивают оба механизма: захват и всплывание события, /н* заметку Синтаксис для захвата событий в NN6 несколько отличается от принятого в NN4. Ме- • тоды captureEvents(), releaseEvents(), handleEvent() И routeEvent() объектов window, document и layer рассматриваются только в среде браузера NN4. Если разрабатываемая вами DHTML-страница не требует поддержки в NN4, вы можетв пропустить его. Метод window. captureEvents () в качестве параметров использует один или не- сколько типов событий. Типом события является константа, встроенная в NN4 в объект Event. Для каждого типа обработчика, допустимого в объектах документов в NN4, существует один тип события. Применяется следующий синтаксис: имя объекта события (Event) и имя собы- тия прописными буквами, разделенные точкой. Например, если окно должно перехватывать все события щелчка мышью, то задается следующий оператор. window.captureEvents(Event.CLICK); Несколько событий необходимо разделить символом вертикальной черты (|). window.captureEvents(Event.MOUSEDOWN | Event.KEYPRESS); После установка захвата события объектом window следует подготовить функцию, обраба- тывающую событие. Предположим, что функция проверяет все события Event. MOUSEDOWN щелчка правой кнопкой, а также определяет, какому элементу формы предназначается собы- тие. Целью может служить, например, отображение всплывающего меню (в отдельном слое). Если событие вызвано щелчком левой кнопкой мыши, то оно перенаправляется к другой цели. Чтобы определенному типу события, перехватываемому объектом window, поставить в со- ответствие функцию, ее необходимо присвоить событию. Например, для назначения функции doClickEvent (), перехватывающей события щелчков, применяется следующий оператор. window.onclick=doClickEvent; Обратите внимание на то, что имя функции задается как ссылка (без скобок и кавычек), — не так, как это определяется в обработчике события в дескрипторе. Данная функция считает- ся функцией постольку, поскольку в качестве параметра она автоматически получает ко- пию объекта Event. Отключить захват событий одного или нескольких типов позволяет ме- тод window.releaseEventО. Глава 16. Объекты window и frame 437
/ Захват событий на уровне окна, документа или слоя в NN4 не всегда работает 'На заметку так, как ожидается. Особенно это заметно в документах, содержащих таблицы. Например, перехват событий мыши в NN4 для Windows не работает, пока указа- тель не будет наведен на границу ячейки. Наиболее надежно захват событий выполняется в том случае, когда для объекта определен обработчик (даже если он равен пустой строке), а элемент является целью события (например при вво- де текста в поле). Для всех остальных элементов захват событий на уровне до- кумента или окна может быть просто невозможен. Пример Пример использования метода captureEvents () приведен в листинге 16.21. Как толь- ко объект window захватывает события щелчка, запускается функция flash(). В этой функции событие анализируется: только после нажатия клавиши <Ctrl> и щелчке кнопкой, имя которой начинается с button, фон страницы начинает мерцать красным цветом. Все ос- тальные события щелчка (которые возникают в объектах страницы, имеющих обработчики onclick) обрабатываются методом routeEvent (). <html> <head> <title>Window Event Capture</title> «script type="text/javascript"> // вызывается при захвате окном события щелчка function flash(е) { if (е.modifiers == Event.CONTROL_MASK && e.target.name.indexOf("button") == 0) { document.bgColor = "red"; setTimeout("document.bgColor = 'white'", 500); } I/ продолжение перемещения события routeEvent(e) ; } // стандартный захват событий щелчка window.captureEvents(Event.CLICK); // назначение функции flash событиям щелчка, захваченным окном window.onclick = flash; </script> </head> «body bgcolor="white"> «form name="buttons"> <b>Turn window click event capture on or off (Default is "On")«/b> «pxinput name="captureOn" type="button" value="Capture On" onclick="window.captureEvents(Event.CLICK)" />&nbsp; «input name="captureOff" type="button" value="Capture Off" onclick="window.releaseEvents(Event.CLICK)" I></p> «hr /> <b>Ctrl+Click on a button to see if clicks are being captured by the window (background color will flash red):</b> <ul> «lixinput name="buttonl" type="button" value="Informix" onclick="alert('You clicked on Informix.')" /></li> 430 Часть III. Объекты документа
clixinput name="buttons" type="button" value="Oracle" onelick="alert('You clicked on Oracle.')" /></li> clixinput name="buttons" type="button" value="Sybase" onclick="alert('You clicked on Sybase.')" /></li> </ul> </form> </body> </html> При тестировании этой страницы отключите захват событий окна. Таким образом будут выполняться только обработчики onclick кнопок; страница начнет мерцать красным цветом. См. также: методы window. disableExternalCapture (), window.enableExternal- Capture (), window. handleEvent (), window. releaseEvents (), window. routeEvent (). clear Interval (интервал) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 14- Метод window, clearinterval () отключает выполнение действия в цикле через оп- ределенный интервал времени, установленный методом window, setinterval (). Пара- метром является идентификатор, возвращаемый методом setinterval (). Обычно методи- ка задания интервалов в JavaScript используется в анимации объекта на странице. Если несколько действий выполняются таким образом, что для каждого из них задан интервал, то все они имеют отдельные идентификаторы в памяти браузера. Идентификатор позволяет от- ключить любое из них. Если цикл остановлен, сценарий не может продолжить его: цикл не- обходимо начинать сначала, при этом ему будет присвоен новый идентификатор. Пример В листингах 16.36 и 16.37 приведен пример использования методов clearinterval () и setinterval(). См. также: методы windpw.setlnterval (), window.setTimeout (), window. clear- Timeout (). clearTimeout(задержка) Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Метод window. clearTimeout () обычно используется в сочетании с методом window. setTimeout (), описанным ниже в этой главе, когда необходимо отключить таймер, задающий запуск выражения. Параметром является идентификатор, возвращаемый методом window. setTimeout (). Метод clearTimeout () отменяет указанную ранее за- держку. Правильная методика заключается в том, чтобы проанализировать ситуации, когда действия пользователя могут отменить запуск таймера. Пример Страница, представленная кодом листинга 16.22, содержит одно текстовое поле и две кнопки (рис. 16.9). Первая кнопка запускает посекундный обратный отсчет (отсчет начинает- ся с одной минуты, но может использоваться и любое другое время), а вторая — прекращает его. По истечении минуты на экране появляется окно с сообщением. Глава 16. Объекты window и frame 439
<html> <head> <title>Count Down Timer</title> «script type="text/javascript"> var running = false; var endTime = null; var timerlD = null; function startTimer() { running = true; now = new Date(); now = now.getTime(); endTime = now + (1000 * 60 * 1); showCountDown(); } function showCountDown() { var now = new Date(); now = now.getTime(); if (endTime - now <= 0) { stopTimer(); alert("Time is up. Put down your pencils."); } else { var delta = new Date(endTime - now); var theMin = delta.getMinutesO; var theSec = delta.getSeconds(); var theTime = theMin; theTime += ((theSec < 10) ? ":0" : ":”) + theSec; document.forms[0].timerDisplay.value = theTime; if (running) { timerlD = setTimeout("showCountDown()",1000); } } } function stopTimer() { clearTimeout(timerlD); running = false; document.forms[0].timerDisplay.value = "0:00"; } </script> </head> <body> <form> «input type="button" name="startTime" value="Start 1 min. Timer" onclick="startTimer()" /> «input type="button" name="clearTime" value="Clear Timer" onclick="stopTimer()" /> «pxinput type="text" name="timerDisplay" value="" /></p> </form> </body> </html> 440 Часть III. Объекты документа
В сценарии используется три глобальных переменных: running, endTime и timerlD. Они применяются во многих функциях сценария, поэтому объявлены вне последних. В функции startTimer () устанавливается флаг запуска операции обратного отсчета. С помощью функций управления датами (глава 29) извлекается текущее время, выраженное в миллисекундах и к нему добавляется 1 минута (также выраженная в миллисекундах). Конечное время сохраняется в глобальной переменной, а потому функция может вызвать другую функ- цию, сравнивающую текущее и конечное время и выводящую их разницу в текстовом поле. Ранее в функции showCountDown () выполнялась проверка обнуления счетчика. Если этого не сделать, то сценарий продолжит рассчитывать разницу между двумя временами и форматировать полученное значение в виде mtn: ss. Пока флаг операции обратного отсчета (running) установлен в значение true, функция перед повторным выполнением устанавли- вать таймер в значение 1 минута. Чтобы остановить таймер в произвольный момент (с помо- щью функции stopTimer ()), первым делом необходимо отменить в браузере одноминут- ную задержку. Для этого используется метод clearTimeout () и глобальная переменная timerlD. Впоследствии функция сбросит флаг running и обнулит содержимое поля. См. также: метод window. setTimeout (). close () Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Метод window. close () закрывает окно браузера, на которое указывает объект window. Чаще всего он используется для закрытия вспомогательных окон, созданных из главного окна документа. Если вызов происходит не из вспомогательного окна, исходный объект window будет содержать запись о вложенном объекте. Для этого значение, возвращаемое методом window. open (), следует сохранить в глобальной переменной, которая будет доступна и другим объектам (например, в переменной, инициализированной не внутри функции). Если, с другой стороны, метод window. close () вызывает объект внутри вспомогательного окна, достаточно использовать ссылку window или self. Глава 16. Объекты window и frame 441
В ссылку необходимо обязательно ввести ключевое слово window. Иначе JavaScript будет трактовать это выражение как document. close (), которое имеет несколько другое при- менение (см. главу 18). Закрыть окно из сценария можно только методом window, close О. Закрытие окна, конечно же, запускает обработчик события onunload. Когда метод window. close () запущен, его уже нельзя остановить. Более того, обработчик события onunload, который запускает процессы, требующие некоторого времени на выполнение (например, отправка формы из закрываемого окна), может не завершиться, поскольку окно закроется до окончания процесса. Это поведение невозможно исправить (за исключением об- работчика onbef oreunload в браузерах IE4+). Особым является случай, когда вспомогательное окно пытается закрыть главное окно брау- зера (оператором self .opener, close ()), в списке посещенных документов которого со- держится более'одной записи. Мерой предосторожности против сценариев, которые закрывают окна, созданные не ими, является следующее: в браузерах NN3+ и IE4+ у пользователя запраши- вается подтверждение на закрытие главного окна (с помощью диалогового окна, генерируемого браузером). Это средство защиты можно отменить только с помощью защищенных сценари- ев в NN4+, когда пользователю предоставляются права на управление браузером (глава 46). Пример В листинге 16.4 (демонстрирующем применение свойства window.closed) приведен пример использования метода window. close (). См. также: методы window. open (), document. close (). confirm("сообщение”) Возвращаемое значение: булевого типа Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Диалоговое окно подтверждения представляет собой сообщение в модальном окне, со- держащем также кнопки ОК и Отмена (Cancel). Такое окно запрашивает подтверждение у пользователя, как правило, на выполнение действий сценария, которые можно отменить. Запрос пользователя на продолжение обычной навигации после взаимодействия (например, с элементом формы) в большинстве случаев не приносит никакого результата. Однако для операций, которые могут выявить личность пользователя (например, при отправке данных формы на сервер), диалоговые окна подтверждения JavaScript могут оказаться нелишними. Пользователь может щелкнуть на кнопке случайно, поэтому разработчику стоит позаботиться о возможности прервать операцию до ее выполнения. Поскольку метод возвращает значение булевого типа (ОК = true; Отмена (Cancel) = false), им можно пользоваться в операторе сравнения или присвоения. В этом случае метод нахо- дится внутри оператора, запрашивающего значения булевого типа. if (confirm("Are you sure?")) { alert("OK"); } else { alert("Not OK") ; } В данном случае возвращаемое методом значение используется в конструкции if . . .else (глава 31). Метод может быть задан также и в правой части оператора присвоения. var adult = confirm("BaM больше 18 лет?"); if (adult) { //для взрослых } else { 442 Часть III. Объекты документа
I/для детей } В окнах такого типа в JavaScript заменить кнопки значками или изменить их заголовок нельзя. Вы не можете определить другие подписи и значки для двух кнопок в диалоговом окне подтверждения. Пример Пример в листинге 16.23 показывает, как можно использовать диалоговое окно подтвер- ждения операции удаления набора данных. Текст в строке заголовка окна (рис. 16.10) в ста- рых браузерах изменить нельзя. Ш w 16,23. Диалоговоеокно <html> <head> <title>window.confirm() Method</title> <script type="text/javascript"> function clearTableO { if (confirm("Are you sure you want to empty the table?")) { alert("Emptying the table..."); // для демонстрации // операторы очистки полей } } </script> </head> <body> <form> <!-- другие операторы отображения и заполнения таблицы --> <input type="button" name="clear" value="Reset Table" onclick="clearTable()" /> </form> </body> </html> Puc. 16.10. Диалоговое окно подтверждения в WinlE См. также: методы window.alert (), window.prompt (), form, submit (). createPopup() Возвращаемое значение: ссылка на объект всплывающего окна Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Всплывающее окно в IE —- это прямоугольная область без элементов управления, появ- ляющаяся поверх текущего окна. В отличие от диалоговых окон, генерируемых методами Глава 16. Объекты window м frame 443
showModalDialog () и showModelessDialog (), содержимое такого окна должно пол- ностью находиться под управлением сценария. Это относится также к размеру и расположе- нию окна. Генерирование окна методом createPopup () лишь создает в памяти объект, не отображая его на экране. Ссылка, возвращаемая этим методом, может использоваться для по- зиционирования окна, заполнения его содержимым и последующего отображения (подробнее см. описание объекта popup далее в этой главе). Пример Пример использования метода createPopup () приведен в листинге 16.49. См. также: объект popup. execScript (" списокВыражений" [, язык]) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Метод window. execScript (), уникальный для IE, запускает один или несколько опе- раторов, переданных как строковые выражения. Они указываются в первом аргументе (несколько операторов разделяются точкой с запятой). Второй (необязательный) аргумент за- дает интерпретатор языка, выполняющий выражения. Допустимы следующие значения: JavaScript, JScript, VBS и VBScript. По умолчанию он имеет значение JScript, по- этому его можно опустить, если применяются операторы JavaScript. В отличие от функции eval (), встроенной в ядро языка JavaScript (которая также выполня- ет оператор JavaScript, представленный строковым выражением), метод execScript () не возвращает значения. Метод работает с глобальной областью определения переменных окна, содержащего документ. Например, если в сценарии документа определена глобальная переменная var myVar; метод execScript () может получать и изменять ее значение. window.execScript("myVar = 10; myVar += 5"); После выполнения этого оператора значение myVar будет равно 15. Пример Используйте приложение The Evaluator для изучения метода execScript (). Это при- ложение содержит заранее объявленные глобальные переменные, представленные буквами от а до z. Введите следующее выражение в верхнее поле и ознакомьтесь с возвращаемым ре- зультатом. а При первой загрузке переменная объявляется, но она не содержит значения. window.execScript("а = 5") Метод не возвращает значения, поскольку оператор не определен. а Теперь переменная принимает значение 5. window.execScript("b = а * 50") b Глобальная переменная b имеет значение 250. Рассмотрите другие переменные приложе- ния. Для одновременного ввода в поле нескольких операторов, разделите их запятыми. См. также: функция eval (). 444 Часть III. Объекты документа
f ind ([" строкаПохска" [, чувствительностьКРегиссру, яаправлемлсе] ]) Возвращаемое значение: булевого типа для недиалогового поиска Совместимость: WinlE-, MacIE-, NN4+, Mozl+, Safari- Метод window. f ind (), уникальный для NN4, эмулирует действия диалогового окна Поиск (Find), вызываемого в результате щелчка на соответствующей кнопке на панели инст- рументов. Этот метод недоступен в NN7/Mozl. Если метод вызван без параметров, на экране появится обычное диалоговое окно (как при использовании кнопки Найти (Find)). В таком случае функция не возвратит никаких значений. Строку для поиска можно задать в аргументе функции. Поиск основан на простом сравне- нии строк и никак не связан с поиском на основе регулярных выражений (см. главу 42). Если при поиске найдено соответствие, браузер прокрутит страницу до найденного слова и выде- лит его — все происходит так же, как и при использовании диалогового окна. Кроме того, при нахождении соответствия функция возвращает значение true. Если соответствий в до- кументе не найдено или они отсутствуют в направлении текущего поиска (по умолчанию по- иск происходит от начала к концу документа), функция возвращает значение false. Два дополнительных параметра логического типа позволяют указать чувствительность к регистру и направление поиска Они полностью идентичны опциям в диалоговом окне Поиск (Find) в NN4. По умолчанию поиск происходит без учета регистра в направлении сверху вниз. Если указывается один из параметров, необходимо указывать и второй. IE4+ имеет и другие средства поиска текста, реализованные, однако, совершенно другим способом (с помощью объекта TextRange, описанного в главе 35). Визуально их поведение также имеет отличия: в последнем случае слово не выделяется и страница не прокручивается до него. Пример В самом простом случае оператор f ind () вызывается следующим образом. var success = window.find("contract"); Если поиск производится с учетом регистра, то в операторе вызова используйте не менее двух параметров. success = window.find(matchstring,caseSensitive,backward); Поскольку этот метод выполняется только в NN4, то детальное описание операции поиска в JavaScript вы найдете в главе 35. См. также: объекты TextRange, Range (глава 35). forward() См. window.blur(). handleEvent (событхе) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Когда в NN4 происходит перехват событий объектами window, document или layer (с помощью метода captureEvents (), заданного для них), сценарий управляет тем, куда события направляются после перехвата. Чтобы направить событие к своей исходной цели (например, пользователь щелкнул на кнопке), примените метод rout eEvent (). Но если не- обходимо перенаправить событие (или класс событий) определенному обработчику в докумен- те, обратитесь к другому методу — handleEvent (). Глава 16. Объекты window и frame 445
Каждый объект в NN4, имеющий связанные с ним обработчики событий, обладает мето- дом handl eEvent О. Поэтому если события щелчка перехватываются (например, окном), то их можно перенаправить определенной кнопке или ссылке на странице— эти объекты умеют управлять данными событиями. Рассмотрим следующий фрагмент кода. «script type="text/javaScript"> // запускается при захвате окном события щелчка function doClicks(evt) { // все щелчки передаются первой ссылке документа document.links[0].handleEvent(evt); } // указание захвата окном всех событий щелчков window.captureEvents(Event.CLICK); // назначение функции doClickO событиям щелчка, захваченным окном window.onclick = doClicks; </script> Все события щелчка перехватываются окном. Всякий раз, когда пользователь щелкает мышью на элементе, поддерживающем это событие, вызывается функция doClicks О. Она содержит один оператор, который перенаправляет событие щелчка в качестве параметра для обработки первой ссылки в документе. В дескрипторе ссылки необходимо определить обра- ботчик события onclick, иначе этот код не будет выполняться. Поскольку объект event передается автоматически, обработчик имеет доступ к его свойствам (например, координатам указателя мыши в момент щелчка), которые он может при необходимости изменить до нача- ла выполнения ссылкой своей задачи. Предыдущий пример демонстрирует использование метода handleEvent О, скорее, с объектом link, чем с объектом window. Для других объектов редко возникает необходимость перехватывать события, предназначенные для окна, но этот метод является частью любого объекта в NN4, поддерживающего события. В модели событий W3C аналогичный метод перехвата событий называется dispatchEvent (), а его эквивалент в IE5+ — f ireEvent (). Пример Подробности и примеры управления объектами событий приведены в главе 25. См. также: методы window. captureEvents (), window. releaseEvents (), window. routeEvent (); объект event. home () Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Как и другие методы объекта window, новые для NN4, window. home () представляет собой специфический для этого браузера способ выполнения в сценарии действия, аналогич- ного задаваемому кнопкой на панели инструментов (речь идет о кнопке перехода к начальной странице (Ноте)). Щелчок на ней заставляет браузер перейти к URL, установленному в на- стройках браузера в качестве адреса начальной страницы. Выбранную в браузере пользовате- ля начальную страницу по умолчанию изменить средствами сценария нельзя. См. также: методы window. back (), window. forward (); свойство window. toolbar. moveBy (del taX, del taY) moveTo {x, y) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4+, Mozl+, Safari 1+ 446 Часть III. Объекты документа
В браузерах IE4+ и NN4+ средства JavaScript позволяют управлять расположением окна на экране компьютера. Это относится и к главному окну, и к любому окну, созданному сцена- рием. Netscape Navigator рассматривает возможность перемещения окна за пределы экрана как потенциальную дыру в системе безопасности данных, поэтому в NN4+ для выполнения этого действия требуются защищенные сценарии. Расположение окна может быть задано абсолютно или в виде относительного смещения вдоль горизонтальной и/или вертикальной осей. Область определения горизонтальной (х) и вертикальной (у) координат представляет собой весь экран, где левому верхнему углу соот- ветствует точка 0,0. Аргументами методов moveBy () и moveTo () служат координаты лево- го верхнего угла внешней части окна браузера. Поэтому перемещение окна в точку 0,0 вы- равнивает его по левой и верхней границам экрана. Это положение не соответствует окну, открытому во весь экран, для всех браузеров и операционных систем, поскольку координаты последнего являются, как правило, отрицательными. Если попытаться изменить расположение окна так, чтобы отдельная его часть “вышла” за экран, то оно автоматически будет смешено в пределы экрана. Иная ситуация в NN4 возмож- на лишь при использовании защищенных сценариев, получивших разрешение пользователя на частичное или полное смещение окна за пределы видимой области экрана. Перемещение един- ственного видимого окна браузера полностью за пределы экрана создает опасную ситуацию, так как для пользователя существует только один способ вернуть его — перезапустить браузер. Разница между методами moveTo () и moveBy () заключается в том, что первый исполь- зует абсолютные координаты, а второй задает смещение относительно текущей позиции ок- на. Другими словами, параметрами метода moveTo () являются точные координаты распо- ложения левого верхнего угла окна по вертикали и по горизонтали в пикселях. Метод moveBy (), напротив, показывает, на какое расстояние следует переместить окно в каждом направлении. Если окно необходимо переместить на 25 пикселей вправо, все равно исполь- зуйте два аргумента, но при этом второе значение обязательно будет равно нулю. window.moveBy(25,0); Для перемещения влево первый параметр должен быть отрицательным. Пример Несколько примеров использования методов moveTo () и moveBy () приведены в лис- тинге 16.24. На показанной странице — 4 кнопки, каждая из которых перемещает окно брау- зера в своем направлении. <html> <head> <title>Window Gymnastics</title> <script type="text/javascript"> var isNav4 = ((navigator.appName == "Netscape") && (parselnt(navigator.appVersion) >= 4)); function init() { // заполнение отсутствующих свойств IE if (!window.outerwidth) { window.outerwidth = document .body. clientWidth; window.outerHeight = document.body.clientHeight + 30; } // заполнение отсутствующих свойств IE4 if (!screen.availwidth) { Глава 16. Объекты window и frame 447
screen.availwidth = 64 0; screen.availHeight .= 480; } } // запускается при захвате окном события щелчка function moveOffScreen() { // ветвление для системы защиты данных в NN if (isNav4) { netscape.security.PrivilegeManager. enablePrivilege("UniversalBrowserWrite"); } var maxX = screen.width; var maxY = screen.height; window.moveTo(maxX+1, maxY+1); setTimeout("window.moveTo(0,0)",500); if (isNav4) { netscape.security.PrivilegeManager. disablePrivilege("UniversalBrowserWrite"); } } // устанавливает круговое движение окна function revolve() { var winX = (screen.availwidth - window.>outerWidth) / 2 var winY = 50; window.resizeTo(400,300); window.moveTo(winX, winY); for (var i = 1; i < 36; i++) { winX += Math.cos(i * (Math.PI/18)) * 5; winY += Math.sind * (Math.PI/18) ) * 5; window.moveTo(winX, winY); } } // устанавливает зигзагообразное движение окна function zigzag() { window.resizeTo(400,300); window.moveTo(0,80); var incrementX = 2; var incrementY = 2 ; var floor = screen.availHeight - window.outerHeight; var rightEdge = screen.availwidth - window.outerwidth; for (var i = 0; i < rightEdge; i += 2) { window.moveBy(incrementX, incrementY); if (i%60 == 0) { incrementY = -incrementY; } } } // увеличивает окно на всю доступную область экрана function maximize() { window.moveTo(0,0); window.resizeTo(screen.availwidth, screen.availHeight) } </script> 448 Часть III. Объекты
</head> «body onload="init()"> «form name="buttons"> <b>Window Gymnastics«/b> <ul> «lixinput name="offscreen" type= "button" value="Disappear a Second" onclick="moveOffScreen()" /></li> «lixinput name="circles" type= "button" value="Circular Motion" onclick="revolve()" /x/li> «lixinput name = "bouncer" type= "button" value="Zig Zag" onclick="zigzag()" /></li> «lixinput name="expander" type="button" value="Maximize" onclick="maximize()" /></li> </ul> </form> </body> </html> Для успешного выполнения этого сценария в NN (до версии 7) вам необходимо устано- вить доверителя (глава 46), иначе вы не получите доступ к подписанному сценарию. Функция moveOff Screen () мгновенно смещает окно браузера с экрана. Обратите внимание на то, что сценарий определяет размер окна перед его смещением. После смещения с экрана окно отображается в левом верхнем углу рабочего стола. Вторая функция, revolve (), располагает уменьшенное окно браузера в верхней части экрана и перемещает его вдоль окружности (36 раз смещает окно с шагом 10 градусов). Этот пример демонстрирует способ динамического перемещения окна, основанный на математи- ческих вычислениях. Чтобы продемонстрировать возможности метода moveBy (), используется третья функ- ция— zigzag (). В ней в цикле for координаты окна изменяются таким образом, чтобы окно перемещалось на экране вдоль пилообразной траектории. Четвертая функция имеет широкое практическое применение. Она максимизирует окно таким образом, чтобы оно заняло всю площадь экрана. См. также: свойства window.outerHeight, window.outerwidth; методы window.resizeBy(), window.resizeTo(). navigate(" URL") Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN-, Moz-, Safari- Метод window.navigate (), поддерживаемый только в IE, позволяет загрузить новый документ в окно или фрейм. Его действие полностью аналогично присвоению URL свойству location. href, которое доступно во всех версиях браузеров NN и IE, поддерживающих сце- нарии. Если ваша аудитория использует только браузер IE, применение этого метода является вполне безопасным. В противном случае рекомендуем применить свойство location. href. Пример В качестве аргумента метода navigate () чаще всего применяется корректный URL. window.navigate("http://www.dannyg.com"); См. также: объект location. Глава 16. Объекты window и frame 449
open(" URL", "имяОкна" [, " средстваОкна"] [,флаг]) Возвращаемое значение: объект window, представляющий новое окно; null, если вы- полнение завершилось неудачей Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Метод window. open () обеспечивает разработчику сценариев возможность вывода на экран нового окна Web-браузера, поддерживающего немало различных опций. Большая часть элементов управления окна отображается во всех браузерах, поддерживающих JavaScript, без необходимости применения защищенных сценариев. Поскольку элементы интерфейса пред- ставить себе легче всего, начнем с описания их параметров метода window. open (). Установка элементов нового окна Дополнительный параметр средстваОкна представляет собой одну строку, которая со- стоит из списка операторов присвоения, разделенных запятыми (наподобие атрибутов деск- риптора HTML). Важно отметить следующее: для совместимости с разными браузерами по- сле запятых не следует вводить пробелы. Если третий параметр опущен, то метод создает новое окно того же типа, который указан в опции New1^ Window (Создать^Окно) меню File (Файл). Этот параметр управляет тем, какие элементы управления должны присутство- вать в новом окне. Помните важное правило: если указать хотя бы одно из значений в треть- ем параметре, все остальные средства окна будут скрыты (кроме тех, которые указаны явно). В табл. 16.3 перечислены атрибуты нового окна во всех браузерах. Кроме указанных исклю- чений, все значения булевого типа по умолчанию равны yes, если третий аргумент не указан. С- : t - Л » J Таблица А^мйуты метвда wj open Q, управляемые сценарием । Атрибут Браузеры Описание alwaysLowered3 NN4+ (Булевого типа). Всегда под другими окнами браузера alwaysRaised3 NN4+ (Булевого типа). Всегда над другими окнами браузера channelmode IE4+ (Булевого типа). Режим с переключателем каналов (по умолчанию по) copyhistory NN2+, IE3+ (Булевого типа). Копирует в новое окно содержимое меню Go исходного dependent NN4+ (Булевого типа). Новое окно закрывается при закрытии основного । directories NN2+, IE3+ (Булевого типа). Панель папок с кнопками What's New и т.д. fullscreen IE4+ (Булевого типа). Без заголовка и меню (по умолчанию по) height NN2+, IE3+ (Целочисленного типа). Высота области содержимого в пикселях hotkeys NN4+ (Булевого типа). Если true, то при скрытой строке меню запрещены комбинации клавиш (кроме Quit (Выход) и Security Info (Информация о защите)) innerHeight4 NN4+ (Целочисленного типа). Высота области содержимого в пикселях; совпадает со свойством height innerWidth4 NN4+ (Целочисленного типа). Ширина области содержимого в пикселях; совпадает со свойством width left IE4+ (Целочисленного типа). Горизонтальная координата левого верхнего угла экрана location NN2+, IE3+ (Булевого типа). Поле, отображающее текущий URL 450 Часть III. Объекты документа
Окончание табл. 16.3 Атрибут Браузеры Описание menubar1 NN2+, IE3+ (Булевого типа). Строка меню в верхней части окна outerHeight4 NN4+ (Целочисленного типа). Высота видимой части окна outerWidth4 NN4+ (Целочисленного типа). Ширина видимой части окна resizable2 NN2+, IE3+ (Булевого типа). Элементы интерфейса, позволяющие изменять размеры окна в результате операций перетаскивания screenX4 NN4+ (Целочисленного типа). Горизонтальная координата левого верхнего угла экрана screenY4 NN4+ (Целочисленного типа). Вертикальная координата левого верхнего угла экрана scrollbars NN2+, IE3+ (Булевого типа). Если документ не помещается в окне, отображаются полосы прокрутки status NN2+, IE3+ (Булевого типа). Строка состояния в нижней части окна titlebar3 NN4+ (Булевого типа). Заголовок и другие граничные элементы окна toolbar NN2+, IE3+ (Булевого типа). Панель с кнопками Back (Назад), Forward (Вперед) и т.д. top IE4+ (Целочисленного типа). Вертикальная координата левого верхнего угла экрана width NN2+, IE3+ (Целочисленного типа). Ширина области содержимого в пикселях z-lock3 NN4+ (Булевого типа). Слой окна, который расположен под окнами браузера 1 Не на платформе Macintosh, поскольку строка меню не является частью окна браузера: при от- ключении MacNN4 отображает сокращенный для Мас вариант строки меню. 2 На платформе Macintosh все окна позволяют изменять свои размеры. 3 Требует защищенного сценария. 4 Требует защищенного сценария для изменения размеров или положения окна за пределами види- мой области. Значения булевого типа обрабатываются несколько неожиданным образом. Значение true может быть представлено как yes, 1 или именем самого свойства, значение false — по или 0. Все опущенные атрибуты булевого типа по умолчанию имеют значение false. Поэтому для создания, например, нового окна, имеющего только заголовок и строку состоя- ния, а также элементы, позволяющие изменять размер окна, метод выглядит так. window.open("newURL","NewWindow”, "toolbar,status,resizable"); Новое окно, для которого не указаны высота и ширина, будет создано такого же размера, как и при использовании команды New=C>Window (Создать^Окно) меню File (Файл). Дру- гими словами, новое окно автоматически не приобретет размер окна, в котором вызван метод window. open (). Если не указаны атрибуты расположения, доступные в NN4+ и IE4+, новое окно, создаваемое в сценарии, позиционируется произвольным образом. Обратите внимание, что атрибуты в разных браузерах называются по-разному (screenX и screenY в NN; left и top в IE). Оба набора атрибутов можно включить в строку параметров, поскольку неиз- вестные атрибуты браузер просто игнорирует. Глава 16. Объекты window и frame 451
Защищенные сценарии (только для NN) Многие специфические для NN атрибуты считаются небезопасными и поэтому требуют применения защищенных сценариев и разрешения пользователя. Если пользователь не дает разрешения на использование, то защищенный параметр игнорируется. Некоторые такие атрибуты ведут себя по-разному в различных операционных системах (в зависимости от того, как их приложения управляют окнами). Например, на платформе Windows атрибуты alwaysLowered, alwaysRaised и z-locked могут определяться для слоев, отличных от отведенных для окон браузера NN в Windows; в Мас слои окон в JavaScript рассматриваются только для NN. Разница заключается в том, что Windows позволяет окнам различных приложений находиться рядом с окнами браузера, тогда как в Мас окна каждого приложения располагаются только в смежных слоях. Чтобы защищенный сценарий создавал новое окно с особыми свойствами, необходимо разрешить права доступа UniversalBrowserWrite (см. главу 46). Фрагмент кода, соз- дающий окно в стиле alwaysRaised, выглядит следующим образом. «script type="text/javaScript" archive="myJar.jar" id="l"> function newRaisedWindow() { netscape.security.PrivilegeManager. enablePrivilege("UniversalBrowserWrite"); var newWindow = window.open"height=100,width=300, alwaysRaised=yes"); netscape.security.PrivilegeManager. disablePrivilege("UniversalBrowserWrite"); var newContent = "«htmls<bodys«bs "On top of spaghetti!"</b>"; newContent += "<form><center><input type='button1 value='OK'"; newContent += "onclick=’self.close()'s«/centers«/forms</bodys«/htmls"; newWindow.document.write(newContent); newWindow.document.close(); } </script> С видом и поведением новых окон можно экспериментировать, подбирая любые комби- нации атрибутов в листинге 16.25. На этой странице представлена таблица со сведениями о специфических для NN булевых атрибутах окон. На основе сделанного выбора создается новое окно размером ЗООхЗОО пикселей. На странице подразумевается, что при использова- нии NN4 во время управления защищенными сценариями вы обладаете правом изменения всех необходимых параметров (см. главу 46). С отключением заголовка и горячих клавиш нужно быть осторожным. При отключении заго- ловка содержимое окна как бы “витает в воздухе”, поскольку границы окна не отображаются. Если горячие клавиши включены, комбинация <CtrI+W> позволяет закрыть окно, не имеющее границ (на платформе Мас при отключении заголовка горячие клавиши всегда запрещены). Таким об- разом компьютер можно превратить в проектор: открыть окно, совпадающее по размерам с эк- раном, и установить его опции как "titlebar=no, hotkeys=no, alwaysRaised=yes". . /Ъштииг16.25.Создание ноюгореш J «htmls <head> «titl6swindow.open() Options«/titles «script type="text/javascript"s var isNav4 = (navigator.appName == "Netscape" && navigator.appVersion.charAt(0) s= 4) ? true : false; 452 Часть III. Объекты документа
function makeNewWind(form) { if (isNav4) { netscape.security.PrivilegeManager. enablePrivilege("UniversalBrowserWrite"); } var attr = "width=300,height=300"; for (var i = 0; i < form.elements.length; i++) { if (form.elements[i].type == "checkbox") { attr += + form.elements[i].name + "="; attr += (form.elements[i].checked) ? "yes" : "no"; } } var newWind = window.open("bofright.htm","subwindow",attr); if (isNav4) { netscape.security.PrivilegeManager. revertPrivilege("CanvasAccess"); } } «/script» «/head» «body» «b»Select new window options:</b> «form» «table border="2"> «tr» «td colspan="2" bgcolor="yellow" align="middle"» All Browsers Features:</td> «/tr» «tr» ctdxinput type="checkbox" name="toolbar" /> toolbar«/td» «tdxinput type="checkbox" name="location" /> location«/td» «/tr» «tr» «tdxinput type= "checkbox" name="directories" /> directories«/td» «td»«input type="checkbox" name="status" /»status«/td» </tr> «tr» «tdxinput type=“checkbox" name = "menubar" /> menubar«/td» <tdxinput type="checkbox" name="scrollbars" /> scrollbars</td> «/tr» «tr» «tdxinput type="checkbox" name="resizable" /> resizable«/td» ctdxinput type= "checkbox" name="copyhistory" /> copyhistory«/td» «/tr» «tr» <td colspan="2" bgcolor="yellow" align="middle"> Communicator Features:</td> </tr> <tr> <tdxinput type="checkbox" name="alwaysLowered" /> a1waysLowe red</1 d> Глава 16. Объекты window и frame 453
<tdxinput type="checkbox" name="alwaysRaised" /> alwaysRai sed</ td> </tr> <tr> <tdx input type="checkbox" name="dependent" /> dependent </td> «tdxinput type="checkbox" name="hotkeys" checked="checked" />hotkeys</td> </tr> <tr> «tdxinput type="checkbox" name="titlebar" checked="checked" />titlebar</td> <td><input type="checkbox" name="z-lock" />z-lock</td> </tr> <tr> <td colspan="2" align="middle"xinput type="button" name="forAll" value="Make New Window" onclick="makeNewWind(this.form) " /x/td> </tr> </table> </form> <br /> </body> </html> Указание имени окна Вторым аргументом метода window, open О является имя нового окна (его не следует путать с заголовком документа, который устанавливается в HTML-коде страницы. Имя окна должно быть таким же идентификатором (из одного слова), как имя объекта или переменной. Кроме того, это имя представляет собой совершенно иную сущность, чем объект window, возвращаемый методом open (). Оно нигде более не используется в сценариях, за исключе- нием атрибута target в ссылках и формах. Загрузка содержимого в новое окно Обычно сценарий заполняет окно информацией одного из двух типов. Существующий документ HTML, URL которого известен заранее. Страница HTML, создаваемая “на лету”. Чтобы создать новое окно с существующим HTML-документом, в качестве первого аргу- мента метода window. open () необходимо указать его URL. Если загрузка новой страницы не выполняется (кроме случая, описанного в совете “Устранение ошибки в NN2”), то укажите полный URL-адрес документа (а не только имя файла). Если первым аргументом является пустая строка, новое окно открывается с пустым доку- ментом, который готов к заполнению содержимым средствами сценария (или загрузке от-' дельным оператором, в котором указан URL). Если вы планируете заносить данные в окно “на лету”, создайте одну длинную строку, содержащую весь HTML-код, а затем воспользуй- тесь методом document .write () для ее добавления в новое окно. Если запись данных происходит за один сеанс, в конце следует вызвать метод document .close (), который со- общит браузеру, что разметка страницы завершена (в результате чего в строке состояния, ес- ли она представлена в окне, появится сообщение Layout: Complete или Done). 454 Часть III. Объекты документа
Вызов метода window, open () возвращает ссылку на объект нового окна, если его соз- дание прошло успешно. Это значение жизненно важно для сценария при обращении к эле- ментам нового Окна (например, при записи в документ). Чтобы другие функции сценария имели доступ к новому окну, результат метода window. open () необходимо присвоить глобальной переменной. До первой записи в до- кумент проверьте значение переменной — если оно равно null, значит, создание окна не было выполнено успешно (например, из-за недостатка свободной памяти). Если все в по- рядке, то этой переменной можно воспользоваться для задания ссылки на любое свойство или объект нового окна. var newWindow function createNewWindowO { newWindow = window.open("",""); if (newWindow != null) { newWindow.document.write("<htmlxhead><title>Hi!</title> </head>"); } Глобальная переменная доступна всем функциям (например, для закрытия окна методом close ()). Если сценарии вспомогательного окна будут взаимодействовать с объектами и сценария- ми главного окна, убедитесь, что новое окно имеет свойство opener. Обратитесь к описа- нию свойства window. opener ранее в этой главе. Выполнение нескольких методов window, open () с одним и тем же именем окна (во вто- ром аргументе) не создает дополнительных копий окна в браузере Netscape Navigator (хотя в Internet Explorer это возможно). JavaScript не позволяет создать два окна с одним и тем же именем. Помните, что метод window. open () не выводит существующее окно с указанным именем на передний план: для этого используется метод window. focus (). Особенности Internet Explorer Создание новых окон в IE иногда затруднено нежелательным поведением браузера. Чаще всего проблема возникает при попытке воспользоваться методом document .write () для заполнения нового окна содержимым. IE, особенно некоторые его последние версии, не успе- вает открыть окно до запуска метода document. write (). Это вызывает ошибку сценария, поскольку ссылка на окно еще не вступает в силу. Чтобы обойти эту ошибку, необходимо по- местить операторы генерирования HTML-кода и метод document. write () в отдельную функцию, которая запускается методом setTimeout О после создания окна. Пример этого подхода приведен в листинге 16.26. Другая проблема, возникающая в IE, — это нарушение прав доступа, а именно: отображе- ние предупреждения (access denied — доступ запрещен) при попытке обращения к окну из сценария. Оно генерируется в том случае, когда страница, содержащая сценарий открытия и обращения к новому окну, находится на Н Г ГР-сервере, а не на локальном жестком диске. Пример Страница, представленная кодом листинга 16.26, содержит одну кнопку, с помощью ко- торой создается новое окно строго указанного размера, содержащее из дополнительных эле- ментов только строку состояния. В сценарии описаны многие элементы окна браузера, кото- рые отображаются при создании нового окна браузера в большинстве платформ. Ссылка на объект нового окна сохраняется в глобальной переменной newWind. Перед созданием нового окна выполняется проверка его существования (если окно еще не создано, то переменная Глава 16. Объекты window и frame 455
newWind имеет значение null). Если новое окно не найдено, то вызывается метод ореп(). В противном случае новое окно активизируется с помощью метода focus () (в IE3+ и NN4+). В связи с временной задержкой генерации новых объектов в IE, HTML-код нового окна добавляется с помощью отдельной функции, вызываемой через 50 миллисекунд (остальные браузеры создают окно и его содержимое одновременно). Для создания строки, отображае- мой в новом окне, я использовал оператор += (с его помощью значение справа от оператора добавляется к значению, расположенному слева от оператора). В нашем примере текст выво- дится с помощью дескриптора <hl>. «html> <head> <title>New Window«/title> «script type="text/javascript"> var newWindow; function makeNewWindow() { if (!newWindow || newWindow.closed) { newWindow = window.open("","","status,height=2 00, width=300"); // небольшар задержка в IE setTimeout("writeToWindow() ", 50) ; } else { // окно уже открыто; вывод его на передний план newWindow.focus(); function writeToWindow() { // генерация содержимого нового окна var newContent = "<html><headxtitle>One Sub Window«\/title> <\/head>"; newContent += "«body>«hl>This window is brand new.«\/hl>"; newContent += "<\/bodyx\/html>" ; // вывод документа нового окна newWindow.document.write(newContent); newWindow.document.close О; // закрытие потока записи } «/script> «/head> «body> «form> «input type="button" name="newOne" value="Create New Window" ' onclick="makeNewWindow()" /> «/form> «/body> «/html> См. также: методы window, close (), window.blur (), window, focus (); свойство window.closed. print () Возвращаемое значение: отсутствует Совместимость: WinIE5+, MacIE5+, NN4+, Mozl+, Safari- 456 Часть III. Объекты документа
f Метод print () представляет собой способ печати окна или фрейма из сценария. В лю- [ бом случае, на экране появляется диалоговое окно параметров печати, в котором пользова- г тель имеет возможность указать принтер и выбрать другие настройки. Такой подход не раз- L решает некорректного использования команды print () без ведома пользователя. г Точное поведение метода print () немного отличается в браузерах NN и Е (не говоря | уже об операционных системах). В NN4+ (за исключением платформы Windows) все фреймы ; из набора можно распечатать с помощью одной команды print (), выполненной для роди- тельского документа. NN4 для Windows не печатает весь набор фреймов целиком. Для это- го необходимо использовать сценарий, который интерактивно' просматривает все фреймы и с задержкой отправляет их содержимое в пул принтера. function printFrames(n) { » parent.frames[n++].print(); if (n < parent.frames.length) { setTimeout("printFrames(" + n + ")",5000); } } Для распечатки всех фреймов вызывается функция printFrames (0). В Е5 в диалоговом окне предоставлена возможность выборочно распечатать один или все фреймы окна. Поэтому убедитесь, что метод print () запускается для желаемого фрейма, если вы хотите распечатать только его. По умолчанию браузер распечатывает только один фрейм. Е5 имеет несколько обработчиков событий, предназначенных для печати, которые запус- каются и при печати из сценария, и при печати вручную. События происходят после того, как пользователь завершает работу в диалоговом окне настройки параметров печати. Обработчик onbeforeprint применяется, например, для вывода невидимого в данный момент содер- жимого, которое появится на бумаге. После отправки данных в пул принтера обработчик со- . бытия onaf terprint восстанавливает исходный вид страницы. , Пример Пример использования метода print () приведен в листингах 16.27 и 16.28. Первый пред- ставляет набор фреймов, а второй — документ, загружаемый в верхний фрейм и копирующий данные в нижний фрейм. <html> <head> «title>window.print() method</title> «/head> «frameset rows="25%,75%"> «frame name="controls" src="lstl6-28.htm" /> «frame name="display" src="bofright.htm" /> </frameset> </html> Две кнопки на странице, представленной листингом 16.28, позволяют распечатать весь набор фреймов (в поддерживающих эту операцию браузерах) или только нижний фрейм. При печати набора фреймов на последний создается ссылка с участием ключевого слова parent. Если вам не понравился результат печати документа, то воспользуйтесь командами брау- зера, а не средствами JavaScript. Глава 16. Объекты window и frame 457
<html> <head> <title>Print()</title> </head> <body> <form> cinput type="button" name="printWhole" value="Print Entire Frameset" onclick="parent.print()" /> <p><input type="button" name="printFrame" value="Print Bottom Frame Only" onelick="parent.display.print()" /></p> </form> </body> </html> См. также: методы window.back (), window, forward (), window.home (), window.f ind(). prompt (11 сообщение", "поУмолчаншо") Возвращаемое значение: строка текста, введенная пользователем, или null Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Третий тип диалогового окна, отображаемого JavaScript, содержит сообщение, которое задается автором сценария, и две кнопки (ОК и Cancel (Отмена) или Yes и No в NN2 и NN3 для платформы Мас). Автор сценария может задать предварительный вариант: если значение по умолчанию приемлемо, пользователю достаточно щелкнуть на кнопке ОК (или нажать клавишу <Enter>) без дополнительного введения данных. Важно указать оба аргумента мето- да window. prompt (). Даже если нет необходимости задавать ответ по умолчанию, в каче- стве второго параметра следует указать пустую строку. prompt("What is your postal code?",""); Если второй параметр опущен, то поле диалогового окна JavaScript выведет строку undef ined. Эта надпись обескураживает большинство посетителей Web-страниц. Значение, возвращаемое этим методом, представляет собой строку, находящуюся в поле диалогового окна в тот момент, когда пользователь щелкает на кнопке ОК. Если планируется запрашивать у пользователя число, то помните, что значение, возвращаемое данным мето- дом, является строкой. Преобразование типа данных для последующих вычислений можно выполнить с помощью функций parselnt () или parseFloat () (см. главу 34). Если в момент щелчка на кнопке ОК текст в поле отсутствует, то метод возвращает пустую строку (" "). Щелчок на кнопке Cancel заставляет метод возвратить значение null. Поэтому при создании сценария необходимо обеспечить проверку возвращаемого значе- ния, чтобы убедиться, что пользователь ввел какое-либо значение, которое будет обраба- тываться далее в сценарии. var entry = prompt("Enter a number between 1 and 10:",""); if (entry != null) { // Операторы, выполняемые при вводе значения } В этом фрагменте сценария результат метода присваивается переменной, а вложенные операторы выполняются лишь в том случае, если его значение не равно null (т.е. пользователь 458 Часть III. Объекты документа
щелкнул на кнопке ОК). Затем в сценарии осуществляется проверка принадлежности числа заданному диапазону (см. главу 43). Может показаться, что диалоговое окно запроса является удобным средством ввода поль- зовательских данных. Тот факт (и это справедливо для других диалоговых окон JavaScript), что оно является модальным, нарушает обычную процедуру навигации и может привести к не- корректной работе макросов, используемых для автоматического перемещения по Web-узлам. Для ввода текста предпочтительнее использовать поля HTML-форм. Наиболее безопасный спо- соб — это отображение диалогового окна после щелчка на определенной кнопке или элементе лишь в том случае, когда одной строки достаточно для введения всей необходимой информа- ции. Последовательность диалоговых окон запроса данных применять не рекомендуется. Пример Функция, принимающая значение из диалогового окна ввода данных (листинг 16.29 и рис. 16.11), выполняет проверку данных, однако она еще не так совершенна, чтобы использовать ее на коммерческих Web-узлах. Вначале функция проверяет равенство возвращаемого значения null (Отмена) или пустой строке (пользователь ничего не ввел и щелкнул на кнопке ОК). Де- тально о проверке данных речь пойдет в главе 43. 16.29. Диалоговое окно ввода данных «html> «head> «title>window.prompt() Method«/title> «script type="text/javascript"> function populateTable() { var howMany = prompt("Fill in table for how many factors?",; if (howMany != null && howMany != ) { alert("Filling the table for " + howMany); //операторы проверки данных, //введенных в поля таблицы } } </script> </head> <body> <form> , <!-- другие операторы отображения таблицы --> «input type="button" name="fill" value="Fill Table..." onclick="populateTable0" /> «/form> «/body> </html> Puc. 16.11. Диалоговое окно запроса данных из листинга 16.29 См. также: методы window, alert (), window, conf irm (). Глава 16. Объекты window м frame 459
releaseEvents (списокСобытий) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Если в сценарии включен присущий только NN4 способ захвата событий объекта window (document или слоя), то его можно отключить с помощью метода releaseEvents (). Он не препятствует событиям достичь их конечной цели. После отключения захвата событий объектами, находящимися выше в иерархии, сами события не прекращают свое перемеще- ние. Параметрами метода releaseEvents () являются события одного или нескольких ти- пов. Каждый тип рассматривается отдельно; таким образом, если окно перехватывает все со- бытия, можно блокировать все или только некоторые типы событий. Например, если страница загружается и перехватывает три типа событий. window.captureEvents(Event.CLICK | Event.KEYPRESS | Event.CHANGE); Позднее можно отключить захват всех событий, кроме щелчка. window.releaseEvents(Event.KEYPRESS | Event.CHANGE); Окно продолжает перехватывать и обрабатывать события щелчка, а события keyPress и change направляются напрямую к целевым объектам. Новый механизм (удаление получателя события) реализован в NN6 на основе модели со- бытий W3C. Более подробно он описан в главах 14 и 25. См. также: методы window. captureEvents (), window. routeEvent (). resizeBy (del taX, deltaY) resizeTo(внешняяШирина, внешняяВысота) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN4, Moz-, Safaril+ Начиная с NN4 и IE4, сценарии имеют возможность управлять размером текущего окна браузера “на ходу”. Несмотря на то, что можно установить значения отдельных внутренних и (в NN) внешних свойств width и height, методы resizeBy () и resizeTo () позво- ляют выполнить эту задачу в одном операторе. В обоих случаях изменения относятся к правому нижнему углу окна: для перемещения левого верхнего угла применяются методы window.moveBy() или window.moveTo(). Каждый метод изменения размера требует различных параметров. Метод res i zeBy () кор- ректирует размер окна на определенное число пикселей вдоль одной или обеих осей. Например, для увеличения окна на 100 пикселей по горизонтали и 50 по вертикали используется оператор. window.resizeBy(100, 50); Оба параметра являются обязательными. Если необходимо изменить размер только в од- ном направлении, другой аргумент необходимо установить в значение нуль. Используя отри- цательные значения, размер окна можно уменьшить. Метод resizeTo () применяется часто, особенно когда известно, что на определенной платформе окно требует корректировки ширины и высоты для улучшенного отображения элементов форм. Параметрами метода resizeTo () выступают реальные внешние ширина и высота окна в пикселях— они совпадают со свойствами window, outerwidth и window.outerHeight в NN. Изменить размер окна так, чтобы оно занимало всю доступную часть экрана (за исключе- нием панели задач в Windows и строки меню в Macintosh), можно с помощью свойств объек- та screen, указывающих размеры доступного пространства. window.resizeBy(screen.availwidth, screen.availHeight); 460 Часть III. Объекты документа
Тем не менее, это действие не совпадает с открытием окна во весь экран в системе Win- dows. Для достижения такого эффекта окно необходимо поместить в точке (-4,-4) и добавить восемь к двум параметрам метода resizeBy (). window.moveTo(-4,-4); window.resizeTo(screen.availwidth + 8, screen.availHeight + 8); Этот фрагмент кода скрывает границы окна шириной четыре пикселя, что, собственно, и происходит при открытии окна во весь экран с помощью средств операционной системы (см. также описание объекта screen (глава 38), в котором подробно указаны специфические для операционной системы атрибуты). На практике в NN4 метод resizeTo () не возвращает однозначных результатов. На неко- торых платформах задаются внутренние размеры, а не внешние. Если требуется гарантировано задать внешний размер, то предпочтительнее использовать свойства window. outerHeight и window.outerwidth. 1 Netscape Navigator накладывает определенные ограничения на максимальный и мини- мальный размер окна. Оба типа ограничений задаются видимой областью экрана и минимально различимым окном браузера. Ограничения не накладываются на защищенные сценарии (см. главу 46). С разрешения пользователя окно может принять размеры, большие видимой области экрана. Пример Вы можете смело экспериментировать с методами изменения размера окна, если восполь- зуетесь листингом 16.30. Два раздела формы позволят вывести значения отдельно для каждо- го метода. В первом разделе вы также можете указать количество повторных перемещений, чтобы лучше ознакомиться с эффектом метода. <html> <head> «title>Window Resize Methods«/title> «script type="text/javascript"> function doResizeBy(form) { var x = parselnt(form.resizeByX.value); var у = parselnt(form.resizeByY.value); var count = parselnt(form.count.value); for (var i = 0; i < count; i++) { window.resizeBy(x, y); } } function doResizeTo(form) { var x = parselnt(form.resizeToX.value); var у = parselnt (form.resizeToY.valued- window. resizeTo (x, y) ; } «/script> «/head> <body> «form> «b>Enter the x and у increment, plus how many times the window should be resized by these increments: </bxbr /> Horiz:«input type=“text" name="resizeByX" size="4" /> Vert:«input type="text" name="resizeByY" size="4" /> How Many:«input type="text" name="count" size="4" /> Глава 16. Объекты window и frame 461
<input type="button" name="ResizeBy" value="Show resizeByO” onclick="doResizeBy(this.form)" /xhr /> <b>Enter the desired width and height of the current window: </bxbr />Width:<input type="text" name="resizeToX" size="4" /> Height:cinput type="text" name="resizeToY" size="4" /> cinput type="button" name="ResizeTo" value="Show resizeToO" onclick="doResizeTo (this. form) " /> c/form> c/body> c/html> См. также: свойства window.outerHeight, window.outerWi-dth; методы window.moveTo(), window.sizeToContent(). routeEvent (событие) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Если в сценарий включен присущий NN4 способ захвата событий объектов окна, доку- мента или слоя (с помощью метода captureEvents О), обработчики перехватят события и не допустят их отправки в целевые объекты. Такой подход используется при разработке оп ределенных страниц, что позволяет объектам более высокого уровня обрабатывать все собы- тия определенного типа. Если же целью разработчика является предварительная обработка событий до отправки их в точку назначения, ему необходимо организовать способ их отправ- ки по обычному маршруту. Этой цели и служит метод routeEvent (). Возможно, более обшей причиной перехвата событий на уровне окна (или подобном ему) служит обработка особых действий, например нажатия клавиши <Ctrl> с одновременным щелчком на элементе. В этом случае, даже если обработчик получает все события щелчка, он производит последующую обработку лишь тогда, когда свойство event .modifiers он ределяет, что клавиша <Ctrl> нажата, а свойство eventObj . target указывает на эле мент ссылки, а не кнопки. Все другие варианты события щелчка направляются в свои пункты назначения. Объект event знает, куда отправляются события, поэтому в методе routeEvent () специально это указывать не нужно. Аргументом метода routeEvent () является объект события, который передается функ- ции, обрабатывающей событие высокого уровня. function flashRed(evt) { [операторы, устанавливающие красный фон по определенному событию] routeEvent (evt) Объект события evt используется для отправки объекту, на котором произошел щелчок, в неизмененном виде. В модели событий W3C DOM (реализованной в NN6) перехваченное событие продолжает путь к целевой точке после того, как завершается цепочка обработки в более высоком в ие- рархической структуре элементе. Пример Пример использования метода routeEvent () приведен в листинге 16.21 при рассмот- рении метода window.captureEvents(). См. также: методы window.captureEvents(), window.releaseEventsО, window. handleEvent (); объект event (глава 25). 462 Часть III. Объекты документа
scroll (горКоордин, вертКоордин) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Метод window.scroll О появился впервые в браузере NN3 и затем был реализован во всех браузерах, поддерживающих языки написания спенариев. Однако вскоре он был заменен методом window. scrollTo (), который синтаксически лучше сочетается с другими методами объекта окна. Если страница предназначена для пользователей NN3, применяется метод window, scroll (), в NN4+ и ГЕ4+ лучше воспользоваться методом window. scrollTo (). Метод window.scroll () имеет два параметра: горизонтальная (х) и вертикальная (у) координаты документа, отвечающие левому верхнему углу документа в окне или фрейме. Ьомните, что окно и документ имеют похожие, но независимые системы координат. С точки зрения окна, координаты левой верхней точки (области содержимого) равны (0,0). Координа- ты левой верхней точки всех документов также равны (0.0). Точка (0,0) окна неподвижна, а в документе она имеет возможность перемещаться — при прокрутке вручную или с помо- щью сценария. Несмотря на то, что метод scroll () принадлежит окну, он ведет себя как метод документа, перемещая последний в пределах окна. И наоборот, можно считать, что ок- но движется, чтобы переместить свою точку (0,0) в определенную часть документа. Аргументы могут принимать значения, большие размера документа или меньшие нуля, однако конечный результат зависит от используемой платформы. На текущий момент метод window.scroll () наиболее подходит для прокрутки в верхнюю часть документа (window, scroll (0,0)), чтобы переместить пользователя к началу. Для вертикальной про- крутки большого документа лучшей альтернативой может служить дескриптор ссылки на ан- кер (хотя он не позволяет задавать положение документа по горизонтали). Пример Чтобы продемонстрировать возможности метода scroll (), в листинге 16.31 был создан набор фреймов с документом в верхнем фрейме (листинг 16.32) и панелью управления в нижнем фрейме (листинг 16.33). В последнем представлено несколько кнопок и текстовых полей — с их помощью и прокручивается верхний документ. В качестве содержимого доку- мента выбрано большое GIF-изображение. JteSw 16^1 . Набор фреймов в примере яркдош досужмп* <html> <head> <title> window.scrol1() Method </title> </head> <frameset rows="50%,50%"> <frame src=”lstl6-32.htm” name="display" /> <frame src="lstl6-33.htm" name="control" /> </frameset> </html> / гинг 16.32. Прокручиваемое изображение <html> <head> Глава 16. Объекты window и frame 463
<title> Arch </title> </head> «body> <hl> A Picture is Worth... </hl> <hr /> <center> «table border»"3"> <caption align»"bottom"> A Splendid Arch </caption> <tr> <td> <img alt="image" src="arch.gif" /> </td> </tr> </table> </center> </body> </html> <html> <head> <title> Scroll Controller </title> «script type»"text/javascript"> function scroll(x,y) { parent.frames[0].scroll(x,y); } function customscroll(form) { parent.frames[0].scroll(parselnt(form.x.value), parselnt(form.у.value)); } </script> </head> <body> <h2> Scroll Controller </h2> <hr /> «form name="fixed"> Click on a scroll coordinate for the upper frame: <P> «input type»"button" value="0,0" onclick="scroll(0,0)" /> «input type="button" value="0,100" onclick="scroll(0,100)" /> «input type="button" value="100,0" onclick="scroll(100,0)" /> </p> 464 Часть III. Объекты документа
<р> <input type="button" value="-100,100" oiiclick="scroll (-100,100) " /> <input type="button" value="20,200" onclick="scroll(20,200)" /> <input type="button" value="1000,3000" onclick="scroll(1000,3000)" /> </p> </form> <hr /> <form name="custom"> Enter a Horizontal cinput type="text" name="x" value="0" size="4" /> and Vertical cinput type="text" name="y" value="0" size="4" /> value. Then cinput type="button" value="click to scroll" onclick="customScroll(this.form)" /> c/form> c/body> </html> Обратите особое внимание на функцию customscroll (). JavaScript должен конверти- ровать строковые значения, введенные в текстовых полях, в целые числа (с помощью метода parselnt ()). Нечисловые данные вызывают сбои. См. также: методы window. scrollBy (), window. scrollTo (). scrollBy (del taX, deltaY) scrollTo (x,y) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Современные браузеры располагают связанными методами, предназначенными для прокрутки окна. Метод window. scrollTo () представляет собой новую версию метода window, scroll (). Оба они работают идентично, размещая определенную точку докумен- та в левом верхнем углу окна. Нежелательная прокрутка Многие Windows-совместимые компьютеры оснащены мышью, которая имеет колесико про- крутки, активизируемое по нажатию. Помните, что даже та страница, которая загружена в ок- но или фрейм без полос прокрутки, будет прокручиваться при использовании этого элемента мыши (если документ или его фоновое изображение больше, чем видимая область окна). Пользователи могут даже не заметить, что прокрутили страницу (поскольку она не имеет со- ответствующих полос). Если это влияет на дизайн страницы, необходимо создать процедуру (с помощью метода setTimeout ()), которая будет периодически устанавливать координаты документа в значение 0,0. Метод window.scrollBy() позволяет указать относительное положение документа в окне. Аргументы указывают, на сколько пикселей необходимо прокрутить окно (по гори- зонтали или вертикали). Значения могут быть и отрицательными (прокрутка влево и/или вверх). Метод scrollBy () оказывается удобным, если вы отключили полосы прокрутки, он предлагает пользователям альтернативный способ навигации внутри окна. Например, для перемещения на один экран в длинном документе можно воспользоваться свойством window. innerHeight (в NN) или document. body. clientHeight (в IE) для определе- ния смещения относительно текущей позиции. Глава 16. Объекты window и frame 465
if (document.body && document.body.clientHeight) { window.innerHeight = document.body.clientHeight; window.scrolIBy(0, window.innerHeight); При прокрутке вверх второй аргумент должен быть отрицательным. window.scrolIBy(0, -window.innerHeight); Прокрутка документов на платформе Macintosh демонстрирует ошибки в работе браузера. Иногда кажется возможной прокрутка документа за его пределы. На самом деле документ прокручивается до своей границы, но окно или фрейм не обновляются должным образом. Для получения эффекта прокрутки позиционируемого элемента применяются не только эти методы. Такой тип действий достигается путем установки свойств объекта style (см. главу 39). Пример Чтобы детально изучить методы scrollByO и scrollTo(), изучите листинги 16.34 и 16.35. Замените метод scrollTo () на scroll (). Полученный результат должен быть дру- гим. В примере с методом scrollBy () начните с листинга 16.34. В нем загружается тот же документ, что и в листинге 16.32, но используется другая панель управления (листинг 16.35). Листинг 16 х. Набор йм «тода acrooixw< i I ‘ ’ •’ А*.---—-Г. — - -i. . . к» ..Ж <html> <head> etitle> window.scrolIBy() Method </title> </head> «frameset rows=”50%,50%"> <frame src="lstl6-32.htm" name="display" /> eframe src="lstl6-35.htm" name="control" /> e/frameset> e/html> В листинге 16.35 все ссылки на свойства и методы окна относятся к фрейму display. Строковые значения, введенные в полях, преобразуются в числа с помощью глобальной функции parselnt (). Листинг 15.15. ЙЯШМММВ ватм* «зх«11ву 4 > ehtml> ehead> etitle> ScrollBy Controller e/title> escript type="text/javascript"> function page(direction) { var pixFrame = parent.display; var deltaY = (pixFrame.innerHeight) ? pixFrame.innerHeight : pixFrame.document.body.scrolIHeight; if (direction == "up") { deltaY = -deltaY; } 466 Часть III. Объекты документа
parent.display.scrollBy(0, deltaY); } function customscroll(form) { parent.display.scrollBy(parselnt(form.x.value), parselnt(form.у.value)); } «/script> </head> «body> <b>ScrollBy Controller«/b> «form name="custom"> Enter an Horizontal increment «input type="text" name="x" value="O" size="4" /> and Vertical «input type="text" name="y" value="O" size="4" /> value.«br /> Then «input type="button" value="click to scrollByO" _ onclick="customScroll (this . form) " /xhr /> «input type="button" value="PageDown" onclick="page('down')" /> «input type="button" value="PageUp" onclick="page(1 up')" /> </form> </body> </html> См. также: свойства window.pageXOffset, window.pageYOffset; метод window.scroll (). setinterval ("выражение", задержка [, язик]) setinterval (ссылкаНаФункцию, задержка [, aprl, , aprn]) Возвращаемое значение: целочисленный идентификатор интервала Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Важно понимать отличие между методами setinterval () и setTimeout (). До того как метод set interval () стал частью языка JavaScript, авторы сценариев имитировали его поведение с помощью setTimeout (), что часто требовало дополнительных усилий. Метод set Interval () используется тогда, когда в сценарии необходимо запускать функцию или выполнять некоторое выражение постоянно через определенный интервал вре- мени. Интервал отличается от состояния задержки, которое доступно в других языках: в JavaScript другие процессы не приостанавливаются на этот период времени. Типичные при- ложения, например, реализуют с его помощью анимацию, которая достигается перемещени- ем объекта по странице с определенной скоростью (без использования интервала JavaScript перемещает объект со скоростью, зависящей только от производительности процессора). В приложении-презентации метод set Interval () позволяет “прокручивать” слайды в от- дельных фреймах или слоях, изменяя вид страницы каждые десять секунд. Данный метод вполне подходит для отображения часов или другого цифрового устройства (в этой книге приведены примеры, в которых для достижения таких целей используются устаревшие спо- собы, применяющие метод setTimeout ()). Метод setTimeout () рекомендуется применять в тех случаях, когда необходимо запус- тить функцию или оператор через некоторое время в будущем (см. далее в этой главе). Исходная функциональность метода setinterval () идентична в NN и IE, однако каж- дый браузер предлагает дополнительные возможности в зависимости от указанных аргументов. Глава 16. Объекты window и frame 467
В простых случаях некоторые параметры подходят для всех браузеров, поддерживающих этот метод. Вначале мы рассмотрим именно такие аргументы. Первым параметром метода setinterval () является имя функции или выражения, кото- рое необходимо запустить через заданный интервал времени. Значение представляет строку в кавычках. Если параметр является функцией, то в скобках запрещено использовать ее аргументы, кроме случая, когда они являются строками (см. раздел “Передача параметров функции”). Вторым аргументом метода является число в миллисекундах (тысячных долях секунды), которые задает интервал времени. Несмотря на то, что значение задается с высокой точно- стью, не стоит доверять ему на все 100%. Различные задержки внутренних процессов могут повлиять на длину указанного интервала времени. Как и setTimeout (), метод setinterval () возвращает целочисленный идентифика- тор процесса. Он позволяет завершить процесс методом clearinterval (). Единственным аргументом последнего является именно этот идентификатор. Такой механизм позволяет за- пустить несколько интервальных процессов, что позволит сценарию остановить любой из них, не прерывая при этом другие. IE4+ имеет дополнительный третий параметр, задающий язык сценариев для выражения или функции, указанной в первом аргументе. Поскольку вы используете JavaScript (он же JScript), в его установке нет необходимости. Передача параметров функции NN4+ обеспечивает простой механизм передачи параметров функции, запускаемой мето- дом setinterval (). Для его применения первым аргументом'должна быть не строка, а указатель на функцию (т.е. имя без скобок). Второй аргумент, как и ранее,— задержка в миллисекундах. Далее, начиная с третьего аргумента, указывается список параметров функ- ции, разделенный запятой. intervallD = setinterval(cycleAnimation, 500, "figurel"); Функция получает аргументы так же, как и любая другая функция. function cycleAnimation(elemID) {...} Для применения метода set Interval () в более широком диапазоне браузеров мож- но воспользоваться конкатенацией строк, поскольку функция передается методу как стро- ковое выражение. Например, если функция обрабатывает события для поиска элемента, на котором щелкнул- пользователь (чтобы начать выполнение анимационного движения), идентификатор этого элемента, содержащийся в переменной, можно передать функции следующим образом. function findAndCycle() { var elemID; // Выражения в этом блоке проверяют события и // извлекают идентификатор элемента, // присваивая его переменной elemID intervallD = setinterval("cycleAnimation(" + elemID + ")", 500); Если при каждом запуске функции в методе setinterval () ей требуется передать раз-, личные параметры, то советуем воспользоваться методом setTimeout () как последним оператором функции, вызывающим ее снова. Пример Пример использования метода setinterval () можно рассмотреть в двухфреймовой среде (листинг 16.36). 468 Часть III. Объекты документа
ТЬпинг 16.36. Набор фреймов для примера метой eetlnterval О <html> <head> <title>setlnterval() Method</title> </head> <frameset rows="50%,50%"> <frame src="lstl6-37.htm" name="control" /> <fratne src="bofright.htm" name="display" /> </frameset> </html> В верхнем фрейме представлена панель управления, содержащая несколько кнопок, кото- рые предназначены для автоматической прокрутки документа нижнего фрейма. Листинг 16.37 включает код документа панели управления. Многие операции, выполняемые с ее помощью, реализуются благодаря методу set Interval (). В начале сценария объявляется несколько глобальных переменных. Три из них представ- ляют параметры, с помощью которых выполняется прокрутка документа. Последний — это идентификатор, возвращаемый методом setinterval (). Глобальной эта переменная сде- лана затем, чтобы остальные функции могли отменить прокрутку, воспользовавшись методом clearInterval(). Прокрутка документа выполняется с помощью функции autoScroll (). Для простоты все ее параметры также имеют глобальную область действия. Более того, этот прием позволяет вы- полнить автоматическую прокрутку документа с последними используемыми параметрами. Листинг 16.37. Панель управления в примере метода eetinterwaF) <html> <head> <title>ScrollBy Controller</title> <script type="text/javascript"> var scrollSpee<4 = 500; var scrollJump = 1; var scrolIDirection = "down"; var intervalID; function autoScroll() { if (scrollDirection == "down") { scrolljump = Math.abs(scrollJump); } else if (scrollDirection == "up" && scrolljump > 0) { scrollJump = -scrollJump; } parent.display.scrollBy(0, scrollJump); if (parent.display.pageYOffset <= 0) { clearinterval(intervallD); } } function reducelnterval() { stopScroll(); scrollspeed -= 200; startscroll(); } function increaseInterval() { Глава 16. Объекты window и frame 469
stopScroll(); scrollspeed += 200; startscroll(); } function reduceJumpt) { scrolljump -= 2; } function increasejump() { scrolljump += 2; } function swapDirection() { scrollDirection = (scrollDirection == "down") ? "up" : "down"; } function startscroll() { parent.display.scrollBy(0, scrolljump); if (intervallD) { clearInterval(intervallD); } intervallD = setinterval("autoScroll()",scrollspeed); function stopScroll() { clearInterval(intervallD); } </script> </head> <body onload="startScroll() "> <b>AutoScroll by setinterval() Controller</b> <form name="custom"» <input type="button" value="Start Scrolling" onclick="startscroll()" /> <input type="button" value="Stop Scrolling" onclick="stopScroll()" /> <pxinput type="button" value="Shorter Time Interval" onclick="reducelnterval()" /> <input type="button" value="Longer Time Interval" onelick="increaseInterval()" /></p> <pxinput type="button" value="Bigger Scroll Jumps" onclick="increaseJump()" /> cinput type="button" value="Smaller Scroll Jumps" onclick="reduceJump()" /></p> cpxinput type="button" value="Change Direction" onclick="swapDirection()" /></p> </form> </body> </html> Метод setinterval () вызывается в функции startscroll (). Эта функция исходно прокручивает страницу на один интервал scrolljump. Данная операция выполняется для определения возможности прокрутки страницы вверх с помощью функции autoScroll (), выполняемой перед основной частью сценария. В функции проверяется существование пере- менной intervallD. Если такая существует, то она очищается перед установкой нового значения. Это очень важная операция, поскольку повторный щелчок на кнопке Start Scrolling приведет к установке нескольких интервалов. Тем не менее, в переменной intervallD со- храняется только последний интервал. Упомянутая проверка выполняется с той целью, чтобы удостовериться в установке только одного интервала. Одна из глобальных переменных, scrollspeed, используется для сохранения задержки, подставляемой в качестве аргумента 470 Часть III. Объекты документа
метода set Interval (). Чтобы динамически изменить это значение, сценарий должен пре- рвать текущий процесс, изменить переменную scrollspeed и запустить новый процесс. См. также: методы window, clear Interval (), window. setTimeout (). setTimeout("выражение”, задержка [, язык]) setTimeout (ссылкаНаФункцию, задержка [, aprl, , аргп]) Возвращаемое значение: идентификатор для использования в методе window.clear- Timeout() Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Этот метод имеет непривычное имя, особенно для тех, кто уже работал с задержками в других языках программирования. В JavaScript задержка представляет собой интервал вре- мени (в миллисекундах) перед выполнением выражения. Данный метод устанавливает за- держку не в выполнении сценария, а в запуске выражения или функции. Операторы, следую- щие после вызова setTimeout (), выполняются немедленно. Пусть, например, Web-страница позволяет пользователям взаимодействовать с различны- ми кнопками или полями в пределах указанного интервала времени (страница с презентаци- ей). Можно установить задержку, скажем, в две минуты (120 тысяч миллисекунд), после ко- торой (если пользователь не взаимодействовал со страницей ) страница будет прокручиваться вверх или выводить подсказку. При отключении задержки, когда пользователь осуществляет навигацию, необходимо, чтобы одна из кнопок вызывала метод clearTimeout () (см. ранее в этой главе). Несколько таймеров могут запускаться одновременно. При этом они совершен- но независимы друг от друга. Несмотря на то, что исходная функциональность метода setTimeout () идентична в NN и IE, каждый браузер предлагает дополнительные возможности в зависимости от указанных аргументов. В простых случаях некоторые параметры подходят для всех браузеров, поддер- живающих этот метод. Вначале мы рассмотрим именно такие аргументы. Первым аргументом метода window. setTimeout () является строка в кавычках, со- держащая вызов функции, метода или просто оператора JavaScript. По истечении временной задержки выражение выполняется. Важно понимать, что установленная задержка не прерывает выполнения сценария. При использовании метода setTimeout () в сценарии немедленно выполняются следующие по- сле него операторы, и лишь после указанного интервала времени запускается выражение в скобках. Поэтому рекомендуется устанавливать задержку в последнем выражении функции: пусть сначала будут выполнены все остальные операторы, а затем метод setTimeout () прервет последующее выполнение сценария на определенный интервал времени. В действи- тельности если этот метод запущен, пользователь может совершенно однозначно выполнять действия. После того, как задержка будет задана, время корректировке не поддается. Для вы- полнения такой задачи необходимо сначала отменить задержку и установить новую. Если метод setTimeout () используется внутри функции, ее следует разбить на две части, применив метод как разделитель. Пример такого подхода приведен в листинге 16.26, где IE требуется небольшая задержка для открытия окна до того, как в него будут записы- ваться данные. Если бы задержки не требовалось, то обе части действия можно было бы вы- полнить в одной функции. Зачастую метод setTimeout () запускается из функции, которая указана в его аргумен- те. Например, если применяется Java-аплет, взаимодействие с которым осуществляется с по- мощью LiveConnect, сценарию нужно подождать некоторое время до его полной загрузки и инициализации. Несмотря на то, что обработчик события onload показывает, что объект аплета доступен сценарию, он ничего не сообщает о его состоянии. Для этого создается Глава 16. Объекты window и frame 471
функция JavaScript, которая каждые 500 миллисекунд проверяет внутреннее значение аплета, указывающее на степень его готовности. var t function autoReport О { if (!document.myApplet.done) { t = setTimeout("autoReport()",500); } else { clearTimeout(t) ; // операторы, использующие данные аплета // ) ’ JavaScript не имеет встроенного эквивалента команды wait. Наихудшей ее реализацией может служить цикл, приостанавливающий дальнейшее выполнение сценария на определен- ное время. К сожалению, этот подход прекращает выполнение других процессов, поэтому предпочтительнее пользоваться методом setTimeout (). NN4+ имеет механизм передачи параметров функции, заданной в первом аргументе мето- да setTimeout О (см. раздел “Передача параметров функции”, в котором описывался ме- тод window, setinterval О). Замечание для программистов-, ни setinterval (), ни setTimeout () не порождают но- вых процессов для выполнения своих операций. Когда интервал истекает и вызывается функ- ция, этот процесс размещается в конце очереди на преобразование интерпретатором JavaScript. Пример При загрузке HTML-страницы из листинга 16.38 запускается функция updateTimeO, которая отображает в строке состояния текущее время (в формате hh:mm am/pm). Вместо того, чтобы выводить в строке состояния секунды (многих это обескураживает), эта функция в качестве последнего символа значения времени использует звездочку (*), которая появляет- ся и исчезает через секунду. now = new Date(); theHour = now.getHours(); theMin = now.getMinutes(); theTime = "" + ((theHour > 12) ? <html> <head> <title>Status Bar Clock</title> <script type="text/javascript"> var flasher = false; function updateTimeO { var var var var theTime += ((theMin < 10) ? ":0" : theTime += (theHour >= 12) ? " pm1 theTime += ((flasher) ? " " : "*"), flasher = !flasher; window.status = theTime; timerlD = setTimeout("updateTime()",1000); theHour - 12 : theHour) ; ") + theMin; " am" ; </script> </head> «body onload="updateTimeО </body> </html> 472 Часть III. Объекты документа
В такой функции Метод setTimeout () используется следующим образом. Как только текущее время (включая мерцающую звездочку) появятся в строке состояния, выполнение сценария приостанавливается на 1 секунду (1000 миллисекунд), спустя которую функция вы- зывается повторно. Вам не нужно очищать значение timerlD, поскольку JavaScript это де- лает автоматически каждые 1000 миллисекунд. Возникает логический вопрос: почему не использовать метод setinterval () ? В данном случае большой разницы нет. Оба метода прекрасно справятся со своей задачей. В последнем случае вам необходимо установить интервал вне функции updateTime () .При этом сценарий не будет выполняться в браузерах версии, ниже IE4 и NN4, а код из листинга 16.38 выполняется. Чтобы продемонстрировать, как в функцию updateTime () подставляются параметры, представьте время, отображаемое в строке состояния, с помощью переменных. Таким обра- зом, в функции будет использоваться параметрическая переменная, изменяющаяся каждый раз при вызове метода setTimeout О. Для всех браузеров функция будет выглядеть сле- дующим образом. function updateTime(i) { window.status = theTime + " (" + i + I/ подстановка обновленного значения счетчика timerlD = setTimeout("updateTime(" + i+1 + ")",1000); } При выполнении этой функции в NN4+ можете использовать более удобную запись по- следнего оператора. timerlD = setTimeout(updateTime,1000, i+1); В любом случае обработчик onload также необходимо изменить. onload = "updateTime(0)"; См. также: методы window. clearTimeout О , window, setinterval О , window.clearinterval(). showModalDialog("URL"[, аргументы] [, средства]) showModelessDialog("URL" [, аргументы] [, средства]) Возвращаемое значение: returnvalue (модальные) или объект window (безрежим- ные) окна Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- IE4+ поддерживает методы открытия модальных диалоговых окон, отображение которых делает главное окно браузера недоступным пользователю. ВIE5 разработчики Microsoft добави- ли безрежимный тип диалогового окна, которое также отображается поверх основного окна, но разрешает доступ к последнему. В диалоговое окно можно загрузить любую HTML-страницу или изображение, указав URL в аргументе метода. Дополнительные параметры позволяют передать окну данные, управляющие его видом. К сожалению, такие типы окон не поддерживаются в NN. В лучшем случае их поведение можно эмулировать, но эта задача не под силу начинающим. Окна, генерируемые обоими методами, представляют (почти) полноценные объекты window с некоторыми полезными дополнительными свойствами. Вероятно, наиболее важным из них яв- ляется window. dialogArgument. Это свойство позволяет сценарию читать данные, пере- даваемые окну во втором аргументе showModalDialog () или showModelessDialog (). Они могут иметь любой из поддерживаемых в JavaScript типов, включая объекты и массивы. Глава 16. Объекты window и frame 473
Вывод модального диалогового окна, как правило, приводит к ветвлению сценария. В частности, его выполнение приостанавливается на операторе, вызывающем метод showModalDialog (), до тех пор, пока окно остается отображенным на экране. В это вре- мя выполняются сценарии документа из этого диалогового окна. После его закрытия продол- жается выполнение сценария в главном окне. Вызов безрежимного диалогового окна не при- водит к остановке выполнения сценария в главном окне, так как сценарии из разных окон могут взаимодействовать друг с другом в режиме реального времени. Данные диалогового окна Чтобы передать данные из модального диалогового окна главному, сценарий должен ус- тановить свойство window.returnvalue равным необходимому значению. Именно его и возвращает метод setModalDialog (), как показано ниже. var specifications = window.showModalDialog("preferences.html"); Данные находятся под полным управлением сценария. Автоматически метод не возвра- щает никаких значений. Поскольку безрежимное диалоговое окно доступно одновременно с главным, возврат данных из него не так прямолинеен, как для модального окна. Второй аргумент метода showModelessDialog () выполняет специальную задачу: в нем указывается ссылка на глобальную переменную или функцию. Сценарий безрежимного окна использует ее как спо- соб передачи данных главному окну (когда пользователь закрывает безрежимное окно или, например, щелкает на кнопке Apply). Этот механизм даже позволяет передать данные функ- ции в главном окне. Например, пусть в нем определена функция. function receivePrefsDialogData(a, b, с) { // операторы обработки входных значений // } При открытии безрежимного окна следует передать ссылку на эту функцию. dlog = showModelessDialog("prefs.html", receivePrefsDialogData); В новом окне этой ссылкой можно воспользоваться, например, в функции обработчика события onclick для кнопки Apply. var retumFunc = window.dialogArguments; function apply(form) { returnFunc(form.color.value, form.style.value, form.size.value) ; } Данный подход блокирует способы получения параметров диалоговым окном при откры- тии, однако им всегда можно пользоваться для непосредственной установки значений полей форм или переменных в главном окне. dlog = showModelessDialog("prefs.html", receivePrefsDialogData); dlog.document.forms[0].userName.value = GetCookie("userName"); Помните, что диалоговое окно, открытое каким-либо из двух методов, не поддерживает связь с главным окном с помощью свойства opener. Его значение не определено. Свойства диалогового окна Оба метода имеют дополнительный, третий аргумент, указывающий состояние дополни- тельных элементов окна. Если он опущен, все элементы отображаются по умолчанию. Все параметры задаются в одной строке, и каждый из них представлен парой имя-значение с сии-; таксисом attribute:value, подобным используемому в CSS-стилях. Все возможные для двух типов окна свойства перечислены в табл. 16.4. Если вам необходима совмести- 474 Часть III. Объекты документа
мость с IE4, то ваши возможности ограничены только модальным окном и набором свойств, отмеченных в таблице. Все значения (кроме принадлежащих булевому типу) принимают одно из четырех значений: yes, no, 1, 0. Свойства дмлыяшь «ив в нЕ Свойство Тип П° умолчанию Описание center Булев yes Центрирование диалогового окна (отменяется свойствами dialogLef t и/или dialogTop)’ dialogHeight Длина Разное Внешняя высота окна. ВIE4 длина по умолчанию указывается в ет; в IE5 — в рх dialogLeft Целочисленный Разное Смещение диалогового окна от левого края экрана в пикселях dialogTop Целочисленный Разное Смещение диалогового окна от верхнего края экрана в пикселях dialogwidth Длина Разное Внешняя ширина окна. ВIE4 длина по умолчанию указывается в ет; в IE5 — в рх edge Строка raised| sunken Стиль границы help Булев yes Отображение значка Help (Справка) в заголовке. resizable Булев no Возможность изменения размеров окна (только в IE5+) status Булев Разное Отображение строки состояния внизу окна (только в IE5+). Для непроверенных диалоговых окон значение по умолчанию yes; для проверенных — по. Синтаксис CSS позволяет разместить в одной строке любое количество свойств, разде- ленных точкой с запятой. var dlogData = showModalDialog("prefs.html", defaultData, "dialogHeight:ЗООрх; dialogwidth:46Opx; help:no"); Хотя это не указано явно в свойствах диалогового окна, если содержимое выходит за его пределы, в окне отображаются полосы прокрутки. Если это нежелательно, при открытии страницы следует установить свойство document .body. scroll в значение false. Предупреждения, касающиеся использования диалоговых окон Потенциальная проблема (с точки зрения пользователя) заключается в том, что обычно диалоговое окно не отображается до тех пор, пока в него полностью не загружен HTML- файл. Поэтому, когда происходит загрузка сложного документа, возникает пауза, при которой пользователь не видит каких-либо признаков активности. В данном случае можно поэкспе- риментировать со стилевым свойством cursor, временно изменив его, а затем восстановив по окончании загрузки документа Одной из причин, по которым я назвал диалоговое окно почти объектом window, является то, что в IE4 недоступны некоторые обычные свойства этого объекта. Например, если в диалоговое окно загрузить набор фреймов, внутренние сценарии не смогут получить доступ к переменным или методам родительского окна. Поэтому кнопка в модальном диалоговом окне IE4 не сможет запустить метод parent. close () для его закрытия. Такой недочет устранен в IE5. Глава 16. Объекты window и frame 475
Пример Чтобы продемонстрировать два типа диалоговых окон, мы наделили модальное и немо- дельное окна одинаковыми функциональными возможностями. Впоследствии вы сможете нау- читься правильно передавать данные из основного окна в оба типа диалоговых окон и наоборот. Первый пример касается использования модального окна. В данном случае данные под- ставляются в диалоговое окно, а в сценарий возвращаются значения. Листинг 16.39 представ- ляет HTML-код и код сценария основной страницы. Обработчик onclick запускает функ- цию, отображающую диалоговое окно на экране. Документ диалогового окна (листинг 16.40) содержит несколько элементов управления, с помощью которых вводится имя пользователя и задаются отдельные цвета основного документа. Данные, получаемые из диалогового окна, заносятся в массив и передаются в основное окно. Массив после закрытия диалогового окна сохраняется в локальной переменной prefs. Как только пользователь отменяет введенные в диалоговом окне данные (кнопка Отмена), возвращается пустая строка, поэтому в формуле getPref sData () данные не обрабатываются. При щелчке на кнопке ОК массив заполняет- ся данными. Каждый элемент массива считывается и приравнивается к значению свойства или элемента управления. Все эти данные также сохраняются в глобальном массиве currPref s. Это позволяет отправить данные в диалоговое окно (в качестве второго аргу- мента метода showModalDialog ()) при последующем отображении его на экране. <httnl> <head> <title>window.setModalDialog() Method</title> <script type="text/javascript"> var currPrefs = new Array(); function getPrefsData() { var prefs = showModalDialog("lstl6-40.htm", currPrefs, "dialogWidth:400px; dialogHeight:300px") ; if (prefs) { if (prefs["name"]) { document. all. f irstName. innerText = prefs [ "name" ] ; currPrefs["name"] = prefs["name"]; } if (prefs["bgColor"]) { document.body.style.backgroundcolor = prefs [ "bgColor"] ; currPrefs ["bgColor"] = prefs ["bgColor"] } if (prefs["textcolor"]) { document.body.style.color = prefs["textcolor"]; currPrefs["textcolor"] = prefs["textcolor"]; } if (prefs["hlSize"]) { document.all.welcomeHeader.style.fontsize = prefs["hlSize"]; currPrefs["hlSize"] = prefs["hlSize"]; } } } function init() { document.all.firstName.innerText = "friend"; 476 Часть III. Объекты документа
} </script> </head> <body bgcolor="#EEEEEE" style="margin:2Opx" onload="init()"> <hl>window.setModalDialog() Method</hl> < hr / > < h2 id="welcomeHeader">Welcome, <span id="firstName">&nbsp; </span>!</h2> < hr / > < p>Use this button to set style preferences for this page: cbutton id="prefsButton" onclick="getPrefsData()"> Pref erences</buttonx/p> </body> </html> Документ диалогового окна, представленный листингом 16.40, запрашивает данные у поль- зователя (для этого используются специальные элементы управления) и передает полученную £ информацию в основное окно. Обратите внимание на то, что при выполнении сценария в за- » головке диалогового окна отображается элемент title этого окна. I После загрузки документа в диалоговое окно вызывается функция init О , анализирую- ll щая свойство window.dialogArguments. Если это свойство содержит данные, то они I, представляют текущие настройки основного окна. Функция setSelectedO назначает за- I: данные в диалоговом окне настройки в качестве настроек основного окна. . Кнопки в нижней части страницы располагаются так, чтобы отображаться в нижнем правом Г углу экрана. Каждая кнопка вызывает функцию, выполняющую необходимые действия и закры- S вающую диалоговое окно. В случае использования кнопки ОК функция handleOK () устанав- I ливает в качестве значения свойства window. returnValue данные, полученные из функции get FormData (). Последняя функция считывает значение элемента управления и сохраняет К его в массиве. Впоследствии эти данные можно легко использовать в сценарии основного ок- L на, поскольку порядок следования элементов управления уже не будет играть особой роли. 16.40. Документ модального окна I <html> <head> <title>User Preferences</title> <script type="text/javascript":» // Закрытие диалогового окна function closemeO { window.close(); } 11 Обработка щелчка на кнопке OK i function handleOK() { window.returnValue = getFormData(); closeme(); } // Обработка щелчка на кнопке Cancel function handlecancel() { window.returnValue = ""; closeme(); } Глава 76. Объекты window и frame 477
// Общая функция преобразования пар имя-значение элементов // формы в массив function getFormData() { var form = document.prefs; var returnedData = new Array(); // Получение данных для каждого типа элементов формы for (var i = 0; i < form.elements.length; i++) { if (form.elements[i].type == "text") { returnedData[form.elements[i].name] = form.elements[i].value; } else if (form.elements[i].type.indexOf("select") != -1) { returnedData[form.elements[i].name] = form.elements[i].options[form.elements[i]. selectedlndex].value; } else if (form.elements[i].type == "radio") { returnedData[form.elements[i].name] = form.elements[i].value; } else if (form.elements[i].type == "checkbox") { returnedData[form.elements[i].name] = form.elements[i].value; } else continue; } return returnedData; } // Инициализация - настройка элементов формы // соответственно введенным данным function init() { if (window.dialogArguments) { var args = window.dialogArguments; var form = document.prefs; if (args["name"]) { form.name.value = args["name"]; if (args["bgColor"]) { setSelected(form.bgColor, args["bgColor"]); if (args["textColor"]) { setSelected(form.textcolor, args["textColor"]); if (args["hlSize"]) { setSelected(form.hlSize, args["hlSize"]); } } } // Функция установки элемента select в одно значение function setSelected(select, value) { for (var i = 0; i < select.options.length; i++) { if (select.options[i].value == value) { select.selectedlndex = i; break; } } return; } // Функция обработки нажатия клавиши 478 Часть III.
// <Enter> вместо' щелчка на кнопке ОК function checkEnterO { if (window.event.keyCode ==13) { handleOKO ; } } </script> </head> <body bgcolor="#EEEEEE" onload="ini t()"> <h2>Web Site Preferencesc/h2> <hr /> <form name="prefs" onsubmit="return false"> <table> <tr> <td>Enter your first name:cinput name="name" type="text" value="" size="20" onkeydown="checkEnter()" /></td> </tr> <tr> <td>Select a background color: cselect name="bgColor"> <option value="beige">Beigec/option> coption value="antiquewhite">Antique Whitec/option> coption value="goldenrod">Goldenrodc/option> copt ion value= " lime " >Limec/opt ion> coption value="powderblue">Powder Bluec/option> coption value="slategray">Slate Grayc/option> c/select>c/td> c/tr> ctr> ctd>Select a text color: cselect name="textColor"> coption value="black">Blackc/option> copt ion value= " whi t e " > Whi t e c /opt ion> coption value="navy">Navy Bluec/option> coption value="darkorange">Dark Orangec/option> coption value="seagreen">Sea Greenc/option> coption value="teal">Tealc/option> c/select>c/td> c/tr> ctr> ctd>Select "Welcome" heading font point size: cselect name="hlSize"> coption value="12">12c/option> coption value="14">14c/option> coption value="18">18c/option> coption value="24">24c/option> coption value="32">32c/option> coption value="48">48c/option> c/select>c/td> c/tr> c/table> c/form> cdiv style="position:absolute; left:200px; top:220px"> cbutton style="width:80px" onclick="handleOK()">OKc/button>&nbsp;&nbsp; cbutton style="width:80px" onclick="handleCancel()">Cancelc/button> c/div> c/body> c/html> Глава 16. Объекты window и frame 479
Последним важным элементом модального окна, с которым следовало бы вас ознакомить, является обработчик onkeypress текстового поля. Он вызывается при нажатии клавиши <Enter>. Если при нажатии этой клавиши текстовое поле неактивное, то вызывается все та же функция handleOK (). Такой подход позволяет сделать кнопку ОК используемой по умолчанию. При переходе от модального окна к немодальному структура приложения несколько из- меняется (листинг 16.41). В этом листинге показан документ, загружаемый в основном окне. В данном случае в сценарии инициализируется переменная Pref sDlog, которая возвращает- ся методом showModelessWindow () и сохраняет ссылку на немодальное диалоговое окно. Эта переменная используется для вызова функции init () в немодальном диалоговом окне, но при этом принимает участие в условии конструкции if, анализирующей необходимость создания диалогового окна. Такая конструкция необходима, чтобы не допустить одновремен- ного создания нескольких немодальных диалоговых окон. Новое диалоговое окно не создает- ся до тех пор, пока переменная pref sDlog содержит значение и пока текущее диалоговое окно не будет закрыто (проверяется по свойству window. closed диалогового окна). Второй параметр метода showModelessDialog () представляет собой ссылку на функ- цию в основном документе, которая обновляет последний. Как вы сможете убедиться далее, эта функция вызывается из диалогового окна по щелчку пользователя на кнопке ОК или Apply диалогового окна. <html> <head> <title>window.setModelessDialog() Method</title> <script type="text/javascript"> var currPrefs = new Array(); var prefsDlog; function getPrefsData() { if (!prefsDlog || prefSDlog.closed) { prefsDlog = showModelessDialog("lstl6-42.htm", setPrefs, "dialogWidth:400px,- dialogHeight:ЗООрх") ; prefsDlog.init(currPrefs) ; } } function setPrefs(prefs) { if (prefs["bgColor"] ) { document.body.style.backgroundcolor = pref s["bgColor"]; currPrefs["bgColor"] = prefs["bgColor"]; } if (prefs["textcolor"] ) { document.body.style.color = prefs["textcolor"]; currPrefs["textcolor"] = prefs["textcolor"]; } if (prefs ["hlSize'.'] ) { document.all.welcomeHeader.style.fontsize = prefs["hlSize"]; currPrefs["hlSize"] = prefs["hlSize"]; } if (prefs["name"]) { document.all.firstName.innerText = prefs["name"]; currPrefs["name"] = prefs["name"]; } 480 Часть III. Объекты да
} function initО { document.all.firstName.innerText = "friend"; } </script> I </head> «body bgcolor="#EEEEEE" style="margin:2Opx" onload="init()"> <hl>window.setModelessDialog() Method«/hl> < hr / > < h2 id="welcomeHeader">Welcome, «span id="firstName">&nbsp; </span>1</h2> < hr / > <p>Use this button to set style preferences for this page: «button id="prefsButton" onclick="getPrefsData()"> Preferences«/button>«/p> «/body> </html> Изменения в документе немодального диалогового окна (листинг 16.42) весьма ограниче- ны. В нижнюю часть окна добавлена новая кнопка Apply. С ее помощью текущие настройки диалогового окна применяются к основному документу без закрытия первого. Кнопка Apply вызывает функцию handleApply (), которая выполняет все те же дейст- вия, что и функция handleOKO, но не закрывает диалогового окна. Однако эти функции взаимодействуют с данными основного окна несколько иначе чем в случае использования модального окна. Ссылка на функцию обработки данных основного окна подставляется в ка- честве второго аргумента метода showModelessDialog (); она представлена свойством window. dialogArguments объекта диалогового окна. <html> «head> <title>User Preferences«/title> «script type="text/javascript"> // Закрытие диалогового окна function closemeO { window.close(); } // Обработка щелчков на кнопке OK function handleOKO { var returnFunc = window.dialogArguments; returnFunc(getFormData()); closeme(); }. // Обработка щелчков на кнопке Apply function handleApply() { var returnFunc = window.dialogArguments; returnFunc(getFormData()) ; } // Обработка щелчков на кнопке Cancel function handlecancel() { Глава 75. Объекты window и frame 481
window.returnvalue = closeme(); } // Общая функция преобразования пар имя-значение элементов // формы в массив function getFormData() { var form = document.prefs; var returnedData = new Array 0; // Получение данных о каждом типе элементов формы for (var i = 0; i < form.elements.length; i++) { if (form.elements[i].type == "text”) { returnedData[form.elements[i].name] = form.elements[i].value; } else if (form.elements[i].type.indexOf("select") != -1) returnedData[form.elements[i].name] = form.elements[i].options[form.elements[i]. selectedlndex].value,- } else if (form.elements[i].type == "radio") { returnedData[form.elements[i].name] = form.elements[i].value; } else if (form.elements[i]-type == "checkbox") { returnedData[form.elements[i].name] = form.elements[i].value,- } else continue; } return returnedData; } // Инициализация - настройка элементов формы // соответственно подставленным данным function init(currPrefs) { if (currPrefs) { var form = document.prefs; if (currPrefs["name"]) { form.name.value = currPrefs["name"]; if (currPrefs["bgColor"]) { setSelected(form.bgColor, currPrefs["bgColor"]),- if (currPrefs["textColor"]) { setSelected(form.textColor, currPrefs["textColor"]),- if (currPrefs["hlSize"]) { setSelected(form.hlSize, currPrefs["hlSize"]); } } } // Устанавливает элемент select в одно значение function setSelected(select, value) { for (var i = 0,- i < select.options.length; i++) { if (select.options[i].value == value) { select.selectedlndex = i; break; 482 Часть III. Объекты дос
return; } // Функция обработки события нажатия клавиши // «Enter> вместо щелчка на кнопке ОК function checkEnter() { if (window.event.keyCode == 13) { handleOK(); «/script> </head> «body bgcolor="#EEEEEE" onload="init()"> <h2>Web Site Preferences</h2> <hr /> «form name="prefs" onsubmit="return false"> <table> <tr> <td>Enter your first name: «input name="name" type="text" value="" size="20" onkeydown="checkEnter()" />«/td> <tr> «td>Select a background color: «select name="bgColor"> «option value="beige">Beige«/option> ’ «option value="antiquewhite">Antique White«/option> «option value="goldenrod">Goldenrod«/option> «option value="lime">Lime«/option> «option value="powderblue">Powder Blue«/option> «option value="slategray">Slate Gray«/option> «/select>«/td> «/tr> <tr> «td>Select a text color: «select name="textColor"> «option value="black">Black«/option> «option value="white">White«/option> «option value="navy">Navy Blue«/option> «option value="darkorange">Dark Orange«/option> «option value="seagreen">Sea Green«/option> «option value="teal">Teal«/option> «/select>«/td> «/tr> «tr> «td>Select "Welcome" heading font point size: «select name="hlSize"> «option value="12">12«/option> «option value="14">14«/option> «option value="18">18«/option> «option value="24">24«/option> «option value="32">32«/option> «option value="48">48«/option> </select>«/td> «/tr> «/table> «/form> «div style="position:absolute; left:120px; top:220px"> «button style="width:80px" onclick="handleOK()">OK«/button>&nbsp;&nbsp; Глава 16. Объекты window и frame 483
<button style="width:80px" onclick="handlecancel()"> Cancel</button>&nbsp;&nbsp; cbutton style="width:80px" onclick="handleApply()">Apply</button> </div> </body> </html> Вам придется самостоятельно решить, какой тип диалогового окна лучше использовать. Каждый из них есть имеет преимущества и недостатки. Решать только вам и пользователям создаваемых вами страниц. См. также: метод window. open (). sizeToContent() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Метод window. sizeToContent () в NN6+ применяется при проверке размера окна (особенно нового) на оптимальное отображение в нем содержимого. Однако при его исполь- зовании следует проявлять осторожность, иначе от него будет больше вреда, чем пользы. Выполнение метода sizeToContent () приводит к изменению размера окна таким об- разом, чтобы все его содержимое было максимально видимым на экране. Заботы о разных типах представления данных в различных операционных системах уже ушли в прошлое. Ес- тественно, такое действие следует производить в окне, содержимое которого занимает мень- шее пространство, чем предоставляет наименьший режим разрешения монитора (обычно 640x480 пикселей, однако в будущих версиях браузеров для портативных компьютеров будут применяться намного меньшие режимы). Если дважды запустить метод для окна, содержащего сценарий, могут возникнуть про- блемы. Такое действие заставит окно принять больший размер, чем видимая область экрана. Последующие вызовы метода могут и не придать окну нужного размера. Тем не менее, не- сколько вызовов вполне безопасно использовать для новых окон, если операторы сценария находятся в главном окне. Пример Приложение The Evaluator, загруженное в NN6, позволяет детально ознакомиться с мето- дом sizeToContent (). Предполагается, что вы запускаете это приложение из папки при- меров для главы 13. Вы можете открыть подокно для других примеров из этой главы и изме- нить его размер. Введите в верхнее поле приложения следующее выражение. а = window.open("1st13-02.htm") а. sizeToContent() Теперь ширина окна браузера минимальна, а высота такова, что в окне отображается все- го незначительная часть документа. См. также: метод window. resizeTo (). stop() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Поддерживаемый только в NN метод stop () снабжает сценарий кнопкой, аналогичной - кнопке Stop (Стоп) на панели инструментов. Наличие этого метода позволяет создать на стра- нице собственную панель инструментов и скрыть исходную (в новом окне или с помощью 484 Часть III. Объекты документа
защищенных сценариев в главном). Например, если на странице расположено изображение, имитирующее кнопку Stop, его можно сделать ссылкой, прекращающей загрузку страницы. <а href =" javascript: void stop О "ximg src="myStop.gif " border=0x/a> Сценарий не может прекратить загрузку своего документа — это возможно сделать толь- ко в другом фрейме или окне. Кроме того, если текущий документ динамически загружает новое изображение или элемент мультимедийного типа MIME, то метод stop () подходит только для остановки такого процесса. Несмотря на то, что метод stop () принадлежит объ- екту window, он не привязан к определенному окну или фрейму. См. также: методы window.back(), window.find О , window.forward(), window. home (), window. print (). Обработчики событий onafterprint onbeforeprint Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Bee эти обработчики (не поддерживаемые в Мас1Е5) запускаются по щелчку на кнопке ОК в диалоговом окне печати браузера IE. Так происходит при печати вручную (с помощью меню или кнопок браузера) и при вызове метода window. print (). Печать обычно организована по принципу WYSIWYG, однако вполне возможно, что бу- мажная версия будет содержать больше или меньше информации, чем отображается на экра- не. Например, при выводе каждой страницы на бумагу к ней можно добавить сообщение об авторских правах. Тем не менее, свойство display таблиц стилей соответствующего эле- мента с таким содержимым при загрузке страницы может иметь значение попе. До начала печати документа, свойство необходимо изменить, чтобы элемент отображался как блоко- вый; по окончании процесса печати следует опять вернуться к исходному значению. Обработчик события onbef oreprint запускается сразу же после щелчка на кнопке ОК в диалоговом окне Print. После отправки страйиц(ы) на принтер или в пул печати запускается обработчик onafterprint. Пример Следующий фрагмент кода взят из сценария страницы, содержащей элемент div, на- стройки стиля которой включают оператор display: none. При этом в заголовке страницы обработчики событий печати назначены свойствам. function showPrintCopyright() { document.all.printcopyright.style.display = "block"; function hidePrintCopyright() { document.all.printcopyright.style.display = "none"; } window.onbeforeprint = showPrintCopyright; window.onafterprint = hidePrintCopyright; onbeforeunload Совместимость: WinIE4+, MacIE5+, NN-, Moz-, Safari- Любое действие (пользователя или сценария), выгружающее текущую страницу или заме- няющее ее новой, запускает обработчик события onbef oreunload. В отличие от обработчика Глава 16. Объекты window и frame 485
события onunload, onbeforeunload более эффективен в ситуации, когда сложному сце- нарию необходимо завершить работу до реальной выгрузки страницы. Кроме того, обработ- чик возвращает строковое значение, присвоенное свойству event. returnvalue. Эта стро- ка является частью сообщения в окне предупреждения, выводимом на рассмотрение пользователю. Если пользователь предпочитает остаться на странице, она не выгружается, и никаких действий не выполняется. Пример Пример использования обработчика onbeforeunload приведен в листинге 16.43. В нем показано, как отменить выгрузку документа из браузера. <html> <head> <title>onbeforeunload Event Handler</title> <script type="text/javascript"> function verifyClose() { event .returnvalue = "We really like you and hope you will stay longer."; } window.onbeforeunload = verifyClose </script> </head> <body> <hl>onbeforeunload Event Handler</hl> <hr /> <p>Use this button to navigate to the previous page: cbutton id="go" onclick="history.back()"> Go Back</buttonx/p> </body> </html> См. также: обработчик события onunload. ondragdrop Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- При расширяющейся интеграции рабочего стола и браузеров можно разместить ярлыки (ссылки) на URL на рабочем столе или в других документах. NN4 позволяет запрограммиро- вать операцию перетаскивания таких элементов в окно браузера. Событие dragdrop окна запускается тогда, когда пользователь перетаскивает в него файл или другой объект, имею- щий собственный URL. Пример Обработчик события ondragdrop можно включить в дескриптор <body> и вместе с объектом события передать в него дополнительные сведения, определяющие, на каком эле- менте завершилась операция перетаскивания, а также URL перетаскиваемого элемента. Такую информацию получает и обрабатывает функция, вызываемая обработчиком события. Поскольку событие принадлежит окну, включать захват событий методом window. captureEventsf) необходимости нет. 486 Часть III. Объекты документа
Основную характеристику события — URL перетаскиваемого элемента —- можно полу- чить только с помощью защищенного сценария с разрешения пользователя (см. главу 46). В листинге 16.44 приведен простой документ. Он отображает URL и позицию на экране, которые были получены с помощью объекта события, передаваемого вместе с событием dragdrop. Данный листинг лучше работает на платформе Windows. <html> <head> <title>DragDrop Event«/title> «script type="text/javascript"> function reportDrag(e) { var msg = "You dropped the file:\n"; netscape. security. PrivilegeManager. enablePrivilege("UniversalBrowserRead"); msg += e.data; netscape.security.PrivilegeManager. disablePrivilege("UniversalBrowserRead"); msg += "\nonto the window object at screen location ("; msg += e.screenX + "," + e.screenY + ")."; alert(msg); return false; } </script> </head> «body ondragdrop="return reportDrag(event)"> <b>Drag and Drop a file onto this window</b> </body> «/html> dragdrop является единственным событием, использующим свойство data объекта со- бытия в NN4. Это свойство содержит URL. Свойство target указывает на объект window. Чтобы получить координаты точки, в которой была отпущена кнопка мыши, следует обра- титься к свойствам screenX и screenY объекта события. См. также: объект event (глава 25). onerror Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ См. описание свойства window. onerror ранее в этой главе. onhelp Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Общий обработчик события onhelp рассматривался в главе 15, однако он запускается и тогда, когда пользователь активизирует контекстную справку внутри модального или без- режимного диалогового окна. В последнем случае пользователь может щелкнуть мышью на значке Help (Справка) в заголовке окна, после чего указатель примет форму вопросительно- го знака. После этого пользователь может щелкнуть на любом элементе окна. По второму щелчку запускается обработчик события onhelp, при этом объект события содержит ин- формацию об элементе (ссылка на определенный элемент находится в свойстве event. srcElement), что позволяет сценарию вывести справочную информацию о нем. Глава 16. Объекты window и frame 487
Чтобы отключить появление встроенного справочного окна, обработчик события дол- жен или заканчиваться оператором return false (IE4+), или устанавливать свойство event. returnvalue равным false (IE5+). Пример Следующий фрагмент сценария можно реализовать в безрежимном диалоговом окне (только в IE5), добавив его к листингу 16.44. В примере показано, как отображаются справочные све- дения для двух полей формы. function showHelpO { switch (event.srcElement.name) { case "bgColor" : alert("Choose a color for the main window\’s background."); break; case "name" : alert("Enter your first name for a friendly greeting."); break default : alert("Make preference settings for the main page styles."); } event. retumValue = false; } window.onhelp = showHelp Справка выводится для элементов формы; для этого в операторе switch используется их свойство name. Для других типов страниц более подходящим может оказаться свойство id. См. также: объект event (глава 25); оператор switch (глава 31) onload Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Обработчик события onload запускается в текущем окне по окончании загрузки доку- мента (после пересылки всех текстовых и графических элементов с исходного сервера в брау- зер, а также загрузки всех модулей и Java-аплетов). К этому моменту память браузера содер- жит все необходимые объекты и компоненты сценария. Обработчик события onload является атрибутом дескриптора <body> для документа с одним фреймом или же дескриптора <f rameset> для набора фреймов. В последнем слу- чае событие происходит лишь после полной загрузки документов во всех указанных фреймах. Для вставки обработчика события onload используется один из двух следующих сценариев. <html> <head> </head> <body [другие атрибуты] onLoad=”операторИлиФункция"> [содержимое] </body> </html> <html> <head> </head> <frameset [другие атрибуты] onLoad="операторИлиФункция"> <frame> спецификации фрейма</frame> </frameset> < /html > 488 Часть III. Объекты документа
Этот обработчик, являющийся частью определения набора фреймов, обладает специаль- ным свойством: он не запускается до тех пор, пока не запустятся обработчики onload всех дочерних фреймов набора. Поэтому, если сценарии инициализации зависят от компонент, на- ходящихся в других фреймах, их следует запускать в обработчике onload набора фреймов. Из всего этого следует одно из основных правил программирования на JavaScript: сценарии, запускаемые во время загрузки документа, должны участвовать в процессе генерирования до- кумента и его объектов. Обработчик события onload может содержать дополнительные функции управления объектами документа. Обычно в обработчик события onload включают те операции, которые выполняются быстро и без вмешательства пользователя. Пользователи не должны ожидать окончания дей- ствий после загрузки страницы, они имеют право сразу взаимодействовать с ней. Ни в коем случае в обработчике onload не следует открывать модальное диалоговое окно. Если поль- зователи применяют макросы для автоматической навигации, нежелательно, чтобы процесс останавливался при выводе диалогового окна предупреждения, подтверждения или запроса. С другой стороны, такую операцию, как установка свойства window.defaultStatus, можно смело включить в обработчик события onload. То же самое относится к инициализа- ции обработчиков событий как свойств объектов элементов страницы. См. также: обработчик события onunload; свойство window. def aultStatus. ozunove Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Когда пользователь перетаскивает окно браузера NN4, это действие вызывает событие move для объекта window. Когда обработчику события присваивается функция (например window.onmove = handleMoves), ей передается объект события; его свойства screenX и screenY содержат координаты точки (по отношению ко всему экрану), в которой нахо- дится левый верхний угол окна. См. также: объект event (глава 25). onresize Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari- Если пользователь изменяет размеры окна, для объекта window запускается обработчик события onresize. Когда событию присваивается функция (например, window, onresize = handleResizes), объект события в NN имеет свойства width и height, содержащие ши- рину и высоту внешней части окна. Изменение размеров окна не должно приводить к переза- грузке документа, как это происходит при запуске обработчика onload (хотя некоторые ранние версии NN вызывают это событие). / Изменению размеров окна браузера NN4, особенно если в нем содержатся пози- /Назаметку ционируемые элементы (div или layer), вызывает серьезные проблемы с ото- » бражением содержимого и с выполнением сценариев страницы. Содержимое на- кладывается, а сценарии могут совсем исчезнуть. Единственная надежда — в использовании обработчика события onresize для перезагрузки страницы. Некоторые идеи по поводу того, как обойти эту проблему, приведены в статье по адресу http://developer.netscape.com/viewsource/goodman_resize/ goodman_resize.html. В статье не рассказано о том, что версия NN4 для Windows запускает событие resize, когда в окне появляются полосы прокрут- ки. Это событие в определенной ситуации может привести к бесконечному циклу. Для его предотвращения следует проверить свойства window. innerWidth и window. innerHeight, показывающие, действительно ли изменилось окно (эти свойства сохраняют свои значения и при появлении полос прокрутки). Ниже Глава 16. Объекты window и frame 489
приведен пример кода, который размещается в дескрипторе заголовка страницы. Он предназначен для предотвращения этой проблемы в NN4. var Nav4 = (navigator.appName == "Netscape" && parselnt(navigator.appVersion) == 4); if (Nav4) { var loadwidth - window.innerWidth; var loadHeight = window.innerHeight; } function restore() { if (loadwidth != window.innerWidth || loadHeight != window.innerHeight) { history.go(0) ; } } if (Nav4) window.onresize = restore; См. также: объект event (глава 25). onunload Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Событие unload происходит в текущем окне непосредственно перед выгрузкой докумен- та. Чаще всего выгрузка документа вызывается загрузкой нового HTML-документа или его созданием “на лету” средствами сценария. Желательно ограничить обработчик события onunload быстрыми операциями, которые не препятствуют переходу от одного документа к другому. Не используйте методов, открывающих диалоговые окна! Обработчики события onunload размещаются в тех же частях документа, что и обработчики onload: в атрибуте дескриптора <body> для однофреймового окна или в атрибуте дескриптора <f rameset> для набора фреймов. Оба обработчика могут находиться водном дескрипторе (<body> или <frameset>, не вызывая проблем). Обработчик события onunload хранится в памяти браузера до тех пор, пока не произойдет событие unload. Следует высказать одно предостережение по поводу обработчика события onunload. Несмотря на то, что событие происходит перед очисткой документа, не стоит связывать с ним такие долго выполняемые задачи, как генерирование новых объектов или отправка данных форм. Скорее всего, документ исчезнет до того, как функция завершится, в результа- те чего она будет обращаться к уже несуществующим значениям или объектам. Предпочти- тельно ограничить обработчик события onunload минимальным количеством действий. См. также: обработчик события onload. Элемент frame Свойства, методы и обработчики событий этого HTML-элемента описаны в главе 15. Свойства Методы Обработчики событий allowTransparency bordercolor contentDocument contentwindow 490 Часть III. Объекты документа
Окончание таблицы Свойства Методы Обработчики событий frameBorder height longDesc marginHeight marginwidth name noResize scrolling src width Синтаксис Доступ к свойствам и методам объекта frame из элемента frameset. (IE4+) document.all.идентификаторФрейма.свойство \ метод ([параметры]) (IE5+/W3C) document. getElementByld ("идентификаторФрейма") . свойство | метод ([параметры]) Доступ к свойствам и методам объекта frame из документа фрейма. (IE4+) parent.document. all. идентификаторФрейма. свойство | метод( [па- раметры] ) (IE5+/W3C) parent. document. getElementByld (" идентификаторФрейма") . свойст- во| метод( [параметры] ) Описание объекта Как отмечалось во вступлении к данной главе, элемент frame отличается от объекта фрей- ма, который представлен как объект window в иерархии документа. Элемент frame досту- пен сценариям только там, где все элементы HTML включены в объектную модель, т.е. в брау- зерах IE4+ и NN6+, Mozilla и Safari. Так как элемент frame является элементом HTML, он имеет те же свойства, методы и обра- ботчики событий, что и другие элементы HTML, о которых рассказано в главе 15. Элемент frame используется для установки или изменения значений атрибутов в дескрипторе < frame >. Для упрощения этой задачи следует присвоить уникальный идентификатор атри- буту id этого дескриптора. Если сценарии обращаются к фрейму в рамках стандарта исход- ной объектной модели (по ссылке parent. f rameName), дескриптору требуется атрибут name. Несмотря на то, что допускается использовать один и тот же идентификатор в атрибу- тах name и id, желательно присваивать разные слова, чтобы избежать конфликтов в браузе- рах, поддерживающих оба способа. Для изменения размеров фрейма следует обратиться к элементу frameset, в котором определены атрибуты cols и rows. Эти свойства можно изменить “на ходу” только в брау- зерах D34+ и W3C. Глава 16. Объекты window и frame 491
Свойства allowTransparency Значение: булево Чтение/Запись Совместимость: WinIE6+, MacIE-, NN-, Moz-, Safari- Это свойство указывает на прозрачность фона фрейма. Как правило оно характеризует элемент if rame, поскольку обычные фреймы не требуют использования прозрачных фонов. borderColor Значение: три шестнадцатеричных значения или строковое Чтение/Запись имя цвета Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Если фрейм имеет границу (которая определяется атрибутом frameborder элемента frame или атрибутом border элемента frameset), она может окрашиваться в цвет, отлич- ный от цвета других фреймов. Исходный цвет (если он отличается от цвета набора фреймов), как правило, устанавливается в атрибуте bordercolor дескриптора <f rame>. В сценарии при необходимости можно изменить эту установку. Изменение цвета границы одного фрейма иногда оказывается рискованным делом (это за- висит от используемых цветовых комбинаций). На практике разные браузеры следуют раз- личным правилам в тех ситуациях, когда возникают конфликты или требуется определить, насколько граница одного фрейма “уходит” в пространство страницы. Более того, в WinIE5 при изменении цвета границы одного фрейма возникает странный эффект. Изменения цвета границы отдельного фрейма не всегда отображается на экране. Поэтому комбинации цветов следует проверять во всех возможных браузерах на разных платформах. Пример Вы можете столкнуться с проблемой изменения цвета границы отдельного фрейма, не- смотря на это, использование синтаксиса W3C DOM и свойства borderColor является оп- равданным. document.getElementByld("contentsFrame").borderColor = "red"; В IE также можно использовать следующее выражение. document.all("contentsFrame"].bordercolor = "red"; Эти примеры предполагают, что имя фрейма подставляется в функции сценария в тексто- вом виде. Если сценарий выполняется только в одном фрейме набора, то в выражение необ- ходимо добавить ссылку parent. См. также: свойства frame. frameBorder, frameset. frameBorder. contentDocument Значение: ссылка на объект document Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Moz-, Safari- Свойство contentDocument элемента frame представляет собой не более, чем ссылку, на документ, содержащийся во фрейме. Это свойство компенсирует разницу между элемен- том frame и объектом frame. Оба этих объекта содержат один и тот же объект document, но в ссылках сценария, чаще всего объект frame используется для доступа к документу внутри фрейма, а элемент frame — к свойствам, содержащимся в атрибутах этого дескрип- тора. Если сценарий имеет ссылку на элемент frame, свойством contentDocument можно воспользоваться как ссылкой на документ, а значит, и на любое содержимое фрейма. 492 Часть III. Объекты документа
Пример В многофреймовом документе для обращения к отдельному фрейму с целью получения его свойств весьма удобно использовать идентификатор элемента frame. Но начинать всегда нужно со ссылки на объект document. var doc = document.getElementByld("Frame3").contentDocument; Далее в сценарии объявленную ранее переменную можно использовать самым произволь- ным образом. var val = doc.mainForm.entry.value; См. также: объект document. contentwindow Значение: объект document Только для чтения Совместимость: WinIE5.5+, MacIE-, NN7+, Mozl+, Safari- Это свойство элемента frame представляет собой ссылку на окно фрейма. С помощью этой ссылки удобно обращаться к документу в окне фрейма. Пример Вы можете создать ссылку на объект window фрейма, воспользовавшись следующим вы- ражением. var win = document.getElementByld("Frame3").contentwindow; См. также: объект window. frameBorder Значение: yes | no 111 0 как строковые значения Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari- Свойство frameBorder обеспечивает доступ к атрибуту frameborder элемента frame сценария. Браузеры IE4+ не всегда реагируют корректно на изменение этого свойства после загрузки страницы. Значения свойства frameBorder являются строками, замещающими значения булевого типа. Значение yes или 1 означает (предположительно) отображение границы, а по или 0 — ее отсутствие. Пример По умолчанию свойство frameBorder имеет значение yes. Вы можете создать в сцена- рии функцию отображения и скрытия границы фрейма (которая в IE может и не выполнять- ся). \УЗС-совместимая версия этой функции приведена ниже. function toggleFrameScroll(framelD) { var theFrame = document.getElementByld(framelD); if (theFrame.frameBorder == "yes") { theFrame.frameBorder = "no"; } else { theFrame.frameBorder = "yes"; } } См. также: свойство frameset. frameBorder. Глава 16. Объекты window и frame 493
height width Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Браузеры IE4+ позволяют узнать высоту и ширину элемента frame. Эти значения не все- гда совпадают с document, body. clientHeight и document .body, clientwidth, поскольку фреймы часто содержат собственные элементы управления, например полосы про- крутки. Эти значения предназначены только для чтения. Изменение размеров фрейма можно произвести с помощью свойств rows и cols объекта элемента frameset. Читать целочис- ленные значения высоты и ширины фрейма значительно удобнее, чем анализировать строко- вые свойства rows и cols. Пример Следующий фрагмент кода предполагает, что основной документ состоит из двух верти- кальных фреймов. Приведенные ниже выражения содержатся в сценарии основного документа. С их помощью ширина левого фрейма извлекается и увеличивается на 10%. Здесь используется ХМЗС-синтаксис, хотя его можно легко адаптировать под поддерживаемый в IE синтаксис. var framewidth = document.getElementById("leftFrame").width; document.getElementByld("mainFrameset").cols = (Math.round(framewidth * 1.1)) + Обратите внимание, что исходная ширина фрейма увеличивается на 10%, а полученное зна- чение конкатенируется с текстовой частью свойства cols набора фреймов. Звездочка после за- пятой указывает на необходимость автоматического определения ширины левого фрейма. См. также: объект frame set. longDesc Значение: строка URL Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+-, Safaril+ Свойство longDesc является эквивалентом (для сценария) атрибута longdesc дескрип- тора <f rame>. Этот атрибут стандарта HTML 4.0 предназначен для передачи браузерам URL документа, содержащего длинное описание элемента. Будущие версии браузеров, возможно, будут использовать это свойство при выведении информации о фрейме для пользователей с плохим зрением. marginHeight marginwidth Значение: целочисленное Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Браузеры автоматически вставляют содержимое во фрейм, добавляя поля вблизи его гра- ниц. Значения полей представлены свойствами marginHeight (верхняя и нижняя граница) и marginwidth (левая и правая граница). Эти свойства предназначены не только для чте- ния, однако их изменение после загрузки набора фреймов не влияет на отображение докумен- та во фрейме. Если требуется изменить поля документа, следует воспользоваться свойствами стиля document.body.style. 494 Часть III. Объекты документа
Несмотря на то, что по умолчанию эти значения являются пустыми (т.е. атрибуты marginheight и marginwidth дескриптора <frame> не установлены), поля встроены в саму страницу. Их точное значение в пикселях зависит от операционной системы. См. также: объект style (глава 26). name Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Это свойство идентифицирует фрейм в наборе фреймов основного документа. Вы можете его свободно использовать в ссылках на фрейм (например, top. frames [ "myFrame" ]). noResize Значение: булевого типа Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ В большинстве случаев Web-дизайнеры фиксируют размеры фреймов, не позволяя поль- зователям изменять их (в результате перетаскивания границы). Свойство noResize позволя- ет получить и откорректировать поведение фрейма после того, как страница загрузилась. На- пример, во врем;} взаимодействия с пользователем ему можно разрешить вручную изменить размер фрейма (в определенном режиме) или же предоставить однократную возможность этой операции. Когда запускается обработчик события onresize, сценарий устанавливает свойство noresize элемента frame в значение false. Если отключить возможность изме- нения размеров, все границы фрейма станут неподвижными, независимо от значения свойст- ва noresize соседних фреймов. Отключение возможности изменения размеров фрейма пользователем не оказывает никакого влияния на способность сценариев выполнять эту опе- рацию с помощью свойств cols и rows элемента frameset. Пример Следующее выражение отключает возможность изменения размера фрейма. parent.document.getElementByld("myFramel").noResize = true; Поскольку имя свойства уже указывает на отрицание, то установка его в значение true предполагает отключение возможности изменения размера фрейма. Внимательно следите за этим в своих сценариях. См. также: свойства frameset. cols, frameset. rows. scrolling Значение: yes | no 111 0 как строковые значения Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство scrolling позволяет сценариям включать или отключать полосы прокрутки внутри одного фрейма или целого набора. По умолчанию они отображаются, если только их не отменяет атрибут scroll дескриптора <f rame>. Свойство scrolling содержит строку, заменяющую значения булевого типа. Значение yes или 1 означает, что полосы прокрутки отображаются (при условии, что часть содержимого находится за пределами видимой области), а по или 0 скрывает их. Браузеры IE4+ также под- держивают (и устанавливают по умолчанию) автоматическое (auto) значение этого свойства. Глава 16. Объекты window и frame 495
f Это свойство в WinlE5.5+ поддерживается только частично. Изменение значения /назммпсу свойства никак не отражается на фрейме. NN6 имеет эту и другие проблемы * (например, свойство не возвращает никакого значения, если атрибут scrolling не указан в дескрипторе элемента frame явно). Пример Листинг 16.45 демонстрирует пример создания восьми фреймов. Содержимое фреймов создается сценарием (функция f ilIFrame О ). Обработчики onclick каждого фрейма вы- зывают функцию toggleFrameScroll О . В данном листинге приведено оба способа об- ращения к фреймам (версия для IE закомментирована). В функции toggleFrameScroll () с помощью оператора if выполняется проверка ра- венства свойства значению, отличному от по. Обратите внимание, что полосы прокрутки в IE5.5, NN6, Moz и Safari из окна не исчезают. Лшмг Упрмдммм ‘ •• 1 <html> <head> <title>frame.scrolling Property«/title> «script type="text/javascript"> function toggleFrameScroll(framelD) { // IE5+/W3C var theFrame = document.getElementByld(framelD); // IE4+ // var theFrame = document.all[framelD]; if (theFrame.scrolling != "no") { theFrame. scroll ing = " no " } else { theFrame.scrolling = "yes"; } } // генерирование содержимого для каждого фрейма function fillFrame(framelD) { var page = "«htmlxbody onclick= 'parent.toggleFrameScroll(\"" + framelD + "\")'> «span style='font-size:24pt; page += "«p>This frame has the ID of:«\/p>«p>" + framelD + ".<\/p>"; page += "«\/span>«\/body>«\/html>"; return page; } </script> </head> «frameset id="outerFrameset" cols="50%,50%"> «frameset id="innerFramesetl" rows="25%,25%,25%,25%"> «frame id="myFrame1" src="javascript:parent.fillFrame('myFramel')" /> < f rame id="myFrame2" src="javascript:parent.fillFrame('myFrame2')" /> « frame id="myFrame3" src="javascript:parent.fillFrame('myFrame31)" /> < f rame id="myFrame4" src="javascript:parent.fillFrame('myFrame4')" /> 496 Часть III. Объекты документа
</frameset> <frameset id="innerFrameset2" rows=,l25%/25%,25%,25%"> <frame id=,,myFrame5" src="javascript:parent.fillFrame('myFrame51)" /> <frame id="myFrame6" src="javascript:parent.fillFrame(’myFrame6')" /> < f rame id= " my Frame 7 " src="javascript:parent.fillFrame('myFrame7')" /> <frame id="myFrame8" src="javascript:parent.fillFrame('myFrame8')" /> </frameset> </frameset> </html> src Значение: строка URL Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство src элемента frame представляет собой дополнительный способ перехода к другой странице в пределах фрейма (кроме присвоения нового URL свойству location.href объек- та frame). Для совместимости с предыдущими версиями браузеров рекомендуется продолжать использовать свойство location, href. Помните, что свойство src принадлежит элементу frame, а не объекту window, который оно представляет. Поэтому ссылаться на свойство src следует с помощью идентификатора элемента или иерархической структуры узлов. Пример Рекомендуется использовать в свойстве src полные URL-адреса. parent.document.getElementByld("mainFrame").src = "http://www.dannyg.com"; Относительные URL-адреса и выражения j avascript: псевдО—URL также находят ши- рокое применение в этом свойстве. См. также: свойство location. href. Элемент frameset Свойства, методы и обработчики событий этого Элемента HTML описаны в главе 15. Свойства Методы Обработчики событий border bordercolor cols frameBorder framespacing rows Глава 16. Объекты window и frame 497
Синтаксис Доступ к свойствам и методам элемента frameset из элемента frameset. (IE4+) document.all.идентификаторНабораФреймов.свойство|метод([па- раметры]) (IE5+/W3C) document. getElementByld ("идентификаторНабораФреймов”) . свойст- во] метод ( [параметры]) Доступ к свойствам и методам элемента frameset из документа внутри фрейма. (IE4+) parent.document. all. идентификаторНабораФреймов. свойство | метод ([параметры]) (IE5+/W3C) parent. document. getElementByld ("идентификаторНабораФреймов”) . свойство|метод([параметры]) Описание объекта Элемент frameset представляет собой эквивалент дескриптора <frameset> для сце- нариев. Он отличается от родительского объекта (окна) исходной объектной модели. Объект frameset имеет свойства и методы элемента HTML; в отличие от него объект window, на который с помощью ключевых слов parent или top ссылаются документы внутри фрейма, содержит документ со всем его содержимым. Во вложенных наборах фреймов существует родительско-дочерняя взаимосвязь между уз- лами. Например, рассмотрим следующую вложенную структуру фреймов. <frameset id="outerFrameset" cols=“30%, 70%"> <frame id="framel"> <frameset id="innerFrameset” rows="50%,50%"> <frame id="frame2"> <frame id="frame3"> </Frameset> </frameset> Сценарии, обращающиеся к фреймам в этой структуре, используют ссылки в менее рас- ширенной иерархической структуре, чем предоставляет HTML. Сценарий из любого фрейма ссылается на окно с набором фреймов с помощью указателя parent, а на другой фрейм — parent. f rameName. Другими словами, объекты window из фреймов, определенных в до- кументе, являются сестринскими узлами с одним родителем. Дело обстоит иначе, если на эту структуру взглянуть с точки зрения терминологии узлов W3C. Взаимоотношения узлов основываются на принципе вложенности элементов HTML, независимо от того, какие окна создает браузер. Поэтому фрейм f rame2 имеет только один сестринский узел— f гатеЗ. Оба они имеют одного родителя— innerFrameset. В свою очередь, innerFrameset и f ramel являются дочерними по отношению к outerFrameset. Если сценарий находится во фрейме frame2, то для изменения свойства cols набора outerFrameset необходимо пройти по двум поколениям узлов. frame2Ref.parentNode.parentNode.cols = "40%,б0%"; На практике применение этого объекта зачастую выглядит еще запутаннее: сценарий, принадлежащий одному из фреймов, должен использовать терминологию объекта окна для перехода от текущего объекта window к набору фреймов. Другими словами, нет прямого способа перейти от документа к элементу frame, в котором он находится. Сценарий доку- мента обращается к иерархии узлов набора фреймов с помощью ссылки parent. document. Последняя является ссылкой на объект document, содержащий всю структуру фреймов. 498 Часть III. Объекты документа
К счастью, в W3C DOM существует метод getElementByld О, предназначенный для полу- чения ссылки на любой узел, вложенный в документе. Таким образом, документ внутри одно- го из фреймов получает доступ к элементу frame так же, как к любому другому своему объекту. parent.document.getElementByld("frame2") В данном случае нет необходимости ссылаться на элемент frameset. Например, чтобы изме- нить ширину столбца в сценарии, находящемся в одном из фреймов, используется выражение. parent.document.getElementById("outerFrame").cols = "40%,60%"; Для доступа к внутреннему набору фреймов применим этот же синтаксис. Свойства border Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safaril+ Свойство border элемента frameset позволяет получить толщину (в пикселях) границ фреймов в наборе. Если атрибут border дескриптора, задающего набор фреймов, не уста- новлен, то это свойство является пустым (оно не отражает толщину границ, использующуюся по умолчанию). Пример Несмотря на то, что это свойство имеет атрибут чтение/запись, редактирование его значе- ния не вызывает изменения толщины отображаемой в браузере границы. Если вам необходи- мо задать толщину границы, то используйте ссылку, подобную приведенной ниже. var thickness = parent.document.all.outerFrameset.border; См. также: свойство frameset. frameBorder. bordercolor Значение: три шестнадцатеричных значения или имя цвета Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство bordered or позволяет получить значение цвета, которое устанавливается в атрибуте bordercolor дескриптора, определяющего набор фреймов. Данное свойство предназначено для чтения и записи, однако изменение цвета в сценарии не влияет на вид фрейма. Значения, установленные как имена цветов в строковом виде, при чтении восприни- маются как корректные шестнадцатеричные числа. Пример Чтобы получить текущий цвет набора фреймов, используйте ссылку следующего формата, var bordercolor = parent.document.all.outerFrameset.bordercolor; См. также: свойства frame. bordercolor, frameset. frameBorder. cols rows Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Глава 16. Объекты window и frame 499
Свойства cols и rows элемента frameset позволяют получить и изменить размеры фреймов после их загрузки. Оба этих свойства определены в W3C DOM. Значения обоих свойств являются строками, которые могут включать символы процента или звездочки. По- этому при попытке увеличить или уменьшить размер столбца или строки фрейма вначале следует обработать строку и извлечь из нее значения, используемые в математических вы- числениях (в браузерах IE4+ воспользуйтесь свойствами height и width элемента frame, содержащими текущие размеры фрейма в пикселях). IE4+ позволяет полностью изменить набор фреймов путем корректировки этих свойств (добавляются и удаляются строки или столбцы в наборе фреймов). Поскольку модификация структуры набора влияет на сценарии, изменяя массив фреймов, привязанный к родительско- му окну, или выгружая документы, содержащие нужные данные, тестируйте сценарии в обо- их состояниях набора фреймов. Если требуется удалить фрейм, просто укажите нулевой раз- мер строки или столбца в наборе. Конечно же, нулевой размер сохраняет на экране однопиксельный фрейм, однако он невидим, если имеет тот же цвет фона, а границы скрыты. Второй аргумент в пользу использования такой методики заключается в том, что восстано- вить фрейм можно без изменения структуры документа. Если в одном документе определены вложенные наборы фреймов, убедитесь, что ссылки указывают на требуемый объект элемента frame set. В одном объекте могут быть определе- ны столбцы, а в другом (вложенном)— строки. Каждому элементу frameset необходимо присвоить уникальный идентификатор. Пример В листингах 16.46-16.48 приведен код документа, который размещается в наборе из несколь- ких фреймов. Этот документ содержит в отдельном фрейме список разделов основной статьи. В листинге 16.46 приведен код настройки трехфреймового документа. Левый фрейм со- держит оглавление, представленное листингом 16.47. Правая часть страницы разделена на два горизонтальных фрейма. В верхнем фрейме содержится простой элемент управления (листинг 16.48), скрывающий и отображающий оглавление (левый фрейм). Как только поль- зователь щелкнет на подчеркнутом тексте этого элемента управления (вставлен в элемент span), его обработчик onclick вызовет функцию toggleTOC (). Приведенный в листингах синтаксис полностью ХУЗС-совместимый. Чтобы исправить его для выполнения в IE, замените ссылку document. getElementByld ("outerFrameset") на document. all. outerFrameset, a elem. firstChild.nodeValue — на elem. innerText. Листинг 16.46. Набор фреймов и сценарий отображения/скрытия фрейма <html> <head> <title>Hide/Show Frame Example</title> <script type="text/javascript"> var origCols; function toggleTOC(elem, frm) { if (origCols) { showTOC(elem) ; } else { hideTOC(elem, frm); } } function hideTOC(elem, frm) { var frameset = document.getElementByld("outerFrameset"); origCols = frameset.cols; 500 Часть III. Объекты документа
frameset.cols = "0,*"; } function showTOC(elem) { if (origCols) { document.getElementByld("outerFrameset")-cols = origCols,• origCols = null; } } «/script> </head> «frameset id="outerFrameset" frameborder="no" cols="150,*"> «frame id="TOC" name="TOCFrame" src="lstl6-47.htm" /> «frameset id="innerFrameset1" rows="80,*"> «frame id="controls" name="controlsFrame" src="lstl6-48.htm" /> «frame id="content" name="contentFrame" src="bofright.htm" /> «/frameset> «/frameset> «/html> Перед скрытием фрейма свойство cols сохраняется в глобальной переменной. Впослед- ствии она будет использоваться в функции showTOC () для восстановления исходной струк- туры фреймов. йьлчмыг 1Л Л7 ЙЬаХш iter m I «html> «head> «title>Table of Contents«/title> «/head> «body bgcolor="#EEEEEE"> «h3> Table of Contents «/h3> «hr /> «ul style="font-size:10pt"> < li>«a href=11 bof right .htm#articlel" target="contentFrame">Article I«/a>«/li> «li>«a href="bofright.htm#article2" target="contentFrame11 >Article II«/a>«/li> < li>«a href="bofright.htm#article3" target="contentFrame">Article III«/a>«/li> < li>«a href="bofright.htm#article4" target="contentFrame">Article IV«/a>«/li> «li>«a href="bofright,htm#article5" target="contentFrame">Article V«/a>«/li> < li>«a href="bofright.htm#article6" target="contentFrame">Article VI«/a>«/li> «li>«a href="bofright.htm#article7" target="contentFrame">Article VIl«/a>«/li> < li>«a href="bofright.htm#article8" target="contentFrame">Article VIll«/a>«/li> < li>«a href="bofright.htm#article9" target="contentFrame">Article IX«/a>«/li> < li>«a href="bofright.htm#articlelO" target ="cont ent Frame">Art ic1e X«/a>«/li> Глава 16. Объекты window и frame 501
</ul> </body> </html> <html> <head> <title>Control Panel</title> </head> <body> <pxspan id="tocToggle" style="text-decoration:underline; cursor:pointer" onclick="parent.toggleTOC()">&lt; &lt;Hide/Show&gt;&gt;</span> Table of Contents</p> </body> </html> См. также: объект frame. frameBorder Значение: yes | no 1110 как строковые значения Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство frameBorder обеспечивает сценариям доступ к атрибуту frameborder эле- мента frame set. Браузеры IE4+ некорректно реагируют на изменение этого свойства после загрузки страницы. Свойство frameBorder содержит строку, заменяющую значения булевого типа. Значе- ние yes или 1 означает, что границы отображается, а по или 0 скрывает их. Пример По умолчанию свойство frameBorder принимает значение yes. Вы можете создать специальную функцию, которая его изменяет (хотя в IE она выполняется не всегда). function toggleFrameScroll(framesetID) { var theFrameset = document.all(framesetID); if (theFrameset.frameBorder == "yes") { theFrameset.frameBorder = "no"; } else { theFrameset.frameBorder = "yes"; } } См. также: свойство frame. frameBorder. frameSpacing Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, МасШ4+, NN-, Moz-, Safari- Свойство framespacing элемента frameset позволяет получить расстояние (в пиксе- лях) между фреймами. Если атрибут framespacing дескриптора, задающего набор фрей- мов, не установлен, то это свойство является пустым (оно не отражает толщину границ, ис- пользующихся по умолчанию, обычно равную 2 пикселям). 502 Часть III. Объекты документа
Пример Это свойство имеет атрибут чтение/запись, однако его настройка в IE4+ не изменяет рас- стояния между фреймами в окне браузера. Если вы хотите определить расстояние, заданное атрибутом дескриптора, то используйте ссылку следующего вида. var spacing = parent.document.all.outerFrameset.frameSpacing; См. также: свойство frameset. border. Элемент iframe Свойства, методы и обработчики событий этого элемента HTML описаны в главе 15. Свойства Методы Обработчики событий align '' allowTransparency contentDocument contentwindow height hspace longDesc marginHe ight marginwidth scrolling src vspace width Синтаксис Доступ к свойствам и методам элемента iframe из документа внутри него. (IE4+) document. all .идентификатор, свойство}метод] [параметры]) (IE4+/W3C) window.frames [”имяФрейма"] . свойство|метод] [параметры]) (IE5+/W3C) document. getElementByld ("идентификатор") . свойство} метод ( [па- раметры] ) Доступ к свойствам и методам элемента i f rame из документа внутри элемента iframe. (IE4+) parent.document.all.идентификатор, свойство}метод] [параметры] ) (IE5+/W3C) parent .document .getElementByld! "идентификатор”) . свойство| ме- тод] [параметры] ) Глава 16. Объекты window и frame 503
Описание объекта Элемент i frame (DE4+ и NN6) позволяет загрузить HTML-содержимое из источника в тело другого документа. В некотором смысле элемент layer в NN4 является предшествен- ником концепции iframe, но, в отличие от layer, он не является наследственно позицио- нируемым. Его можно позиционировать как и любой другой элемент HTML, присвоив соот- ветствующие атрибуты в таблицах стилей, заданных для элемента iframe. Если его положение не указано явно, элемент iframe размещается в теле документа в месте, задан- ном исходным кодом страницы. В отличие от фрейма или набора фреймов, iframe можно разместить в любом месте документа. Если размеры элемента iframe изменяются с помо- щью сценария, прилежащие к нему элементы смещаются соответствующим образом. Что действительно отличает iframe от других элементов HTML, так это возможность за- 1 гружать и отображать содержимое Внешних HTML-файлов, причем, различные страницы мо- гут загружаться, не влияя на содержимое основного документа. Страницы, загружаемые в iframe, могут содержать сценарии и любые другие средства любого HTML-документа (включая, например, XML-данные). Элемент iframe имеет большой набор атрибутов, позволяющих автору страницы управ- лять видом, размером (height и width) и, в некоторой степени, поведением фрейма. Мно- гие атрибуты доступны сценарию как свойства элемента iframe. Важно помнить, что во многом элемент iframe ведет себя как обычный объект frame, особенно, если речь идет о взаимосвязях с окнами. Если включить элемент iframe в доку- мент главного окна, он будет представлен в объектной модели как фрейм. window.frames[i] window.frames[имяФрейма] Внутри объекта iframe находится документ со всем его содержимым. Все ссылки на ' объекты документа внутри iframe должны использовать “портал” iframe. И наоборот, сценарии документа внутри элемента iframe могут взаимодействовать с главным окном с помощью ключевого слова parent. Конечно же, заменить содержимое ; главного окна другим HTML-документом (с помощью, например, location.href), не уничтожая iframe, нельзя. Свойства align Значение: строка Чтение/Запись Совместимость: WinDE4+, Мас1Е4+, NN6+, Mozl+, Safaril+ Свойство align управляет выравниванием элемента iframe по отношению к окружающе- му его содержимому страницы. Два возможных значения (left и right) управляют положе- ] нием iframe по отношению к левому и правому краю (соответственно) элемента, содержащего ] iframe (обычно BODY). Содержимое документа обтекает элемент iframe так же, как это про- исходит для изображения. Все возможные значения и их описание приведены в табл. 16.5. Когда сценарий изменяет значение свойства al ign, страница отображается повторно. j Пример По умолчанию это свойство принимает значение baseline. Чтобы изменить выравнива- I ние, например, по правому краю, воспользуйтесь в сценарии следующим выражением. document.getElementByld("iframel").align = "right"; См. также: свойства iframe. hspace, iframe. vspace. j 504 Часть III. Объекты документа
16.5. Значения свойства ali^n Зн ачение Описание absbottom Выравнивает нижнюю границу iframe по подстрочной линии символов окружающего текста absmiddle Выравнивает середину iframe по центральной линии между top окружающего текста И absbottom baseline Выравнивает нижнюю границу iframe по базовой линии окружающего текста ‘ bottom Совпадает со свойством baseline в IE left Выравнивает iframe по левому краю элемента-контейнера middle Выравнивает воображаемую центральную линию окружающего текста с воображаемой линией элемента iframe right Выравнивает iframe по правому краю элемента-контейнера texttop Выравнивает верхнюю границу элемента iframe по надстрочной линии символов окружающего текста top Выравнивает верхнюю границу элемента iframe по верхней границе окружающего текста allowTransparency Значение: ссылка на объект document Только для чтения Совместимость: WinIE6+, MacIE-, NN-, Moz-, Safari- Это свойство определяет прозрачность фона фрейма. Чтобы сделать фоновое изображе- ние или цвет прозрачным, установите свойство allowTransparency в значение true. contentDocument Значение: ссылка на объект document Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari! + Свойство contentDocument элемента iframe является простой ссылкой на документ, который содержится во фрейме. Если сценарий имеет ссылку на элемент iframe, свойством contentDocument можно воспользоваться как указателем на документ, а значит, и на лю- бое содержимое фрейма. Пример В сценариях документов часто используются идентификаторы элементов iframe. С их помощью можно не только изменить свойства фрейма, но и обратиться к объекту document. var doc = document.getElementByld("Frame3").contentDocument; Далее вы можете обратиться к форме документа. var val = doc.mainForm.entry.value; См. также: объект document. contentwindow Значение: объект document Только для чтения Совместимость: WinIE5.5, MacIE-, NN7+, Mozl+, Safari- Глава IS. Объекты window и frame 505
Свойство contentwindow элемента if rame служит ссылкой на объект window, сгене- рированный фреймом. Вы можете использовать ее для получения доступа к объекту document и любых его объектам. См. также свойство contentDocument; объект window. height width Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, МасТЕ4+, NN6+, Mozl+, Safaril+ Эти свойства задают высоту и ширину объекта i frame, а потому используются для уста- новки размеров фрейма. Оба свойства задаются в пикселях. hspace vspace Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Эти свойства, поддерживаемые в IE, позволяют устанавливать отступы для элемента i frame. Свойства hspace и vspace (и соответствующие им атрибуты HTML) были заменены пара- метрами CSS. Они не поддерживаются ни в одном из ста^артов W3C (включая HTML 4.0). Значения этих свойств являются целочисленными и задают отступ в пикселях между эле- ментом и окружающим его содержимым документа. Значение hspace задает отступ слева и справа, a vspace — сверху и снизу. Изменение этих свойств в сценарии не оказывает ни- какого влияния на вид страницы в WinIE5+. См. также: свойство style .padding. longDesc Значение: строка URL Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство longDesc является эквивалентом (для сценария) атрибута longdesc дескрип- тора <iframe>. Этот атрибут стандарта HTML 4.0 предназначен для передачи браузерам URL документа, содержащего длинное описание элемента. Будущие версии браузеров, воз- можно, будут использовать это свойство при выведении информации о фрейме для пользова- телей с плохим зрением. marginHeight marginwidth Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Браузеры автоматически вставляют содержимое во фрейм, добавляя поля вблизи его гра- ниц. Значения полей представлены свойствами marginHeight (верхняя и нижняя грани- цы) и marginwidth (левая и правая границы). Эти свойства предназначены не только для чтения, однако их изменение после загрузки набора фреймов не влияет на вид документа во фрейме. Если требуется изменить поля документа, воспользуйтесь свойствами стиля document.body.style. 506 Часть III. Объекты документа
Помните: хотя по умолчанию эти значения являются пустыми (при задании атрибутов marginheight и marginwidth дескриптора <if rame>), поля отдельно задаются для са- мой страницы. Их точное значение в пикселях зависит от операционной системы. См. также: объект style (глава 26). name Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Представляет идентификатор фрейма, используемый при обращении к последнему. Обычно имя фрейма задается с помощью атрибута name. scrolling Значение: yes | no 1110 как строковые значения Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство scrolling позволяет сценариям включать или отключать полосы прокрутки внутри одного фрейма или целого набора. По умолчанию они отображаются, если только их не отменяет атрибут scroll дескриптора <if rame>. Свойство scrolling содержит строку, заменяющую значения булевого типа. Значение yes или 1 означает, что полосы прокрутки отображаются (при условии, что часть содержи- мого находится за пределами видимой области), а по или 0 скрывает их. Браузеры IE4+ так- же поддерживают (и устанавливают по умолчанию) автоматическое значение. Пример Следующая функция toggle iFrameScroll О принимает в качестве аргумента иден- тификатор элемента iframe (представленный строкой) и изменяет свойство scrolling. Оператор if проверяет, установлено ли свойство в значение, отличное от по. function toggleFrameScroll(frameID) { /I IE5 & NN6 var theFrame = document.getElementByld(framelD); I/ IE4+ // var theFrame = document.all[framelD] if (theFrame.scrolling 1= "no") { theFrame.scrolling = "no"; } else { theFrame.scrolling = "yes"; } } См. также: свойство frame. scrolling. src Значение: строка URL Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойство src элемента iframe представляет собой дополнительный способ перехо- да к другой странице в пределах фрейма (кроме присвоения нового URL свойству location.href объекта фрейма). Помните, что свойство src принадлежит элементу iframe, а не объекту window, который оно представляет. Поэтому ссылаться на свойство src следует с помощью идентификатора элемента и/или иерархии узлов. Глава 7ft Объекты window и frame 507
Пример Рекомендуется использовать в качестве значения этого свойства полные URL-адреса, document.getElementByld("mylframe").src = "http://www.dannyg.com"; Относительные адреса и операторы javascript:псевдс Ш.Ь также допускается при- менять, но иногда они вызывают сбои. См. также: свойство location.href. Объект popup Свойства Методы Обработчики событий document hide() isOpen show() Синтаксис Создание объекта popup. var popupObj = window.createPopup() Доступ к свойствам и методам объекта popup из документа, создавшего всплывающее окно. popupObj.свойство|метод([параметры] ) Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Описание объекта Объект popup представляет собой всплывающее окно без элементов управления. Оно рас- полагается поверх документа, который его генерирует. Это окно отображается поверх диалого- вых окон. В отличие от последних, генерируемых в IE методами showModalDialog () и showModelessDialog (), сценарии должны не просто создавать окно, а также заполнять его содержимым и указывать его положение на экране. Поскольку всплывающее окно не имеет элементов управления (заголовка, элементов из- менения размера и т.д.), оно должно иметь рамку и/или другой цвет фона, чтобы выделяться на странице. Ниже представлена типичная последовательность операторов, применяемая для создания, заполнения содержимым и отображения объекта popup. var popup = window.createPopup(); var popupBody = popup.document.body; popupBody.style.border = "solid 2px black"; popupBody.style.padding = "5px"; popupBody.innerHTML = "<p>Here is some text in a popup window</p>"; popup.show(200,100, 200, 50, document.body); Всплывающее окно, создаваемое в IE, является окном лишь с точки зрения документа. Та- ким образом, хотя набор свойств и методов объекта popup невелик, свойство parent Window документа внутри него указывает на исходное свойство window. Помните, что всплывающее окно не отображается отдельно среди окон на панели задач Windows. Если пользователь щелкает мышью за пределами всплывающего окна или активизирует другое приложение, ок- но исчезает; для его восстановления необходимо заново вызвать метод show () (с указанием параметров размера и положения). При заполнении окна содержимым следует удостовериться, что оно помещается в преде- лах окна. Если это не так, полосы прокрутки все равно не отображаются. 508 Часть III. Объекты документа
Свойства document Значение: ссылка на объект document Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Свойство document используется как своеобразный шлюз для содержимого всплывающего окна. Это единственная точка доступа сценария, создавшего всплывающее окно, к документу в нем. Например, для создания границы всплывающего окна (поскольку само по себе оно не имеет элементов управления), сценарий присваивает значения свойству style документа. myPopup.document.body.style.border = "solid 3px gray"; Помните, что объект document всплывающего окна поддерживает не все возможные свой- ства. Например, свойству document. url во всплывающем окне нельзя присвоить новый URL. Пример Приложение The Evaluator (глава 13) используется для изучения объекта popup и его свойств. Введите в верхнее текстовое поле следующие выражения. Первый оператор создает всплывающее окно; ссылка на него задается глобальной переменной а. Следующий оператор представляет со- бой ссылку на тело документа всплывающего окна; эта ссылка сохраняется в глобальной пере- менной Ь. Остальные операторы управляют указанными двумя глобальными переменными. а = window.createPopup() b = а.document.body b.style.border = "solid 2px black" b.style.padding = "5px" b.innerHTML = "<p>Here is some text in a popup window</p>" a.show(200,100, 200, 50, document.body) См. описание метода show (). См. также: объект document. isOpen Значение: булево Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Пока всплывающее окно является отображаемым, свойство isOpen возвращает значение true; в ином случае оно равно false. Поскольку любое действие пользователя В браузере приводит к удалению окна с экрана, это свойство применяется только в тех операторах сце- нария, которые выполняются после отображения окна. Пример Свойство isOpen также можно легко изучить, воспользовавшись приложением The Evaluator. Введите в верхнее текстовое поле следующие выражения. Указанная последователь- ность операторов начинается с создания всплывающего окна, ссылка на которое сохраняется в глобальной ‘переменной а. Обратите внимание, что последняя строка состоит из двух опера- торов; второй оператор выполняет только тогда, когда всплывающее окно все еще открыто. а = window.createPopup(); а.document.body. innerHTML = "<p>Here is a popup window</p>",- a.show(200,100, 200, 50, document.body); alertC'Popup is open:" + a.isOpen); Глаза 16. Объекты window и frame 509
Если вы щелкнете в основном окне для скрытия всплывающего окна, то получите резуль- тат, который зависит от того, будет ли введен в верхнее поле следующий оператор. alert("Popup is open:" + a.isOpen); См. также: метод popup. show (). Методы hide() show(слева, справа, ширина, высота[, позиционирование}) Возвращаемое значение: отсутствует Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Созданный с помощью метода window. createPopup () объект popup необходимо яв- ным образом отобразить на экране — для этого и предназначен метод show (). Если окно не отображается на экране по причине того, что пользователь щелкнул мышью где-либо в брау- зере, метод show () (со всеми параметрами) необходимо запустить заново. Чтобы скрыть ок- но, для объек±а popup используется метод hide (). Четыре первых аргумента метода show () задают расположение и размер всплывающего окна в пикселях. По умолчанию координатным пространством для left и top служит экран. Поэтому значения left и top, равные нулю, размещают окно в левом верхнем углу экрана. Указав пятый, дополнительный аргумент, можно определить другое координатное простран- ство. Этот параметр является ссылкой на элемент страницы. Чтобы ограничить координатное пространство окном браузера, необходимо указать объект document. body. Пример В листинге 16.49 приведен пример использования методов hide () и show (). Щелчок на кнопке страницы приводит к вызову функции self Timer (), которая выполняет большин- ство операций этого примера. Наша цель — создание всплывающего окна, которое “самоуничтожается” спустя пять секунд после открытия. При всем этом во всплывающем ок- не отображается секундомер. Ссылка на всплывающее окно сохраняется в глобальной переменной popup. После соз- дания объекта popup функция initContent () форматирует содержимое всплывающего окна с помощью свойств style и innerHTML. Содержимое окна генерируется автоматиче- ски в процессе его создания. В документ всплывающего окна также включен элемент span, чтобы в дальнейшем еще одна функция могла изменить только фрагмент данных документа. Обратите внимание, что добавление содержимого во всплывающее окно выполняется на эта- пе инициализации последнего (переменная popup принимает значение), хотя само окно при этом не отображается. Объект popup отображается с помощью функции self Timer (). Ус- тановка правильного размера окна требует проведения определенных подготовительных опе- раций; все необходимые настройки задаются в функции initContent (). После отображения всплывающего окна на экране вызывается функция countDown (). Перед выполнением остальных действий эта функция проверяет, инициализировано и ото- бражено окно на экране или нет. Если пользователь щелкнет при обратном отсчете в основ- ном окне, то свойство isOpen примет значение false, и ни один оператор внутри конст- рукции if выполняться не будет. Функция countDown () извлекает текст элемента span и использует метод parselnt () для извлечения целого числа. 510 Часть III. Объекты документа
<html> <head> • <title>popup Object</title> <script type="text/javascript"> var popup; function initContent() { if (popup && 1popup.isOpen) { var popBody = popup.document.body; popBody.style.border = "solid 3px red"; popBody.style.padding = "lOpx"; popBody.style.fontsize = "24pt",- popBody.style.textAlign = "center"; var bodyText = "<P>This popup will self-destruct in "; bodyText += "<span id='counter'>05<\/span>"; bodyText += " seconds...<\/P>"; popBody.innerHTML = bodyText; } } function countDown() { if (popup && popup.isOpen) { var currCount = parselnt(popup.document.all.counter.innerText, 10); if (--currCount == 0) { popup.hide(); popup = null; } else { popup.document.all.counter.innerText = "0" + currCount; setTimeout("countDown()", 10 0 0); } } } function selfTimerO { popup = window.createPopup(); initContent(); popup.show(200,200,400,100,document.body); setTimeout("countDown()", 1000); } </script> </head> <body> <form> <input type="button" value="Impossible Mission" onclick="selfTimer()" /> </form> </body> </html> Метод hide () запускается в сценарии при отображенном всплывающем окне. Поскольку окно скрывается автоматически по истечении короткого промежутка времени, то вызывать этот метод при щелчке пользователем в основном окне нет смысла. Для умышленного закры- тия всплывающего окна используется метод parentwindow. close (). См. также: свойство popup. isOpen; метод window. createPopup (). Глава 16. Объекты window и frame 511
Объекты history и location м 1г"Ч е все объекты в модели документа можно просмот- L U реть в области окна браузера. Каждое окно или фрейм имеет ссылки на дополнительную информацию по те- ме страницы, отображаемой пользователем в текущий мо- мент. URL страницы, отображенной в окне браузера, называ- ется адресом', браузеры сохраняют эту информацию в объекте location. Во время пребывания пользователя в се- ти URL-адреса страниц, посещенных им в прошлом, сохра- няются браузером в объекте history. Вручную можно про- сматривать содержимое этого объекта в меню браузера, таким образом переходя на предыдущие страницы. В данной главе описаны объекты history и location, которые не используются на Web-странице явно, однако играют немало- важную роль при написании сценария. Данные объекты могут использоваться не только для простого управления браузерами. С их помощью можно по- лучить URL-адреса страниц, загруженных пользователем в другие окна браузера или посещенных им узлов. Эту задачу легко осуществить при написании даже самого простого сценария. В конечном счете, разработчики снабдили браузе- ры средствами защиты, ограничивающими доступ к некото- рым свойствам данных объектов (это ограничение не отно- сится к NN4+). В последующих версиях браузеров эти свойства стали просто недоступны.
Объект location Свойства Методы Обработчик событий hash host hostname href pathname port protocol search assign() reload() replace () нет Синтаксис Загрузка нового документа в текущее окно. [window.]location.href="URL" Доступ к свойствам или методам объекта location. [window. ] location, свойство\метод( [параметры] ) Описание объекта В иерархической структуре объектов документа объект location расположен на один уро- вень ниже объектов window. Таким образом, он представляет информацию об URL-адресе лю- бого открытого в настоящее время окна или определенного фрейма. В многофреймовых окнах в поле адреса браузера отображены URL родительских окон. Каждому фрейму также соответст- вует ссылка, хотя она и не всегда отображена в окне браузера. Чтобы получить информацию об URL документа, расположенного в другом фрейме,.в объекте location должна содержаться ссылка на фрейм данного окна. Пусть у вас есть окно, состоящее из двух фреймов. В табл. 17.1 приведены возможные усылки на объекты location для существующих в сети фреймов. ! С помощью сценариев нельзя изменить URL, отображенный в поле адреса брау- /На заметку зера. Чтобы обеспечить защиту данных, в этом поле не отображается ничего, • кроме URL-адреса текущей либо загружаемой страницы. Ссы/Жив ofibeiCTt lo^t 1ОЙ длй 1 Ссылка Описание location (или window, location) URL фрейма, содержащего документ, из которого запускается сценарий с данной ссылкой parent.location URL родительского окна, для представления которого использована структура дескриптора <f rameset> parent.frames[0].location URL первого вложенного фрейма Глава 17. Объекты history и location 513
Окончание табл. 17.1 Ссылка Описание parent. frames [1] . location URL второго вложенного фрейма parent. именаДругихФреймов. location URL остальных фреймов того же дескриптора Большинство свойств объекта location используется для работы в сети. Это касается дан- ных о физическом расположении документа в сети, включая хост-сервер, используемые прото- колы и другие компоненты URL. При создании полного URL обычной Web-страницы каждой час- ти URL-адреса с помощью объекта window. location назначается индивидуальное значение. http://www.giantсо.com:8 О/pronios/newproducts.html#giantGiznio Свойство Значение protocol hostname "http:" "www.giantco.com" port host "80" "giantco.com:80" pathname hash href "/promos newproducts.html" "#gi an tGi zmo" "http://www.giantco.com:80.promos newproducts.html#giantGizmo" Если при написании сценария требуется дополнительная информация об URL, удобно ис- пользовать объект window, location. Можно также получить основную ссылку, на кото- рой и базируются URL-адреса документов, выбранные пользователем для дальнейшей рабо- ты. Данный объект часто используется при разработке узла на одном компьютере и при последующей его отправке на сервер (возможно, через узел Internet-провайдера), на котород в свою очередь, существует собственная структура папок. При написании сценария необходимо создать основные ссылки на текущий документ, расположенный в той или иной папке. Таким образом можно формировать полные URL для загрузки любых документов. Совсем необяза- тельно вручную изменять основные ссылки в документах при перемещении файлов с одногб компьютера на другой или из одной папки в другую. Для того чтобы извлечь часть URL- адреса и затем изменить его для соответствующей папки, используют следующее выражение.' var baseRef=location.href.substring(0,location.href. lastIndexOf ("/") + 1),; Безопасность: для обеспечения безопасной работы в Internet и защиты от ecei можных посягательств в браузерах, поддерживающих сценарии, доступ к св( вам объекта location заблокирован из фреймов, которые расположены на сер и в домене (кроме того, в котором расположен соответствующий сценарий). Од это не относится к использованию защищенных сценариев в NN4+ и ситуации, i в IE установлены доверительные отношения с узлом. Таким образом, в проекты гих разработчиков помещается специальная функция, обеспечивающая защиту кументов от Web-посетителей, имеющих "виды” на ваш сценарий. Если вы л таетесь предоставить такой доступ к свойствам объекта location, то нв зк| появится предупреждающее сообщение, извещающее о “запрещении доступа”. Установив значения некоторых свойств location, можно контролировать докуме загружаемые в окно или фрейм. Если необходимо загрузить в окно браузера новую crpat или узел, введите в поле адреса соответствующий URL, предварительно задав его в свой 514 Часть III. Объекты д(
window, location.href (некоторые, наверное, считают, что в JavaScript существует ме- тод с ключевыми словами Go или Open — как аналог кнопок панели управления браузера). window.location.href="http://www.dannyg.com/”; Наиболее “верный” способ для установки новой ссылки в объекте — использование опе- ратора (=). При установке в объекте location.href URL другого MIME-типа (это могут быть различные мультимедийные форматы) браузер вынужден загрузить эти файлы в допол- нительных приложениях, указанных в настройках браузера. Первоначально метод location. assign () был предназначен для внутреннего использования браузером, однако на самом деле, программисты также имеют к нему доступ (хотя и не рекомендуется исполь- зовать данный метод для “путешествия” по сети). В объектной модели Internet Explorer суще- ствует еще один метод для загрузки документа в окно — window.navigate (), однако его нельзя использовать в приложениях, предназначенных для запуска в браузере. Два других метода дополняют в объекте location средства навигации по Web. Один из методов представляет собой сценарий, выполнение которого аналогично результату, полу- ченному при щелчке на кнопке Reload (Обновить); другой метод обеспечивает возмож- ность перемещения содержимого текущего документа в соответствии со следующим вы- бранным URL-адресом. I Свойства hash Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Символ “решетки” (#), или hash-символ, является стандартным символом в URL-адресе, с по- мощью которого в браузере происходит перемещение к указанному в документе анкеру. Лю- бое имя, назначенное анкеру (в дескрипторе <а name=" </а>) с использованием этого значка, становится частью URL. Свойство hash объекта location является именем “анкерной части” текущего URL (которая состоит из символа # и собственно имени анкера). Если пользователь перемещается по документу с помощью анкеров и соответствующих им ссылок, то можно заметить следующее: хотя в ссылке документа анкер и представлен как часть URL (например в поле Location), значение анкера не изменяется, если пользователь просматривает документ, прокручивая его вручную. В URL-адресе анкер изменятся только тогда, когда переход в текущую точку документа осуществлялся с помощью анкерной ссылки либо в соответствии со сценарием, в котором задан новый URL. К другим анкерам, расположенным в том же документе, можно перемещаться с помощью любого URL, заданного свойством window, location.href. В данном случае необходимо изменить только свойство hash, при этом не используя самого символа (как показано в сле- дующем примере) в имени анкера. Такое перемещение даже в пределах документа иногда влечет за собой перезагрузку текущего документа в IE, чего не происходит в NN3+. Пример В листинге 17.1 продемонстрирован пример использования hash для доступа к анкерной части URL. При загрузке кода этого листинга измените размер окна браузера так, чтобы в нем отображался только один раздел. По щелчку на кнопке сценарий переместит вас к следую- щему логическому разделу или в верхнюю часть документа. Глава 17. Объекты history и location 515
<html> <head> <title>location.hash Property</title> <script type="text/javascript"> function goNextAnchor(where) { window.location.hash = where; } </script> </head> <body> <hlxa id="start" name="start">Top</ax/hl> <form> cinput type= "button" name="next" value="NEXT" onclick="goNextAnchor('seel')" /> </form> <hr / > <hlxa id="secl" name="secl">Section l</ax/hl> <form> cinput type="button" name="next" value="NEXT" onclick="goNextAnchor('sec2')" /> c/form> chr / > chl>ca id="sec2" name="sec2">Section 2c/a>c/hl> cform> cinput type="button" name=l,next" value="NEXT" onclick="goNextAnchor(1sec3') " /> c/form> chr /> chl>ca id="sec3" name="sec3">Section 3c/a>c/hl> cform> cinput type="button" name="next" value="BACK TO TOP" onclick="goNextAnchor('start')" /> , c/form> c/body> c/html> Имена анкеров подставляются в качестве аргументов обработчиков событий onclick кно- пок. Вместо использования в функции значения window, location и добавления символа диеза, а также анкерной части адреса, я изменил свойство hash объекта location текущего окна. Если вы попытаетесь заново считать в сценарии свойство window. location. hash, то не всегда получите корректную информацию, извлекаемую из настроек браузера. Чтобы не допустить возвращения неправдоподобной информации, составьте URL из тех же выраже- ний, что использовались ранее для изменения свойства hash. Не стоит полностью полагаться на браузер при получении информации об адресе. См также: свойство location. href. host Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ В свойстве location. host описывается имя хоста и порт URL-адреса. Значение порта в этом свойстве сохраняется только тогда, когда оно явно указано в полном URL. Если в поле 516 Часть III. Объекты документа
Location браузера отображен URL, не содержащий номера порта, то свойства location. host и location. hostname возвращают одинаковые значения. Для получения части URL, называемой hostname :port, используйте свойство location.host. Такая возможность применяется для формирования URL-адреса опреде- ленного документа, к которому в процессе его загрузки происходит обращение из сценария. Пример Используйте листинги 17.2-17.4 для изучения свойства host. Это свойство принимает значение только в случае включения имени порта в URL-адрес. Если в поле адреса браузера введен URL, который не содержит имени порта, то свойство location.host содержит та- кое же значение, как и location. hostname. Используйте свойство location.host для извлечения из URL-адреса документа, ото- браженного в окне браузера, части location: port. Эта возможность часто используется при создании URL-адреса документа, доступ к которому необходимо получить в процессе выполнения сценария. В приведенных ниже листингах используется намного больше значений, чем возвращает свойство window, location. Откройте в браузере файл листинга 17.2. Эта страница содер- жит два фрейма. Слева располагается временный заполнитель (листинг 17.4), а справа — до- кумент (листинг 17.3), позволяющий указать URL-адреса загружаемых страниц и отобразить составляющие свойства location (фрейм для загрузки страницы можно указать отдельно). phmmr 17.2. Набор фреймов дляприложения изучения <html> <head> <title>window.location Properties</title> </head> <frameset cols="50%,50%" border="l" bordercolor="black"> <frame name="Framel" src="lstl7-04.htm" /> <frame name="Frame2" src="lstl7-03.htm" /> </frameset> </html> <html> <head> <title>Property Picker</title> «script type="text/javascript"> var isNav = (typeof netscape != "undefined") ? true : false; function fillLeftFrame() { newURL = prompt("Enter the URL of a document to show in the left frame; if (newURL != null && newURL != "") { parent.frames[0].location = newURL; } } function showLocationData(form) { for (var i = 0; i <3; i++) { Глава 17. Объекты history и location 517
if (form.whichFrame[i].checked) { var windName = form.whichFrame[i].value; break; } } var theWind = "" + windName + ".location"; if (isNav) { netscape.security.PrivilegeManager. enablePrivilege("UniversalBrowserRead"); } var theObj = eval(theWind); f orm.wi ndNarne.value = windName; form.windHash.value = theObj.hash; form.windHost.value = theObj.host; form.windHostname.value = theObj.hostname; form.windHref.value = theObj.href; form.windpath.value = theObj.pathname; form.windport.value = theObj.port; form.windprotocol.value = theObj.protocol; form.windsearch.value = theObj.search; if (isNav) { netscape.security.PrivilegeManager. disablePrivilege("UniversalBrowserRead"); } } </script> </head> <body> Click the "Open URL" button to enter the location of an HTML document to display in the left frame of this window. <form> cinput type="button" name="opener" value="Open URL..." onclick="fillLeftFrame()" /> chr /> <center> Select a window/frame. Then click the "Show Location Properties" button to view each window.location property value for the desired window. cpxinput type="radio" name="whichFrame" value="parent" checked="checked" />Parent window cinput type="radio" name="whichFrame" value= "parent.frames[0] " />Left frame cinput type="radio" name="whichFrame" value= "parent, frames [1] " />This framec/p> cpxinput type="button" name="getProperties" value="Show Location Properties" onclick="showLocationData(this.form)" /> cinput type=”reset" value="Clear" /x/p> ctable border="2"> ctr> ctd align="right">Window:c/td> ctdxinput type="text" name="windName" size="30" /x/td> c/tr> ctr> ctd align="right">hash:c/td> ctdxinput type="text" name= "windHash" size="30" /x/td> c/tr> ctr> ctd align="right">host:c/td> 518 Часть III. Объекты документа
ctdxinput type="text" name="windHost" size="30" />c/td> </tr> <tr> <td align="right">hostname:c/td> ctdxinput type="text" nams="windHostname" size="30" /x/td> </tr> <tr> <td align="right">href:</td> ctdxtextarea name="windHref" rows="3" cols="30" wrap="soft"> </textareax/td> </tr> <tr> <td align=11 right" >pathname: </td> ctdxtextarea name= "windPath" rows="3" cols="30" wrap="soft"> c / textareax/td> ctd align="right">port:c/td> ctdxinput type="text" name="windPort" size="30" /x/td> </tr> ctd align="right">protocol:c/td> ctdxinput type="text" name=“windProtocol" size="30" /x/td> </tr> ctr> ctd align="right">search:c/td> ctdxtextarea naire= "windsearch" rcws="3" cols="30" wrap="soft"> c/textareax/td> c/tr> c/table> c/center> с/form> c/body> c/html> <html> chead> ctitle>Opening Placeholderc/title> c/head> cbody> Initial placeholder. Experiment with other URLs for this frame (see right). c/body> c/html> Для получения наилучших результатов отобразите Web-документ, расположенный в се- ти, в том же домене и на том же сервере, что и документы, которые представлены листин- гами 17.2-17.4 (возможно, это локальный жесткий диск). Если возможно, загрузите доку- мент, который содержит анкеры, позволяющие перемещать страницы по разделам. Покажите в левом фрейме исходную страницу, а в правом —- составляющие свойства location. См. также: свойства location.port, location. hostname. Глава 17. Объекты history и location 519
hostname Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Имя хоста в типичном URL — это сетевое имя сервера, на котором располагается про- сматриваемый в браузере документ. Для большинства Web-узлов имя сервера включает в се- бя не только имя домена, но также и префикс www. Однако в имени хоста номер порта не со- держится, даже если он и определяется в URL. Пример Пример использования свойства hostname приведен в листингах 17.2-17.4. См. также: свойства location.hostname, location.port. href Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Из всех свойств объекта location, href (гипертекстовая ссылка), вероятно, одно из наиболее часто встречающихся в сценарии свойств. Свойство location.href напрямую связано со строкой полного URL, указанного в объекте window. Для того чтобы открыть в окне документ, находящийся по определенному URL-адресу, в JavaScript используют именно это свойство, располагая его в левой части выражения. Ниже приведены способы, с помощью которых можно загрузить страницу данного Web-узла в од- нофреймовое окно браузера. window.location = " http: 11 www.dannyg.com " window.location.href = " http: // www.dannyg.com"; Если пользователь не указывает ссылку на нужное окно, то время от времени он может сталкиваться с некоторыми трудностями. Иногда, например, в JavaScript возникает путаница и происходит ошибочное обращение к свойству document. location. Чтобы не допустить подобных ситуаций, разработчики JavaScript заменили document. location свойством document. URL. Таким образом, всегда указывая ссылку на соответствующее окно, пользо- ватель точно не “заблудится” в сети. / Очень важно уметь правильно назначать новый URL объекту location, не включая /н« заметку в него имя свойства href (например location=”http://www.dannyg.com”). f Однако, в отличие от большинства современных браузеров, некоторые старые программы (особенно IE3) работают более надежно, если пользователь назна- чает необходимый URL свойству location.href, а не location. Поэтому ре- комендуется всегда использовать первое свойство, а не второе. Иногда в сценарии нужно так указать имя текущей папки, чтобы при выполнении соот- ветствующих операторов к URL добавлялась ссылка на необходимый документ перед его за- грузкой. Несмотря на то, что остальные свойства объекта location отвечают за получение любых частей URL, ни один из них не поможет получить полный URL папки текущих доку- ментов. Для выполнения этой задачи используйте обычные строковые преобразования JavaScript, не задействуя при этом объекты. Данная возможность демонстрируется в листинге 17.5. В разных браузерах небуквенные символы в значении свойства location.href были представлены по-разному, но чаще всего для этого использовался код ASCII. Такое представ- ление символа состоит из знака % и числового ASCII-кода. Наиболее часто используемый в URL символ — это пробел: % 2 0. Если необходимо получить строковое значение URL и вы- вести его в документе, примените к имеющемуся закодированному значению специальную 520 Часть ///. Объекты документа
функцию JavaScript unescape (). Например, если URL одной из страниц узла Giantco имеет ввд http: //www. giantco. com/product%2 Olist, то строковое значение адреса можно получить, подставив данный URL в функцию unescape (), как показано в примере ниже. var plainURL = unescape(window.location.href) // результат "http://www.giantco.com/product list"; В JavaScript существует и обратная функция— escape О, которая предназначена для отправки закодированных значений в CGI-программу, располагаемую на серверах. Пример В листинге 17.5 приведен пример использования свойства href. В этом примере приме- няется функция unescape (), которая не выполняет функционально важных операций, а всего лишь отображает URL-адрес в окне предупреждения. <html> <head> «titlesExtract pathname</title> «script type="text/javascript"> // функция общего назначения, извлекающая URL function getDirPath(URL) { var result = unescape(URL.substring(0,(URL.lastlndexOf("/")) + D); return result; } // обрабатывает события кнопки function showDirPath(URL) { alert(getDirPath(URL)); } «/scripts </heads <body> <form> «input type="button" value="View directory URL" onclick="showDirPath(window.location.href)" /> «/forms «/bodys «/htmls См. также: свойства location.pathname, document. location; объект String (глава 34). pathname Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Путь является частью URL-адреса, который представляет внутреннюю структуру папок сервера. Другими словами, корневая папка (имя сервера в HTTP-соединении) не является ча- стью пути. Если путь, указанный в URL, соответствует файлу в корневой папке, то свойство location.pathname имеет вид обычного символа обратной черты. Любой другой путь, который начинается с этого символа, указывает папку, находящуюся в корневой папке. Зна- чение location. pathname также включает в себя и имя документа. Глава 17. Объекты history и location 521
Пример Пример использования свойства pathname приведен в листингах 17.2-17.4. См. также: свойство location. href. port Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ В наше время редко встречаются Web-узлы, в которых необходимо указывать номер пор- та как часть URL. Наиболее часто номер порта встречается в малопопулярных протоколах, в URL частных узлов либо узлов, не имеющих своего имени домена. Это значение можно по- лучить с помощью свойства location.port. Намереваясь использовать значение порта одного URL-адреса в другом, удостоверьтесь в том, что не пропущен знак двоеточия между номером порта и IP-адресом сервера. Пример Пример использования свойства port приведен в листингах 17.2-17.4. См. также: свойство location. host. protocol Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Первой составляющей любого URL является протокол, используемый для определения типа соединения. Для страниц World Wide Web (WWW) стандартный протокол— это Hypertext , Transfer Protocol (http). Существуют и другие общепринятые протоколы, которые используют- ся в браузере: HTTP-Secure (https), File Transfer Protocol (ftp), File (file) и Mail (mailto). В значениях location.protocol содержится не только имя протокола, но еще и знак двое- точия. Таким образом, для типичного URL Web-страницы в свойстве location.protocol сохраняется значение http: Запомните, что символы обратной черты, расположенные после имени протокола в URL, не являются частью значения location.protocol. Из всех свойств объекта location только в полном URL (location. href) можно увидеть обратную черту между именем про- токола и другими компонентами адреса. Пример Пример использования свойства protocol приведен в листингах 17.2-17.4. См. также: свойство location.href. search Возвращаемое значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Каждый пользователь, наверное, сталкивался с длинными, загадочными URL-адресами, которые отображаются в поле адреса браузера всякий раз, когда мы пользуемся услугами по- исковых средств WWW, вводя ключевое слово в соответствующем поле. Как правило, URL состоит из следующих компонентов: имени протокола и, имени хоста и пути. Традиционный 522 Часть III. Объекты документа
URL — это команда, с помощью которой приводится в действие поисковое средство (на сер- вере запускается соответствующая CGI-программа). Начать заново либо продолжить эту до- вольно долгую операцию можно с помощью свойства location. search. Каждое поисковое средство имеет собственную формулу для представления запроса, основанного на формах HTML, в которые пользователь вводит необходимую информацию. Эти запросы на поиск задаются в закодированном формате и могут представляться в любом формате, кроме языка программы. При написании сценария запроса на поиск используют свойство location, search, которое задает искомую строку (что требует полного пони- мания механизма поиска данных). Наиболее распространенный формат для поиска данных — это наборы пар имя/значение. Знак равенства (=) отделяет имя от значения. Если пара содержит несколько значений одного параметра, то между ними располагаются символы амперсанта (&). Если в строке URL-адреса содержатся пробелы, следует использовать функцию escape () для преобразования ее в со- ответствующий URL-формат. Свойство location.search применяется к любой части URL, которая следует после имени файла (включая параметры, которые отправляются в CGI-программы, расположенные на сервере). Обмен данными между страницами с помощью URL Нередко требуется сделать так, чтобы некоторые данные, содержащиеся на одной страни- це, были доступны для сценария другой страницы (будто он “запрашивает” их). Этого можно достичь, загрузив страницу одним из трех методов: с помощью свойства document. cookie (глава 18), в результате изменения установок в многофреймовых документах и благодаря строке, по которой проводится поиск URL-адресов. В действительности при посещении по- исковых и коммерческих узлов, с которых в браузер пользователя отправляется информация, происходит следующее: вместо сохранения критериев поиска на сервере, они отправляются обратно клиенту, но уже как часть URL. В следующий раз, когда этот URL активизируется, на сервер поступают те же значения, но уже для обработки (например, для того чтобы переслать пользователю следующую страницу результатов поиска по сделанному запросу). Обмен данными между страницами не ограничен связью клиент-сервер. Для того чтобы передать данные от одной страницы к другой, можно использовать строку поиска только на стороне клиента. Если на сервере отсутствуют CGI-приложения, запрограммированные на управление строкой поиска, на Web-сервере эта строка воспринимается как часть данных, получаемых вместе с адресом. С помощью специального сценария в последней загруженной странице может быть найдена строка поиска (благодаря свойству location.search) и “отделена” для дальнейшего ее помещения в переменные сценария. В примере на компакт- диске демонстрируется применение описанной выше методики. Как отмечалось в начале главы 16, в наборе фреймов можно одновременно отобразить несколько HTML-страниц. Воспользовавшись свойством search, примените один и тот же набор фреймов для загрузки в нем различных контекстно-зависимых документов (вместо соз- дания отдельных наборов фреймов для каждой комбинации страниц). Именно этот принцип и продемонстрирован в приведенных ниже листингах. Таким образом, если пользователь знает URL-адрес одного из контекстно-зависимых документов (ссылка на него добавлена в папку Избранное), то соответствующий набор фреймов будет загружаться автоматически при следующем посещении страницы. Структурно приложение делится на две части. Первая часть располагается в контекстно- зависимых страницах; сценарий проверяет, загружена ли страница в наборе фреймов. Если нет, то создается строка поиска, которая добавляется в URL-адрес документа набора фрей- мов. Документ набора фреймов также содержит короткий сценарий, который проверяет Глава 17. Объекты history и location 523
существование в адресе строки поиска. Последняя используется для загрузки контекстно- зависимой страницы в соответствующий набор фреймов. Листинг 17.6 представляет документ набора фреймов. Функция getSearchAsArray() намного сложнее, чем требует данный пример. С ее помощью вы можете легко преобразовать любое количество пар имя-значение, подставленных из строки поиска (в стандартном форма- те namel=valuel&name2=value2& и т.д.), в массив, индексы которого представлены именами (таким образом в сценарии проще извлекать необходимые данные). Ветвление про- граммы для разных браузеров необходимо, поскольку браузеры версий до IE4 и NN3 не под- держивают методы управления текстовыми данными и массивами, используемыми в функ- ции getSearchArray(). <html> <head> <title>Example Frameset</title> <script type="text/javascript"> // преобразует значение location.search в массив, // индексированный по именам function getSearchAsArray() { var results = new Array(); var input = unescape(location.search.substr(1)); if (input) { var srchArray = input.split("&"); var tempArray = new Array(); for (var i = 0; i < srchArray.length; i++) { tempArray = srchArray[i].split("="); results[tempArray[0]] = tempArray[1]; } } return results; } function loadFrameO { if (location.search) { var srchArray = getSearchAsArray(); if (srchArray["content"]) { self.content.location.href = srchArray["content"]; } } } </script> </head> <frameset cols="250,*" onload="loadFrame()"> <frame name="toc" src="lstl7-07.htm" /> <frame name="content" src="lstl7-08.htm" /> </frameset> </html> В листинге 17.7 показан код HTML-страницы с оглавлением. Он не является ничем осо- бенным, поскольку создает стандартные средства навигации. 524 Часть III. Объекты документа
<html> <head> <title>Table of Contents</title> </head> cbody bgcolor="#EEEEEE"> <h3>Table of Contents</h3> <hr /> <ul> clixa href="lstl7-08.htm" target="content">Page l</ax/li> clixa href ="lstl7-08a .htm" target="content">Page 2</ax/li> clixa href="lstl7-08b.htm" target = "content">Page 3c/ax/li> </ul> </body> </html> - Листинг 17.8 представляет одну из контекстно-зависимых страниц. В процессе ее загрузки вызывается функция checkFrameset (). Если страница не загружена в наборе фреймов, то сценарий переходит к набору фреймов, подставляя URL-адрес текущей страницы в ка- честве строки поиска. Обратите внимание на то, что в браузерах, поддерживающих метод location, replace (), загрузка страницы вне набора фреймов не регистрируется в журна- ле, а потому к ней нельзя получить доступ по щелчку на кнопке Back (Назад). <html> <head> <title>Example Frameset</title> cscript type="text/javascript"> // преобразует значение location.search в массив, // индексированный по именам function getSearchAsArray!) { var results = new Array(); var input = unescape(location.search.substr(1)); if (input) { var srchArray = input.split("&"); var tempArray = new Array(); for (var i = 0; i c srchArray.length; i++) { tempArray = srchArray[i].split("="); results[tempArray[0]] = tempArray[1]; } } return results; } function loadFrameO { if (location.search) { var srchArray = getSearchAsArray(); if (srchArray["content"]) { self.content.location.href = srchArray["content"]; c/script> </head> Глава 17. Объекты history и location 525
<frameset cols="250,*" onload="loadFrame()"> <frame name="toc" src="lstl7-07.htm" /> <frame name="content" src="lstl7-08.htm" /> </frameset> </html> На практике рекомендуется сохранить код функции checkFrameset () в виде отдель- ной библиотеки (. j s), а в сценариях — создать ссылку на эту библиотеку. Именно поэтому в данной функций используется свойство location. href — его можно применить в любой контекстно-зависимой странице. Листинги 17.6-17.8 представляют двухфреймовый документ. В левом фрейме содержится оглавление, с помощью которого указывается загружаемая контекстно-зависимая страница. Первая из них загружается в правом фрейме по умолчанию. Обратите внимание на то, что новая страница задается в качестве параметра content свойства search. Istl7-06.htm?content=hello.htm См. также: свойство location. href. Методы assign ("URL") Возвращаемое значение: нет Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ В предыдущих главах при описании объекта location речь шла о назначении нового URL объекту location либо свойству location. href как об одном из способов перехода на другую страницу. При использовании метода location. assign () выполняется анало- гичная операция. При установке URL в объекте location в JavaScript автоматически при- меняется метод assign (). С помощью данного метода нельзя выполнить важные операции (кроме приведения кода сценария к более понятному и читабельному виду). Данный метод при разработке документа используется довольно редко, но это совсем не означает, что поль- зователь не может применять его, если считает это удобным. См. также: свойство location. href. reload(булевФлаг) Возвращаемое значение: нет Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Для данного метода имя location, reload () не совсем уместно, так как сразу возни- кают ассоциации с кнопкой Reload/Refresh (Обновить), расположенной в панели инстру- ментов браузера. Метод reload () функциональнее, чем данная кнопка. Многие элементы форм при нажатии кнопки Refresh сохраняют состояние окна (кроме IE3). В текстовом поле и его объектах отображается любой содержащийся в нем текст; переключа- телям и флажкам соответствует указанный в них статус; в объектах списков (select) хра- нится информация о выделенном элементе. Единственное, что теряется при использовании кнопки Reload/Refresh, — это глобальные переменные и любые устанавливаемые, но явно не отображаемые на Web-странице свойства (например, значение свойства hidden (скрытого) объекта input). Перезагрузка такого типа называется программной. > Загрузка документа в кэш-память браузера каждый раз осуществляется по-разному. Тео- ретически, применение метода location, reload () должно восстанавливать страницу из, 526 Часть III. Объекты документа
кэш-памяти, если она все еще доступна в этой области памяти (хотя метод history. go (0) может быть даже более удобен, так как в нем сохраняются установки элементов управления формы). Установка параметра true в данном методе предполагает осуществление безуслов- ного получения данных с сервера без использования уже имеющейся версии страницы. Если в приложении возникают проблемы с загрузкой страницы из кэш-памяти (быстрый способ) или с сервера (в кэш заносится новая копия), то, естественно, загрузка в браузере не происхо- дит должным образом. Возможно, дескрипторы meta изначально разрабатывались для более частого сохранения страницы. Некоторым программистам удается успешно перезагрузить страницу, установив в location.href ее URL и слегка изменив строку поиска (например, на основе строкового представления объекта Date) так, чтобы избежать совпадения URL- адреса страницы с ее версией в кэш-памяти. Пользователь должен быть готов к тому, что придется перебирать различные схемы для достижения необходимого эффекта, а также к тому, что в конечном итоге можно и не полу- чить ожидаемого результата Пример В листинге 17.9 содержится код приложения, позволяющего исследовать преимущества обоих типов перезагрузки. Отобразите эту страницу в браузере и выберите один из переклю- чателей. Введите текст и выберите значение в списке (элемент select). Щелкая на кнопках в нижней части страницы, вы будете выполнять те же действия, что и при использовании кнопок Reload (Перезагрузить) и Refresh (Обновить) браузера. В первом случае использует- ся метод location. reload (), а настройки всех элементов управления принимают значе- ния по умолчанию. Shminr 17.в. <html> chead> <title>Reload Comparisonsc/title> <script type="text/javascript"> function hardReloadO { location.reload(true); function softReloadO { history.go(0); } </script> c/head> <body> cform name="myForm"> <input type="radio" name="radl" value="l" />Radio lcbr /> cinput type="radio" name="radl" value="2" />Radio 2cbr /> cinput type="radio” name="radl" value="3" />Radio 3 cp>cinput type="text" name="entry" value="Original" />c/p> cp>cselect name="theList"> coption>Redc/option> copt ion>Greenc/opt ion> , coption>Bluec/option> c/select>c/p> chr /> cinput type="button" value="Soft Reload" onclick="softReload()" /> cinput type="button" value="Hard Reload" Глава 17. Объекты history и location 527
one1i ck="hardReload()" /> </form> </body> </html> См. также: метод story. go (). replace (" URL”) Возвращаемое значение: нет Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ B некоторых больших Web-узлах могут содержаться страницы, не предназначенные для посещения и, тем более, занесения их в список посещенных документов. Например, последо- вательная структура узла может привести пользователя к одной или нескольким промежуточ- ным HTML-страницам, которые в дальнейшем для него не будут представлять ни малей- шего интереса. Особенно нежелательно, чтобы пользователи попадали на эти страницы снова, щелкнув на кнопке Back для возвращения к предыдущему URL. С помощью метода location, replace () можно перейти к необходимому URL-адресу без занесения его в список документов, переход к которым осуществляется щелчком на этой кнопке. Несмотря на то, что невозможно предотвратить добавление в список просмотренных до- кументов посещенной пользователем страницы, при использовании данного метода в окне браузера загружается совершенно другой документ, адрес которого заменят в списке посе- щенных документов текущий URL. Естественно, список посещенных документов браузера не очищается, просто текущий элемент списка удаляется прежде, чем следующий URL-адрес будет загружен. Таким образом, удаление соответствующего элемента из списка не допускает повторной загрузки нежелательной страницы, выполняемой щелчком на кнопке Back. Пример Пример использования метода replace () приведен в листинге 17.10. При вызове этого метода браузер загружает в текущем окне страницу с новым URL-адресом. Но эта операция не регистрируется в журнале. Мн* <html> <head> <title>location.replace() Method</title> escript type="text/javascript"> function doReplace() { location.replace("lstl7-01.htm”) ; } </script> </head> <body> cform name="myForm"> cinput type="button" value="Replace Me" onclick="doReplace()" /> </form> </body> </html> См. также: объект history. 528 Часть III. Объекты документа
Объект history Свойство Метод Обработчик событий current length next previous back () нет forward() go О Синтаксис Доступ к свойствам или методам объекта history. [window. ] history. свойство | метод ( [параметры] ) Описание объекта При перемещении в Internet в браузере автоматически создается список последних URL, посещаемых пользователем. Этот список представлен в объектной модели браузера элемен- том history. При выполнении сценария фактические URL, содержащиеся в этом списке, извлечь нельзя. Исключением являются защищенные сценарии (в NN4h-описанные в гла- ве 46), предоставляющие данную возможность только отдельным пользователям. В незащи- щенном сценарии позволяется только переходить к каждому URL, указанному в списке со- стояний (выбирая соответствующий ему элемент в списке или возвращаясь к URL-адресам в обратной последовательности). В результате пользователь будет просматривать страницы, появляющиеся “сами собой” (будто браузером управляет кто-то невидимый). В Web-сооб- ществе разработчику запрещается управлять средствами навигации, предоставленными поль- зователю, без его полного на то согласия за пределами разработанного им Web-узла Применение объекта history и его методов back () и go () аналогично применению кно- пок Back и Forward в HTML-документах. Эти кнопки вызывают сценарий, при выполнении ко- торого производится проверка нужных элементов списка посещенных документов, а затем осу- ществляется переход на предыдущую страницу. В текущем документе не должна содержаться информация о том URL-адресе, с которого осуществлялся переход на данную страницу. В NN4 есть еще одно немаловажное отличие в управлении JavaScript методами объекта history. В браузер данной версии включены два специальных метода: window .back () и window, forward (), которые также имитируют работу кнопок Back и Forward. Методы объекта history не определяются во фрейме как часть ссылки. Если пользователь с помо- щью метода parent. f rameName. history. back () переходит к фреймам, ссылки на ко- торые указаны в списке посещенных страниц, то после достижения последнего фрейма в этом списке переход к предыдущим страницам не осуществляется. В IE механизм обращения к списку состояний не предполагает перехода к отдельным фреймам. Вместо этого методы history .back () и history, forward () приводят к тем же результа- там, что и щелчок на соответствующих кнопках панели управления браузера. Чтобы осуществить правильный переход по фреймовой структуре в разных версиях браузеров, ссылки на методы history. back () и history. forward () задавайте исключительно в родительских окнах. Объект history существует уже довольно давно. Поэтому, учитывая все написанное выше, рекомендуется использовать данный объект и его методы только в случаях крайней необходимости. Проект должен быть достаточно хорошо продуман, чтобы обеспечить нормальное перемещение пользователя по страницам данного Web-узла (например, должна осуществляться проверка те- кущего URL-адреса перед переходом на него с помощью данных методов). Иначе существует Глава 17. Объекты history и location 529
риск запугать пользователя, отображая для него совершенно неожиданные Web-страницы. Мо- гут возникнуть проблемы и в том случае, если в сценарии нельзя определить местоположение текущего документа в последовательности списка посещенных документов. Свойства current next previous Возвращаемое значение: строковое Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Mozl+, Safari 14- Как отмечалось ранее, в браузере существует список URL-адресов, посещенных пользова- телем Web-страниц, переход на которые можно осуществить щелчком на кнопках Back и Forward. Для тех, кто собирается нарушить конфиденциальность и узнать адреса узлов и страниц, посещаемых определенным пользователем, эта информация будет довольно по- лезной. Свойства current, next и previous, поддерживаемые только в NN, фактически оставляют незащищенными эти URL. Поэтому разработчики браузера установили ограниче- ние: данные свойства применяются только к страницам с цифровой подписью (посетитель получает разрешение на доступ к “личным” данным браузера (см. главу 46)). С подобным разрешением можно просматривать любые данные списка посещенных докумен- тов в любом фрейме или окне. Поскольку список— это тот же массив, можно извлечь его отдель- ные элементы с помощью соответствующего индекса. Например, если в массиве содержится 10 элементов, то пятый можно извлечь, используя метод индексирования нормального массива. var fifthEntry = window.history[4]; He существует ни одного свойства или метода, с помощью которого непосредственно оп- ределяется значение загруженного в настоящее время URL-адреса. Но кГожно написать сце- нарий, в котором значения свойств current, next и previous объекта history будут сравниваться со значениями списка. Наверное, никому не приятно, если неизвестные люди следят за его действиями в сети. Поэтому имейте в виду, что использование данных свойств может привести к большим не- приятностям. В диалоговом окне, в котором указано, что сценарий защищен, не приводится информация о последствиях раскрытия данных такого уровня. / Такие свойства доступны в NN3 только в относительной форме. Доступ к ним /На заметку требует кратковременного обеспечения безопасности. Этот процесс никогда не * осуществлялся полностью, и потому разработчики браузера заменили его за- щищенными сценариями. См. также: свойство history, length. length Возвращаемое значение: строковое Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Для определения количества элементов в списке посещенных документов используют свойство history. length. К сожалению, эта информация не может быть особенно полез- ной для перемещения по страницам с помощью сценария, так как нет возможности считывать данные из этого списка. Если текущий документ находится в начале списка (последний за- груженный документ), то можно ориентироваться относительно этого положения. Пользова- 530 Часть III. Объекты документа
тели могут перемещаться по списку состояний в любой последовательности с помощью меню Go/View. Даже при возврате на предыдущую страницу порядок расположения элементов в списке не изменяется. Значение свойства history. length=l указывает на то, что текущий документ — единственный загруженный пользователем в текущем сеансе работы браузера. Пример Пример использования свойства length приведен в листинге 17.11. <html > <head> «titloHistory Object</title> «script type="text/javascript"> function showCount() { var histCount = window.history.length; if (histCount > 5) { alert("My, my, you\'ve been busy. You have visited " + histCount + " pages so far."); } else { alert("You have been to " + histCount + " Web pages this session."); </script> </head> <body> <form> «input type="button" name="activity" value="My Activity" onclick="showCount()" /> </form> «/body> </html> Методы back() forward() Возвращаемое значение: нет Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ B версиях, предшествующих NN4, результат применения данного метода был аналогичен щелчку на кнопке Back. В NN4 метод history.back () используется только для фреймов и окон. Поэтому при последовательном применении метода back () во фрейме, находящемся в пределах данного набора фреймов, метод не работает при загрузке в него одного документа. Щелчок на кнопке Back (и новый метод window.back()) приводит к выгрузке набора фреймов, таким образом, пользователь продолжает возвращаться назад в соответствии со списком документов браузера Перед тем, как преднамеренно завести пользователя в тупик на своем Web-узле, удосто- верьтесь в том, что HTML-документ обеспечивает возвращение назад на какое-нибудь узна- ваемое место в сети. Поскольку совсем не трудно создать новое окно, не содержащее никаких панелей инструментов и меню (это не касается браузеров для Macintosh), можно самим за- Глава 17. Объекты history и location 531
вершить путешествие своего пользователя, так как он не имеет никакой возможности вы- браться из подобного окна. Лучше всего, когда в документе содержится кнопка, обеспечи- вающая пользователю обратный путь к последнему месту его “пребывания”. Если нет необходимости выполнять какие-либо дополнительные действия перед возвра- том на предыдущую страницу, используйте метод history.back () как параметр обработ- чика событий для кнопки. Чтобы гарантировать совместимость всех браузеров, необходимо управлять данным методом из сценария родительского документа, находящегося во фрейме. Как и history. back (), метод history. forward () не предназначен для управления в сценарии. Применяя данный метод, пользователь перемещается к следующему элементу в списке состояний браузера. Уверенно использовать метод history, forward () можно только после применения метода history. back () в этом же сценарии. Причем в сценарии обязательно должно быть точно указано количество переходов посетителя в обоих направлени- ях. Используйте метод history.forward() осторожно и только после многократной “проверки” страницы посетителями (для подтверждения того, что были предвидены все вариан- ты реакции пользователя). Предостережения о различиях метода history. back () в NN4 от- носятся и к history. forward (): переход вперед осуществляется только согласно списку посещенных документов данного окна или фрейма, а не полного списка состояний браузера. Пример Пример использования методов back () и forward () приведен в листингах 17.12 и 17.13. Листинг 17Ж ЗДЭД ЩЙАЙ9 документа hrhmunp <html> <head> <title>Back and Forward</title> </head> <frameset cols="45%,55%"> <frame name="controller" src="lstl7-13.htm" /> <frame name="display" src="lstl7-01.htm" /> </frameset> </html> Листинг 17*3 Ранель управлениегаимГафей <html> <head> <title>Lab Controls</title> </head> <body> <b>Load a series of documents into the right frame by clicking some of these links (make a note of the sequence you click on): </b> <pxa href="lstl7-01 .htm" target="display">Listing 17-1 </axbr /> <a href="lstl7-05.htm" target="display">Listing 17-5 </axbr /> <a href="lstl7-09.htm" target="display">Listing 17-9 </axbr /></p> <hr /> <form name="input"> <b>Click on the various buttons below to see the results in this frameset:</b> <ul> 532 Часть III. Объекты документа
<lixb>NN4+</b> Substitute for toolbar buttons -- <tt>window.back()</tt> and <tt>window.forward()</tt>: cinput type="button" value="Back" onclick="window.back()" /> cinput type="button" value="Forward" onclick="window.forward()" /x/li> cli>ctt>history.back()c/tt> and ctt>history.forward()c/tt> for righthand frame:cinput type="button" value="Back" onclick="parent.display.history.back()" /> cinput type="button" value="Forward" onclick="parent.display.history.forward()" />c/li> cli>ctt>history.back()c/tt> for this frame: cinput type="button" value="Back" onclick="history.back()" />c/li> cli>ctt>history.back()c/tt> for parent: cinput type="button" value="Back" onclick="parent.history.back()" />c/li> c/ul> ’ c/form> c/body> </html> См. также: методы history. forward (), history .go (). go (относительноеЧисло | " инЬилиЗаголовок") Возвращаемое значение: нет Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Для перемещения в пределах списка документов, отображенных ранее браузером, исполь- зуйте в своем сценарии метод history.до (). При определении URL как параметра необ- ходимо знать, что точный URL в этом списке уже задан. Потому не расценивайте этот метод как альтернативу установки в объекте window. location нового URL-адреса. Для осуществления n-го количества переходов на любую сторону списка посещенных до- кументов используйте параметр относительноеЧисло в методе history. go (). Этот па- раметр представляет собой целочисленное значение, которое определяет необходимый эле- мент списка относительно текущего положения пользователя. Например, если текущий URL является первым в списке (следовательно, кнопка Forward на панели инструментов не дос- тупна) для перехода к URL, находящемся в этом же списке на два элемента ниже, данный ме- тод используют следующим образом. history.до (-2); Другими словами, текущий URL определяется выражением hi story, до (0) (в данном случае произойдет перезагрузка документа). Указанное целое число обозначает переход на нужную позицию в списке. Таким образом, history.до (-1) выполняется аналогично ме- тоду history. back (), a history .go (1) — аналогично history, forward (). Для применения метода history. go () можно также использовать URL-адреса или заголов- ки документа, содержащиеся в списке посещенных документов (заголовки отображаются в меню Go/View). В данном методе указанная строка сравнивается со всеми элементами, содержащимися в списке. Первый элемент, в состав которого входит строковый параметр, принимается как иско- мый. Но если указанный элемент не содержится в списке, то никакого перехода не последует. Подобно большинству других методов объекта history, из сценария документа доволь- но трудно управлять как текущим, так и остальными URL, заданными в списке состояний. Таким образом, затрудняется возможность выполнения в сценарии следующих действий: точного определения области перемещения по списку в том или ином направлении и факти- Глава 17. Объекты history и location 533
ческих URL или заголовков, предназначенных для перехода. Используйте этот метод только тогда, когда Web-страницы и действия пользователя на них полностью контролируемы (а также для сценариев, автоматически запускаемых при посещении определенного узла). Как только пользователь получит контроль над переходами, нет никакой гарантии, что он станет просматривать страницы в том порядке, в каком хотелось бы разработчику. Следовательно, не будут работать и сценарии, построенные на использовании объекта history. Наиболее часто данный метод применяют в виде history.до(0) для осуществления “легкой” перезагрузки текущего окна. При написании страницы, совместимой со всеми браузерами, необходимо знать, Совет что в Internet Explorer и в Netscape Navigator метод go () работает по-разному. Во- первых, ошибка в IE3 приводит к тому, что при использовании в history, до О ' любого ненулевого значения параметр всегда воспринимается как 1. Во-вторых, в IE3 данный метод вообще не работает со строками (браузер генерирует сооб- щение об ошибке); для IE4+ соответствующая строка должна быть частью URL, а не частью заголовка документа, как в NN. И наконец, перезагрузка страницы с использованием history.до (0) часто приводит к повторной загрузке страни- цы с сервера, а не восстановлению ее из кэш-памяти. Пример Пример использования метода до () для перемещения по списку журнала приведен в лис- тинге 17.14. Введите в первом поле номер записи в журнале или название страницы, затем щелкните на соответствующей кнопке для перемещения к указанной странице. Листинг 17.Г1. 3згруз)Э сфаянц, xypwit _ J <html> <head> <title>history.go() Method</title> <script type="text/javascript"> function doGoNum(form) { window.history.go(parselnt(form.histNum.value)); } function doGoTxt(form) { window.history.go(form.histWord.value); } </script> </head> <body> <form> <b>Calling the history.go() method:</b> <hr /> Enter a number (+/-):<input type="text" name="histNum" size="3" value="0" /> cinput type="button" value="Go to Offset" onclick="doGoNum(this.form)" /> <p>Enter a word in a title:<input type="text" name="histWord" /> cinput type="button" value="Go to Match" onclick="doGoTxt(this.form)" /></p> </form> </body> </html> См. также: методы history. back (), history. forward (), location. reload (). 534 Часть III. Объекты документа
Объекты document и body mi . 1^4 e все объекты в модели документа взаимодействуют с И V пользователем— этот важный фактор необходимо учитывать при создании сценария JavaScript Большинство взаи- модействий между сценарием и пользователем происходит с помощью объекта document и его компонентов. Понимание возможностей данного объекта, вплоть до каждой предостав- ленной объектной модели,— ключ к успешному созданию приложений, совместимых со всеми версиями браузеров. Обратите внимание на расположение объекта document в общей иерархической структуре объектов. На основе рис. 18.1 можно сделать вывод о том, что document является одним из центральных объектов JavaScript. Рис. 18.1. Иерархическая структура объектной модели документа Объект document вместе со всем своим содержимым настолько велйк, что для удобства восприятия его описание приведено в нескольких главах, в каждой из которых рас- сматриваются связанные между собой группы объектов.
В этой главе описаны объекты document и body (взаимосвязанные концептуально), а в ка- ждом ее разделе речь идет об объектах, входящих в состав объекта document. Необходимо подчеркнуть, что наиболее распространенной ошибкой средн начинающих программистов на JavaScript является мнение о том, что нет ничего сверхсложного в измене- нии содержимого загруженной страницы. И действительно, много ли нужно: тут поменять текст, там исправить ячейку таблицы. Однако важно помнить, что эти средства, большая часть которых принадлежит динамическому HTML, доступны только в современных браузе- рах — в IE4+ и Nbfc+. Причем преимущество данных браузеров состоит не только в распо- знавании элементов HTML в языках написания сценариев. В них также появилась возмож- ность автоматической перезагрузки страницы при неправильном изменении содержимого. Во всех предыдущих версиях браузеров при написании сценариев для страниц использовался не- большой набор объектов, поддающихся изменению (элементов форм и изображений). Если для работы приложения требуется обеспечить совместимость со всеми браузерами, поддерживающими сценарии, разработчик должен помнить, что после загрузки страницы можно изменить только часть ее неявных отображаемых свойств. Если в содержимом со- вместимых страниц необходимо произвести обновление или изменения, основанные на дан- ных, которые вводит пользователь, следует разрабатывать свои страницы так, чтобы перед пересохранением страницы (с учетом сделанных настроек) сначала производилось изменение старого содержимого с помощью сценария. Объект document Свойства Методы Обработчики событий activeElement attachEvent()* onactivate*" > alinkColor captureEvents() onbeforecut* all* clear() onbeforedeactivate* anchors[] clearAttributes()* onbeforeeditfocus* applets[] close() onbeforepaste* attnbutes* createAttribute() onclick* bgColor createComment() oncontextmenu* body createDocumentFragment() oncontrolselect* charset createElement() oncut* characterset createEvent() ondblclick* childNodes* createEventObj ect() ondrag* compatMode createStyleSheet() ondragend* cookie createTextNode() ondragent er* defaultcharset createTreeWalker() ondragleave* defaultview detachEvent()* ondragover* designMode elementFromPoint() ondrags tart* doctype execCommand() ondrop* documentElement focus()* onhelp* domain getElementByld() onkeydown* embeds [] getElementsByName() onkeypress* expando getElementsByTagName()* onkeyup* 536 Часть III. Объекты документа
Продолжение таблицы Свойства Методы Обработчики событий fgColor getSelection() onmousedown* fileCreatedDate handleEvent() onmousemove* fileModifiedDate hasFocus()* onmouseout* filesize mergeAttributes()* onmouseover* firstChild* open() onmouseup* forms[] queryCommandEnabled() onpaste* frames [] queryCommandlndterm () onpropertychange* height queryCommandState() onreadystatechange* ids [] queryCommandSupported() onresizeend* images [] queryCommandText() onresizestart* implementation queryCommandValue() onselectionchange lastchild* recalc() onstop lastModified releasecapture()* layers[] releaseEvents() linkcolor routeEvent() links [] setActive()* location write() media mimeType namespaces [] namespaceURL* nextSibLingt* nodeName* nodeType* ownerDocument * parentNode* parentwindow plugins[] previousSibling* protocol readyState* referrer scripts[] security selection stylesheets[] tags [] .title uniquelD* writein() Глава 18. Объекты document и body 537
Окончание таблицы Свойства URL URLUnencoded vlinkColor Методы Обработчики событий width * См. главу 15 Синтаксис Доступ к свойствам и методам объекта document. [window. ] document. свойство\метод] [параметры]) Описание объекта В объекте document описываются все элементы, расположенные в области окна браузе- ра или фрейма (исключая панели инструментов, строки состояния и т.д.). Документ — это комбинация содержимого и элементов интерфейса, с помощь которых разработчики и при- влекают посетителей на Web-страницу. В более современных браузерах, обрабатывающих элементы HTML как узлы иерархической структуры, объект document является корневым узлом, из которого происходят все остальные. Так как объект document неявно представлен в документе HTML-дескрипторами или другими элементами, разработчики JavaScript и объектных моделей решили сделать объект document своего рода “порталом” для получения доступа к атрибутам, которые представле- ны в HTML как принадлежащие к элементу body. В дескрипторе последнего элемента со- держатся атрибуты, применяемые ко всему документу, они изменяют такие параметры, как цвет фона (bgcolor) или цвет ссылки в различных ее состояниях (alink, link и vlink). Также в данном элементе задаются формы, гиперссылки и анкеры. Несмотря на это в объекте document дублируется большинство функций элемента body. Кроме того, этот объект явля- ется наиболее удобным средством для получения в сценарии таких свойств, которые приме- няются за пределами элемента body, например, элемент заголовка (title) или URL-адреса ссылки, с помощью которой пользователь переходит на нужную страницу. При просмотре исходного кода HTML может показаться, что объект document представляет собой бес- смысленней программный элемент. Несмотря на это, он служит прекрасной платформой для ссылок на исходные объекты — формы, изображения и аплеты. Конечно, подобная ситуация возникала до того, как каждый элемент HTML, включая эле- мент body, был представлен в качестве объекта в современных объектных моделях. Удиви- тельно, но даже с использованием объектной модели 1Е4+.И W3C DOM (в обоих случаях эле- мент body воспринимается как отдельный объект, не принадлежащий объекту document) совместимость сценария с оригинальной объектной моделью осуществляется довольно про- сто. Простое представление данного объекта в оригинальной объектной модели и модели, благодаря которой объект document был отделен от элемента body, содержащегося в нем, обеспечило размещение его в основе иерархии. Исходя из синтаксиса сценария определяется, к какой модели относится данный объект. Это означает, что довольно часто существует не- сколько разных способов обращения к одному и тому же объекту. Например, чтобы получить количество объектов форм, содержащихся в документе, можно использовать следующее вы- ражение во всех браузерах, поддерживающих сценарии. document.forms.length 538 Часть III. Объекты документа
ВIE4+ можно даже применить такую формулировку. document.tags["form"].length В W3C DOM, аналогично IE5+ и NN6/Moz1 +/Safaril+. document.getElementsByTagName("form").length Современные версии браузеров обеспечивают универсальные способы доступа к элемен- там (массив tags в IE4+ и метод getElementsByTagName {) в W3C DOM) для удовлетво- рения требований объектных моделей, представляющих каждый элемент HTML (и XML) как отдельный объект. Итак, элемент body перешел в ранг объектов, естественно, это повлекло за собой появ- ление нового синтаксиса для управления такой объектной моделью. Вследствие этого в объект document автоматически были добавлены некоторые свойства, которые изначально входили в состав элемента body. Многие свойства, которые принадлежали объекту document, были переименованы при их передаче элементу body. Например, свойство document. alinkColor в новой модели называется body.aLink, хотя свойство bgColor осталось со старым име- нем. Для обеспечения совместимости современные браузеры признают как старые, так и но- вые свойства, даже притом, что в W3C DOM (в попытке не отставать от мирового развития) старые версии свойств объекта document были удалены. На первый взгляд это может показаться странным, но чтобы разобраться в том, когда об- ращаться к объекту document, а когда использовать новый синтаксис, не потребуется много времени. Все зависит от того, что будет указываться в правой части выражения (ссылки). Старые свойства и методы обеспечивают использование первоначального объекта document, а новый объект document, соответственно, обладает новыми свойствами и методами. К сча- стью, определение объекта выполняется автоматически. Свойства activeElement Значение: ссылка на объект Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- В IE4+ свойство document.activeElement можно использовать непосредственно в сценарии для проверки того, к какому элементу в данный момент обращается браузер. Воз- вращенное значение и будет ссылкой на нужный элемент. Можете применять любые свойства и методы, перечисленные в главе 15, для анализа данного объекта. Но знайте, что обращаться можно далеко не ко всем элементам существующих операционных систем. Например, кнопки в IE4 для Macintosh не доступны. Обычно элементы используются для генерирования наиболее “доступных” событий мыши или клавиатуры (не считая кнопок Мас1Е4), однако не рекомендуется применять свойство activeElement для того, чтобы выявить элемент, генерирующий данные события. Лучше для этого подходит свойство event. srcElement в Internet Explorer. Пример Приложение The Evaluator (глава 13) позволяет изучить свойство activeElement в браузерах IE4+. Введите в верхнее поле следующее выражение. document.activeElement.value После нажатия клавиши <Entei> в области результатов появится значение, соответствую- щее введенному в верхнем текстовом поле оператору. Если вы щелкнете на кнопке Evaluate, то будет отображено значение свойства value объекта кнопки. См. также: свойство event. srcElement. Глава 18. Объекты document и body 539
allnkColor bgColor fgColor linkColor vlinkColor Значение: шестнадцатеричное значение или название цвета Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Эти пять свойств являются эквивалентами атрибутов дескриптора <body> с аналогичны- ми именами (хотя имена свойств на самом деле довольно чувствительны к регистру). Все пять параметров настройки выводят информацию только для чтения, поэтому возможность изменять как все, так и некоторые из этих свойств, не однозначна. Все зависит от браузера и платформы клиента. В табл. 18.1 приведено описание тех браузеров и платформ, в которых существует возможность установки параметров цвета. Таблица 18.1. Установка цветов в документе (версии браузеров) 2 Свойство цвета Netscape Navigator Internet Explorer Windows Mac UNIX Windows Mac UNIX bgColor Все версии 4+ 4+ Все версии Все версии 4+ Все остальные 6+ 6+ 6+ Все версии Все версии 4+ Экспериментируя с установками document.bgColor в Macintosh или UNIX-версиях NN2 и NN3, можно некорректно установить свойства, даже не подозревая об этом. Даже если значение свойства остается верным, данные платформы не обновляют их должным образом в своих окнах. Если цвет изменяется после завершения компиляции содержимого сценария, то вся красота установленного пользователем нового цвета отобразится лишь после того, как окно будет перезагружено. Самый безопасный способ установки свойств цвета документа за- ключается в следующем действии: для содержимого фрейма или окна, описанного в сцена- рии, установите атрибуты цвета дескриптора <body> динамически, когда документ будет выводиться в текущем окне с помощью метода document. write (). Значения свойств цвета могут иметь формат как обычного шестнадцатеричного триплета HTML (например ttOOFFOO), так и любого названия цвета, принятого в Netscape Navigator. В Internet Explorer также можно использовать простые описательные названия. Но помните, что некоторые из них работают только при установке глубины цветов монитора в 16 или 24-разрядный режим. Если сценарий рассчитан на выполнение исключительно в IE4+ или NN6+, для обращения к этим свойствам необходимо использовать объект document. body. Пример В листинге 18.1 приведен пример произвольного применения цветовых настроек в HTML- документе. В небольшом окне содержится кнопка и небольшой текстовый фрагмент со ссыл- ками. В результате вы сможете ознакомиться с цветовыми настройками, заданными в основ- ном окне. Сценарий изменяет цвета небольшого окна в результате переписывания его исход- ного кода. Все используемые в небольшом окне цвета приведены в текстовой области основного окна (в виде шестнадцатеричных значений). Вы можете изменить цвета в исход- ном коде приложения, чтобы создать другие цветовые решения. 540 Часть III. Объекты документа
: Яистшкг <html> <head> <title>Color Me</title> escript type="text/javascript"> // может блокироваться при загрузке браузером var newWindow = window.open("","","height=150,width=300"); function defaultcolors() { return "bgcolor='#c0c0c0 ' vlink='#551a8b' link='#0000ff'"; } function uglyColorsO { return "bgcolor='yellow' vlink='pink' link='lawngreen'"; } function showColorValues() { var result = "" ; result += "bgColor: " + newWindow.document.bgColor + "\n"; result += "vlinkColor: " + newWindow.document.vlinkColor + "\n"; result += "linkcolor: " + newWindow.document.linkColor + "\n"; document.forms[0].results.value = result; } // динамическая запись содержимого в другое окно function drawPage(colorstyle) { // обработка блокировки if (InewWindow || newWindow.closed) { newWindow = window.open"height=150,width=30P"); } var thePage = ""; thePage += "<htmlxheadxtitle>Color Sampler<\/title> <\/headxbody " ; if (colorstyle == "default") { thePage += defaultcolors(); } else { thePage += uglyColorsO; } thePage += ”>Just so you can see the variety of items and color, <a "; thePage += "href='http://www.nowhere.com'> here\'s a link<\/a>, and <a href='http://home.netscape.com'> here is another link <\/a> you can use on-line to visit and see how its color differs from the standard link."; thePage += "<form>"; thePage += "cinput type='button' name='sample' value='Just a Button'>"; thePage += "<\/formx\/bodyx\/html>" ; newWindow.document.write(thePage); newWindow.document.close(); showColorValues(); } // следующее корректно выполняется только в WinNN function setcolors(colorstyle) { Глава 18. Объекты document и body 541
if (colorstyle == "default") { document.bgColor = "ttcOcOcO"; } else { document.bgColor = "yellow"; </script> </head> <body> Try the two color schemes on the document in the small window. <form> <input type="button" name="default" value='Default Colors' onclick="draw₽age(1 default')" /> <input type="button" name="weird" value="Ugly Colors" onclick="draw₽age('ugly')" /> <pxtextarea name="results" rows="3" cols="20"> </textareax/p> chr /> These buttons change the current document, but not correctly on all platforms cpxinput type="button" name="default" value='Default Colors' onclick="setcolors('default')" /> cinput type="button" name="weird" value=“Ugly Colors" ' onclick="setColors ('ugly') " /x/p> c/form> c/body> c/html> Чтобы удовлетворить любопытных, я добавил в рассмотренный выше пример две кнопки, позволяющие динамически изменять цветовую гамму нового окна. Если вы используете брау- зеры, описанные в табл. 18.1, то приложение должно выполняться у вас в полной мере. Если же у вас браузер старой версии, то в окне могут не отобразиться кнопки и другие элементы документа. Существует также вероятность полного отображения всех элементов, которые не будет корректно окрашиваться или выполнять возложенные на них программные обязанно- сти. Если вы не уверены в том, что потенциальная аудитория ваших документов состоит из пользователей, которые регулярно обновляют программное обеспечение, откажитесь от из- менения цветовой гаммы, используемой по умолчанию. См. также: свойства body.aLink, body. bgColor, body, link, body, text, body.vLink. anchors [] Значение: массив объектов анкеров Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Объекты анкеров (описанные в главе 19) представляют собой выражения в документе HTML, описанные в дескрипторе <name=" Данные объекты обозначаются в URL симво- лом #, расположенным между URL страницы и имёнем анкера. Подобно остальным объектным свойствам, в которых содержится список вложенных объектов, свойство document. anchors (обратите внимание на множественное число) представляет собой индексированный массив анкеров, находящихся в документе. Используйте массив ссылок для точного определения нужного анкера и дальнейшего восстановления его свойств. 542 Часть III. Объекты документа
Нумерация массива анкеров начинается с 0: таким образом, первый анкер в документе представлен ссылкой document. anchors [0]. По причине того, что это выражение выпол- няется в любом встроенном массиве объектов, всегда можно определить количество элемен- тов массива, измерив его длину с помощью соответствующего свойства. var anchorcount = document.anchors.length; Свойство document. anchors предназначено только для чтения. Для перехода к нуж- ному анкеру в сценарии определите значение одного из объектов window, location или window. locat ion. hash (см. предыдущую главу). Пример Листинг 18.2 основан на листинге 17.1; из него вы узнаете, как в сценариях можно эффек- тивно управлять документами, содержащими анкеры. Сценарий автоматически сохраняет в виде массива все анкеры, найденные в документе. Чаще всего вам не придутся выводить этот массив для изучения пользователями, а потому применять свойство document. anchors на практике вам придется нечасто. Объектная модель документа устанавливает его автоматиче- ски при создании объектов анкеров. <html> <head> <title>document.anchors Property</title> «script type="text/javascript"> function goNextAnchor(where) { window.location.hash = where; } </script> </head> <body> <hl><a id="start" name="start”>Top</a></hl> <form> «input type="button" name="next" value="NEXT" onclick="goNextAnchor('seel')" /> </form> «hr /> <hl>«a id="secl" name="seel">Section l«/a>«/hl> <form> «input type="button" name="next" value="NEXT" onclick="goNextAnchor('sec2')" /> </form> «hr /> <hl>«a id="sec2" name="sec2">Section 2</a>«/hl> <form> «input type="button" name="next" value="NEXT" onclick="goNextAnchor(’sec3')" /> </form> «hr /> <hl>«a id="sec3" name="sec3">Section 3</ax/hl> <form> «input type="button" name="next" value="BACK TO TOP" onclick="goNextAnchor('start1)" /> </form> «hr /> <p> Глава 18. Объекты document и body 543
«script type="text/javascript"> document.write("<i>There are " + document.anchors.length + " anchors defined for this document<\/i>") «/scripts </p> </bodys </htmls См. также: объекты anchor и location; свойство document. links. applets Значение: массив объектов аплетов Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Благодаря свойству applets можно обращаться к аплетам Java, которые содержатся в документе, использующем дескриптор «applets. Аплет не является реальным объектом до тех пор, пока не будет полностью загружен. Работа по управлению Java-аплетами в JavaScript преимущественно осуществляется с по- мощью методов и переменных, определенных внутри аплета. Вы можете ссылаться на аплет согласно индексу элемента массива аплетов, однако надежнее использовать имя объекта ап- лета (во избежание возможной путаницы). Обратите внимание на то, что аплеты не доступны для JavaScript в Internet Explorer для Macintosh. Пример Свойство applets устанавливается автоматически при создании браузером объектной модели документа, содержащего аплеты. Чаще всего это свойство используется для подсчета количества объектов аплетов в документе. См. также: объект applet. bgColor См. alinkcolor body Значение: объект элемента body Чтение/Запись Совместимость: WinIE4+, МаЫЕ4+, NN6+, Mozl+, Safari 14- Свойство document. body — это сокращенная ссылка на объект элемента body в новых . объектных моделях. Далее в главе объясняется, что в объекте body существует целый ряд клю- чевых свойств, предназначенных для управления внешним видом всей страницы. Поскольку ‘ объект document является корневым элементом всех ссылок в пределах любого окна или фрейма, j для получения свойств объекта BODY лучше использовать выражение document. body вместо длинных ссылок, с помощью которых обычно обращаются к объектам элементов HTML в объектных моделях IE4-I- и W3C. Пример Приложение The Evaluator (глава 13) поможет вам быстро изучить свойство body. Снача- । ла удостоверьтесь, что свойство document. body представляет собой объект элемента, вы- 1 зываемого с помощью более длинной ссылки. В браузерах IE54-, NN64- и W3C введите в верхнее < поле следующее выражение. document.body == document.getElementsByTagName("body")[0] 544 Часть III. Объекты документа
Далее изучите свойства объекта body, также введя их в верхнее текстовое поле. document.body.bgColor document.body.tagName См. также: объект элемента body. charset Значение: строковое Чтение/Запись Совместимость: WinIE4+, МасЕЕ4+, NN-, Moz-, Safari- В свойстве charset определяется набор символов, используемый браузером для компи- ляции текущего документа (в версии NN6 это свойство называется characterset). Все возможные значения этого свойства можно найти по адресу: ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets В каждом браузере и операционной системе существует собственный набор символов, ус- тановленный по умолчанию. Так же значения могут устанавливаться в дескрипторе <meta>. Пример Приложение The Evaluator также с успехом применяется для изучения свойства charset. Вве- дите следующее выражение в верхнее поле страницы, не изменяя его настроек по умолчанию. document.charset Если вы используете WinIE5+, то можете ввести в это поле такое выражение, чтобы изме- нить набор символов документа. document.charset = "iso-8859-2" Если ваша версия Windows не поддерживает указанный набор символов, то браузер спро- сит разрешения на загрузку и установку этого набора. См. также: свойства characterset, defaultcharset. characterset Значение: строковое Чтение/Запись Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- B свойстве characterset определяется набор символов, используемый браузером для компиляции текущего документа (в версии IE4+ это свойство называется charset). Все воз- можные значения этого свойства можно найти по адресу: ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets В каждом браузере и операционной системе существует собственный набор символов, ус- тановленный по умолчанию. Так же значения могут устанавливаться в дескрипторе <meta>. Пример Экспериментировать со свойством characterset в приложении The Evaluator у вас по- лучится только после загрузки его в браузере NN6+/Mozl+. Введите в верхнем текстовом по- ле следующее выражение, чтобы ознакомиться с набором символов в текущем документе. document.charset См. также: свойство charset. Глава 18. Объекты document и body 545
compatMode Значение: строковое Только чтение Совместимость: WinIE6+, MacIE6+, NN7+, Mozl+, Safaril+ Это свойство переводит документ в режим совместимости, что определяется содержимым эле- мента doctype. Свойство CompatMode принимает одно из следующих значений: BackCompat и CSSICompat. Первое значение используется по умолчанию. Пример Вы можете использовать режим совместимости для выполнения специфических для одно- го браузера операций в другом браузере. Чтобы обеспечить обратную совместимость доку- мента, используйте такое выражение. if (document.compatMode == "BackCompat") { // операторы, выполняемые в режиме обратной совместимости } cookie Значение: строковое Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ В Web-браузере механизм cookie-значений позволяет хранить небольшие объемы ин- формации о компьютере клиента в довольно безопасной форме. Другими словами, если необ- ходимо получить определенную информацию о клиенте во время загрузки различных HTML- документов (причем эта информация должна использоваться между сеансами запуска браузе- ра), используют механизм cookie. Как правило, cookie применяется для хранения имени пользователя и пароля, который он вводит в соответствующее поле Web-узла, защищенного паролем. При первичном вводе данной информации в CGI-форму, используя Netscape Navigator, программа CGI производит запись информации в файлы cookie, сохраняемые на жестком диске пользователя (обычно после шифрования пароля). В следующий раз, когда пользова- тель решит перейти на тот же узел, ему не нужно будет опять вводить свои данные. Сервер найдет cookie-файл, сохраненный именно для этого сервера, и извлечет содержащиеся там регистрационное имя и пароль, которые затем будут введены автоматически. Другие записи cookie сохраняют ссылки пользователя и информацию о предыдущем по- сещении узла. Ссылки могут включать также стили и размеры шрифта, а при желании поль- зователя их содержимое будет отображаться внутри набора фреймов. Временное хранение сведений о посещенных ранее документах позволяет вывести на экран выделенные другим цветом изображения рядом с содержимым, которое было изменено со времени последнего посещения пользователем этой страницы, даже если она неоднократно обновлялась (см. гла- ву 54). Перед тем как регистрировать “новые” состояния, возникшие с момента последнего посещения пользователем узла, сценарии “выделяют” новую информацию для пользователя. Файл cookie Некоторые CGI-программы могут как считывать, так и записывать данные на жесткий диск пользователя. Вам необходимо решить, использовать их или нет. Механизм cookie, содержащийся в браузере, не позволяет использовать папки пользователя для всеобщего дос- j тупа (или проводить незаконные операции в них). Вместо этого он обеспечивает доступ толь- > ко к одному определенному текстовому файлу (в NN/Mozilla/Safari) или набору текстовых, файлов (в Internet Explorer), которые сохраняются в строго определенном месте жесткого диска пользователя (в зависимости от операционной системы). 546 Часть III. Объекты документ! :
Файл cookie представляет собой обычный текстовый файл (но в Netscape Navigator для Macintosh файл MagicCookie не текстовый, поэтому пользователи Macintosh могут открыть его только с помощью специальных приложений). Для того чтобы просмотреть cookie-файл, ре- комендуется предварительно сделать копию в другой папке и только после этого его открывать. Любое изменение существующего файла может испортить содержащуюся в нем ценную запись, использование которой предоставляет доступ к регулярно посещаемому данным пользователем узлу. Формат данных cookie в Netscape Navigator и Internet Explorer разный, что зависит от разных методик, которые используются в них для регистрации cookie-записей. В файле Netscape Navigator (после нескольких закомментированных строчек, которые предупреждают о недопустимости изменения пользователем файла вручную) приводится текст в виде таблицы. Каждая строка содержит информацию одной записи. На первый взгляд, cookie-файл ничем не отличается от обычной базы данных. В Internet Explorer в cookie-файле сохраняются те же данные, что и в Netscape Navigator, но сами записи представлены в виде списка. Структура этих файлов не имеет особого значения для занесения в них данных, так как оба браузера ис- пользуют одинаковый синтаксис чтения и записи, применяя свойство document. cookie. / Когда экспериментируют с записями браузера, то нередко возникает соблазн про- смотреть cookie-файл после внесения в него новых данных, cookie-файл не бу- * дет содержать недавно записанных данных, так как сохранение проводится на дис- ке только после того, как пользователь покидает браузер; и наоборот, cookie- файл может быть загружен в память браузера только при запуске последнего. Когда браузер работает, пользователь может считывать, записывать и удалять данные из cookie-файла. Но результаты его деятельности останутся в опера- тивной памяти (для ускорения обработки данных); сохранены они будут после завершения текущего сеанса. cookie-запись Каждая cookie-запись содержит следующие “поля” (не обязательно в таком же порядке). Домен сервера, создавшего запись. Информацию о том, требуется ли пользователю установить безопасное НТТР- соединение для доступа к записям. Путь расположения документов с URL, которым предоставлен доступ к записям. Срок службы записи. Имя записи. Строка, содержащая запись. Заметьте, что записи зависят только от доменов. Другими словами, если запись создается одним доменом, другой домен не сможет* считать эту запись, используя обычный cookie- формат. Поэтому совершенно безопасно хранить так называемые невосстанавливаемые паро- ли (пары имя пользователя-пароль, необходимые для доступа к некоторым узлам со свобод- ной регистрацией) в записях. Кроме того, пароли к узлам, хранящиеся в записях, обычно имеют вид зашифрованных строк. Это усложняет доступ к информации, находящейся в cookie-файле, если компьютер оставлен без присмотра. Таким образом, вычислить лич- ный пароль пользователя оказывается довольно трудно. Кстати, cookie-запись имеет срок службы. Поскольку в некоторых браузерах количество записей ограниченно (300 в Netscape Navigator), cookie-файл может за несколько лет пере- полниться. Поэтому, если во время работы браузера планируется сохранять cookie-запись, автор этой записи должен установить срок ее службы. Браузеры автоматически удаляют “просроченные” записи. Глава 18. Объекты document и body 547
Однако не все записи должны создаваться во время работы браузера. Сценарии, в которых используются временные записи, при работе с Web-узлами имеют сходную структуру. Многие коммерческие узлы создают одну или несколько временных cookie-переменных для дальней- шего занесения в них названий тех товаров, которые пользователь намеревается приобрести. Эти элементы содержатся в виде копии в определенной форме. Но после представления этой формы серверу, данные о клиенте, содержащиеся в ней, не будут иметь никакого определенного значения. Следовательно, если сценарий не определяет дату истечения срока службы записи, браузер продолжает записывать новые cookie в свою кэш-память, не занося их в cookie-файл. Когда пользователь покидает браузер, данные cookie исчезают, как это и предполагалось. Доступ из JavaScript Доступ к записям cookie из JavaScript ограничен заданием cookie (с рядом необяза- тельных параметров) и получением данных cookie (но уже без параметров). Оригинальная объектная модель определяет cookie-записи как свойства документов, но такая формулировка не совсем корректна. При использовании заданного по умолчанию пути для установки cookie (текущая папка документа, при выполнении сценария из которого ис- пользуется первая cookie-запись) все документы той же папки на том же сервере имеют доступ для записи и чтения к содержащимся там cookie-данным. Преимущество такого расположения состоит в следующем: если есть приложения, представленные несколькими документами, и все они обслуживаются из одной папки, то данные cookie могут использо- ваться ими совместно. Однако Netscape Navigator и Internet Explorer установили ограничение: 20 cookie-записей для каждого домена; в ТЕЗ задается еще более строгое ограничение для одной записи (одна пара имя-значение) на домен. Если пользователя не устраивают постав- ленные условия, то ему необходимо найти другой способ записи cookie-данных (данный способ описан в приложении Decision Helper в главе 55). Сохранение cookie-записей Для записи данных в cookie-файл в JavaScript используется простой оператор, который на- значает свойству document. cookie определенное значение. Но форматирование данных явля- ется ключевым моментом в осуществлении доступа к записям. Существует определенный синтак- сис для переопределения cookie (необязательные элементы заключены в квадратные скобки). document.cookie = "имяСоокге = ДанныеСоок1е [; expires = времяФорматаСМТ] [; path=nyTb] [; <1ота1п=имяДомена] [; secure]" Отдельно изучите каждое свойство. Имя/данные Каждая cookie-запись должна иметь имя и строковое значение (даже если этому значе- нию соответствует пустая строка). Такие пары имя-значение наиболее часто встречаются в HTML, но в соответствующем выражении они используются по отдельности. Например, ес- ли пользователь собирается сохранить слово “Фред” в cookie-записи с именем userName, выражение на JavaScript будет иметь такой вид. document.cookie = "userName=Fred"; Если браузер не находит cookie-записи с таким именем в текущем домене, он создает ее автоматически; если запись с таким именем уже существует, браузер просто заменяет ее ста- рые данные новыми. Поиск document. cookie в этом пункте выдает следующую строку. userName=Fred 548 Часть III. Объекты документа
Можно пренебречь другими параметрами cookie-записей, в этом случае браузер исполь- зует значения по умолчанию, более подробно этот процесс описан в следующем абзаце. Для создания временных cookie (которые не должны сохраняться после выключения браузера) кроме набора имя-значения, обычно больше ничего не используют. Полный набор такого типа должен быть представлен строкой, не содержащей точек с за- пятой, просто запятых или символов пробелов. Для того чтобы убрать пробелы между слова- ми, предварительно обработайте значение записи функцией JavaScript escape (), которая переведет пробелы в ASCH-код, равный %20 (примените функцию unescape (), чтобы убе- диться в правильности восстановления пробелов в случае возникновения такой необходимости). Нельзя сохранять массив или объект JavaScript в cookie-записи. С помощью метода Array, join О преобразуйте массив в строку; используйте String, split () для создания этого массива заново после последнего прочтения полученной cookie-записи. Эти два ме- тода доступны в NN3+, Mozillal+ и IE4+. Срок службы (хранения) Устанавливаемая дата срока службы записи должна соответствовать значению времени по Гринвичу (Greenwich Mean Time — GMT)) (см. славу 29, повествующую о времени и датах). Чтобы вычислить дату истечения срока службы записи, основанную на сегодняшней дате, используйте объект Date, представленный в JavaScript, следующим образом. var exp = new Date(); var oneYearFromNow = exp.getTimeO + (365 * 24 * 60 * 60 * 1000); exp.setTime (oneYearFromNow); Затем преобразуйте дату в принятый строковый формат GMT. document.cookie = "userName=Fred; expires=" + exp.toGMTStringO ; В cookie-файле срок службы и время хранятся как числовые значения (в секундах), но для их установки необходимо использовать формат времени соответственно GMT. cookie- запись можно удалить прежде, чем истечет срок ее службы — установите для данной записи новый срок, уже прошедший относительно текущего времени и даты. Самый безопасный па- раметр срока хранения приведен ниже. expires=Thu, Ol-Jan-70 00:00:01 GMT Отсутствие даты срока службы сообщает браузеру о том, что эта cookie-запись является временной. Таким образом, браузер не записывает ее в cookie-файл, а при следующем за- пуске этого браузера она не будет существовать в его буфере. Путь Для cookie-записей, осуществляемых стороной клиента, наиболее удобно принять путь, заданный по умолчанию (в текущей папке). Конечно, можно создать дополнительную копию cookie в другой папке (для другого домена), таким образом, одни и те же данные будут дос- тупны документу, расположенному в другой области Web-узла (или вообще сети). Домен Для синхронизации cookie-данных с определенным документом (или их группой) брау- зер определяет домен текущего документа и помещает в cookie-файл записи, соответст- вующие этому домену. Поэтому, если пользователь собирается просмотреть список всех cookie-данных, содержащихся в свойстве document. cookie, он должен просмотреть все наборы имя-значение, находящиеся в cookie-файле, с именем домена текущего документа. Если пользователь уверен, что документ не будет скопирован на другой сервер в пределах его Глава 18. Объекты document и body 549
домена, он может и не использовать параметр domain при сохранении cookie-записей. Ав- томатическое определение домена текущего документа и занесение его в cookie-файл про- изводится по умолчанию. Необходимо знать, что в формате представления домена должно содержаться по крайней мере две точки. .mcom.com .hotwired.corn В противном случае нужно записать полный URL-адрес домена, включая протокол http: //. SECURE Если при сохранении cookie-записи параметр SECURE отсутствует, подразумевается, что cookie-данные доступны для любого документа или CGI-программы, которая находится в узле пользователя, определяет другой домен и соответствующий ему путь. В процессе соз- дания cookie-записей на стороне клиента при сохранении cookie этот параметр опускается. Получение cookie-данных Данные cookie, используемые в JavaScript, представляют собой одну-единственную строку, которая содержит все наборы имен и данных. Даже при том, что cookie-файл хра- нит параметры каждой cookie-записи, с помощью JavaScript можно получить только набо- ры имен и данных. Кроме того, когда две cookie-записи или более (максимум 20) удовле- творяют критериям домена, в JavaScript они будут представлены в одной строке данных, разграниченных точкой с запятой и пробелом. Например, строка document. cookie может выглядеть следующим образом. userName = Fred; password = NikL2sPacU Другими словами, нельзя обращаться к cookie-записям как к объектам. Необходимо анализировать всю cookie-строку, извлекая данные из нужного набора. Если пользователь уверен, что в существующем файле содержится только одна cookie- запись (и к этому домену записи больше добавляться не будут), он может извлечь эту запись, используя ее имя. Например, данные cookie-записи, имя которой состоит из семи символов, можно извлечь, используя следующее выражение. var data = unescape(document.cookie. substring(7,document.cookie.length)); Первый параметр метода substring () включает знак = для отделения имени от данных. Целесообразно создать функцию общего назначения, которая сможет управлять одной или несколькими cookie-записями. Далее приводится подобная функция, которую исполь- зуют в сценариях некоторые разработчики. function getCookieData(labelName) { var labelLen = labelName.length; 11 однократное чтение свойства cookie var cookieData = document.cookie; var cLen = cookieData.length; var i = 0; var cEnd; while (i < cLen) { var j = i + labelLen; if (cookieData.substring(i,j) == labelName) { cEnd = cookieData.indexOf(";",j); if (cEnd == -1) { cEnd = cookieData.length; } return unescape(cookieData.substring(j+l, cEnd)); 550 Часть III. Объекты документа
} } return ""; • } При обращении к этой функции имя нужной cookie-записи передается как параметр. Функция анализирует полную строку cookie, обрабатывая ее частями (разделенными точ- кой с запятой). Таким образом, отбрасываются лишние элементы до тех пор, пока не будет найдено имя требуемой cookie-записи. Если у вас возникли затруднения с пониманием данного кода, то обратитесь к набору функций, написанных опытным программистом JavaScript и Web-дизайнером Биллом Дорт- чем (Bill Dortch) из hldaho Design. Созданные им функции обеспечивают универсальный дос- туп к cookie-записям, которые можно использовать во всех страницах, управляемых cookie. В листинге 18.3 представлены cookie-функции Билла; они содержат различные методы предотвращения ошибок в дате, которые могут появиться в некоторых версиях NN2. Вас может смутить большой объем этого листинга, однако ре волнуйтесь: большинство строк — простые комментарии. <html> <head> <title>Cookie Functions</title> </head> <body> «script type="text/j avascript"> <! - - начало сценария И // Соок1е_функции — "Night of the Living Cookie" версия (25.07.96) // // Написан: Биллом Дортчем, hldaho Design < bdortch@hidaho.com > // Следующие функции созданы для работы с существующим доменом // Эта версия выполняет более "жесткое" удаление // cookie-записей. Предыдущие версии устанавливали дату истечения // срока службы записи на одну миллисекунду меньше, чем; // текущее время однако, этот метод не работал в Netscape // Navigator2.02 (хотя он работает как в более ранних, так и // в более поздних версиях этого браузера),.так как в // результате его действия появлялись вечно живущие записи- // "призраки", которые никак нельзя было удалить. // Теперь DeleteCookie устанавливает в качестве даты истечения // срока хранения записи самую раннюю дату, пригодную для // использования (первая секунда 1970 года), и на всякий случай // обнуляет ее значение. // Также в этой версии функции DeleteCookie добавлены // необязательные параметры пути и домена. Необходимо указывать // путь и/или домен как при создании, так и при удалении // cookie**, иначе запись не будет удалена. // Функция FixCookieDate должна вызываться только для исправления // ошибок в дате на Мас 2.x. Эта функция должна вызываться *один // раз* после создания объекта Date и перед обращением к // SetCookie. Поскольку ошибка в дате в Мас воздействует на все // даты, а не только на те, которые передаются // в функцию SetCookie, необходимо привыкнуть к тому, что // придется вызывать FixCookieDate при создании каждого Глава 18. Объекты document и body 551
// нового объекта: И // var theDate = new Date(); // FixCookieDate (theDate) ,- 11 // Функция FixCookieDate не работает ни на одной платформе // кроме Мас, поэтому нет необходимости определять платформу // пользователя перед каждым ее вызовом. // В этой версии также проведены некоторые незначительные // усовершенствования. // ** Заметьте, что можно устанавливать несколько записей с одним //и тем же именем, но различными путями. Например: И II SetCookie ("color","red",null."/outer"); // SetCookie ("color","blue",null ."/outer/inner"); H II Однако GetCookie не может различить эти два выражения и // возвращает значение первой найденной записи с данным именем. // Поэтому рекомендуется ‘не* использовать одинаковые имена // для cookie с разными путями. (Имейте в виду, что у каждой // записи ‘всегда* есть свой путь; если он полностью не // определен, используется путь, установленный документом.) И II История обновления: И II "Toss Your Cookies" версия (22.03.96) 11 Добавление функции FixCookieDate() для исправления ошибок // в дате в Мас И II "Second Helping" версия (21.01.96) // Функция SetCookie() дополнена путем, доменом и параметрами // безопасности // "Самодельные" функции кодирования/декодирования заменены // на новые // функции escape и unescape в Netscape Navigator И II "Free Cookies " версия (декабрь 95) И II За более подробной информацией о значениях cookie параметров //ио cookie пожалуйста, обращайтесь на официальный узел: // http: /./ www.netscape.com/newsref/std/cookie_spec.html и И II "Внутренняя" функция для возвращения декодированного значения И function getCookieVal (offset) { var endstr = document.cookie.indexOf (";", offset); if (endstr == -1) endstr = document.cookie.length; return unescape(document.cookie.substringtoffset, endstr)); } u II Эта функция необходима для исправления ошибок в дате на // Мас 2.x. Вызывайте ее для проверки объекта даты перед // отправкой данных в функцию SetCookie. // ВНИМАНИЕ: Эта функция должна вызываться только *один раз* // для каждого полученного объекта даты! // См. пример в конце листинга. 552 Часть III. Объекты документа
и function FixCookieDate (date) { var base = new Date(0); var skew = base.getTime(); // отсчет времени (Unix) должен начинаться с О if (skew >0) // везде кроме Мас date.setTime (date.getTime() — skew); } // // Функция предназначена для возвращения значения cookie, // используя параметр "name". // name — строковый объект, содержащий имя cookie. // returns — строковый объект,, содержащий значение cookie либо 0, // если таковая запись не существует // function GetCookie (name) { var arg = name + "="; var alen = arg.length; var clen = document.cookie.length; var i = 0; while (i < clen) { var j = i + alen; if (document.cookie.substring(i, j) == arg) return getCookieVal (j); i = document.cookie.indexOf(" ", 1) + 1; if (i ==0) break; } return null; } // // Функция для создания или обновления cookie. 11 name — строковый объект, содержащий имя cookie. // value — строковый объект, содержащий значение cookie. // Может содержать любой действительный строковый символ. // [expires] — объект Date, содержащий срок службы cookie. // Если таковое отсутствует, удаляет cookie после завершения // сеанса работы браузера. // [path] — строковый объект, указывающий путь нужной cookie // записи. Если он не указан либо имеет нулевое значение, // использует путь вызванного документа. // [domen] — строковый объект, указывающий домен нужной // cookie-записи. Если он не указан или имеет нулевое значение, // используется домен вызванного документа. // [secure] — булево значение (true / false), определяет // необходимость использования безопасного соединения (HTTPS) // Первые два параметра необходимы. Остальные, если указаны, // то должны быть переданы в порядке, описанном выше. Для того // чтобы зарезервировать поле, не используемое в данный момент, // определите его как нулевое. Например, код для вызова функции // SetCookie с заданными именем, значением и путем, имеет // следующий вид: // SetCookie ("myCookieName", "myCookieValue", null, "/"); // // Заметьте, что перемещение опущенных параметров не требует // метки—заполнителя. Чтобы установить безопасный cookie в // "/myPath", срок службы которого заканчивается после // текущего сеанса, необходимо использовать выражение: И Глава 18. Объекты document и body 553
// SetCookie (myCookieVar, cookieValueVar, null, "/myPath", null, true); H function SetCookie (name,value,expires,path,domain,secure) { document.cookie = name + + escape (value) + ((expires) ? expires=+ expires.toGMTString() : "") + ((path) ? path=" + path : "") + ((domain) ? "; domain'" + domain : "") + ((secure) ? "; secure" : ""); } // Функция для удаления cookie. (Устанавливает дату истечения // срока службы записи в начало) // name — строковый объект, содержащий имя cookie. // path — строковый объект, содержащий путь cookie-записи, // которая впоследствии будет удалена. Это должен быть тот же // путь, который использовался при создании cookie, или нулевое // значение, если при создании записи путь не был определен. // domen — строковый объект, который содержит домен cookie, // предназначенный для удаления. Это должен быть тот же домен, // который использовался для создания cookie, или нулевое // значение, если при создании записи домен не был определен, function DeleteCookie (name,path,domain) { if (GetCookie(name)) { document.cookie = name + "=" + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + "; expires=Thu, 01-Jan-70 00:00:01 GMT"; } } 11 II Примеры: 11 var expdate = new Date (); FixCookieDate(expdate); // Исправляет ошибки в дате Mac, // используется только один раз для каждого объекта Date! expdate.setTime (expdate.getTime() + (24 * 60 * 60 * 1000)); // 24 от текущего времени SetCookie ("ccpath", "http://www.hidaho.coin/colorcenter/", expdate); SetCookie ("ccname", "hidaho Design ColorCenter", expdate); SetCookie ("tempvar","Это временная cookie."); SetCookie ("ubiquitous","Эта cookie будет работать в любом месте данного домена",nul1,"/"); SetCookie ("paranoid","Эта cookie обеспечивает безопасное соединение",expdate,"/“,null,true); SetCookie ("goner","Эта cookie должна быть удалена!"); document.write (document.cookie + "<br>"); DeleteCookie ("goner"); document.write (document.cookie + "<br>"); document.write ("ccpath = " + GetCookie("ccpath") + "<br>"); document.write ("ccname — " + GetCookie("ccname") + "<br>"); document.write ("tempvar = " + GetCookie("tempvar") + "<br>"); // конец сценария --> </script> </body> </html> 554 Часть III. Объекты документа
Дополнительные пакеты Можно создать узел, для которого потребуется более чем 20 cookie на соответствующий домен. Например, никогда не известно, сколько элементов может загрузить покупатель в по- требительскую корзину, находясь на коммерческом узле. Так как каждая cookie-запись сохраняет данные в виде обычного текста, можно создать собственные текстовые структуры данных для последующего размещения в них записей, со- стоящих из нескольких частей. (Но не следует забывать о практическом пределе: 2 000 сим- волов на пару имя-значение в пределах максимума (4 000 символов для каждой объединенной cookie-записи домена).) Таким образом определяется символ-разделитель, который не исполь- зуется ни в одной из cookie-записей. Например, в приложении Decision Helper (глава 55) для разделения нескольких целых чисел, сохраненных в cookie, используется точка. В случае применения установленного символа-разделителя необходимо написать функции для сбора этих подчиненных “cookie” в одну строку, и наоборот, разделения ее на отдельные записи. Такой путь более длинный, но он обеспечивает постоянство сведений о клиенте. Пример Поэкспериментируйте с последней группой операторов в листинге 18.3 для создания, по- лучения и удаления cookie-записей. Кроме того, вы можете активно пользоваться возмож- ностями приложения The Evaluator (устанавливая пары имя/значение и используя в дальней- шем свойство cookie). См. также: методы строковых объектов. defaultcharset Значение: Строковое Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство defaultcharset содержит набор символов, по умолчанию используемый браузером для обработки текущего документа. Возможные значения этого свойства можно найти по адресу. ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets Каждый браузер и операционная система имеют собственный, заданный по умолча- нию, набор символов. Эти значения также могут устанавливаться с помощью дескрипто- ра <meta>. Различие между свойствами def aultCharset и charset окончательно не установлено, так как оба они предназначены для чтения/записи (изменение свойства defaultcharset не имеет никакого визуального эффекта на странице). Однако, если в сценарии временно изменяется свойство charset, для восстановления оригинального на- бора символов можно использовать свойство defaultCharset. document.charset = document.defaultCharset; Пример Приложение The Evaluator позволяет работать и co свойством def aultCharset. Чтобы ознакомиться с настройками по умолчанию, введите в верхнем поле следующее выражение. document.charset = document.defaultCharset; См. также: свойства charset, characterSet. Глава 18. Объекты document и body 555
defaultview Значение: строковое Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Свойство defaultview возвращает ссылку на объект, выступающий в роли “просмотрщи- ка” документа (он отвечает за визуализацию документа). В NN6+ свойство defaultview воз- вращает объект window или frame, содержащий документ. В W3C DOM Level 2 это свой- ство предоставляет доступ к вычисляемым значениям CSS, примененным к любому HTML- элементу (с помощью метода document.defaultview.getComputedStyle() или, в боле» простом случае, с помощью метода window. getComputedStyle ()). См. также: свойства window и frame; метод window. getComputedStyle (). designMode Значение: строковое Чтение/Запись Совместимость: WinIE5+, MacIE-, NN7.1, Mozl.4, Safari- Свойство designMode используется только тогда, когда средства IE5+ выступают в ка- честве компонента другого приложения. Это свойство указывает, будет ли модуль браузера использоваться для редактирования HTML-кода. Изменение свойства на типичной странице HTML в браузере IE5+ не будет иметь никаких результатов. В Mozilla свойство можно при- менять для включения и отключения объекта document элемента iframe. doctype Значение: ссылка на объект DocumentType Только для чтения Совместимость: WinlE-, MacIE5+, NN6+, Mozl+, Safari- Свойство doctype позаимствовано из W3C DOM. С его помощью возвращается объ- ект DocumentType — формат представления данных документов, представленный DTD. Объект DocumentType (даже если он явно не определен в исходном тексте) является пер- вым дочерним узлом корневого узла документа (следовательно, его можно считать “потомком” HTML-элемента). В W3C DOM, как и в NN6, всего несколько свойств действительно пригодны для непо- средственного использования. В табл. 18.2 представлен список типичных свойств объекта DocumentType и значений для создаваемой HTML-страницы. В новой версии DOM эти свойства будут доступны для чтения и записи. Свойство Значение entities null internalsubset (нет) name notations html null publicid systemid -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd См. также: дочерний объект (глава 14). 556 Часть Ш. Объекты документа
documentElement Значение: ссылка на элемент HTML или XML-объекта Только для чтения Совместимость: WinIE5+, МасЕ5+, NN6+, Mozl+, Safaril+ Свойство documentElement возвращает ссылку на объект HTML-элемента (или XML- элемента), который представляет содержимое всего текущего документа. Данное имя не со- всем точно соответствует действительности, так как узел корневого документа не является элементом, его единственный дочерний узел — это элемент html (или xml). В лучшем слу- чае можно считать, что это свойство как бы присуждает звание “элемента” объекту document и узлу документа, который связан с текущей страницей, загруженной в браузере. Пример Используйте приложение The Evaluator для детального изучения свойства document- Element. В браузере E5+/W3C введите в текстовое поле следующее выражение. document.documentElement.tagName Возвращаемый результат— HTML. См. также: свойство ownerDocument (глава 15). domain Значение: строковое Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Ограничения системы безопасности могут помешать нормальной работе сценария, если узел имеет более одного сервера в своем домене. Так как некоторые объекты, особенно объект location, не разрешают доступ к свойствам других серверов, загруженных в другие фреймы, законный доступ к их свойствам окатывается заблокированным. Например, довольно часто узлы общего доступа располагаются на сервере с именем, подобным www. popular. com. Если стра- ница на этом сервере оснащена поисковым интерфейсом search .popular. com, то пользова- тель, в браузере которого установлена подобная защита, получает отказ в доступе. Для того чтобы обойти подобную защиту, можно запустить сценарии в документах обоих серверов, таким образом, оба сервера будут восприниматься браузером как одинаковые. В преды- дущем примере требовалось установить в свойстве document. domain значение popular. com для обоих документов. Если данное свойство не установлено пользователем, то по умолчанию его значение содержит имя текущего сервера, что порождает несоответствие между именами. Прежде, чем “подделывать” другие сервера, сначала убедитесь в том, что сможете задать свойство document. domain для документа на серверах, относящихся к одному домену. Та- ким образом, для документов, расположенных только на ххх. popular. com, можно устано- вить свойства document. domain равными именам других серверов,. См. также: метод window. open (); объект window. locat ion; безопасность (глава 46). embeds Значение: массив объектов элемента embed Только для чтения Совместимость: WinIE5+, Цас1Е5+, NN6+, Mozl+, Safari 1+ Всегда, когда необходимо загрузить данные, требующие надстройки (внедряемого моду- ля)— приложения для их воспроизведения либо вывода на экран, используют дескриптор <embed>. Свойство document. embeds — это единственный способ определения таких де- скрипторов, добавленных в документ. var count = document.embeds.length; Глава 18. Объекты document и body 557
Для управления надстройками в Netscape Navigator можно использовать технологию LiveConnect, описанную в главе 44. См. также: элемент embed (глава 40). expando Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Microsoft называет любое обычное свойство, которое не является “родным” для объекта document, расширяемым. По умолчанию в последних версиях браузеров в большинство объектов с помощью сценария можно добавить новые свойства (как способ временного хра- нения данных без явного определения глобальных переменных). Например, если нужен счет- чик, который содержал бы количество вызовов определенной функции, можно создать поль- зовательское свойство объекта document и использовать его как средство хранения. document.counter = 0; IE4+ позволяет управлять способностью объекта document к хранению расширенных свойств. По умолчанию значение свойства document. expando равно true. Это позволяет использовать расширенные свойства объекта. Но дело в том, что на стадии разработки стра- ницы расширенное свойство, содержащее ошибки, может быть названо именем уже сущест- вующего стандартного свойства; оно будет принято объектом document “без всяких подозре- ний”. В результате может получиться так, что пользователь не поймет, почему строка заголовка окна браузера не изменяется при установке свойству document .Title (которое в чувстви- тельном к регистру JavaScript отличается от свойства document .title) нового значения. Пример Вы можете использовать приложение The Evaluator (глава 13) для изучения свойства expando в IE4+. Сначала удостоверьтесь, что объект document может управлять пользова- тельскими свойствами. Введите в верхнее текстовое поле следующее выражение. document. spooky = "Boo! " Это свойство добавляется в документ и поддерживается в нем до выгрузки или переза- грузки документа. Заблокируйте возможность управления в документе пользовательскими свойствами. document.expando = false Если вы попытаетесь добавить новое свойство, то получите извещение об ошибке. document.happy = "tra la" Несмотря на отключение свойства document. expando исходно добавленное пользова- тельское свойство остается доступным для использования. См. также: свойство prototype пользовательских объектов (глава 33). fgColor См. al inkColor. fileCreatedDate fi1eModifiedDate filesize Значение: строковое, целочисленное (filesize) Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- 559 Часть ///. Объекты документа
Эти три свойства, предназначенные для работы только в Internet Explorer, возвращают информацию о файле, который содержит текущий документ. Два из них определяют даты создания и изменения файла текущего документа. Для неизмененного файла эти даты оста- ются прежними. Свойство fileSize отображает объем документа в байтах. Значения даты, возвращаемые в первых двух свойствах, отформатированы по-разному в IE4 и IE5. Функции предоставляют полную информацию о текущей дате, которая содержит- ся в формате mm/dd/yyyy. Однако заметьте, что значения содержат только дату, а не время. Это значение всегда можно использовать как параметр для вызова конструктора new Date (). Значение даты пригодиться вам, например, при расчете периода времени, прошедшего с дня последнего изменения документа. Не все серверы могут определить предыдущую дату или размер файла, а если и могут, то не всегда в том формате, который поддерживается в Internet Explorer. Проверьте выполнение этой операции на сервере, чтобы убедиться в совместимости данных. Необходимо также знать, что эти свойства доступны только для чтения файла, загружен- ного в браузер в данный момент. Средствами языка JavaScript нельзя получить эту информа- цию о файле, находящемся на сервере, но не загруженном в браузер. IE5.5+ представляет на рассмотрение разработчиков свойство с именем fileUpdatedDate, но оно не возвращает никаких значений. Это “фантомное” свойство, возможно, осталось от предыдущей версии браузера. Пример Код листинга 18.4 динамически генерирует несколько фрагментов, указывающих на да- ту создания и изменения файла, а также извещающих о его размере. Что более важно, этот код демонстрирует, как преобразовать возвращаемое значение даты в объект даты, кото- рый можно использовать в вычислениях. В листинге 18.4 исчисление ведется в виде целых дней между датой создания и датой просмотра. Обратите внимание на то, что динамически сгенерированное содержимое добавляется в документ с помощью свойства innerText и размещается в элементах span. <html> <head> <title>fileCreatedDate and fileModifiedDate Properties</title> «script type="text/javascript"> function filllnBlanks() { 'var created = document.fileCreatedDate; var modified = document.fileModifiedDate; document.getElementByld("created").innerText = created; document.getElementByld("modified").innerText = modified; var createdDate = new Date (created) .getTimeO; var today = new Date().getTime(); var diff = Math.floor((today - createdDate) / (1000*60*60*24)); document.getElementByld("diff").innerText = diff; document.getElementByld("size").innerText = document.fileSize; } </script> «/head> «body onload="filllnBlanks() "> <hl>fileCreatedDate and fileModifiedDate Properties«/hl> Глава 18. Объекты document и body 559
chr /> «p>This file («span id="size">&nbsp;«/span> bytes) was created on «span id=”created">&nbsp;«/span> and most recently modified on «span id="modified">&nbsp;«/span>.«/p> <p>It has been «span id="diff">&nbsp;«/span> days since this file was created.</p> </body> </html> См. также: свойство lastModif ied. forms [] Значение: массив Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Как было показано в главе 21, посвященной объекту form, форма HTML (содержится в паре дескрипторов <fortn>. . .</form>) представляет собой объект JavaScript, находя- щийся сам в себе. Можно создать ссылку на форму согласно ее имени (назначенному в атри- буте name). Например, если в документе содержится следующее определение формы. « form name = "phoneData" > определение элементов управления «/form>, то в сценарии для обращения к этому объекту формы может использоваться указанное имя. document.phoneData Однако с помощью объекта document к данной форме можно обратиться и другим спосо- бом: как к массиву объектов form. Первым элементом массива document. forms является первая форма, загруженная в данный документ (она приведена в самом начале HTML-кода). Ес- ли документ определяет одну форму, свойство форм представляет собой массив, состоящий из одного элемента; в случае определения трех отдельных форм — массив из трех элементов. Используйте стандартную структуру массивов для получения доступа к определенным формам из массива document. forms. Например, первая форма документа (“нулевой” эле- мент в массиве document. forms) вызывается так. document.forms[0] Свойство или метод объектов форм становятся доступны, если добавить к этому выраже- нию имя нужного свойства или метода. Например, для определения значения текстового поля с именем home Phone второй формы документа используется ссылка, которая задается сле- дующим образом. document.forms[1].homePhone.value В использовании свойства document. forms для обращения к объектам форм или элемен- тов, заменяющих фактическое имя формы, есть одно большое преимущество. Речь идет о воз- можности создания библиотеки генерируемых сценариев, с помощью которых можно в цикле получить доступ ко всем формам в документе и выбрать ту, для которой определено необходи- мое свойство. Следующий фрагмент сценария (часть цикла, более подробно Описанного в гла- ве 31) использует переменную-счетчик (i) для просмотра всех форм, содержащихся в документе. for (var i = 0; i « document.forms.length; i++) { if (document.forms[i] . ... ) { операторы 560 Часть III. Объекты документа
Еще один вид ссылок на элементы формы представляет замену именем формы (стро- ковое значение) индекса массива forms. Например, форма с именем phoneData может быть вызвана так. document. forms [11 phoneData " ] При назначении имен объектам рекомендуется использовать следующий способ задания ссылок на формьЕ document. FormName. В этой книге описан как индексированный, так и именованный массив ссылок на формы. Преимущество применения именованных ссылок состоит в том, что даже при изменении страницы и порядка размещения форм в документе ссылки на имена этих форм остаются и будут действительны, в то время как индексы форм часто изменяются. В главе 21 описаны объекты форм и способ передачи их в функцию. Пример Документ, представленный листингом 18.5, настраивает и отображает диалоговое окно предупреждения, которое имитирует подключение к музыкальному Web-узлу, основываясь на состоянии флажка. В данном случае пользователь вводит данные на двух формах: одна со- держит флажок, а вторая кнопку. В середине страницы находится простой заполнитель, кото- рый в реальных документах заменяют конечными данными. Щелчок на нижней кнопке (вторая форма) вызывает функцию, которая получает состояние флажка, используя выраже- ние document. forms [i] как часть адреса. <html> <head> <title>document.forms example«/title> «script type="text/javascript"> function goMusicO { if (document.forms[0].bluish.checked) { alert("Now going to the Blues music area..."); } else { alert("Now going to Rock music area...; <7script> «/head> <body> «form name="theBlues"> «input type="checkbox" name="bluish" />Check here if you've got the blues. «/form> «hr /> M«br /> o«br /> r«br /> e«br /> «br /> C«br /> o«br /> p«br /> y«br /> «hr /> «form name="visit"> «input type="button" value="Visit music site" Глава 18. Объекты document и body 561
onclick="goMusic()" /> </form> ' </body> </html> См. также: объект form (глава 21). frames [] Значение: массив Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство document.frames подобно свойству window.frames. Иногда такая схо- жесть вызывает путаницу. Объекты, которые содержатся в массиве, возвращенном из этого свойства, являются объектами окна любых элементов frame (в документе, состоящем из не- скольких фреймов) или элементов iframe (в простом документе HTML). Различие между объектами окна и объектами элементов существует; его очень важно понимать. Объекты окна имеют различные свойства и методы, в отличие от элементов frame и iframe. Обычно свойства последних определяют атрибуты дескрипторов этих элементов. Если документ не содержит элементов iframe, массив frames имеет нулевую длину. Можно обращаться к определенному объекту фрейма, используя синтаксис, привычный для массива (например document.frames [0]), а можно использовать дополнительный синтаксис, предусмотренный Microsoft для управления набором объектов. Индекс элемента массива можно поместить в круглые скобки, как в данном примере. document.frames(О) Более того, если фреймы имеют значения, назначенные в атрибутах name, их можно ис- пользовать (в строковой форме) как параметр или индекс. document.frames("contents") Но будьте внимательны в ситуации, когда в наборе встречаются фреймы с одинаковыми именами. При использовании такого же имени, как и у параметра, ссылка возвращает не- сколько объектов фреймов, имеющих одно имя. Можно ограничить количество таких воз- вращаемых объектов, определив необязательный второй параметр, указывающий индекс нужного объекта. Например, если документ имеет два элемента iframe с именем contents, сценарий может обратиться ко второму объекту window так. document.frames("contents", 1) Для обеспечения совместимости с другими браузерами рекомендуется вызвать объекты фреймов с помощью свойства window, frames. Пример В листингах 16.7 и 16.8 приведен пример использования свойства frames. Этот пример выполняется в IE4+, если вы начинаете ссылку на свойство с window или document. См. также: свойство window. frames. height width Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Mozl+, Safaril+ Свойства height и width объекта document в NN4+ определяют в пикселях размер те- кущего окна или фрейма. Если площадь документа имеет размер меньше, чем область браузера, 562 Часть ///. Объекты документа
размеры, возвращенные этим свойством, учитывают и пустое пространство в правой и/или нижней части окна. Но если площадь документа превышает видимые границы окна браузе- ра, размеры задают и неотображаемое пространство. Соответствующие свойства в IE4+ — document .body. scrolIHeight и document .body. scrollwidth. Пример Используйте приложение The Evaluator для изучения свойств height и width. Введите в верхнее текстовое поле следующее выражение. "height=" + document.height + width=" + document.width Измените размер окна таким образом, чтобы видеть вертикальную и горизонтальную по- лосы прокрутки. Щелкните на кнопке Evaluate еще раз. Если оба одно число стало меньше, то значения в области вывода результатов определяют область, занимаемую документом. Ес- ли же вы расширите окно так, что в нем не будут отображаться полосы прокрутки, то значе- ния будут указывать реальный размер окна. См. также: свойства document. body. scrollHeight, document.body. scrollwidth. ids [] Значение: массив Только для чтения Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Свойство ids используется только в NN4 и в качестве альтернативы, основанной на синтак- сисе таблицы стилей браузера. Таблицы стилей в JavaScript используются чрезвычайно редко. В некоторых случаях свойство document. ids работает подобно свойству document. all в1Е4+, но document.ids не может использоваться в регулярных сценариях получающих доступ к объектам элементов. См. также: свойство tags. images [] Значение: массив Только для чтения Совместимость: WinIE4+, MacIE3+, NN3+, Mozl+, Safaril+ Изображенйя, обрабатываемые как объекты особой важности во всех браузерах, начиная с NN3 и IE4, будут представлены в документе как массив дескрипторов всех изображений, указанных на странице (аналогично анкерам и ссылками). Основное преимущество в хране- нии изображений как объектов состоит в простоте изменения их содержимого (исходный файл, содержащий параметры изображения). Более подробно объект изображения описан в главе 20. Для точного определения текущего изображения используйте массив ссылок на изобра- жения. Тогда можно задавать любое его свойство или назначить новые файлы изображений в его свойстве src. В массивах изображений нумерация элементов начинается с 0: первое изображение в документе определяется по ссылке document. images [0]. Аналогично лю- бому объекту массива, можно определить количество изображений, содержащихся в данном массиве, с помощью свойства length. var imageCount = document.images.length; Изображения также могут иметь названия, поэтому в случае необходимости вы вправе обратиться к объекту изображения, используя его имя var ImageLoaded = document.имяИзображения.complete; или var ImageLoaded = document.images[имяИзображения].complete; Глава 18. Объекты document и body 563
Массив document. images применяется для определения расположения в документе новых изображений. Любой браузер, который обрабатывает элемент img как объект, всегда формирует массив document. images для данной страницы. Если на странице не найдено ни одного изображения, массив все равно существует, но с количеством элементов, равным нулю. Его существование указывает на совместимость объекта изображения с объектной мо- делью браузера. Так как document. images описывает массив объектов (если таковые под- держиваются), выражение может использоваться как условие для перехода к операторам, с помощью которых изменяются изображения. if (document.images){ // Замена или предварительная загрузка изображения Более ранние версии браузеров, которые не имеют этого свойства, устанавливают значе- ние document. images как undefined (неопределенное), и, таким образом, условие полу- чает значение false. Пример Свойство document. images назначается автоматически при создании браузером объект- ной модели в документах, которые содержат изображения. См. также: объект Image (глава 20). implementation Значение: объект Только для чтения Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ В базовой модели W3C DOM используется свойство document. implementation для нахождения сценарием средств (или элементов), которые поддерживаются в текущей среде. Объект, возвращенный данным свойством (объект DOMlmplementation), не имеет никаких свойств, но поддерживает метод hasFeature (), который позволяет сценариям определять, например, что именно поддерживает данная среда — HTML или только XML. Первым пара- метром метода hasFeature () является средство, представленное В виде строки. Второй параметр — это строковое представление номера версии. Метод возвращает булево значение. В разделе спецификации W3C DOM, называемом Conformance, приведены имена моду- лей (стандарт также позволяет проверить с помощью метода hasFeature () средства, под- держиваемые в браузере). Имена модулей, как правило, содержат сочетания слов HTML, XML, MouseEvents и т.д. Нумерация версий модулей W3C D0M соответствует уровням W3C D0M. Таким образом, модуль XML D0M 2.0 соответствует DOM 2.0. Обратите внимание, что версии представлены для DOM-модулей, а не для отдельных стандартов (например HTML). Пример Приложение The Evaluator подойдет и для всестороннего изучения метода document. imple- mentation. hasFeature (). Введите следующие выражения поочередно в верхнее тек- стовое поле. document.implementation.hasFeature("HTML","1.0") document.implementation.hasFeature("HTML",“2.0") document.implementation.hasFeature("HTML","3.0") document.implementation.hasFeature("CSS","2.0") document.implementation.hasFeature("CSS2","2.0") He бойтесь вводить другие значения параметров. 564 Часть III. Объекты документа
lastModified Значение: строковая дата Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Каждый файл на диске имеет изменяемый временный файл, и большинство серверов (но не все) настроены на то, чтобы считывать его информацию в браузере при обращении к фай- лу. Эта информация доступна для получения изювойства document. lastModif ied. Если клиент получает подобную информацию от сервера, можно использовать значение этого свойства для предоставления данной информации посетителям Web-страниц. Сценарий авто- матически обновит значение, вместо того чтобы предлагать пользователю сделать это вруч- ную (и так каждый раз при изменении HTML-документа). Если появившееся на экране возвращенное значение представляет собой дату 1969 года, это означает, что пользователь находится западнее Гринвичского меридиана (некоторые ча- совые пояса, находящиеся западнее GMT, попадают в зону, где дата определяется как 1 янва- ря 1970). Исходя из этого, серверы не смогут обеспечить определение соответствующих дан- ных при обслуживании этих файлов. Иногда конфигурация сервера может вызвать сбой, но это встречается редко. Возвращенное значение не является объектом даты (глава 29); это, скорее, строка, пред- ставляющая время и дату, сохраненные в файле документа. Формат строки изменяется в зави- симости от браузеров и их версий. Но всегда можно конвертировать эту строку в объект даты JavaScript и использовать соответствующие методы для извлечения определенных элементов и преобразования их в формат, пригодный для чтения. Даже локальные файловые системы не всегда обеспечивают корректную интерпретацию данных для каждого браузера. Но тот же самый файл, помещенный в UNIX или Windows Web-сервер, имеет правильную дату изменения, если получить к нему доступ из локальной сети. Пример В листинге 18.6 представлен пример использования этого свойства. Приготовьтесь к то- му, что при тестировании файлов, расположенных на локальном жестком диске, у вас могут возникнуть проблемы. <html> <head> <title>Time Stamper</title> </head> <body> <center> <hl>GiantCo Home Page</hl> </center> «script type=”text/javascript"> update = new Date(document.lastModified); theMonth = update.getMonth() + 1; theDate = update.getDateO ; theYear = update.getFullYear(); document.writein("<I>Last updated:" + theMonth + "/" + theDate + "/" + theYear + "<\/I>") ; </script> <hr /> </body> </html> Глава 18. Объекты document и body 565
При описании объекта Date будьте готовы к тому, что в каждой стране поддерживается свой формат даты (см. главу 29). Зачастую в этих форматах используется непривычный порядок следования элементов. Вам обязательно необходимо учесть этот факт в собственных документах. См. также: объект Date (глава 29). layers [] Значение: массив Только для чтения Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Объект слоя (глава 39)— это средство, использующееся только в NN4 для представления в объектной модели позиционируемых элементов. Таким образом, свойство document. layers— это массив слоев, расположенных в документе. По причине того, что NN4 использует нестан- дартный способ представления позиционируемых элементов, не каждый из подобных эле- ментов содержится в массиве document. layers. Вложенные элементы должны опреде- ляться с помощью иерархической структуры слоев. / Объект слоя и свойство document. layers остались только в NN4; необходи- /наммй$1 мость в них со временем исчезает, поскольку число пользователей NN4 умень- * шавтся. Поэтому следующие комментарии будут полезны только для тех, кто вынужден поддерживать позиционируемые элементы в NN4. В NN6 слой пред- ставлен любым элементом HTML, таблицы стилей которого включают атрибут position. Ссылки на подобные элементы задаются с помощью метода document. getElementByld () либо комбинаций, описанных в главе 14. В Netscape Navigator слой — это контейнер содержимого, которое нужно точно размес- тить на странице. Слои определяются в дескрипторе <layer>, который используется только в NN4 (или в W3C-cHHTaKCHce стандартной таблицы стилей для позиционируемых элементов, которые описаны в главе 39). Каждый слой содержит объект document, хранящий содержи- мое данного слоя. Слои могут быть вложенными, но с помощью ссылки document. layers можно обратиться только к первому уровню слоев, определенному в документе. Ниже приве- дена соответствующая структура HTML-кода. «html> <body> «layer name="Europe"> «layer name="Germany">«/layer> «layer name="Netherlands"X/layer> </layer> «/body> «/html> С точки зрения исходного документа, в данном случае используется только один слой (Europe). Поэтому длина массива document. layers равна 1. Но слой Europe содержит документ с еще двумя вложенными уровнями. Ссылка на массив этих вложенных слоев имеет вид document.layers[1].document.layers или document.Europe.document.layers Длина вложенного массива равна двум: Germany и Netherlands. Не существует ни одного свойства, которое бы определяло полный набор вложенных массивов в документе. Но можно создать цикл for, чтобы перемещаться по всем вложенным слоям (как показано в листинге 18.7). 566 Часть III. Объекты документа
Пример Листинг 18.7 содержит пример использования свойства layers для просмотра всех слоев документа, который отображается в NN4. С помощью функции crawl Layers () сценарий создает список слоев в такой же иерархической последовательности, как у объектов докумен- та, и выводит результат в диалоговом окне. После загрузки страницы сравните выводимый результат со структурой дескрипторов <1ауег> документа. <html> «head» «title»«/title> «script type="text/javascript"» var output = ""; function crawlLayers(layerArray, indent) { for (var i = 0; i < layerArray.length; i++) { output += indent + layerArray [i] .name + "\n"; if (layerArray[i].document.layers.length) { var newLayerArray = layerArray[i].document.layers; crawlLayers(newLayerArray, indent + " "); } } return output; } function revealLayers() { alert(crawlLayers(document.layers, "")) ; } </script» </head> «body onload="revealLayers()"» «layer name="Europe"» «layer name="Germany"» «/layer» «layer name="Netherlands"» «layer name="Amsterdam">«/layer> «layer name="Rotterdam"»«/layer> «/layer» «layer name="France"» «/layer» «/layer» «layer name="Africa"> «layer name="South Africa"» «/layer» «layer name="Ivory Coast"» «/layer» «/layer» «/body» «/html» См. также: объект слоя (глава 39). linkColor См. al inkColor. ' Глава 18. Объекты document и body 567
links [] Значение: массив Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство document. links подобно свойству document. anchors; его отличие со- стоит в том, что объекты, содержащиеся в массиве, являются объектами ссылок — элемента- ми, созданными с помощью дескриптора <а href="">. Используйте массив ссылок для точного определения нужной ссылки и задания любого ее свойства (подобно тому, как в HTML указывается целевое окно). В массивах ссылок нумерация элементов начинается с 0: первая ссылка в документе — document. images [0]. Аналогично любому объекту массива, можно определить количест- во ссылок, содержащихся в данном массиве, используя свойство length. var linkCount = document. links. length; Элементы, представленные свойством document. links, являются полноценными объ- ектами location. Пример Свойство links назначается автоматически при создании браузером объектной модели документа. Это свойство используется очень редко; исключение составляют сценарии, в ко- торых подсчитывается количество ссылок в документе. См. также: объект ссылок; свойство document. anchors. location URL Значение: строковое Чтение/Запись и Только для чтения Совместимость: WinIE3+, МасШЗ+, NN3+, Mozl+, Safaril+ Суть этих методов заключается в том, что JavaScript часто использует одни и те же тер- мины в различных контекстных ситуациях (это может запутать начинающего пользователя). Например, существует свойство document. location. Просто поразительно, как это свой- ство отличается от объекта location (глава 17). На практике во многих сценариях возни- кают ошибки, если в ссылках не указан объект window. В результате, в NN3 и IE4 появилось новое свойство document.URL вместо document.location. Конечно, можно использо- вать и document. location, но тогда из словаря объектной модели могут исчезнуть неко- торые ключевые слова. Поэтому далее будет описываться свойство document. URL. Теперь вернемся к исходному вопросу: какая разница между объектом window, location и свойством document. URL? Ответ: разница в соответствующих им типах данных. Объект location, как уже отмечалось в главе 17, состоит из целого ряда свойств доку- мента, в данный момент загруженного в окно или фрейм. Назначение нового URL-адреса объекту location (или свойству location.href) дает команду браузеру загрузить стра- ницу, соответствующую полученному URL-адресу, во фрейм. С другой стороны, свойство document. URL является просто строкой (в Netscape Navigator только для чтения), в которой отображен URL-адрес текущего документа. Ее значение может быть важно для сценария, но это свойство не имеет “объектной природы” window. location. Нельзя изменить данное значение свойства (указав новое), так как документ имеет только один URL-адрес, опреде- ляющий расположение в сети (или на жестком диске локального компьютера) данного файла, и протокол, требуемый для его получения. 568 Часть III. Объекты документа
Именно в этом и состоит основное отличие вышеуказанного объекта от свойства. Ис- пользуемое обращение (объект window, location или свойство document.URL) зави- сит от действий, которые пользователь собирается выполнить в соответствии со сценари- ем. Если при выполнении сценария необходимо изменить содержимое окна (загружается документ с новым URL), то пользователю ничего не остается, как использовать объект window.location. Аналогично, если в сценарии требуются составляющие части URL- адреса, то наиболее простой способ получить эту информацию — воспользоваться свойством document. URL. Для восстановления URL-адреса документа в строковой форме (независимо от того, находится этот документ в текущем окне или в другом фрейме), можно использовать как свойство document. URL, так и window. location. href. Пример HTML-документы листингов 18.8-18.10 представляют собой приложение тестирования свойства location, URL в многофреймовой среде. Результаты выводятся в виде таблицы, в которой также содержится список свойств document, title, чтобы документы было проще идентифицировать. «html> <head> <title>document.URL Reader</title> «/head? «frameset rows="60%,40%"> «frame name="Framel" src="lstl8-10.htm" /> «frame name="Frame2" src="lstl8-09.htm" /> «/frameset> </html> «html> «head> «title>URL Property Reader«/title? «script type="text/javascript"? function fillTopFrame() { newURL=prompt("Enter the URL of a document to show in the top frame:",""); if (newURL 1= null && newURL != "") { top.frames[0].location = newURL; function showLoc(form,item) { var windName = item.value; var theRef = windName + ".document"; form.dLoc.value = unescape(eval(theRef + ".URL")); form.dTitle.value = unescape(eval(theRef + ".title")); } «/script? «/head? «body? Глава 18. Объекты document и body 569
Click the "Open URL" button to enter the location of an HTML document to display in the upper frame of this window. <form> «input type="button" name="opener" value="Open URL..." onclick="fillTopFrame()" /> </form> <hr Л> <form> Select a window or frame to view each document property values, «pxinput type="radio" name="whichFrame" value= "parent" onclick="showLoc(this.form,this)" />Parent window «input type="radio" name="whichFrame" value="top.frames[0]" onclick="showLoc(this.form,this)" />Upper frame «input type="radio" name="whichFrame" value="top.frames[1]" onclick="showLoc(this.form,this)" />This frame«/p> «table border="2"> «tr> «td align="RIGHT">document.URL:«/td> «tdxtextarea name="dLoc" rows="3" cols="30" wrap="soft"> «/textarea>«/td> «/tr> «tr> «td align="RIGHT">document.title:«/td> «tdxtextarea name="dTitle" rows="3" cols="30". wrap="soft"> «/textareax/td> «/tr> «/table> «/form> «/body> «/html> «html> «head> «title>Opening Placeholder«/title> «/head> «body> Initial place holder. Experiment with other URLs for this frame (see below). «/body> «/html> См. также: объект location; свойства location. href, URLUnencoded. media Значение: строковое Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Чтение/Запись 570 Часть III. Объекты документа
В IE5.5 свойство document.media может принимать одно-единственное значение (по умолчанию): print. Это свойство везде описывается довольно поверхностно, но опреде- ленно можно сказать следующее: оно используется в сценарии для задания эквивалента пра- вилу CSS 2 ©media (одно из так называемых правил “at”, в честь символа @). Это правило таблицы стилей позволяет браузерам назначать отдельные стили для каждого типа устройст- ва вывода, на котором представлена страница (например, возможны отличия в шрифтах на принтере и мониторе). Одиако на практике это свойство в IE5.5 не поддается изменению. mimeType Значение: строковое Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Данное свойство действительно применяется в IE5+, однако его значение ие соответству- ет типу MIME, точнее, его традиционному формату. Кроме того, в браузерах IE5 и IE5.5 по- лучаемые результаты совершенно разные. Возможно, это свойство более часто используется в XML, чем в HTML. В любом случае, такой способ никоим образом не позволяет открывать в текущем браузере документы MIME-типа. nameProp Значение: строковое Только для чтения Совместимость: WinIE6+, MacIE-, NN-, Moz-, Safari- Это свойство возвращает строку, которая содержит заголовок документа, равный значе- нию свойства document. title. Если документие имеет заголовка, то свойство nameProp содержит пустую строку. namespaces[] Значение: массив объектов namespaces Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Объект name space (недавно появился в IE5.5) может динамически импортировать осно- ванное на XML поведение элемента IE. Свойство namespaces возвращает массив всех объек- тов namespace, определенных в текущем документе. parentWindow Значение: ссылка на объект window Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство document .parentwindow возвращает ссылку на объект window, который содержит текущий документ. Возвращается такое же значение, какое имеет ссылка на те- кущее окно. Пример Чтобы доказать, что свойство parentwindow указывает на окно документа, введите сле- дующее выражение в верхнее поле приложения The Evaluator. document.parentwindow == self Это выражение возвращает значение true только в случае равенства двух ссылок. См. также: объект window. Глава 18. Объекты document и body 571
plugins [] Значение: массив Только для чтения Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Свойство document. plugins возвращает тот же массив элементов embed, который можно получить с помощью свойства document. embeds. Но его практически не использу- ют, в отличие от document. embeds. См. также: свойство document. embeds. protocol Значение: строковое Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство document. protocol используется только в. Internet Explorer и определяет •версию протокола, с помощью которой и осуществлялся доступ к текущему документу. На- пример, если за файлом обращаются на Web-сервер, то возвращается свойство Hypertext Transfer Protocol. Данное свойство отличается от location.protocol, так как по- следнее возвращает только часть URL-адреса, содержащую наиболее часто встречающуюся аббревиатуру протокола (например http:). Как правило, разработчик скрывает эти данные от пользователя приложения в Web. Пример Если вы будете использовать приложение The Evaluator для изучения свойства protocol, то обнаружите, что оно возвращает значение File Protocol, поскодаку вы получаете доступ к программному коду, расположенному на жестком или компакт-диске. См. также: свойство location.protocol. referrer Значение: строковое Только для чтения Совместимость: WinIE3+, МасШЗ+, NN2+, Mozl+, Safari 1+ Когда пользователь с помощью ссылки, находящейся в одном документе, попадает в другой документ, то в этом втором документе, используя JavaScript, можно определить URL-адрес пер- вого документа, содержащего ссылку на него. Свойство document. referrer содержит стро- ку с этим URL-адресом. Такая возможность может пригодиться для настройки содержимого страниц, основанного на предыдущем посещенном пользователем документе. Свойство содер- жит значение, только когда пользователь попадает на текущую страницу с помощью ссылки. Любой другой способ перемещения (например, с помощью списка посещенных страниц, за- кладки или ручного введения URL-адреса) устанавливает в этом свойстве пустую строку. ! Свойство document. referrer обычно возвращает пустую строку, если файлы /на заметку получены не с Web-сервера. Более того, ранние версии WinlE никогда корректно < - ^<*' не определяли это свойство. Пример Этот пример состоит из двух документов (в случае использования IE вам необходимо от- крыть документы с Web-сервера). Первый документ (листинг 18.11) содержит простую тек- стовую ссылку на другой документ. Сценарий второго документа (листинг 18.12) проверяет, из какой страницы пользователь перешел к текущей, а затем отображает соответствующее сообщение. Откройте второй документ в новом окне браузера с помощью команды Open File (Открыть) и убедитесь, что свойство referrer в данном случае будет не определено. 572 Часть III. Объекты документа
<html> <head> <title>document.referrer Property l</title> </head> <body> <hlxa href="lstl8-12.htm">Visit my sister document </ax/hl > </body> </html> <html> <head> <title>document.referrer Property 2</title> </head> <body> <hl> «script type="text/javascript"> alert(document.referrer.length + " : " + document.referrer); if(document.referrer.length > 0 && document.referrer. indexOf("lstl8-ll.htm") != -1){ document.write("How is my brother document?"); } else { document.write("Hello, and thank you for stopping by."); } </script> </hl> </body> </html> См. также: объект ссылки. scripts [] Значение: массив Только для чтения Совместимость: WinIE4+, МасШ4+, NN-, Moz-, Safari- Свойство document. scripts возвращает массив всех элементов script, содержащихся в текущем документе. К отдельному объекту элемента script можнф обратиться не только для чтения свойств, совместно используемых всеми элементами HTML (глава 15), но и для опреде- ления таких свойств сценариев, как defer, src и htmlFor. Фактическое создание сценария выполняется с помощью innerText и text для любого объекта элемента script. В отличие от массива document. scripts, который предназначен только для чтения, мно- гие свойства отдельных объектов элементов script поддаются изменению. Добавление или удаление элементов script приводит к изменению длины массива document. scripts. Если в сценарии требуется получить доступ к определенному элементу script, то ему можно назна- чить атрибут id, и уже с его помощью обратиться к данному элементу. Глава 18. Объекты document и body 573
Описываемое свойство предназначено для использования только в Internet; оно является более удобным, чем выражение document. getElementsByTagName (" script") в IE4+ и NN6, которое возвращает массив таких же объектов. Пример Вы можете экспериментировать со свойством scripts в приложении The Evaluator. Ес- ли ввести в верхнее поле следующее выражение, то можно узнать, что страница приложения содержит только сценарий. document.scripts.length Для ознакомления со свойствами объекта script введите в нижнее поле такой оператор, document.scripts[0] В числе его свойств вы найдете innetText и text. Если установить в качестве значения одного из них пустую строку, то сценарий будет удален из объектной модели, но не из памяти браузера. Сценарий не исчезает, хотя в объектной модели он представлен не будет. Если вве- сти следующее выражение в верхнее поле document.scripts[0].text = "" то содержимое сценария будет удалено из объектной модели, хотя использование кнопок Evaluate и List Properties в дальнейшем приведет к возвращению результатов. См. также: элемент script (глава 36). security Значение: строковое Только для чтения Совместимость: Winlp5.5+, MacIE-, NN-, Moz-, Safari- Свойство security представляет информацию о типе защиты, если таковая применяется в текущем документе. selection Значение: объект Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство document. selection возвращает объект selection, содержимое которого отображается в окне браузера как выделение основного текста. Это выделение может осуще- ствляться пользователем (по щелчку и перемещению указателя вдоль текста) или с помощью сценария в объекте TextRange, поддерживаемом в WinlE (см. главу 35). Так как выделение в сценарии (например, нахождение следующего фрагмента выделенного текста) выполняется с помощью объекта TextRange, то полученный текстовый фрагмент необходимо преобра- зовать в этот объект, используя метод document.selection.createRangeО. Более подробно объект selection описан в главе 35. Учтите, что невозможно написать сценарий управления текстового выделения с помощью элементов пользовательского интерфейса (например кнопок). Щелчок на кнопке снимает вы- деление. Используйте другие события (такие как document. onmouseup) для выполнения действия по отношению к выделенному фрагменту. Пример Пример использования свойства selection приведен в листингах 15.30 и 15.39 (только для IE). См. также: объекты selection, TextRange. 574 Часть III. Объекты документ»
styleSheets [] Значение: массив Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Массив document. styleSheets состоит из ссылок на все элементы style, присутст- вующие в документе. Правда, к ним не относятся таблицы стилей, назначенные элементам с по- мощью атрибута style дескрипторов или связанные с помощью элементов link (см. главу 26). См. также: объект stylesheet (глава 26). tags [] Значение: массив Только для чтения Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Свойство tags используется только в NN4 в альтернативном синтаксисе таблиц стилей, ос- нованных на JavaScript. Таблицы стилей JavaScript применяются редко. В некоторых случаях свойство document. tags работает подобно методу document. getElementsByTagName () в W3C, ио document. tags ие может использоваться в обычных сценариях для обращения к объектам элементов. См. также: свойство ids. title Значение: строковое Только для чтения и Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Заголовок документа— это текст, который находится между парой дескрипторов <title>... </title> в разделе Head документа HTML. Обычно он появляется в строке заголовка однофреймового окна браузера. В многофреймовом окне браузер выводит только заголовок самого верхнего документа. Даже в этом случае для отдельного документа, находяще- гося в пределах фрейма, свойство title доступно в сценарии. Например, если доступны два фрейма (UpperFrame и LowerFrame) в сценарии документа, занимающего LowerFrame, можно обратиться к свойству title документа другого фрейма. parent-UpperFrame.document.title Это свойство предназначено только для чтения во всех более ранних версиях браузеров, чем IE4 и NN6. Свойство document - title — это “пережиток” первоначальной объектной модели до- кумента. В последних версиях браузеров HTML элементы по-разному применяют свойство title (см. главу 15). В IE4+ и NN6 заголовок документа задается непосредственно с помо- щью элемента title. См. также: объект history. URL См. location. URLUnencoded Значение: строковое Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Свойство document .URL возвращает строку URL-адреса в виде кода. Это означает, что все иебуквенные и цифровые символы в URL преобразованы в символы, соответствующие URL-адресу (например, пробел будет выглядеть как %20). Можно, конечно, применить функцию Глава 18. Объекты document и body 575
unescape О к значению, которое возвращает свойство document. URL, но зачем делазъ это вручную, если свойство URLUnencoded само выполняет эту операцию. Если в URL- адресе нет закодированных символов, то оба свойства возвращают одинаковые значения. См. также: свойство document. URL. vlinkColor См. linkCol or. width См. height. Методы captureEvents (списокСобытий) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Только в NN4 естественная обработка события начинается с объекта window (через объ- ект document) и уже после этого достигает своей цели. Например, если щелкнуть на кнопке, событие щелчка сначала поступит в объект window; затем перейдет к объекту document; если кнопка определена в пределах слоя, событие также пройдет через этот слой; в конечном счете (в доли секунды) событие достигнет кнопки, и обработчик события oncl'ick произве- дет действие, соответствующее щелчку. Структура объектной модели NN4 позволяет объектам window, document и объектам слоев перехватывать события и обрабатывать их самим (или не допускать их возникновения). Но внешнему контейнеру для перехвата события необходим соответствующий сценарий, со- держащий инструкции по перехвату определенного типа события (для предварительной об- работки его в приложении). Если возникла необходимость в перехвате всех событий опреде- ленного типа объектом document, используйте метод document. captureEvents () для осуществления данной возможности. I Перехват события с различным синтаксисом был стандартизирован в W3C DOM шгп$ и осуществлен в NN6. В главе 15 описан метод addEventListener () для W3C • и метод captureEvents () для NN4. В главе 25 также речь идет о средствах пе- рехвата события, работающих в W3C DOM. В методе document. captureEvents () указывается один или несколько типов собы- тия в качестве параметров. Тип события — это постоянное значение, которое хранится в объек- те Event, поддерживаемом NN4. Существует тип события, который подходит для любого обработчика событий (его можно встретить в объектах document (NN4)). Синтаксис пере- хвата представлен ссылкой на объект Event и именем события заглавными буквами. Напри- мер, при перехвате объектом document всех событий click выражение имеет такой вид. document.captureEvents (Event.CLICK); Для нескольких событий их указывают как параметры, разделенные символом (|). document.captureEvent s(Event.MOUSEDOWN | Event.KEYPRESS); После установки объекта document на перехват определенного типа события нужно опре- делить функцию для его обработки. Например, пусть функция просматривает все события Event. MOUSEDOWN и следит за тем, действительно ли правая кнопка мыши вызывает событие, 576 Часть III. Объекты документа
и какой элемент формы (если таковой существует) соответствует назначенной цели. Целью, на- пример, может быть вызов меню по щелчку правой кнопкой мыши (на отдельном слое). Если щелчок сделан левой кнопкой мыши, то происходит стандартная реакция на это событие. Для того чтобы связать функцию с определенным типом события, перехваченного объек- том document, назначьте ее этому событию. Например, чтобы назначить пользовательскую функцию doClickEvent О событиям click, захваченным объектом document, исполь- зуйте следующее выражение. document.onClick=doClickEvent; Заметьте, что имя функции указано только как имя ссылки, в отличие от обработчика со- бытий, находящегося в дескрипторе. Данная функция подобна любой другой, если не учиты- вать того, что она имеет дополнительную возможность автоматического получения объекта события как параметра. Чтобы отменить перехват события для одного или нескольких типов события, используйте метод documentxReleaseEvent (). Более подробно вопрос управ- ления событиями NN4 освещен в главе 25. ! Перахват событий объектами уровня window и document в NN4 не всегда про- /н> заметку исходит так, как это запланировано. Это случается особенно часто, если в стра- ' нице содержатся таблицы. Например, перехват события мыши не дает никакого результата в NN4 для Windows, если указатель не находится над границей ячей- ки. Наиболее надежно захват события работает, когда объекту в сценарии соот- ветствует определенный обработчик событий (даже если обработчик — просто пустая строка), а элемент является целью события (например, при вводе данных в текстовое поле). Для всех других элементов захват события не может быть проведен непосредственно на уровне window или document. Пример Изучите пример из листинга 16.21 для ознакомления с методом captureEvents (). В нем представлены ссылки на объекты window как ссылки на объекты document. Если вы поня- ли особенности механизма для объектов окон, то без труда сможете изучить механизм захва- та событий для документов. Подобное справедливо для всех остальных методов управления событиями в NN4. См. также: методы document.handleEvent(), document.releaseEvents(), document. routeEvent (); цараллельные методы событий объекта window. clear() Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ В любой версии, начиная с NN2, метод document. clear () предназначен для очистки текущего документа из окна браузера. Этот метод непрактичен, так как обычно требуется, чтобы после очистки документа выполнялся следующий сценарий. Если сценария нет, то, со- ответственно, ничего и не происходит. На практике метод document. clear () непредсказуем (и в более ранних версиях брау- зера это приводит к ошибкам). Вместо использования document. clear () рекомендуется сгенерировать новую страницу с помощью метода document. write (), который очищает оригинальный документ в окне перед добавлением в него нового содержимого. Если нужно действительно очистить окно или фрейм, то используйте document .write (), чтобы соз- дать пустой HTML-документ или загрузить его с сервера. См. также: методы document. close (), document, write (), document. writein (). Глава 18. Объекты document и body 577
Указатель в состоянии “ожидания” Иногда браузеры не могут восстановить нормальное состояние указателя после выполнения методов document.write () и document.close() (и некоторых других сценариев, изме- няющих содержимое окна браузера). Указатель упрямо остается в состоянии “ожидания”, при том что обработка соответствующих данных давно завершилась. Существует один, хоть и нестандартный, способ, который поможет в данной ситуации. Метод document, с lose О дополнительно вызывается в конструкции javascript:псевдо-url (простое добавление еще одного метода document. close () в сценарий ни к чему не приведет). Чтобы исполь- зовать этот способ в наборе фреймов, javascript-.url должен соответствовать вершине иерархии набора фреймов, в то время как document, с lose () выполняется по отношению к фрейму, содержимое которого изменено. Например, если был изменен фрейм с именем content, создайте функцию следующего вида. function recloseDoc() { top.location.href = ”j avascript:void (parent.content.document.close())"; } Если функция recloseDoc О запускается в многофреймовом документе, то в тех сценари- ях, в которых производится изменение содержимого фрейма, можно вызвать зту функцию после любого действия, которое препятствует нормальной работе указателя. close() Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Если рабочий поток был открыт в окне с помощью метода document. open () или лю- бого другого метода для записи документа (выполняющего эту же функцию), его следует за- крыть после создания документа. В ответ на эти действия в строке состояния появятся сооб- щения Layout:Complete и Done (хотя на некоторых платформах могут возникнуть ошибки при их отображении). Процесс закрытия документа очень важен для подготовки окна к последующей загрузке новой HTML-страницы, содержащей сценарий. Если документ ие за- крыт, следующая запись дописывается в нижней части основного документа. Некоторые или даже все данные, предназначенные для отображения в окне, не будут представлены должным образом, если не применить метод document. close (), особенно если изображения должны выводиться как часть потока документа. Основной признак по- добного поведения — это мгновенное появление, а затем исчезновение частей документа. Ес- ли подобное происходит на экране, то это значит, что после последнего вызова метода document. write () не был выполнен метод document. close (). Пример Перед использованием метода close () внимательно изучите метод document. write (), описанный далее в этой главе. После этого создайте в разных папках три отдельных докумен- та для исследования метода close () (листинги 18.16-18.18). В функции takePulse () за- комментируйте оператор с методом document. close (). msg += "<p>Make it a great day! </bodyx/html>"; parent.frames[1].document.write(msg); I/parent.f rames[1].document.close(); Отобразите страницу в браузере. Как вы видите, при каждом щелчке на верхней кнопке в верхний фрейм добавляется текст, при этом исходный текст из фрейма не удаляется. Причина состоит в том, что не закрыт предыдущий процесс. Браузер считает, что вы все еще работаете 578 Часть III. Объекты документа
с ним. Если вы не воспользуетесь свойством close (), то в последней текстовой строке мо- жет не отобразиться добавленный недавно текст. См. также: методы document. open (), document. close (), document. write (), document. writein (). createAttribute (" имяАтрибута") Возвращаемое значение: ссылка на объект атрибута Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safari 14- Метод document. createAttribute генерирует объект атрибута (формально извест- ный как объект Attr в терминологии W3C DOM) и возвращает ссылку на последний. При вызове метода указывается только имя атрибута, таким образом, в сценарии назначается зна- чение свойству nodevalue (этого объекта), а затем новый атрибут добавляется в сущест- вующий элемент с помощью метода setAttributeNode () (описанный в главе 15). Сле- дующий код генерирует атрибут, который становится принадлежным к элементу table. var newAttr = document. createAttribute("width"); newAttr.nodeValue = "80%"; document.getElementByld("myTable").setAttributeNode(newAttr); Атрибуты не всегда должны соответствовать HTML-стандарту, так как метод применим и для XML-элементов, атрибуты которых задаются пользователем. Пример Для создания атрибута и исследования его свойств в верхнее поле приложения The Evaluator введите следующее выражение. а = document.createAttribute("author") Далее используйте нижнее текстовое поле для отображения списка свойств объекта Attr. См. также: метод setAttributeNode () (глава 15). createComment (11 текстКомментария") f Возвращаемое значение: ссылка на объект комментария Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Этот метод создает экземпляр узла комментария. После создания узел будет находиться в памяти браузера; он потребует вставки в документ с помощью метода appendChild () или inSertBef ore (). createDocumentFragment () Возвращаемое значение: ссылка на фрагмент документа Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Данный метод создает экземпляр узла пустого фрагмента документа. Этот узел представ- ляет собой контейнер, в который добавляются Другие узлы документа. После создания и вставки в него всех необходимых узлов сам узел фрагмента документа можно будет вста- вить в объектную модель документа. Узел фрагмента документа особенно эффективен в случаях, когда требуется пополнить документ последовательностью новых элементов или текстовых узлов. Выступая в качестве родительского элемента, он сможет предложить все необходимые для управления другими узлами средства (например, метод appendChild ()). Если узел фрагмента документа вста- вить в объектную модель документа, то в последнюю будут встроены только содержащиеся в нем элементы, но не он сам. Глава 18. Объекты document и body 579
createElement("имяДескрилтора") Возвращаемое значение: ссылка на объект элемента Совместимость: WinIE4+, MacIE4+. NN6+, Mozl+, Safari 14- Метод document. createElement () генерирует объект элемента для любого дескрип- тора HTML (или XML), указанного в качестве параметра. Этот объект официально не являет- ся частью объектной модели текущего документа, так как в состав документа он пока еще не входит. Однако данный метод используется для вызова объекта элемента, который в конеч- ном счете будет помещен в документ. Возвращаемое значение — ссылка на объект. К свойствам этого объекта относят все ат- рибуты (значения которых установлены по умолчанию), определенные объектной моделью браузера для данного элемента. Таким образом, из сценария можно обращаться к объекту с помощью этой ссылки для задания его свойств. Обычно это осуществляется перед вставкой объекта в документ, иначе свойства, предназначенные только для чтения, могут быть измене- ны прежде, чем элемент будет вставлен в документ. После выполнения операции вставки первоначальная ссылка (например, глобальная перемен- ная, используемая для хранения значения, возвращенного с помощью метода createElement ()) все еще будет указывать на объект, даже если он находится в документе и просматривается пользователем. В следующем примере создается простой элемент абзаца, содержащий не- который текст. van newText = document.createTextNode("Four score and seven years ago..."); var newElem = document.createElement("p"); newElem.id = "newestP"; newElem.appendChild(newText); document.body.appendChild(newElem); Суть метола состоит в том, что новый абзац является видимым в документе. Чтобы изме- нить, например, стиль абзаца, обратитесь либо к элементу объектной модели document, ли- бо к переменной, которая содержит ссылку на созданный объект newElem.style.fontsize = "20pt"; или следующим образом document.GetElementByld("newestP").style.Fontsize = "20pt"; Эти две ссылки неразрывно связаны между собой и указывают на один и тот же объект. Поэтому, если нужно использовать сценарий для того, чтобы сгенерировать серию подоб- ных элементов (например, несколько LI элементов), можно воспользоваться методом createElement () для создания первого элемента и установки всех свойств, ему присущих. После этого с помощью cloneNode () создайте новую копию, а уже ее представьте как от- дельный элемент (назначьте ей собственный идентификатор). При написании сценария в среде W3C DOM (в рамках моделей, поддерживаемых IE5 и NN6) можно использовать document. createElement () для обновления содержимого страницы или ее части (если, конечно, вы не предпочитаете свойство innerHTML для добавления содер- жимого в виде строк HTML). В строгой среде W3C DOM создание новых элементов — это не способ вставки HTML-кода, а, скорее, создание подлинного объекта элемента (и текста). Пример В главе 15 приводились многочисленные примеры использования метода createElement () (см. листинги 15.10,15.21,15.22, 15,28 и 15.31). См. также: метод document. createTextNode (). 580 Часть III. Объекты документа
createEvent (" тилСобытия") Возвращаемое значение: ссылка на объект события Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Этот метод создает в W3C DOM экземпляр объекта Event указанного типа. После созда- ния объект события относится к одной из категорий событий. В соответствии с указанным типом объект приобретает набор свойств. После назначения свойств событие можно вызвать, воспользовавшись методом dispatchEvent (). В NN6+/Moz распознаются следующие типы событий: KeyEvents, MouseEvents, MutationEvents и UIEvents. Процесс инициализации события каждого типа требует ис- пользования различных параметров в методе initEvent () (см. главу 25). Пример Следующий пример демонстрирует методы создания события, его инициализации к тре- буемому типу и отправки в указанный объект. var evt = document.createEvent("MouseEvents"); evt.initEvent("mouseup", true, true); document.getElementByld("myButton").dispatchEvent(evt); См. также: метод createEventOb j ect (); объекты Event в W3C DOM (глава 25). createEventObject([объектСобытия) ] Возвращаемое значение: объект события Совместимость: WinIE5.5, MacIE-, NN-, Moz-, Safari- Метод createEventObject () используется только в Internet Explorer; он создает объект event, который можно применять как параметр в любом объекте элемента в методе f ireEvent (). Объект event, который создан этим событием, применяется подобно объек- ту event, созданному пользователем или системой. Необязательный параметр позволяет добавить в данный объект новое событие. Другими словами, свойства только что созданного объекта event аналогичны свойствам объекта, подставленного в качестве параметра. По мере необходимости эти свойства можно изменять. Если параметры в методе не указываются, то нужно задать их вручную (более подробно свойства объекта event описаны в главе 25). Пример Обратитесь к описанию метода f ireEvents () в главе 15, чтобы детальнее ознакомить- ся с использованием createEventObj ect () на практике. См. также: метод f ireEvent () (глава 15); объект event (глава 25). createRange([" URL" [, индекс] ]) Возвращаемое значение: ссылка на объект Range Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод создает пустой объект Range (W3C DOM), который имеет точечный размер и располагается перед первым символом тела документа. См. также: объект Range. Глава 18. Объекты document и body 581
createStyleSheet (["CTRL" [, индекс] ]) Возвращаемое значение: ссылка на объект stylesheet Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Метод createStyleSheet () используется (только в Internet Explorer) для создания объекта stylesheet. Он включает в себя объекты элементов style аналогично таблицам стилей, которые импортируются в документ с помощью элемента link. Таким образом мож- но динамически загрузить внешнюю таблицу стилей даже после загрузки самой страницы. Обратите внимание на то, что этот метод не работает в Мас1Е4. В отличие от других методов “создания”, используемых в W3C DOM, метод create- StyleSheet () не только создает таблицу стилей, но и вставляет объект в объектную мо- дель документа. Таким образом, любые правила таблиц стилей, установленные для данного объекта, сразу же вступают в силу. Если таблица стилей создается отдельно и отдельно под- ключается, то для выполнения первой задачи используется метод createElement (), а для второй — метод внедрения элемента в объектную модель. Если параметры не передаются в метод, создается пустой объект таблицы стилей. Подра- зумевается, что впоследствии будут использоваться методы объекта stylesheet, например, addRule () (не поддерживаемые в Мас1Е5), для добавления в таблицу стилей детальных ха- рактеристик. Чтобы связать таблицы стилей во внешнем файле, в первом параметре метода назначают URL-адрес этого файла. Вновь созданная таблица стилей добавляется в качестве последнего элемента массива document. Stylesheets объекта stylesheet. Второй па- раметр— необязательный, но он позволяет точно определить расположение в наборе эле- ментов новой вставленной таблицы стилей. Установки таблиц стилей для любого элемента переписываются при подключении в документ новой таблицы стилей для этого же элемента. Пример В листинге 18.13 приведен пример использования метода createStyleSheet () для создания внешней и внутренней таблицы стилей в документе. Для внутренней таблицы сти- лей этот метод вызывается в функции addStylel (). Созданная таблица стилей включается в элементы р страницы (не используются в Мас1Е5). Функция addStylel () управляет внешней таблицей стилей. Она состоит из следующих двух правил. h2 {font-size:20pt; color:blue} р {color:blue} Обратите внимание, что в такой структуре внутренний стиль доминирует над внешним. За исключением случаев использования только внешнего стиля, красный цвет элементов р все- гда будет подавлять синий цвет внешнего стиля. Если удалить второй аргумент метода в функции addStyle2 (), то внешний стиль будет добавляться в конец списка таблиц сти- лей. В результате доминировать будет синий цвет. Щелкая на кнопках этого документа, вы будете изменять порядок применения стилей на странице. <html> <head> <title>document.createStyleSheet() Method</title> <script type="text/javascript"> function addStylel() { var newStyle = document.createStyleSheetO; newstyle.addRule("₽", "font-size: 16pt; color:red") } 582 Часть III. Объекты документа
function addStyle2() { var newStyle = document.createStyleSheet("lstl8-13.css", 0) ; } </script> </head> <body> <hl>document.createStyleSheet() Method</hl> <hr /> <form> cinput type="button" value="Add Internal" onclick="addStylel()" />&nbsp; cinput type="button" value="Add External" onclick="addStyle2()" /> c/form> ch2>Section lc/h2> cp>Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> ch2>Section 2</h2> cp>Duis aute irure dolor in reprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseruntmollit anim id est laborum.c/p> c/body> </html> См. также: объект styleSheet (глава 26). createTextNode (" текст") Возвращаемое значение: текстовый объект Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safari 1+ Текстовый узел — это объект W3C D0M, который содержит основной текст, не принад- лежащий ни одному дескриптору HTML (или XML). Обычно он находится в элементе HTML (или XML) (как дочерний элемент). В отличие от Internet Explorer, в котором существует спе- циальное свойство innerText для изменения текста элемента, W3C DOM полагается на ие- рархию узлов документа (NN6 опередил W3C DOM, поддержав свойство innerHTML). Что- бы вставить или заменить текст внутри элемента HTML, по аналогии с W3C DOM создается текстовый узел, а затем для изменения содержимого документа используются методы роди- тельского элемента (например, appendChild О , insertBefore () и replaceChild (), описанные в главе 15). Для того чтобы сгенерировать новый текстовый узел, используйте ме- тод document.createTextNode(). Единственным параметром createTextNode () является строка, содержимое которой становится значением свойства nodeValue объекта текстового узла, возвращаемого данным методом. Также можно создать пустой текстовый узел (содержащий пустую строку) и назна- чить строку в качестве значения nodeValue. Можно изменить свойство nodeValue в сце- нарии, тем самым изменив и текст существующего элемента, но только при условии, что тек- стовый узел находится в документе (более подробно о роли текстовых узлов в W3C DOM рассказывается в главе 14). Глава 18. Объекты document и body 583
Пример В главах 14 и 15 (например, в листинге 15.21) уделено должное внимание методу create- TextNode (). Приложение The Evaluator также поможет вам разобраться в его возможно- стях. Вы можете использовать в этом приложении встроенные глобальные переменные для сохранения ссылок на только что созданные текстовые узлы. Для этого введите в верхнее текстовое поле следующее выражение. а = document.createTextNode("Hello") В области результатов будет указано, что данная операция приводит к созданию объекта. Изучим свойства полученного объекта, воспользовавшись нижним текстовым полем. В списке свойств содержатся элементы, поддерживаемые в IE5+ и W3C DOM. Последние свойства ука- зывают, что нами создан объект третьего типа с именем #text. Он пока не имеет родительских, дочерних н сестринских объектов, поскольку не включен в иерархическую структуру документа. Чтобы научится вставлять текстовый узел в объектную модель документа (абзац туР), введите в верхнее текстовое поле следующий оператор. document.getElementByld("my₽").appendChild(а) Теперь в конце простого абзаца в нижней части страницы появится слово Hello. Вы мо- жете изменить текст узла по своему усмотрению, воспользовавшись ссылкой на узел в иерар- хической структуре или глобальной переменной, назначенной ранее. document.getElementByld("my₽").lastChild.nodeValue = "Howdy" или a.nodeValue = "Howdy" См. также: метод document. createElement (). createTreeWalker(корневойУзел, фильтр, fi1terFunction, entryRefExpansion) Возвращаемое значение: ссылка на объект TreeWalker Совместимость: WinlE-, MacIE-, NN7+, Mozl.4+, Safari- Этот метод создает экземпляр объекта TreeWalker, который используется для навигации по дереву объектов документа. Первый аргумент этого метода указывает узел, используемый в документе в качестве корневого. Второй аргумент — это целочисленная константа, задающая один из встроенных фильтров. Ниже приведен список допустимых значений этого аргумента. NodeFilter.SHOW_ALL NodeFilter.SHOW_CDATA_SECTION NodeFilter.SHOW_DOCUMENT NodeFilter.SHOW_DOCUMENT_TYPE NodeFilter.SHOW_ENTITY NodeFilter.SHOW_NOTATION NodeFilter.SHOW TEXT NodeFilter.SHOW_ATTRIBUTE NodeFilter.SHOW_COMMENT NodeFilter.SHOW_DOCUMENT_FRAGMENT NodeFilter.SHOW_ELEMENT NodeFilter.SHOW_ENTITY_REFERENCE NodeFilter.SHOW_PROCESSING_INSTRUCTION Третий аргумент представляет ссылку на функцию фильтра, которая анализирует узлы де- тальнее, чем позволяет сам фильтр (заданный во втором параметре). Эта функция принимает в качестве аргумента всего один узел и возвращает целочисленное значение, основанное на следующих константах: NodeFilter.FILTER_ACCEPT, NodeFilter.FILTER_REJECT или NodeFilter. FILTER SKIP. Идея функции заключается в анализе каждого узла и воз- вращении значения, указывающего на необходимость включения или исключения его из де- рева объектов документа. Эта функция не просматривает циклически все узлы. Объект TreeWalker устроен так, что функция вызывается необходимое количество раз тогда, когда требуется проанализировать характеристику, по которой будет проводиться фильтрация. 584 Часть III. Объекты документа
Последний аргумент этого метода принимает булево значение и указывает, необходимо ли рассматривать в качестве иерархической структуры содержимое ссылки. Этот параметр используется исключительно в XML-документах. elementFromPoint (х, у) Возвращаемое значение: ссылка на элемент текстового узла Совместимость: WinIE4+, МасШ4+, NN-, Moz-, Safari- Метод elementFromPoint () используется только в Internet Explorer. Он возвращает ссылку на любой объект элемента, находящегося в точке, целочисленные координаты кото- рой определены в методе как параметры. Координатная плоскость в документе начинается с левого верхнего угла в точке (0,0). Эта плоскость может применяться в интерактивных про- ектах, в которых выполняется проверка на пересечение позиционируемых объектов и управ- ление поведением указателя мыши. Когда в одной точке оказывается несколько объектов (например, один элемент находится над другим), возвращается элемент с самым высоким значением z-индекса (уровнем распо- ложения). Позиционируемый элемент всегда “выигрывает”, если он помещается над обыч- ным элементом тела документа. Если несколько накладывающихся друг на друга позициони- руемых элементов имеют одинаковое значение z-индекса (или не имеют его вообще по умолчанию), значения координат последнего поступившего в исходный код элемента воз- вращаются и используются как общие значения. Пример В коде листинга 18.14 приведено большое количество элементов самых разных типов. Каждый из них имеет атрибут id. Обработчик onmouseover объекта document вызывает функцию, которая определяет, над каким объектом располагается указатель при возникнове- нии события. Обратите внимание на то, что координаты события сохраняются в переменных event.clientx и event. clientY. Эти координаты измеряются в той же плоскости, что и размер страницы. Как только вы наведете указатель мыши на элемент документа, его иден- тификатор отобразится на странице. Отдельные элементы (например, Ьг или tr) не занима- ют место на странице, поэтому их идентификатор вы не увидите. В рассматриваемом приме- ре элементы позиционированы в верхней части документа, чтобы вы могли изучить возможности метода elementFromPoint () по управлению перекрывающимися объекта- ми. При прокрутке документа координаты события изменяются соответствующим образом. <html> <head> <title>document.elementFromPoint() Method</title> <script type="text/javascript"> function showElemUnderneathO { var elem = document.elementFromPoint(event.clientx, event.clientY); document-getElementByld("mySpan").innerText. = elem.id; } document.onmouseover = showElemUnderneath; </script> </head> <body id="myBody"> Глава 18. Объекты document и body 585
<hl id="header"?document.elementFrom₽oint() Method«/hl? <hr id="myHR" /? <p id="instructions"?Roll the mouse around the page. The coordinates of the mouse pointer are currently atop an element<br id="myBR" /?whose ID is:"<span id="mySpan" style="font-weight:bold"?«/span?".</p> <form id="myForm"? । «input id=,,myButton" type= "button" value="Sample Button" onclick="" /?&nbsp; </form> «table border="1" id="myTable"? <tr id="trl"? <td id="td_Al"?Cell Al«/td? <td id="td_Bl"?Cell Bl«/td? </tr? <tr id="tr2"? <td id="td_A2"?Cell A2«/td? <td id="td_B2"?Cell B2«/td? </tr? </table? <h2 id="secl"?Section l</h2? <p id="pl"?Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p? <h2 id="sec2"?Section 2</h2? <p id="p2"?Duis aute irure dolor in reprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseruntmollit anim id est laborum.</p? <div id="myDIV" style="position:absolute; top:340; left:300; background-color:yellow"? Here is a positioned element. </div? «/body? «/html? См. также: свойства event.clientX, event.clientY; позиционируемые объекты (глава 39). execCommand (11 имяКоманды" [, флаг] [, параметр]) Возвращаемое значение: булево Совместимость: WinIE4+, МасЕ-, NN7.1, Moz 1.4, Safari- В Ш4+ содержится большой набор команд, которые не входят в состав методов, опреде- ленных для объектов в объектной модели. Эти команды доступны для программистов, кото- рые используют элементы управления ActiveX в Internet Explorer для выполнения задач в приложениях. Метод execCommand () (не поддерживаемый в МасЕ5) — это способ об- ращения JavaScript к этим командам. Серии связанных методов (queryCommandEnableO и другие) также облегчают управление этими командами. Синтаксис для метода execCommand () требует, по крайней мере, одного параметра— имя команды в строковом формате. В именах команд регистр не учитывается. Второй параметр 586 Часть III. Объекты документа
необязателен — это булев флаг, определяющий, следует ли отображать в интерфейсе сделан- ные пользователем изменения, которые вызваны данной командой. По умолчанию устанав- ливается значение— false. Некоторые команды нуждаются в третьем параметре и ждут получения его значения для дальнейшей работы. Например, чтобы установить размер шрифта для текста, применяется следующий синтаксис. myRange. execCommand (" Font Si ze " , true, 5) ; Метод execCommand () возвращает булево значение true, если команда выполнена ус- пешно; false, если безуспешно, и undefined— в Мас1Е5. Некоторые команды могут воз- вращать другие значения (например при выборе имени шрифта), но к ним необходимо обра- щаться с помощью метода queryCommandValue (). Большинство таких команд форматирует текст тела документа, заданный в объекте TextRange. Объект TextRange необходимо создавать исключительно в сценарии (см. гла- ву 35), хотя объект также будет создан в случае выделения пользователем текста в документе. Так как данный объект не зависит от иерархии элементов (действительно, TextRange может генерироваться во многих узлах), он не соответствует спецификации таблиц стилей. Таким об- разом, многие команды, которые изменяют объект TextRange, должны выполнять формати- рование или изменять текст. Список команд, которые выполняются исключительно для объек- тов TextRange, приведен в главе 35 (описание метода TextRange. execCommand ()). Многие команды, предназначенные для управления объектом TextRange, также выпол- няются из объекта document, однако в данном разделе внимание сосредоточено на тех ко- мандах, которые применяются ко всему документу. В табл. 18.3 приведен список этих ко- манд. Кроме того, будут перечислены команды, управляющие исключительно текстовыми фрагментами в документе (независимо от того, приведено изменение пользователем вручную или с помощью объекта TextRange (см. главу 35)). Команда Параметр Описание Refresh Нет Перезагрузка страницы SelectAII Нет Выделение всего содержимого страницы Unselect Нет Отмена любого выделения на странице BackColor Строковое значение цвета Заключение выделенного фрагмента в дескриптор font, с помощью атрибута style которого задается параметр background-color CreateBookmark Строковое значение анкера Заключение выделенного фрагмента (или текстового диапазона) в элемент анкера, атрибут name которого приобретает значение параметра CreateLink Строковое значение URL-адреса Заключение выделенного фрагмента в элемент а, атрибут href которого установлен в значение параметра FontName Название шрифта Заключение выделенного фрагмента в элемент font, атрибут face которого установлен в значение параметра Fontsize Строковое значение размера шрифта Заключение выделенного фрагмента в элемент font, атрибут size которого установлен в значение параметра FontColor Строковое значение цвета Заключение выделенного фрагмента в элемент font, атрибут color которого установлен в значение параметра Indent Нет Занесение в буфер выделенного фрагмента Глава 18. Объекты document и body 587
Окончание табл. 18.3 Команда Параметр Описание JustifyCenter Нет Выравнивание выделенного фрагмента по центру JustifyFull Нет Выравнивание выделенного фрагмента по ширине JustifyLeft Нет Выравнивание выделенного фрагмента по левому краю JustifyRight Нет Выравнивание выделенного фрагмента по правому краю Outdent Нет Удаление выделенного фрагмента RemoveFormat Нет Удаление форматирования для выделенного фрагмента SelectAll Нет Выделение всего текста в документе UnBookmark Нет Удаление анкерных дескрипторов, содержащихся в выделенном фрагменте Unlink Нет Удаление дескрипторов ссылок, содержащихся в выделенном фрагменте Unselect Нет Снятие выделения с любого фрагмента в документе Mozilla 1.4 поддерживает возможность преобразования объекта документа элемента iframe в редактируемый HTML-документ. Метод document. execCommand () — это часть данной технологии. Пример Примеры использования метода execCommand () для объекта textRahges приведены в главе 35. В настоящий момент вы можете воспользоваться для изучения этого метода при- ложением The Evaluator. Поочередно введите каждое из приведенных ниже выражений в верх- нее текстовое поле приложения. document.execCommand("Refresh") document. execCommand (" SelectAl 1") document.execCommand("Unselect") См. также: методы gueryCommandEnabled(), gueryCommandlndterm(), gueryCommandState(), gueryCommandSupported(), gueryCommandText(>, gueryCommandValue(). getElementByld ("идентификаторЭлемента") Возвращаемое значение: ссылка на элемент Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Метод document.getElementByld() относится к синтаксису W3C DOM и применя- ется для задания ссылок на любой элемент в документе, который имеет уникальный иденти- фикатор, назначенный атрибуту id. Если документ содержит более одного экземпляра ука- занного идентификатора, метод возвращает ссылку на первый элемент в исходном коде с соответствующим id. Так как данный метод используется для записи ссылок на объекты, которые должны быть изменены при управлении сценарием, то можно только предположить, насколько важно на- значить элементам уникальные ID. Имя этого метода вводит программистов в заблуждение, особенно если принять во внимание, что в IE4+ ссылка на любой элемент должна начинаться с идентификатора объекта. Но пока в NN6 не будет проведена нормализации массива document. all, метод getElementByld () 588 Часть Ш. Объекты документа
будет использоваться как способ задания ссылок на элементы в браузерах IE5+ и NN6+. При работе с данным методом убедитесь в том, что последний символ в имени этого метода (d) введен в нижнем регистре. В отличие от других, управляющих элементами методов (например, getElementsBy- TagName ()), которые могут быть вызваны в любом элементе документа, getElementByld () метод выполняется исключительно для объекта document. Пример Далее вы ознакомитесь со многими примерами использования метода getElementByld (). Вы всегда можете применить для его изучения приложение The Evaluator. В документе этого приложения многие элементы имеют идентификаторы. Введите приведенные ниже операто- ры как в верхнее, так и в нижнее текстовые поля. Результат их выполнения в верхнем поле представлен ссылками на объекты. Результат выполнения этих выражений в нижнем поле со- стоит из списка свойств. document.getElementByld("myP") document.getElementByld("myEM") document.getElementByld("myTitle") document.getElementByld("myScript") См. также: метод getElementsByTagName () (глава 15). getElementsByName("имяЭлемента") Возвращаемое значение: массив Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Метод document. GetElementsByName () возвращает массив ссылок на объекты, ат- рибут Name которых определяет имя элемента и передается как параметр метода. В NN6 ат- рибуты Name используются даже для элементов, которые не имеют их по умолчанию; в IE5+ этого не происходит. Поэтому для максимальной совместимости документов с браузерами применяйте этот метод только для элементов, имеющих атрибуты Name, определенные для них по умолчанию (например элементы управления форм). Если элемент не существует в до- кументе, метод возвращает массив нулевой длины. В большинстве случаев рекомендуется использовать идентификаторы элементов и метод getElementByld () для задания ссылок на отдельные объекты. Но некоторые элементы, осо- бенно элемент input типа “переключатель”, используют атрибут Name для того, чтобы собрать элементы в одну группу. В этом случае выполнение метода getElementsByName О возвра- щает массив всех элементов, которые совместно используют одно имя. В результате упроща- ется цикл for, в котором проверяется свойство checked группы переключателей. Таким образом, вместо использования старомодной (хотя и полностью совместимой) ссылки с ука- занием формы объекта var buttonGroup = document.forms[0].radioGroupName; можно задать прямую ссылку на имя элемента var buttonGroup = document.getElementsByName(radioGroupName); В последнем случае операция выполняется независимо от номера или имени имеющейся формы объекта. Конечно, подразумевается, что имя группы переключателей на текущей странице нигде больше не используется. Глава 18. Объекты document и body 589
Пример Приложение The Evaluator позволяет ознакомиться и с методом getElementByNmae (). Все элементы управления формы, представленной в верхней части страницы, имеют имена. Введите в верхнее текстовое поле следующие выражения. document. getElementsByNafne ("output") document.getElementsByName("speed").length document.getElementsByName("speed")[0].value Введя приведенный далее оператор в нижнее поле, вы исследуете все свойства текстового поля. document.getElementsByName("speed") [0] См. также: методы document. getElementsByld (), getElementsByTagName (). getSelectlon() Возвращаемое значение: строковое Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Многие пользователи Web-браузеров даже и не подозревают о том, что могут сами выде- лять, копировать и вставлять в другие прикладные документы основной текст страницы. Для данной возможности в NN4+ предлагается способ сохранения текста, выделенного пользова- телем на странице, с помощью сценария. Метод document .GetSelection () возвращает строку текста, выделенного пользователем. Если документ не содержит выделенного текста, то возвращаемым результатом является пустая строка. Возвращенные значения состоят толь- ко из текста, отображаемого на странице в браузере, а не основного HTML-текста. В IE4+ также представлена подобная возможность. Для этого используется свойство document. selection, которое возвращает объект selection в Internet Explorer (в Мас1Е5 не поддерживается). Для получения текста, содержащегося в selection, нужно создать в нем объект TextRange, а затем просмотреть свойство text. var selectedText = document.selection.createRange().text; Пример В листинге 18.15 приведено межбраузерное приложение (не реализуется только в Мас1Е5), позволяющее захватить текст, выделенный пользователем на странице. Выделенный текст вы- водится сценарием в текстовой области. В сценарии выполняется проверка используемого брау- зера, и на основе полученного результата распознаются события выделения текста. <html> <head> ' <title>Getting Selected Text</title> <script type="text/javascript"> var isNav4 = (navigator.appName == "Netscape" && parselnt(navigator.appVersion) == 4); var isNav4Min = (navigator.appName == "Netscape" && parselnt(navigator.appVersion) >= 4); var isIE4Min = (navigator.appName.indexOf("Microsoft") 1= -1 && parselnt(navigator.appVersion) >= 4); function showSelectionO { if (isNav4Min) { document.forms[0].selectedText.value = 590 Часть III. Объекты документа
document.getSelection(); } else if (isIE4Min) { if (document.selection) { document.forms[0].selectedText.value = document. selection. createRange ()*. text ; event.cancelBubble = true; } } } if (isNav4) { document.captureEvents(Event.MOUSEUP); } document.onmouseup = showselection; </script> </head> <body> <hl>Getting Selected Text</hl> <hr /> <p>Select some text and see how JavaScript can capture the selection:</p> <h2>ARTICLE Ic/h2> <p>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.</p> <form> ctextarea name="selectedText" rows="3" cols="40" wrap="virtual"> </textarea> </form> </body> </html> См. также: свойство document. selection. handleEvent(событие) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- B NN4 при явном перехвате события объектами window, document или слоя (в резуль- тате вызова метода captureEvents () для этого объекта) можно контролировать располо- жение событий после их первоначального использования. Чтобы перемещение события к первоначальной цели было продолжено (например, кнопка нажата пользователем), исполь- зуется метод routeEvent (). Но если нужно переадресовать одно событие (или целый класс) в определенный обработчик событий, находящийся в другой части документа, исполь- зуйте метод handleEvent(). Более подробно метод handleEvent () для объекта window был описан в главе 16. Этот метод для всех объектов работает одинаково. См. также: методы document. captureEvents О , document. releaseEvents О , document. routeEvent (); объект event (глава 25). Глава 18. Объекты document и body 591
open ([11 TjaiMime " ] [, замена]) Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Процесс открытия документа отличается от процесса открытия окна. При открытии окна соз- дается новый объект и на экране, и в памяти браузера. С другой стороны, при открытии документа браузер готовится принять данные для дальнейшего отображения их в окне, названном или ука- занном в методе document. open (). (Например, parent. frames [1] . document. open () может обращаться к разным фреймам одного набора, принимая во внимание, что document. open () подразумевает текущее окно или фрейм.) Поэтому имя метода может вводить в заблуждение начинающих разработчиков, так как метод document. open () не име- ет никакого отношения к загрузке документов с Web-сервера или жесткого диска. Этот метод является “прелюдией” к отправке данных в окно с помощью методов document. write () или document.writeln(). В некотором смысле, метод document.open() просто открывает канал, а другие методы пересылают поток данных по этому каналу; метод document. close () закрывает этот канал, когда данные страницы полностью отправлены. Метод document. open () использовать необязательно, так как document. write () при записи данных в закрытый документ автоматически очищает старый документ и открывает по- ток. Независимо от того, использовался ли метод document. open (), убедитесь в том, что вы- полнены все нужные операции записи; только после этого используйте document. close (). В методе document. open () существует необязательный параметр, который позволяет определить тип данных, передаваемых в окно. Тип MIME является спецификацией для пере- дачи и представления мультимедийных данных в Internet (первоначально применялся для пе- редачи почтовых сообщений, а теперь — для любого обмена данными в Internet). В парамет- рах настройки свойств браузера есть описание типов MIME. Тип MIME представлен двумя элементами, разделенными символом косой черты (например, text/html или image/gif). При определении типа MIME как параметра метода document. open () необходимо опре- делить в браузере соответствующий тип получаемых им данных как обрабатываемый. Ниже приведены общие значения, которые принимаются большинством браузеров. text/html; text/plain; image/gif; image/jpeg; image/xbm; Если данный параметр не указан, JavaScript выбирает наиболее часто используемый тип text/html, который обычно указывают в сценарии перед записью данных в окно. Тип text/html представляет любые изображения, ссылки на которые содержит HTML- документ. Определение произвольного типа изображения означает наличие необработанного двоичного представления изображения, которое должно появиться в новом документе. Существует еще одна возможность, с помощью которой можно направлять содержимое метода write () на выполнение в надстройке. В параметре mimeType укажите тип MIME- надстройки (например application/x-director для Shockwave). В следующий раз за- пись данных в эту надстройку будет выполняться автоматически. Указанный метод также применим и для записи данных в приложение справочной системы. ] В IE принимается только параметр типа MIME text/html. 592 Часть III. Объекты документа
В NN4+ и IE5+ задается второй необязательный параметр метода: замена. С помощью этого параметра метод document. open () выполняет операции, подобные тем, которые производятся для объекта location в методе replace (). Для document. open () это оз- начает, что новый документ, который должен быть помещен в окно или фрейм, заменяет пре- дыдущий документ, находящийся в списке посещенных страниц этого окна или фрейма. Пример Пример использования open () приведен в листинге динамического создания содержи- мого другого фрейма (см. описание метода document. write () далее в этой главе). См. также: методы document .close (), document.clear (), document. write (), document.writein(). queryCommandEnabled ("имяКоманды") queryCommandlndterm (" имяКоманды") queryCommandConunandState ("имяКоманды") queryCommandSupported("имяКоманды") queryCommandText ("имяКоманды”) queryCommandValue ("имяКоманды") Возвращаемое значение: любое Совместимость: WinIE4+, MacIE-, NN7.1, Mozl.4, Safari- Перечисленные шесть методов выполняются совместно с методом execCommand () для объектов TextRange и document. При выборе метода execCommand (} для выполнения стилистического форматирования текста можно использовать некоторые из этих методов за- просов, чтобы удостовериться в том, что браузер поддерживает нужную команду, и получить любые возвращаемые значения. В табл. 18.4 описано предназначение и приведены возвра- щаемые каждым из методов значения. ПОД 18.4. Кфл* .... - р»--. .. -* • -- .t'r -М./3 L J r~. Запрашиваемая команда Возвращаемое значение Описание Enabled Булево значение Определяет, находятся ли объекты document, TextRange в приемлемом для вызова состоянии Indterm Булево значение Определяет, находится ли команда в приемлемом для вызова состоянии Commandstate Булево значение|пи11 Определяет, завершено ли выполнение команды (true), процесс все еще идет (false) или данная команда находится в неопределенном состоянии Supported Булево значение Определяет, поддерживается ли команда в текущем браузере Text Строковое значение Возвращает любой текст, поддерживаемый данной командой Value Любые значения Определяет, возвращено ли командой значение (если таковое существует) Глава 18. Объекты document и body 593
По причине того, что метод execCommand () нельзя вызвать на странице во время ее за- грузки, перед запуском команды любые подобные обращения должны проверяться с помо- щью метода queryCommandEnabled (). Следует также проверить, поддерживает ли сцена- рий, запускаемый в данной версии браузера, нужную команду (особенно для команд, появившихся в IE4+). Таким образом, можно анализировать любую команду, вызвав ее с по- мощью следующего выражения. if (queryCommandEnabled(имяКоманцы)&& queryCommandSupported(имяКоманцы)) { ... } Для получения сведений о выделенном тексте используйте методы queryCommandText() или queryCommandValue () (заметьте, что в методе execCommand (), независимо от того, какая команда вызвана, возвращается булево значение). Пример Пример использования методов queryCommandEnabled (), queryCommandlndterm (), queryCommandCommandState(), queryCommandSupported(), queryCommandText(), queryCommandValue () приведен в главе 35, посвященной объекту TextRange. См. также: объект TextRange (глава 35); метод execCommand (). recalc([флаг]) Возвращаемое значение: отсутствует Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- BIE5 представлена концепция динамических свойств. С помощью метода setExpression () для всех элементов и значений таблицы стилей expression () можно установить зависимо- сти между свойствами объектов и потенциально динамическими свойствами — размером ок- на или расположением перетаскиваемого элемента. После установки этих зависимостей ме- тод document. recalc () заставит обновить зависимости в ответ на действие пользователя (например, на изменение размеров окна или перемещение элемента). Единственный необязательный параметр имеет булев тип данных. По умолчанию уста- новлено значение false. Это означает, что обновление выполняется только для выражений, в которых браузер обнаружил изменения, произошедшие со времени последнего обновления. Однако, если указывается значение true, обновляются все выражения, независимо от того, изменились они или нет. Mozilla 1.4 поддерживает возможность преобразования объекта документа элемента iframe в редактируемый HTML-документ. Метод document. execCommand () — это часть данной технологии. Пример Пример использования метода recalc () приведен в листинге 15.32 при описании мето- да setExpression(). В данном примере устанавливается зависимость между текущим временем и свойствами стандартных элементов. См. также: методы getExpressionO, removeExpressionO, setExpression() (глава 15). releaseEvents (списокСобытий) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- 594 Часть III. Объекты документа
Если при выполнении сценариев в NN4 проводится перехват события объектом document (window или слоя), то эту операцию можно отменить с помощью метода releaseEvents (). Такой метод фактически не препятствует событию по достижению поставленной цели. Отме- нив перехват событий объектами высокого уровня, вы больше не сможете заставить эти объек- ты ожидать генерирования событий в документе. Пример В главе 16 описывается метод releaseEvents () для объекта window. Данный метод одинаково работает для всех объектов. См. также: методы document. captureEvents (), document. rout eEvent (). routeEvent (событие) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Если в NN4 осуществляется перехват события в объектах слоя, window или document (с помощью соответствующих методов captureEvents ()), назначенный обработчик со- бытий действительно перехватывает те события, на которые он настроен, не позволяя им достичь поставленной цели. Для некоторых страниц этот перехват осуществляется намерен- но, чтобы позволить объекту более высокого уровня обработать все события определенного типа. Но если цель состоит в том, чтобы выполнить предварительную обработку событий пе- ред тем, как они достигнут своего адресата, используйте способ передачи этого события по обычному пути — собственно для этого и нужен метод routeEvent (). Пример Более подробно метод routeEvent () для объекта window описан в главе 16. Данный метод одинаково работает для всех объектов. См. также: методы document. captureEvents (), document. releaseEvents (). write("строка!" [,"строка2"...[, "строкап"] ]) writein("строка!" [,"строка2"... [, "capoкап"] ]) Возвращаемое значение: при удачном выполнении — булево true Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Оба метода пересылают текст документу для дальнейшего его вывода в окне. Единствен- ное различие между этими методами состоит в том, что document. writein () добавляет в конце каждой строки документа невидимый символ перехода на другую строку. Этот пере- ход нужен для форматирования исходного кода при просмотре его в окне браузера. В отком- пилированном HTML-документе, который генерируется этими методами, для перехода на но- вую строку используется дескриптор <Ьг>, который определяет конец данной строки. Как правило, многие начинающие JavaScript-разработчики делают ошибочное заключение о том, что данные методы позволяют изменять содержимое любого существующего документа с помощью сценариев, но это совсем не так. После полной загрузки документа в окно (или фрейм) единственный совместимый (с браузером) текст, который можно изменять без перезагрузки или перезаписи всей страницы,— это, собственно, текст страницы и объектов text area. В IE4+ код HTML и текст можно изменять с помощью следующих свойств: innerHTML, innerText, outerHTML и outerText, которые задаются для любого элемента. В NN6 и IE5+ допускается Глава 18. Объекты document и body 595
изменять текст элемента, устанавливая его свойства nodeValue или innerHTML; строгое соблю- дение правил в W3C DOM требует создания, вставки, а также замены элементов (см. главу 15). Приведем два наиболее безопасных способа использования методов document .write () и document.writein(): сгенерировать часть или все содержимое страницы с помощью встроенных в до- кумент сценариев; отправить HTML-код либо в новое окно, либо в отдельный фрейм многофреймового окна. В первом случае отдельные части сценария задаются непосредственно в HTML-документе. Сценарии выполняются при загрузке документа, записывая любой нужный HTML-код (эта опе- рация подобна той, которая была представлена в script 1. htm — глава 3). С помощью этого способа можно сгенерировать HTML-страницу, предназначенную для определенного типа браузе- ров, однако при этом помните, что для браузера нужно использовать специфический синтаксис. Во втором случае сценарий может запрашивать у пользователя информацию в одном фрей- ме, а затем в пределах иерархической структуры задавать размещение и результат преобразова- ния этой информации в другом фрейме. Сценарий вызывает HTML-код последнего как строко- вую переменную (включая все необходимые дескрипторы HTML). Прежде чем во фрейм будет записана какая-либо информация из сценария, с помощью этого же сценария необходимо от- крыть поток (чтобы закрыть текущий открытый документ в этом фрейме), используя метод parent. f rameName. document. open (). Метод parent. f rameName. document. write () добавит полную строку в другой фрейм. И наконец, использование метода parents. f rame- Name . document. close () гарантирует запись в текущее окно полного потока данных. Та- кой созданный в памяти фрейм внешне ничем не отличается от фрейма, который создан те- кущим документом, находящимся на сервере. Объект document отдельного окна или фрей- ма является таким же полноправным, как и стандартный объект document. Поэтому во временную HTML-страницу можно совершенно спокойно включать сценарии как часть опре- деленного HTML-документа. Вызов HTML-документа в сценарии для дальнейшей его записи с помощью метода document .write () часто требует навыка в конкатенации строковых значений и совмеще- нии вложенных строк. Некоторые быстрые методы управления строковыми объектами в JavaS- cript облегчают форматирование текста в дескрипторах HTML (см. главу 27). При записи в различные фреймы или окна можно использовать метод document. write () довольно часто. В определенной степени от сложившейся ситуации, а также от стиля програм- мирования зависит, будет ли сценарий отправлять в документ короткие строки, многократно используя document .write () метод, или он вызовет большую строку с помощью одной ко- манды. С профессиональной точки зрения, чем больше проведено предварительных действий в памяти и чем меньше осуществлено запросов ввода/вывода, тем лучше. С другой стороны, по- явление ошибки более вероятно при объединении строк в одну более длинную строку. Я пред- почитаю использовать длинные строки, вы можете руководствоваться личными предпочтениями. Далее мы рассмотрим еще один малоизвестный способ передачи параметров в данный метод. Вместо объединения строковых значений с помощью оператора объединения (+), можно также записать значения, разделив их запятыми. Например, оба следующих выраже- ния приводят к одинаковым результатам. document .write ("Today is " + new DateO); document .write ("Today is ", new DateO); И вновь повторим, что не существует универсальной формы объединения строковых дан- ных, поэтому вы должны использовать тот способ, который больше подходит для избранного стиля программирования. 596 Часть III. Объекты документа
! Генерируемые динамически сценарии требуют дополнительных эксклюзивных /на заметку методов, особенно в NN. Часто проблема возникает в том случае, когда исполь- • зуется следующий код: document.write("<script></script>"). Браузер интерпретирует закрывающий дескриптор сценария как конец сценария, с помо- щью которого производится запись нового документа. Вам необходимо “обмануть” браузер, разместив закрывающий дескриптор в отдельной строке. Старайтесь не использовать символ обратной косой черты. Например, если не- обходимо загрузить различные файлы . js для каждого типа браузеров, код представьте следующим образом. // Переменная 'browserVer1 — строка, используемая только // в браузерах, // a 'page' — HTML-документ, для которого вызывается сценарий page += "<script type='text/javascript' src='" + browseVer + ".js'x" + "\/script>"; Использование методов document. open (), document. write () и document. close () для вывода на экран изображений, содержащихся в документе, требует некоторых дополни- тельных операций. Во-первых, любые URL-адреса, указанные в document .write (), долж- ны быть полными (не относительными) ссылками URL (особенно для пользователей NN2). Альтернативным способом является задание дескриптора <base> для динамически сгенери- рованной страницы (значение его атрибута href должно соответствовать тому файлу, в ко- торый записывается страница). Еще один способ— указать атрибуты height и width для каждого изображения, со- держащегося в сценарии или другой части документа. С помощью этих значений браузер располагает элементы на странице перед их загрузкой. ' Далее приведены примеры использования document. write () (см. листинги 18.16-18.18); однако более полное описание этого метода, предназначенного для отображения изображе- ний и диаграмм, можно найти в приложениях глав 48-57. Известно, что любой существую- щий HTML-документ можно вызвать как строку, которая будет записана в окно или фрейм, ' поэтому настроенный непрерывный документ может быть настолько сложным, насколько во- обще можно себе вообразить документ HTML. Пример Пример использования методов write () и writein () приведен в листингах 18.16-18.18. С их помощью данные добавляются в другой фрейм. Вы можете ввести в этот фрейм любой HTML-код — браузер воспринимает его как исходный код документа фрейма, сохраненный в файле. В данном примере таким образом введены все HTML-дескрипторы документа. <html> <head> <title>Writin' to the doc</title> </head> <frameset rows="50%,50%"> <frame name="Framel" src="lstl8-17.htm" /> <frame name="Frame2" src="lstl8-18.htm" /> </frameset> </html> Глава 18. Объекты document и body 597
<html> <head> <title>Document Write Controller</title> <script type="text/javascript"> function takePulse(form) { var msg = "<htmlxheadxtitle>On The Fly with " + form.yourName. value + "<\/titlex\/head>"; msg += "«body bgcolor=1 salmon'><hl>Good Day " + form.yourName.value + " !<\/hlxhr />"; for (var i = 0; i < form.how.length; i++) { if (form.how[i].checked) { msg += form.how[i].value; . break; msg += "<br />Make it a great day!<\/bodyx\/html>"; parent.Frame2.document.write(msg); parent.Frame2.document.close(); } function getTitleO { alert ("Lower frame document .title is now:" + parent.Frame2.document.title); } </script> </head> <body> Fill in a name, and select how that person feels today. Then click "Write To Below" to see the results in the bottom frame. <form> Enter your first namexinput type="text" name="yourName" value="Dave” /> <p>How are you today? <input type="radio" name="how" value="I hope that feeling continues forever." checked="checked" />Swell <input type="radio" name="how" value="You may be on your way to feeling Swell" /> Pretty Good<input type="radio" name="how" value="Things can only get better from here." />So-So</p> <pxinput type= "button" pame="enter" value= "Write To Below" onclick="takePulse (this. form) " /x/p> <hr /> <input type="button" name="peek" value="Check Lower Frame Title" onclick="getTitle()" /> </form> </body> </html> <html> <head> <title>Placeholder</title> </head> <body> </body> </htjpl> 598 Часть III. Объекты документа
Важно понимать, что содержимое документа зависит от заданных пользователем настро- ек. Установить эти параметры могут только опытные пользователи, которые знакомы с рабо- той CGI-программ. Еще один момент, на котором следует акцентировать внимание, связан с документом, расположенным в отдельном фрейме. В рассматриваемом приложении данные изменяются динамически. Например, дескриптор <title> записываемого документа изменяется, если его заново отобразить с другим именем в верхнем текстовом поле. Если щелкнуть на нижней кноп- ке после обновления нижнего фрейма, то можно заметить, что свойство document. title из- меняется, чтобы отобразить изменение в дескрипторе <title>. Вы можете легко изменить листинг 18.17 так, чтобы результат сохранялся в том же фрей- ме, в котором располагается поле и кнопка. Вместо следующих операторов parent.frames[1]- document.open() parent.frames[1].document.write(msg) parent.frames[1].document.close() используйте такие выражения. document.open() document.write(msg) document.close() Как видите, в данном случае фреймы не используются вообще — они попросту не нужны. Поскольку все содержимое документа сохраняется в одной переменной, то для вывода его в документе достаточно использовать всего один оператор document. write (). Документ набора фреймов (листинг 18.16) создает новый фрейм в результате загрузки пустого документа (листинг 18.18). Рекомендуем сначала создать фрейм, а затем загрузить в него пустой документ (см. главу 16). См. также: методы document. open (), document. close (), document. clear (). Обработчики событий ons e1ectionchange Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Событие onselect ionchange может быть вызвано многими действиями пользователя, хотя все эти действия происходят с элементами, которые находятся в WinIE5.5 в режиме ре- дактирования. См. также: обработчик события oncontrolselect. onstop Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Событие onstop возникает в IE5 при щелчке пользователя на кнопке Stop в браузере. Ис- пользуйте этот обработчик события для остановки потенциально неконтролируемого сценария на странице, так как кнопка Stop не позволяет управлять сценариями после загрузки страницы. Если у вас возникает проблема потери контроля над циклом во время его работы, можно вре- менно использовать этот обработчик события, чтобы приостановить сценарий для отладки. Пример Листинг 18.19 представляет пример использования обработчика onstop. Если вы загру- зите эту страницу в браузере IE5+, то сможете воспользоваться кнопкой Halt Counter для ос- тановки цикла. Эта кнопка и обработчик onstop вызывают одну и ту же функцию. Глава 18. Объекты document и body 599
«html> <head> <title>onStop Event Handler«/title> «script type="text/javascript"> var counter = 0,- var timer ID function startcounter() { document.forms[0].display.value = ++counter; //clearTimeout(timerlD) timerlD = setTimeout("startcounter()", 10); } function haltcounter() { clearTimeout(timerlD); counter = 0; } document.onstop = haltcounter; </script> </head> <body> <hl>onStop Event Handler</hl> «hr / > «p>Click the browser's Stop button (in IE) to stop the script counter.</p> <form> «pxinput type="text" name = "display" />«/p> «input type="button" value="Start Counter" onclick="startcounter()" /> «input type="button" value="Halt Counter" onclick="haltCounter()" /> «/form> «/body> «/html> См. также: циклы (глава 31). Элемент body Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойства, методы и обработчики событий этого HTML-элемента описаны в главе 15. Свойства Методы Обработчики событий al ink createControlRange() onafterprint background createTextRange() onbeforeprint bgColor bgProperties bottomMargin leftMargin doScroll() onscrol1 600 Часть III. Объекты документа
Окончание таблицы Свойства Методы Обработчики событий link noWrap rightMargin scroll scrollLeft scrollTop text topMargin vLink Синтаксис Доступ к свойствам и методам объекта элемента body. [window.]document.body.свойство|метод[параметры] ) Описание объекта В объектных моделях, в которых отображаются объекты элементов HTML, элемент body используется для хранения основного содержимого страницы, представляемой посетителям. Элемент body содержит весь обрабатываемый код HTML. Объект body занимает особое ме- сто в иерархии элементов, которое предполагает и некоторые особые возможности. В наи- большей степени это относится к объектной модели в Internet Explorer. Если говорить о поддержке этого объекта браузерами, то следует отметить, что и в Inter- net Explorer, и в W3C элемент body вызывается одной и той же ссылкой: document. body. Однако данный объект является объектом элемента HTML первого уровня (как указано в списке свойств, методов и обработчиков событий, приведенном в главе 15), поэтому для доступа к элементу body можно использовать любой другой синтаксис. Пользователь, конечно, знаком с некоторыми атрибутами элемента body, которые управ- ляют отображением его содержимого на странице: это цвета состояний ссылок и параметр фона (цвет или изображение). Но при создании сценариев в документах Internet Explorer и Netscape Navigator (и пока W3C) данный элемент играет разные роли. Многие методы и свойства, которые используются в Netscape Navigator как отдельные объекты, предназна- ченные для представления средств управления окном (например, полосы прокрутки и т.д.), в Internet Explorer рассматриваются исключительно как свойства и методы элемента body. Поэтому при использовании одной и той же команды в Netscape Navigator прокручивается все окно (и соответственно, все его содержимое), а в Internet Explorer— только тело про- граммы (в том окне, в котором оно расположено). По причине того, что элемент body за- полняет всю просматриваемую область окна браузера или фрейма, размер этой области определяется в Internet Explorer свойствами scrollHeight и scrollwidth, а в NN4+ — window. innerHeight и window. inherWidth. Важно учесть это различие при опреде- лении в сценарии размеров выводимого окна или документа, поскольку вам, возможно, при- дется указывать соответствующие свойства и методы для объекта window, а также для эле- мента body (в зависимости от используемого браузера(ов)). Глава 18. Объекты document и body 601
'На замод Будьте осторожны при доступе к объекту document.body во время загрузки страницы. Пока страница полностью не загружена, объект официально не суще- ствует. Если необходимо установить некоторые начальные свойства в сценарии, сделайте это с помощью обработчика событий onload, расположенного в деск- рипторе <body>. Попытки установить свойства объекта элемента body непо- средственно в сценарии (в элементе head) могут привести к сообщениям об ошибке в процессе поиска данного объекта. Свойства aLink bgColor link text vLink Значение: шестнадцатеричный числовой триплет или название цвета Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойства aLink, link, vLink представляют собой новые версии свойств alinkColor, linkcolor и vlinkColor объекта document. Свойство bgColor является аналогом ста- рого свойства document .bgColor, a text— document. fgColor. Эти новые свойст- ва — эквиваленты HTML-атрибутов для элемента body. Их новые названия соответствуют атрибутам HTML в большей степени, чем старые. Обращение к цветам ссылок, установленных с помощью псевдоатрибутов в таблицах сти- лей (они представляют атрибуты style элемента body) производится в свойстве style объекта body. Вскоре это свойство, вероятно, перестанет применяться, поскольку таблицы стилей становятся все более популярными. Пример Вы можете изменить листинги 18.1 для использования его в IE44-, NN64-/Mozl47W3C. За- мените все ссылки на объект document ссылками на объект document. body. Пример ис- пользования aLink, bgColor, link, text, vLink приведен на прилагаемом к книге ком- пакт-диске. Например, одна из функций будет обновлена следующим образом. function showColorValues() { var result = ""; result += "bgColor: " + newWindow.document.body.bgColor + "\n"; result += "vLink: " + newWindow.document.body.vLink + "\n"; result += "link: " + newWindow.document.body.link + "\n"; document.forms[0].results.value = result; } См. также: document.alinkColor, document.bgColor, document.fgColor, document.linkColor, document.vlinkColor. t background Значение: строка URL-адреса Чтение/Запись Совместимость: WinIE44-, MacIE44-, NN64-, Mozl4-, Safaril4- 602 Часть III. Объекты документа
С помощью свойства background можно установить или получить URL-адрес фонового изображения страницы (если таковое существует), назначенного в элементе body. Это изо- бражение размещается поверх цвета фона в случае, когда установлены оба атрибута или свойства. Для удаления фонового изображения документа установите в качестве значения свойства document. body. background пустую строку. Пример Если у вас есть изображение, например, images/logoBG. gif, то его можно использо- вать в качестве фона, если выполнить следующий оператор. document.body.background = "images/logoBG.gif"; Для очистки фона от изображения применяется следующее выражение. document.body.background = ""; Если перед изображением фон окрашивался в однородный цвет, то после удаления изо- бражения фон заливается этим цветом. См. также: свойства body. bgCotor, body. bgPropert ies. bgColor Cm. aLink bgProperties Значение: строковая константа Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство bgProperties, используемое только в Internet Explorer, предназначено для ус- тановки такого предписания: следует ли фоновому изображению перемещаться при прокру- чивании документа пользователем. Начальные установки для этого свойства сохраняются в CSS-атрибуте background-attachment, а изменять их можно в сценарии с помощью свойства style .backgroundAttachment элемента body. Независимо от того, какой способ используется для обращения к этому свойству, допус- тимыми значениями будут только строковые константы scroll (по умолчанию) или fixed. Пример Оба приведенных ниже оператора изменяют поведение фонового изображения при про- крутке, заданное по умолчанию document.body.bgProperties = "fixed"; или document.body.style.backgroundAttachment = "fixed"; Последний вариант также выполняется в NN6+. См. также: свойство body. background. bottomMargin leftMargin rightMargin topMargin Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Глава 18. Объекты document и body 603
Данные четыре свойства используются только в Internet Explorer и являются альтер- нативой средства задания четырех атрибутов полей в таблице стилей элемента body (body.style.marginBottom и т.д.). Поля таблицы стилей представляют собой пустое пространство между краем содержимого элемента и наиболее удаленным от него объектом. В элементе BODY этот объект является неявно отображаемым на странице элементом документа. Из всех четырех свойств трудности могут возникнуть только при использовании bottomMargin и то в случае, когда площадь окна или фрейма не заполнена содержимым по вертикали. Грани- цы поля автоматически не увеличиваются для заполнения дополнительного пространства. В IE4+ существует немало целочисленных значений этого свойства, заданных по умолча- нию для каждой операционной системы. Однако помните, что свойства не возвращают эти значения до тех пор, пока пользователь не установит их в собственных атрибутах Internet Ex- plorer для элемента body. Даже при том, что у заданного по умолчанию элемента body ви- димые границы, свойство не возвращает по умолчанию их значения. Пример Оба приведенных ниже оператора изменяют левое поле в IE4+, заданное по умолчанию. document.body.leftMargin = 30; document.body.style.marginLef t = 30; См. также: объект style. leftMargin Cm.bottomMargin. link Cm. alink. noWrap Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Используя свойство noWrap, можно управлять поведением элемента body, если вы изме- ните его обычные настройки, заданные с помощью атрибута nowrap. Так как имя свойства имеет негативную форму (по), то пользователь может запутаться, анализируя булеву логику, применяемую для управления этим свойством. По умолчанию в элементе body существует установка на распределение текста по шири- не окна или фрейма. Это происходит, когда noWrap имеет значение false. При переключе- нии свойства noWrap в значение true текст приобретает вид одной строки, которая про- должается до тех пор, пока не встретится признак конца строки (закончится абзац) или она не выйдет за правую границу окна или фрейма. Вследствие того, что текст выходит за боковую границу окна, в окне (или фрейме) появляется горизонтальная полоса прокрутки (если, ко- нечно, во фрейме не отменено ее использование). Как известно, пользователи вообще не любят прокручивать документ, если в этом нет особой необходимости. Поэтому лучше оставить значение, заданное по умолчанию. Пример Оператор изменения настройки перетекания текста со значения по умолчанию выглядит следующим образом. document.body.noWrap = true; 604 Часть III. Объекты документа
rightMargin См. bottomMargin. scroll Значение: строковая константа Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство scroll используется только в Internet Explorer. С помощью данного свойства можно обеспечить доступ к атрибуту scroll элемента body в Internet Explorer в сценарии. По умолчанию в элементе body (Internet Explorer) назначено отображение вертикальной по- лосы прокрутки, даже если высота документа не превышает высоту окна и для его просмотра прокрутка не требуется; горизонтальная же полоса прокрутки появляется только тогда, когда содержимое документа выходит за рамки окна или фрейма по ширине. Можете убедиться в том, что обе полосы прокрутки будут скрыты, если установить атрибут scroll в значение “нет” или изменить его в сценарии. Возможными значениями этого свойства являются только строковые константы yes и по. Кроме атрибутов frame и защищенных сценариев в NN4+, другие браузеры не обеспечи- вают разработчика средствами отключения полос прокрутки в сценарии. Всегда можно сге- нерировать новое окно (методом window. open ()) и задать в нем скрытие полос прокрутки. Пример Чтобы изменить состояние полос прокрутки со значения по умолчанию, выполните сле- дующий оператор. document .body, scroll = "no"; См. также: свойство window. scrollbars; метод window. open (). scrollLeft scrollTop Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN7+, Mozl+, Safaril+ Даже при том, что свойства scrollLeft и scrollTop объекта body используются аналогично подобным свойствам обычных объектов элементов HTML, они играют важную роль при позиционировании элементов (см. главу 39). По причине того, что событие щелчка мышью и свойства позиционирования элемента обычно устанавливаются относительно ото- бражаемого содержимого окна браузера, то всегда необходимо учитывать и величину про- крутки объекта document. body для указания точного позиционирования. Для обоих свойств используются целочисленные значения, заданные в пикселях. Пример Пример использования свойств scrollLeft, scrollTop приведен в листинге 18.20. Он представляет собой модифицированный пример применения свойств pageXOffset HpageYOffset (листинг 16.13). Эти два листинга полностью идентичны, за исключением полученных значений, которые указывают, насколько документ прокручен в окне. Глава 18. Объекты document и body 605
<html> <head> <title>Master of all Windows«/title> «script type="text/javascript"> function leftFrameO { var output = "<html><bodyxh3>Body Scroll Values <\/h3xhr />\n" ; output += "<form>body. scrollLeft: «input type='text' name='xOffset' size=4 /xbr />\n"; output += "body.scrollTop:«input type='text’ name='yOffset' size=4 /> «br />\n"; output += ”«\/formx\/bodyx\/html:>" ; return output; } function rightFrame() { var output = "«htmlxheadxscript type=1 text/javascript'>\n"; output += "function showoffsets() {\n"; output += "parent.readout.document.forms[0].xOffset.value = document.body.scrollLeft\n"; output += "parent.readout.document.forms[0].yOffset.value = document.body.scrollTop\n}\n"; output += "document.onclick = showOffsets\n"; output += "«\/sCriptx\/headxbodyxh3>Content Page«\/h3>\n"; output += "Scroll this frame and click on a table border to view page offset values.«br /xhr />\n"; output += "«table border=5 width=800>"; var oneRow = "«td>Cell l«\/tdxtd>Cell 2«\/tdxtd>Cell 3 «\/tdxtd>Cell 4«\/tdxtd>Cell 5«\/td>"; for (var i = 1; i «= 30; i++) { output += "<trxtdxb>Row " + i + "<\/bx\/td>" + oneRow + "«\/tr>"; } output += "«\/tablex\/bodyx\/html:>" ; return output; } «/script> «/head> «frameset cols="30%,70%"> «frame name="readout" src="javascript:parent.leftFrameO" /> «frame name="display" src="javascript:parent.rightFrame()" /> «/frameset> «/html> См. также: свойства window. pageXOf fset, window. pageYOf f set. text Cm. al ink. topMargin Cm. bottomMargin. vLink Cm. al ink. 606 Часть III. Объекты документа
Методы createControlRange() Возвращаемое значение: массив Совместимость: WinIE5+, МасЕ-, NN-, Moz-, Safari- Пока разработчики Microsoft толком не ответили на вопрос, когда и как использовать объект control Range, известно только одно: данный объект имеет некоторое отношение к документу в режиме редактирования. В обычном режиме просмотра документа метод createControlRange () (не осуществленный в МасЕ5) возвращает пустой массив. createTextRange() Возвращаемое значение: объект TextRange Совместимость: WinIE4+, МасЕ-, NN-, Moz-, Safari- Объект элемента body— наиболее часто используемый объект для генерирования объекта TextRange в Е4+, особенно если текст, с которым работает пользователь, является частью ос- новного текста документа. В первоначальном объекте TextRange, возвращенном методом createTextRange () (не поддерживаемом в МасЕ5), содержался весь HTML-код и основной текст элемента body. Для дальнейших операций с возвращенным объектом требуется задать начальную и конечную точки диапазона. Более детально объект TextRange описан в главе 35. Пример Пример практического использования этого метода приведен в листинге 35.8. См. также: объект createTextRange () в главе 35. doScroll(["действие"]) Возвращаемое значение: отсутствует Совместимость: WinE5+, МасЕ-, NN-, Moz-, Safari- Используйте метод doScroll () для обеспечения ответной реакции на применение поль- зователем полос прокрутки в том окне или фрейме, в котором располагается текущий доку- мент. Этот метод используется при создании собственных полос прокрутки вместо стандарт- ных. Прокрутка производится мгновенно, даже быстрее, чем проигрывание анимации. Параметром данного метода служит одна из строковых констант, приведенных в табл. 18.5. На практике рекомендуется использовать более длинное имя действия прокрутки для имитации щелчка мышью на элементах панели прокрутки, так как сокращенные названия об- рабатываются с несравненно большей скоростью. Полное имя параметра Сокращенное Имитируемое действие прокрутки имя пзрзметрэ scrollbarDown down Щелчок на стрелке “вниз” scrollbarHThumb нет. Щелчок на горизонтальном бегунке полосы прокрутки (прокрутка не осуществляется) scrollbarLeft left Щелчок на стрелке “влево" Глава 18. Объекты document и body 607
Окончание табл. 18.5 Полное имя параметра Сокращенное имя параметра Имитируемое действие прокрутки scrolIbarPageDown PageDown Щелчок на нижней области страницы или нажатие <PgDn> (по умолчанию) scrollbarPageLeft pageLeft Щелчок на левой области страницы scrollbarPageRight pageRight Щелчок на правой области страницы scrolIbarPageUp pageUp Щелчок на верхней области страницы или нажатие <PgUp> scrolIbarVThumb нет Щелчок на вертикальном бегунке полосы прокрутки (прокрутка не осуществляется) В отличие от прокрутки, которая осуществляется в соответствии с определенным коорди- натным расположением (достигаемым установкой свойств scrollTop и scrollLeft эле- мента body), метод doScrollO полностью зависит от пространственного соотношения содержимого body и размера фрейма или окна. Метод doScroll О также вызывает обра- ботчик события onscoll для объекта элемента body. Помните, что изменение содержимого body в сценарии может привести к изменениям в пространственных соотношениях. В Internet Explorer любые внутренние размеры обновля- ются после изменения содержимого. При попытке вызвать метод doScroll () после подоб- ного изменения расположения элементов прокрутка может выполняться неправильно. В таких случаях обычно используют метод setTimeout (), который задает задержку в несколько до- лей секунды при обращении к методу doScrol 1 (). Пример Приложение The Evaluator можно использовать для изучения метода doScroll () в IE5+. Измените размер окна браузера таким образом, чтобы в нем отображалась хотя бы верти- кальная полоса прокрутки. Введите следующее выражение в верхнее текстовое поле и на- жмите несколько раз <Enter>, чтобы сымитировать нажатие клавиши <PgDn>. document.body.doScroll() Перейдите в верхнюю часть страницы и выполните те же действия, сымитировав исполь- зование кнопки со стрелкой на полосе прокрутки. document.body.doScroll("down") Продолжите, выполнив прокрутку в обратном направлении. См. также: свойства body, scroll, body. scrollTop, body. scrollLeft; методы window.scroll(), window.scrollBy(), window.scrollTo(). Обработчики событий onafterprint onbeforeprint См. обработчик событий onafterprint для объекта window (глава 16). onscroll Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Обработчик события onscroll вызывается для объекта элемента body в результате ручной прокрутки документа (с помощью полос прокрутки или клавиш) и прокрутки, 608 Часть III. Объекты документа
осуществляемой в сценарий с помощью методов doScroll (), scrollIntoView (). Обработ- чик onscrol 1 также вызывается при корректировке таких свойств объекта элемента body, как scrollTop и/йли scrollLeft. При ручной прокрутке и прокрутке с помощью doScroll О событие должно вызываться дважды подряд. Кроме того, свойство event. srcElement возвращает нулевое значение (null), даже если в элементе body используется обработчик события onscrol 1. Пример В листинге 18.21 приведен пример несколько необычного инструмента, добавляемого на Web-страницы. Представьте себе, что размещенный в окне или фрейме документ нужно сделать абсолютно непрокручиваемым (даже с помощью современных мышей, оснащенных колесика- ми). Если пользователь попытается прокрутить документ, то этот документ должен сразу сме- ститься в обратном направлении. Обратите внимание, что в данном примере обработчик собы- тия задается как свойство объекта document. body. Его также можно назначить как атрибут дескриптора <body>. Но в последнем случае необходимо сначала загрузить саму страницу. До этого объект body официально не присутствует в иерархической структуре объектов документа. Листинг 18.21. Предо<1₽*цены$ прйшдом дачйейт* <html> <head> <title>onscroll Event Handler</title> <script type="text/javascript"> function zipBackO { window.scroll(0,0); } function init() { document.body.onscroll = zipBack; } </script> </head> <body onload="init()"> <hl>onscroll Event Handler</hl> <hr /> This page always zips back to the top if you try to scroll it. <pxiframe frameborder="0" scrolling="no" height="1000" src="bof right .htm" ></if ramex/p> </body> </html> См. также: свойства body. scrollTop, body.scrollLeft; методы srcolllnto- View(), body.doScroll(). Объект treewalker Свойства Методы Обработчики событий currentNode expandEnt i tyRef erence filter firstChildO lastchild() nextNode() (нет) Глава 18. Объекты docwnent и body 609
Окончание таблицы Свойства Методы Обработчики событий root nextSibling() whatToShow parentNode() previousNode() previousSibling() Синтаксис Создание объекта TreeWalker. var treewalk = document.createTreeWalker(document, whatToShow, filterFunction, entityRefExpansion); Доступ к свойствам и методам объекта элемента TreeWalker такой. TreeWalker.свойство|метод([параметры] ) Совместимость: WinlE-, MacIE-, NN7, Mozl+, Safari- Описание объекта Объект TreeWalker выступает контейнером для списка узлов, которые удовлетворяют критериям фильтрации. Указанные критерии задаются методом document. createTree- Walker (), который используется для создания объекта TreeWalker. Список узлов, содер- жащийся в объекте TreeWalker, полностью повторяет иерархическую структуру текущего документа. Этот объект используется для навигации по списку узлов, унаследовавших древо- образную структуру. Представьте себе объект TreeWalker в виде указателя, поскольку основное его предна- значение — это перемещение по списку узлов. Тем не менее, список представляет собой ие- рархически упорядоченную структуру, а не простой перечень элементов. Объект TreeWalker содержит указатель в списке узлов, всегда указывающий на “текущий узел”. Таким образом, на- вигация с помощью объекта TreeWalker всегда выполняется относительно указателя. Например, ссылка на предыдущий или следующий узел с помощью методов previousNode () и nextNode () полностью зависит от расположения указателя в структуре. Используйте метод document .createTreeWalker О для создания объекта TreeWalker в текущем документе. Этот метод требует применения пользовательской функции, которая фильтрует узлы, включаемые в древовидную структуру. Ссылка на функцию представлена третьим аргументом метода. Данная функция возвращает константу, определяющую состоя- ние текущего узла: NodeFilter. FILTER_ACCEPT, NodeFilter.FILTER_REJECT или NodeFilter.FILTER_SKIP. Разница между значениями NodeFilter.FILTER_REJECT и NodeFilter. FILTER_SKIP заключается в том, что зависящие от пропущенных узлы мо- гут все еще рассматриваться как часть дерева, а отвергнутые узлы и зависящие от них узлы всегда исключаются из древовидной структуры. Следующая функция используется в проце- дуре создания объекта TreeWalker. function ratingAttrFilter(node) { if (node.hasAttribute("rating")) { return NodeFilter.FILTER_ACCEPT; } return NodeFilter.FILTER_REJECT; } 610 Часть III. Объекты документа
В этом примере только узлы, содержащие атрибут с именем rating, удовлетворяют ус- ловию фильтра, а потому только они добавляются в список (дерево). Имея в распоряжении эту функцию, вы можете вызвать в сценарии метод document. createTreeWalker () для создания объекта TreeWalker. var myTreeWalker = document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT, ratingAttrFilter, false); После создания объекта TreeWalker можно использовать его методы и свойства для по- лучения доступа к отдельным узлам и перемещения по списку узлов. Свойства currentNode Значение: ссылка на узел Чтение/Запись Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safari- Свойство currentNode возвращает ссылку на текущий объект, определяемый указате- лем объекта TreeWalker. Вы можете использовать это свойство не только для доступа к те- кущему узлу, но и для установки текущего узла. Пример Чтобы назначить текущий узел в соответствии с текущим расположением указателя в структуре, выполните выражение определения свойства currentNode. myTreeWalker.currentNode = document.getElementByld("info"); См. также: свойство root. expandEntityReference filter root whatToShow Значение: см. текст Только для чтения Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safari- Эти свойства отражают атрибуты, которые подставляются в метод document. create- TreeWalker (), создающий объект treeWalker. См. также: метод document. createTreeWalker (). Методы firstChild О lastchild() nextSibling() parentNode() previousSibling Значение: ссылка на узел Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safari- Глава 18. Объекты document и body 611
Эти методы возвращают ссылку на узел в древовидной структуре объекта TreeWalker. Они представляют дочерне-родительские отношения в упомянутой структуре узлов. При вы- полнении одного из этих методов указатель перемещается в указанное место, которое и ста- новится в дальнейшем текущим. Пример Приведенный ниже код позволяет получить имя дескриптора родительского узла для те- кущего узла в объекте TreeWalker. if (myTreeWalker.parentNode()) { var parentTag = myTreeWalker.currentNode.tagName; } См. также: методы nextNode () и previousNode (). nextNode() previousNode() Значение: ссылка на узел Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safari- Эти методы используются для навигации по списку узлов, который содержится в объекте TreeWalker. Следует обратить внимание на то, что эти методы воспринимают древовидную структуру в виде “плоского” списка элементов, а потому используют внешние указатели на узлы. Пример Приведенный ниже код демонстрирует применение функции фильтрации узлов и простой функции отображения идентификаторов всех элементов объекта body (которым назначены атрибуты id). Метод nextNode () вызывается первым для установки указателя в первый элемент коллекции. Далее в конструкции do-while извлекаются и фильтруются все осталь- ные элементы объекта. function idFilter(node) { if (node.hasAttribute("id")) { return NodeFilter.FILTER_ACCEPT; } return NodeFilter.FILTER_SKIP; } function showlds() { var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, idFilter, false); // проверка сохранения в TreeWalker по крайней мере одного узла if (tw.nextNode()) { do { alert(tw.currentNode.id); } while (tw.nextNode()); } } См. также: метод parentNode (). 612 Часть III. Объекты документа
Объекты ссылки и анкера Web базируется на простом принципе: любую ин- формацию можно объединить в единое целое с по- мощью гиперссылок— специальных текстовых фрагментов или изображений, щелчок на которых перенаправляет браузер к необходимому для посетителя материалу или информа- ции, которая поможет в дальнейших поисках интересую- щих его данных. Всеми объектами в документе управляет JavaScript; ссылка — это то, что задает связь между данны- ми. Анкеры тоже представляют собой средство навигации, но только в пределах текущего документа, задавая места страницы, на которые можно перейти с помощью ссылок. Подобно тому, как объекты сценариев задают структуру до- кумента, ссылки и анкеры определяют структуру Web. Но ка- жущаяся простота не уменьшает их важности в Web. Под управ- лением сценария ссылки могут стать намного более мощными инструментами, чем простое средство навигации в Web. В современных браузерах (IE4+ и W3C) разделение эле- ментов навигации на ссылки и анкеры привело к тому, что им стали соответствовать разные объекты во всех известных объектных моделях. Ключевое слово link далеко не всеми разработчиками сопоставляется с объектом документа из-за существования в объектной модели новых браузеров элемен- тов link (см. главу36), которые имеют совершенно иное предназначение в сценариях. Занимая место ссылки и анкера в объектной модели, этот объект HTML представляет собой элемент, созданный дескриптором <а>. Как объект элемента а, он получает все свойства, методы и обработчики событий, которые имеют любые HTML-элементы в современных объ- ектных моделях. Вы найдете в этой главе описание всех трех типов объектов. При разработке страниц, которые должны быть совместимы с ранними версиями браузеров, необходи- мо’ уделять особое внимание комментариям о поддержке свойств и обработчиков событий.
Объекты элементов link, anchor и а Свойства, методы и обработчики событий этих элементов описаны в главе 15. Свойства Методы Обработчики событий charset coords hash host hostname href hreflang Methods mimeType name nameProp pathname port protocol protocolLong rel rev search shape target text type urn X У Синтаксис Доступ к свойствам объекта link. (Все) [window.] document.links[индекс].свойство Доступ к свойствам элемента а. (IE4+) [window. ] document .all. идентификатор. свойство | метод ( [параметры]) (IE5+/NN6) [window.] document.all .getElementByld("идентификатор") . свойст- во! метод ( [параметры] ) 614 Часть III. Объекты документа
Описание объектов История создания сценария может вам помочь понять, как создавались объекты ссылки и анкера и какое участие в их образовании принимали элементы а. Используя терминологию базовой объектной модели, можно смело заявить, что объекты ссылки и анкера созданы на основе дескриптора <а>. Ссылку от анкера отличает присутствие атрибута href в дескрипторе. Если атрибут href отсутствует, элемент является объектом анкера, который (в браузерах до версии 4) не имеет свойств, событий и обработчиков собы- тий. Даже в NN4 объект анкера получает только четыре свойства, из которых в NN6+/W3C остается только свойство name. Ссылка, с другой стороны, имеет гораздо больше характеристик объекта — как раз благо- даря включению в нее атрибута href, который обычно указывает URL документа, загружае- мого в окно или фрейм. Многие свойства объекта link в ранних объектных моделях подоб- ны свойствам ранних объектов location— они содержат информацию об URL, присвоенному атрибуту href. Еще одной важной характеристикой объекта ссылки (особенно отличающей его от объекта анкера) является то, что ссылка может реагировать на события. Первоначально обработчиков событий у ссылки было только два: onclick и onmouseover. Начиная с NN4, к этому набору присоединились дополнительные обработчики события дви- жений мыши и двойного щелчка ondblclick. Когда объектная модель обращается к HTML-элементам как к объектам (IE4+ и NN6), объекты ссылок и анкеров представляются элементами а. Таким образом, до сих пор дейст- вительной остается одна важная особенность, которую имеют все объекты, — все элементы а, которые ведут себя как ссылки (благодаря присутствию атрибута href), являются членами массива document, links. Если сценарий требует проверки или изменения свойств всех ссылок на странице, то это реализуется в цикле for просмотра массива объектов ссылки. Это справедливо даже в том случае, если сценарий выполняется только в современных браузерах и в нем необходимо изменить атрибуты стилей всех ссылок (например, свойства style. textDecoration со значения попе на underline). Вышеупомянутый элемент может иметь совершенно разное поведение в зависимости от установленных атрибутов (что делает элемент а потенциально “двуликим” объектом). Поэтому внимательно задавайте ссылки и анкеры в процессе создания собственных сценариев, поскольку функциональное различие между ними намного больше, нежели синтаксическое. Начинающие пользователи часто ошибаются при задании атрибута target элемента а, когда определяют в сценарии ссылку на другой фрейм или окно. Согласно стандарту HTML, атрибут target указывает на окно или фрейм, в котором загружается новый документ (адрес которого присвоен атрибуту href), оставляя текущее окно или фрейм без изменений. Если вы хотите использовать обработчик события для навигации к другому документу (с помощью свойства location.href), то атрибут target в этой ситуации останется невостребован- ным в сценарии. Вместо этого свойству location.href соответствующего окна или фрей- ма определяется URL необходимого документа. Например, если один фрейм содержит табли- цу с данными, целиком состоящими из ссылок, то обработчик события onclick этих ссылок может загружать другие страницы во фрейм main после присвоения соответствующего URL свойству parent.main, location.href. При этом также необходимо отменить стандарт- ное поведение ссылки (см. описание обработчика события onclick в главе 15). Если при щелчке на ссылке (добавленной к текстовому фрагменту или изображению) не- обходимо инициировать действие, отличное от перехода к странице с другим URL, следует использовать специальную методику—задайте оператор javascript:псевдо-URL, кото- рый с помощью URL вызывает функцию JavaScript. Адрес javascript имяФункции() является допустимым значением атрибута href (а не только объекта ссылки). Браузеры, в которых JavaScript не поддерживается, никак не реагируют на щелчок на подобной ссылке. Глава 19. Объекты ссылки и анкера 615
Если необходимо, чтобы ссылка принимала участие только в изменении содержимого строки сос- тояния, выполняемого в обработчике события onmouseover, то создайте пустую функцию и оп- ределите ей в JavaScript адрес URL (например href = " j avascript: voidsomeFunction () "). Начиная c NN3 и IE4, можно также добавить специальный оператор void, который гаранти- рует, что созданная пустая функция не будет выполнять стандартное для ссылки действие (href="javascript:voidsomeFunction() "). Задание пустой строки в атрибуте href приводит к отображению ПН-структуры файлов текущего клиентского компьютера — весьма нежелательный побочный эффект. Не следует также забывать и о том, что если URL указыва- ет на файлы, которые запускаются вспомогательными приложениями браузера (например звуковые файлы RealAudio), то внедряемый модуль или надстройка загружаются автоматиче- ски, а указанный файл воспроизводятся без изменения текущей страницы в окне браузера. Одна ссылка, заданная с помощью JavaScript, может изменить содержимое более чем одного фрейма сразу. Если вы хотите, чтобы только браузеры, поддерживающие JavaScript, реагирова- ли на щелчок на подобной ссылке, используйте выражение javascript: псевдо-URL, в ко- тором вызывается функция, изменяющая свойство location.href нескольких фреймов. Например, рассмотрим следующую функцию, которая изменяет содержимое двух фреймов. function navFrames(urll, url2) { parent.product.location.href = urll; parent.accessories.location.href = url2; } Полученная многоцелевая функция вызывается с помощью выражения javascript: псевдо-URL, и ей передаются специфические параметры ссылок. <а href="javascript: void navFrames(’products/gizmo344.html1, 'access/access344.html1)">Deluxe Super Gizmo</a> Если необходимо, чтобы ссылка выполняла определенные действия в любых браузерах и в то же время инициализировала специальные операции в JavaScript-браузерах, совместите стандартное поведение ссылки с обработчиком события onclick, обеспечив поддержку этих двух ситуаций. function setAccessFrame(url) { parent.accessories.location.href = url; } <a href="products/gizmo344.html" target="product" onclick="setAccessFrame('access/access344.html')">Deluxe Super Gizmo</a> Заметьте, что атрибут target определяет стандартное поведение ссылки в то время, как сценарий присваивает URL свойству location, href фрейма. Один дополнительный метод позволяет отдельному дескриптору ссылки выполняться в любых браузерах, поддерживающих и не поддерживающих сценарии (NN3+ и IE4+). Для браузеров, не поддерживающих сценарии, задание настоящего URL проводится в ссылке. В этом случае обработчик события onclick ссылки должен заканчиваться оператором return false. Во время щелчка на ссылке браузер, поддерживающий сценарии, выполня- ет обработчик события и игнорирует атрибут href; браузер, не поддерживающий сценарии, не выполняет обработчик события и следует ссылке. Более детально этот вопрос рассмотрен при описании обработчика события onclick в главе 15. В процессе создания ссылок не избегайте использования обработчиков события onmouseover и onmouseout в соответствующем операторе ссылки. В общем случае эти обработчики со- бытий применяются для определения значения свойства window, status или установки состояний ролловера. (Раньше элементы img не имели собственных обработчиков событий, поэтому они заключались внутрь элементов а, для которых обработчики события были зада- 616 Часть III. Объекты документа
ны с первого дня существования). В таком случае, когда пользователь наводит указатель мы- ши на ссылку, специальное сообщение (более детальное и содержательное, нежели текст или изображение самой ссылки) появляется в строке состояния в основном окне. Заметит пользо- ватель представленное ему сообщение или нет — это отдельная тема для разговора, поэтому не особо полагайтесь на строку состояния как средство взаимодействия с посетителями. Из- менение изображения, однако, более заметно; оно обеспечивает пользователя обратной свя- зью, которая осуществляется при наведении указателя на значок кнопки. Благодаря обработ- чику события onmousedown возможной становится даже загрузка изображения при наведении указателя мыши на него или специальную ссылку. Свойства charset Значение: строка Чтение/Запись Совместимость: WinlE6+, MacIE6+, NN6+, Mozl+, Safaril+ Свойство charset представляет собой атрибут charset, используемый в HTML 4.0 для элемента а. Это свойство задает в браузере набор символов, используемых для отображения документа, который указан в атрибуте href. Значение этого свойства— один из наборов символов, с которыми вы можете ознакомиться по адресу ftp://ftp.isi.edu/in- notes/iana/assignments/character-sets. coords shape Значение: строка Чтение/Запись Совместимость: WinIE6+, MacIE6+, NN6+, Mozl+, Safaril+ B описании элемента а в HTML 4.0 указано, что ссылка может добавляться к изображению разной формы (прямоугольной, круглой и многоугольной); в этом случае необходимо задать ко- ординаты области, для которой задается ссылка. Свойства coords и shape элемента а пред- ставлены в NN6 (как и в W3C DOM), однако их активная поддержка все еще не реализована. hash host hostname pathname port protocol search Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Эгот большой набор свойств тождественен подобным по имени свойствам объекта location (см. главу 17). Все свойства являются компонентами URL, который задается в ссылках с помо- щью атрибута href объекта. Ни одно из этих свойств не указано в спецификации W3C DOM для элемента а, однако они продолжают поддерживаться в современных браузерах для обес- Глава 19. Объекты ссылки и анкера 617
печения обратной совместимости. Если вам необходимо изменить адрес в ссылке, преобра- зуйте значение свойства href, а не отдельные компоненты URL. См. также: объект location. href Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство href (поддерживается W3C DOM) — это URL конечного документа, на кото- рый указывает элемент а, используемый в качестве ссылки. Адреса URL могут быть относи- тельными или абсолютными. В IE4+ и NN6 вы можете преобразовать объект анкера в объект ссылки, добавив значение свойству href даже в том случае, когда элемент а в HTML не имеет атрибута href. Конеч- но, это преобразование является временным; оно справедливо до того момента, пока страни- ца загружается в браузер. При задании значения свойству href элемента а, в который вклю- чен текст, этот текст преобразуется в ссылку (текст принимает как стандартный для ссылок вид, так и специальный, указанный в таблицах стилей). См. также: объект location. hrefLang Значение: строка Чтение/Запись Совместимость: WinIE6+, MacIE6+, NN6+, Mozl+, Safaril+ Свойство hrefLang информирует браузер (если браузер его поддерживает) о языке, ис- пользуемом для представления содержимого документа, на который указывает атрибут href элемента а. Значения этого свойства представлены в виде двухсимвольного кода языка (например, en-us для американского английского). Methods Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство Methods (обратите внимание на заглавную букву “М”) представляет собой ат- рибут methods элемента а в HTML 4.0. Значения этого атрибута и свойства служат в каче- стве рекомендаций для браузера, в которых указано, какие HTTP-методы лучше использовать для доступа к указанному документу. Практически всегда атрибут HTML 4.0 повторяется в W3C DOM. Несмотря на то, что IE4+ поддерживает это свойство, предоставляемая им Ин- формация в этих браузерах никак не используется. mimeType Значение: строка Только для чтения Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Введенное в IE4 (но не в Мас1Е4) свойство mimeType по-прежнему поддерживается в IE5, но это, по всей видимости, последний браузер, в котором оно будет использоваться. HTML 4.0 и W3C DOM спецификации вместо него представляют атрибут type и свойство type. Возможно, это свойство было задумано как рекомендательное, чтобы позволить брау- зеру предварительно “ознакомимся” с типом MIME. В сценарии соответственно типам MIME можно задавать ветвление, устанавливая разные типы указателей мыши в зависимости от объекта, на который наводится указатель мыши. Свойство не обладает возможностью управ- ления типом MIME загружаемого документа. 618 Часть III. Объекты документа
name Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Пока атрибут паше является необязательным для элемента а, являясь только объектом ссылки, в объекте анкера без него просто не обойтись. Этой величиной управляет в сценарии свойство паше. Свойство можно применить как средство определения объекта ссылки в мас- сиве document. links, используя цикл для его просмотра. for (var i = 0; i < document.links.lenght ; i++) { if (document.links [i].цате == "bottom" { // операторы управления ссылкой с именем "bottom" } } nameProp Значение: строка Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство nameProp, специфическое для IE, удобно использовать для получения фрагмента href, расположенного справа от крайнего правого символа наклонной черты (слеша) в URL. Чаще всего его значение является именем файла, указанного в URL. Но если URL также со- держит номер порта, то он тоже возвращается как часть значения nameProp. protocolLong Значение: строка Только для чтения Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Свойство protocolLong, специфическое для IE, возвращает подробное значение свойства protocol для атрибута href элемента а. Например, если атрибут href указывает на исполь- зование протокола http, то свойство protocolLong возвращает HyperText Transfer Protocol. Введенное в IE4 (но не в Мас1Е4) свойство protocolLong, по-прежнему под- держивается в IE5, но, по-видимому, в следующих версиях оно реализовано не будет. rel rev Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойства rel и rev определяют связь в обратном и прямом направлениях относительно документа, указанного в элементе а. Браузеры до сих пор используют большую часть потен- циала этих атрибутов и свойств. Длинный список значений, заранее определенных для этих свойств, основывается на со- ответствующих величинах атрибутов, которые определяются в HTML 4.0. Если браузер не использует определенное значение, то оно игнорируется. Можно объединить вместе несколь- ко значений в виде отдельной строки. Допускается использовать следующие значения. alternative appendix bookmark chapter contents copyright glossary help index next prev section start stylesheet subsection Глава 19. Объекты ссылки и анкера 619
target Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Важным свойством объекта ссылки является target. Эта величина указывает на имя ок- на, заданное атрибутом target в элементе h. Можно временно изменить целевой объект ссылки. Однако, как и со многими другими свойствами кратковременных объектов, заданные значения удаляются при мягкой переза- грузке. Вместо изменения целевого объекта, подобным образом можно безопасно указать цель, задав в атрибуте href значение javascript: functionName () — псевдо-URL, в котором с помощью функции документ загружается в соответствующем окне, определенном в свойстве window, location. Если вы часто используете в своем документе атрибуты HTML, то избежать использования атрибута target может оказаться весьма проблематично. См. также: свойство document. links. text Значение: строка Только для чтения Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Между открывающим и закрывающим дескрипторами ссылки указывается текст (или изо- бражение), который выделяется цветом, характерным для ссылки в документе. NN4 предос- тавляет возможность получить этот текст с помощью свойства link. text. Это свойство пред- назначено только для чтения. В более поздних версиях браузеров — IE4+ и/или W3C DOM — для получения текста узла ссылки используются специальные свойства (innerText, innerHTML и nodeValue) элемента а. Это свойство не реализовывалось в NN4, который выпущен перед версией 4.02. 'На заметку type Значение: строка Чтение/Запись Совместимость: WinIE6+, MacIE6+, NN6+, Mozl+, Safaril+’ Свойство type представляет собой атрибут type в HTML 4.0, который задает тип MIME содержимого указанного документа, на который указывает атрибут href элемента а. Перво- начально это свойство предназначалось для использования в рекомендательных целях для браузера, которому необходимо знать, например, какой указатель мыши использовать при отображении документа, на который указывает ссылка. До сих пор браузеры не используют преимущества этого свойства. Однако значение типа MIME можно задать в атрибуте (например video/mpeg), чтобы впоследствии использовать его в сценариях для соответст- вующего стилевого изменения текста ссылки после загрузки страницы. IE4+ представляет это свойство как mimeType. См. также: свойство mimeType urn Значение: строка Чтение/Запись Совместимость: WinIE4-i-, MacIE4+, NN-, Moz-, Safari- 620 Часть III. Объекты документа
Свойство urn представляет собой атрибут urn, специфический для IE, он позволяет раз- работчикам использовать URN (Uniform Resource Name —г Универсальное имя ресурса) для указания места назначения элемента а (см. http: //vnrw. ietf. org/rfc/rfС2141. txt). Это свойство не приспособлено для массового пользования. X У Значение: строка Только для чтения Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- Сценарий в NN4 может получать координаты х и у объекта ссылки (верхний правый угол прямоугольного пространства, занимаемого текстом или изображением ссылки) с помощью свойств link.x и link.у. В IE4+ и NN6+/W3C получить координаты типичной ссылки можно с помощью свойств off setLef t и of f setTop элемента a. Глава 19. Объекты ссылки и анкера 621
Объекты изображения, области и карты изображений Изображения и карты изображений являются высоко- уровневыми объектами, созданными для браузеров NN3+ и IE4+ с помощью дескрипторов <img> и <агеа>; они используются в сценарии для обеспечения его интерак- тивности. Изображение, указанное в дескрипторе <img>, можно заменить другими изображениями (это относится только к изображениям одинакового размера в NN3 и NN4). Чтобы разнообразить визуальное представление страницы, можно использовать эффект подсвечивания кнопки со знач- ком в момент наведения на нее указателя мыши. Использо- вание клиентских карт изображений поможет вам сделать ваши страницы “интеллектуальнее” в ответ на щелчки поль- зователя на каком-либо графическом объекте. Заметьте, что разработчик сценария имеет возможность отобразить изображения предварительно, во время загрузки всей страницы. Применение кэшируемых изображений по- зволяет избежать временной задержки при смене одного изображения другим. Изображения и элементы img Свойства, методы и обработчики событий этого HTML- элемента описаны в главе 15.
Свойства Методы Обработчики событий align onabort alt onerror border complete dynsrc fileCreatedDate fileModi f iedDate fileSize fileUpdatedDate height href hspace isMap loop longDesc lowsrc mimeType name nameProp naturaIHeight naturalWidth protocol src start useMap vspace width X У onload Синтаксис Создание объекта image. imageName = new Image([ширина, высота]); Доступ к свойствам и методам элемента img и объекта image. (NN3+/IE4+) [window. ] document. имяИзображения. свойство | метод( [параметры]) (NN3+/IE4+) [window. ] document. images [индекс] . свойство | метол ( [параметры]) (NN3+/IE4+) [window. ] document. images ["имяИзображения”] . свойство | метод ( [параметры]) Глава 20. Объекты изображения, области и карты изображений 623
(IE4+) [window.]document.all.идентификатор.свойство\метод([параметры]) (IE5+/W3C) [window. ] document .getElementByld("идентификатор" ) . свойство| метод ( [параметры] ) Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safari 1+ Описание объекта Прежде чем приступить к описанию изображений как объектов, необходимо четко пред- ставить разницу между образцами статического объекта Image и объектом элемента img. Статический объект Image существует только в памяти браузера. Пользователю он ничего на экране не отображает. Элементы img — это объекты на странице, сгенерированной с помо- щью дескриптора <img> (формально не оговоренный, но допустимый вариант дескриптора < image >). В сценариях объекты Image используются с целью предварительного кэширова- ния изображений на странице; вполне очевидно, что они имеют меньшее количество соответ- ствующих свойств, методов и обработчиков событий, потому что они невидимы на странице и на них не влияют атрибуты, установленные в дескрипторе. Элементы img присутствуют в словаре ключевых слов HTML довольно давно. Но NN3 был первым, кто стал обращаться с ними как с равноправными объектами (наряду с объектом Image), используя для предварительного кэширования изображений. МасПЗЗ.01 обеспечивает частичную поддержку обоих вариантов (предварительное кэширование и смена изображения), а все версии IE4+ рассматривают элементы img как полноценные объекты. Одним из самых главных преимуществ управления img-элементом как объектом является возможность замены изображения, которое представлено на странице даже после загрузки документа и отображения в браузере исходного рисунка. Эта задача выполняется с помощью свойства src изображения. В типичном сценарии страница загружается с начальным изображением. Дескрипторы изо- бражения задают любые дополнительные атрибуты изображения, например, height и width (которые помогают ускорить отображение страницы), и определяют, используется ли в ри- сунке клиентская карта изображения, предоставляющая пользователю дополнительную инте- рактивность (см. описание объекта area ниже в этой главе). Пока пользователь просматри- вает страницу, изображение может измениться (в ответ на действие пользователя или вследствие анализируемого в сценарии события); оно заменяет исходное изображение на но- вое в той же самой области. В браузерах IE4 и NN6, которые поддерживают объект img, вы- соту и ширину начального изображения представляет прямоугольник фиксированного разме- ра, за рамки которого изображение “выйти” не может. Преобразование изображения с целью обеспечения соответствия выделенной для него области приводит к необходимости масшта- бирования. Но в IE4+ и NN6+ изменение размера изображения приводит к автоматической перезагрузке содержимого страницы уже другого размера. Преимущество отдельного объекта Image состоит в том, что с его помощью в сценарии создается виртуальное изображение, в котором удерживается предварительно загруженное изображение. (Изображение загружается в кэш-память, но браузер в начальный момент его не отображает.) Одно или несколько скрытых изображений загружаются в память, в то время как пользователь занят просмотром страницы или ожиданием ее загрузки. Впоследствии в ответ на действия пользователя изображение может отображаться (или изменяться) мгно- венно, что избавит посетителя от дополнительных ожиданий. Предварительная загрузка изображения начинается с назначения нового, пустого объекта изображения глобальной переменной. Новое изображение создается с помощью конструкто- ра объекта Image. var переменнаяОбъекта = new Image(ширина, высота}; 624 Часть III. Объекты документа
Чтобы помочь браузеру выделить необходимую память для изображения, необходимо пе- редать в сценарий информацию о высоте и ширине изображения (в пикселях) в виде парамет- ров. В результате этого в памяти создается объект, свойства которого не инициализированы. Чтобы заставить браузер загрузить изображение в кэш-память, назначьте файл изображения URL свойству src объекта. var onelmage = new Image(55,68) ; onelmage.src = "neatimage.gif"; В процессе загрузки изображения в строке состояния отображается диаграмма загрузки, как для любого другого файла. После этого необходимо приравнять свойство src предвари- тельно загружаемого изображения к свойству src объекта элемента img, который отобража- ется на странице. document.images ["somelmage"].src = onelmage.src; В зависимости от типа и размера изображёния вы будете удивлены быстрой реакцией на, отображение предварительно загруженного изображения. Графические объекты с небольшой палитрой цветов отображаются на экране в этом случае практически мгновенно. Чтобы усовершенствовать пользовательский интерфейс документа, добавьте на страницу изображение в виде активной кнопки, изменяемой при наведении на него указателя мыши. В этом случае предполагается, что генерируется соответствующее событие мыши, которое и активизирует элемент, связанный с объектом. До появления IE4 и NN6 объекты элемента img не отвечали на события (щелчки) мыши. Описанный выше эффект требует вставки img- элемента внутрь элемента а. Это действие позволяет событиям onmouseover, onmouseout и onclick, связываемым с изображением, вызывать определенное действие (обычно пере- ход к другой странице). Если IE4+ и NN6+ задают эти события непосредственно в объектах элемента img (чтобы гарантировать, что все страницы будут обратно-совместимыми с другими версиями браузеров), то необходимо обязательно включить их внутрь элементов А. Примеры использования изображений можно найти в главах 12 и 20. Ролловеры обычно могут находиться в двух различных состояниях: нормальном и актив- ном. У вас может появиться желание увеличить число таких состояний, чтобы более гибко моделировать работу графических кнопок. В некоторых случаях используется третье состоя- ние, определяющее нажатую кнопку. Например, если вы используете ролловер в одном фрейме для представления Web-страниц в другом фрейме, и пользователь щелкает на кнопке перехода к разделу Products, то эта кнопка остается в активной, но в состоянии, отличном от представляемых ролловером. Некоторые разработчики идут дальше, обеспечивая четвер- тое, временное, состояние, задаваемое в процессе загрузки изображения. Каждое из этих со- стояний требует загрузки в документ своего изображения. Чем больше состояний ролловера используется, тем меньшим будет эффект задержки отображения изображений при использо- вании предварительной загрузки страницы. Скорость, с которой происходит замена предварительно загруженных изображений, наводит на мысль об использовании этого метода для добавления на страницу анимации. Несмотря на то, что этот метод и применяется для добавления коротких анимационных клипов, многие дру- гие способы создания анимационных движений на вашей Web-странице (с помощью графиче- ского формата GIF89a или Java-аплетов) обеспечивают более высокую эффективность. Смена предварительно загруженных объектов изображений в JavaScript для получения анимационных эффектов может быть очень быстрой. Поэтому при их использовании необходимо в обязательном порядке создать механизм задержки, реализуемый с помощью метода set Interval (). При этом точная синхронизация кадров будет напрямую зависеть от производительности процессора. Все браузеры, которые поддерживают объект элемента img, вместе с ним поддерживают мас- сив document. images. Можно (и следует) использовать этот массив как условие поддержки объектов элементов img в любых операторах сценария, которые управляют изображениями. Глава 20. Объекты изображения, области и карты изображений 625
if (document.images) { // Операторы, управляющие изображениями как объектами) Более ранние браузеры воспринимают отсутствие этого массива как эквивалент значения false в условной инструкции if. Свойства, обсуждаемые ниже, представляют атрибуты элемента img. Для получения бо- лее детальной информации о значениях и использовании атрибутов обратитесь к документа- ции по спецификации HTML4.0 (http://www.w3 .org/TR/REC-html40) и расширений Microsoft для IE (http: //msdn.microsof t. com/workshop/author/dhtml/ref erence/ obj ect s / img. asp). Свойства align Значение: строка Чтение/Запись Совместимость: WinIE6+, MacIE6+, NN6+, Mozl+, Safaril+ Свойство align определяет, как изображение располагается относительно окружающего его текста. Это свойство двойного назначения, так как его можно использовать для управле- ния вертикальным или горизонтальным выравниванием, в зависимости от значения (и значе- ния атрибута стиля float для данного изображения). В качестве значений этого свойства используются следующие строковые константы. absbottom middle absmiddle right baseline texttop bottom top left Выравнивание, заданное для изображения по умолчанию, — bottom. Все чаще выравни- вание задается с помощью стилей. В Safari поддерживаются только варианты left и right. Пример В листинге 20.1 приведен пример использования свойства align и его влияние на макет до- кумента (расположение текста вокруг изображения на HTML-странице). Измените размер окна браузера, чтобы увидеть, как при этом изменяется способ обтекания текстом графических объек- тов. Каждый браузер по-своему устанавливает параметр align в рассматриваемых случаях. <html> <head> <title>img align Property</title> <script type="text/javascript"> function setAlignment(sei) { document.getElementByld("mylMG").align = sei.options[sei.selectedlndex).value; } </script> </head> <body> 626 Часть III. Объекты документа
<hl>img align Property«/hl> <hr /> <form> Choose the image alignment: <select onchange="setAlignment(this)"> «option value="absbottom">absbottom</option> «option value="absmiddle">absmiddle«/option> «option value="baseline">baseline«/option> «option value="bottom" selected="selected">bottom«/option> «option value="left">left«/option> «option value="middle">middle«/option> «option value="right">right«/option> «option value="texttop">texttop«/option> «option value="top">top«/option> </select> </form> «hr /> <p>Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aliqua. <img alt="image" id="myIMG" src="deskl.gif" height="90" width="120" /> Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> «/body> «/html> См. также: атрибуты стиля float, text-align. alt Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Свойство alt позволяет задавать или изменять текст, который браузер отображает в пря- моугольном заполнителе изображения (если его высота и ширина определены) перед тем как в нем отобразится изображение. Если в браузере отключено отображение рисунков (или браузер не способен отображать изображения), то текст свойства alt поможет пользователям иден- тифицировать изображение, которое обычно представлено в текущей области страницы. Аль- тернативный текст можно изменять даже после загрузки страницы. Пример Используйте приложение The Evaluator для изучения свойства alt объекта изображения document .mylmg. Сначала назначьте свойству src несуществующее изображение, чтобы удалить в документе текущее изображение. document.mylMG.src = "fred.gif" Прокрутите страницу к изображению, и вы сможете увидеть занимаемое им место в доку- менте. Теперь задайте значение свойства alt. document.mylMG.src = "Fred\’s face" Обратная косая черта используется для вывода апострофа в текстовой строке. Прокрутите страницу еще раз, чтобы ознакомиться с заменяющим изображение текстом. См. также: свойство title. border Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Глава 20. Объекты изображения, области и карты изображений 627
Свойство border определяет толщину в пикселях границы вокруг изображения. Помни- те: если поместить изображение внутрь элемента а, чтобы впоследствии использовать собы- тия мыши (в ролловерах и т.д.), то необходимо убедиться в том, что атрибут border деск- риптора <img> имеет нулевое значение. В результате вы не допустите генерирования обычной границы вокруг изображения. Даже при том, что по умолчанию значение атрибута нулевое, помещение изображения в элемент а или вставка изображения в клиентскую карту изображения вызывает добавление границы вокруг изображения. Пример Постарайтесь максимально детально изучить свойство border объекта document. my IMG, воспользовавшись приложением The Evaluator. Это свойство принимает самые различные це- лочисленные значения. См. также: свойства isMap, useMap. complete Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Иногда необходимо удостовериться, что загрузка изображения не происходит (например, перед выполнением другой задачи). Данная ситуация в корне отличается от проверки полной за- грузки изображения, требуемой для выполнения определенного процесса (который задается в обработчике события onload для объекта изображения). Гарантией того, что объект img со- держит все изображение, выступает значение свойства complete. Чтобы убедиться в полной загрузке графического файла, проверьте, является ли значение свойства complete истинным (т.е. равным true); после этого сравните значение свойства src с требуемым именем файла. Свойство complete изображения принимает значение true, даже если указанное изо- бражение загружено в формате lowsrc. Не полагайтесь только на это свойство для опреде- ления загруженности изображения. Обязательно проверьте свойство src или lowsrc, если оно определено в дескрипторе <img>. Один из лучших путей применения этого свойства заключается в использовании условной инструкции if. if (document.mylmage.complete) { // операторы, которые выполняются с объектом document.mylmage ! Свойство complete нельзя назвать надежным в NN4 и некоторых версиях IE. /На заметку Для этих браузеров это свойство возвращает true в любых случаях. Пример Чтобы ознакомиться со свойством complete, завершите работу и заново запустите брау- зер. Далее загрузите в нем документ, представленный листингом 20.2 (изображения расположе- ны в кэше браузера). В процессе загрузки изображений щелкните на кнопке Is it loaded yet?, чтобы ознакомиться с состоянием свойства complete объекта image. Значение false со- хранится в этом свойстве до тех пор, пока изображение не будет загружено. В противном случае будет установлено значение true. Изображение скалы несколько больше фотографии клавиатуры. Для очистки кэша завершите работу в браузере и заново загрузите его. Если у вас возникают трудности с использованием этого свойства в сценариях, то попробуйте приме- нить обработчик onload дескриптора <img>. 628 Часть III. Объекты документа
«html> «head? <title?«/title? «script type="text/javascript"? function loadlt(thelmage,form) { form.result.value = document.images[0].src = thelmage; function checkLoad(form) { form.result.value = document.images[0].complete; } «/script? «/head? «body? <img alt="image" src="cpu2.gif" width="120" height="90" onload="" /? «form? «input type="button" value="Load keyboard" onclick="loadlt('cpu2.gifthis.form)" /? «input type="button" value="Load arch" onclick="loadlt('arch.gif',this.form)" /? «p?<input type="button" value="Is it loaded yet?" onclick="checkLoad(this.form)" /? «input type="text" name="result" /?«/p? «/form? «/body? «/html? См. также: свойства img. src, img.lowsrc, img. readyState; обработчик события onload. dynsrc Значение: строка URL Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство dynsrc -— это URL исходного видеофайла, который (в IE) можно воспроизвести с помощью элемента img. Используйте область, отведенную статическому изображению для отображения видеоклипа, указав URL видеофайла (например . avi или . mpg файлов) в свой- стве dynsrc объекта изображения. В отличие от свойства src объектов изображений, опре- деление URL в свойстве dynsrc не позволяет провести предварительную загрузку видеоклипа. После того, как элемент img отобразит изображение . gif или . jpg, будет рисковано за- давать в нем свойство dynsrc. В такой ситуации можно столкнуться с ошибками в ранних версиях IE. В WinIE5 строка состояния указывает на то, что видеофайл все еше загружается, даже если загрузка уже завершена. Щелчок на кнопке Stop никак не повлияет на сложив- шуюся ситуацию. WinIE5.5 даже может проигнорировать видеофайл, оставив область стра- ницы пустой. В Мас1Е5 переход от статического к динамическому изображению происходит без особых проблем, но при многократном воспроизведении видеофайла в элементе img об- ласть за пределами прямоугольника окрашивается в черный цвет (см. листинг 22.3). Ни одна из этих ошибок не фатальна, но они должны предостеречь вас от использования элемента img при передаче видеосодержимого. Глава 20. Объекты изображения, области и карты изображений 629
Пример Переход от статического изображения к динамическому выполняется с помощью всего одного свойства. В листинге 20.3 показан простой пример подобной операции, заключаю- щейся в изменении свойства dynsrc. Как и следовало ожидать, этот код имеет все недостат- ки, описанные выше. <html> <head> <title>img dynsrc Property</title> <script type="text/javascript"> var training = new Image(160,120); training.src = "amtrak.jpg"; trainlmg.dynsrc = "amtrak.mpg",- function setLoopO { var selector = document.forms[0].looper; document.getElementByld("mylMG").loop = selector.options[selector.selectedlndex].value; } function setImage(type) { if (type == "jpg") { document.getElementByld("mylMG").dynsrc = ""; document.getElementByld("mylMG").src = trainlmg.src; } else { document.getElementByld("myIMG").src = ""; document.getElementByld("mylMG").start = "fileopen"; setLoop(); document.getElementByld("mylMG").dynsrc = trainlmg.dynsrc; } } </script> </head> <body> <hl>img dynsrc Property</hl> <hr / > <form> Choose image type: <input type="radio" name="imgGroup" checked="checked" onclick=setimage('jpg1)" />Still <input type="radio" name="imgGroup" onclick="setlmage('npg')" /> Video <p>Play video how many times after loading: <select name="looper" onchange="setLoop()"> <option value="l" selected="selected">Once</option> <option value="2">Twice</option> <option value="-l">Continuously</option> </selectx/p> </form> <hr / > <img alt="image" id="myIMG" src="amtrak.jpg" height="120" width="160" /> </body> </html> См. также: свойства img. loop, img.start. 630 Часть III. Объекты документа
f ileCreatedDate fileModifiedDate fileUpdateDate fileSize Значение: строка, целочисленное значение (filesize) Чтение/Запись Совместимость: WinIE4+, MacIE5+, NN-, Moz-, Safari- Эти три свойства в IE возвращают информацию о файле, отображаемом в элементе img (в слу- чаях статического и динамического содержимого). Два из этих свойств содержат даты создания и изменения текущего изображения. Для статического (неизменяемого) файла даты создания и изменения — одни и те же. Свойство filesize показывает размер в байтах текущего файла. Значения даты, возвращенные первыми двумя свойствами, форматируются по-разному в IE4 и Е5. IE4 обеспечивает полный формат представления времени и даты; IE5 возвращает их в формате, подобном mm/dd/yyyy. Обратите внимание, однако, что возвращаемые значения со- держат только дату, но не время. В любом случае, вы можете использовать эти значения как па- раметр в функции-конструкторе new Date (). Это позволит использовать дату для получения такой информации, как число дней между текущим днем и датой последнего изменения файла. Не все серверы предоставляют корректные сведения о датах создания и изменения файла или возвращают их в формате, который IE может интерпретировать. Проверьте эти характе- ристики на интересующем вас сервере, чтобы убедиться в его совместимости с создаваемыми вами документами. Примите во внимание, что эти свойства доступны для чтения только в случае, когда файл загружен в браузер. JavaScript самостоятельно не может получить информацию о файлах на сервере, которые не загружены в браузер. Все свойства, предоставляющие сведения о файлах, поддерживаются в IE для /на заметку Мас, но при этом возвращаемые ими значения будут пустыми. Пример Эти свойства подобны свойствам управления именами объекта document. Вы можете ознакомиться с примером их использования в листинге 18.4. Скопируйте этот листинг и соз- дайте изображение, перед тем как заменять ссылку на объект изображения из объекта доку- мента. Детально изучите свойства объекта элемента img. height width Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Свойства height и width возвращают, а в более поздних браузерах задают высоту и ширину объекта изображения в пикселях. Свойства доступны только для чтения в NN3 hNN4, но во всех остальных браузерах, поддерживающих объект элемента img, они пред- ставлены в режиме чтения и записи. Если вы изменяете свойство высоты изображения, браузер автоматически сохраняет про- порции изображения, заданные исходными размерами оригинала. Но изменение свойства ширины никак не влияет на свойство высоты в большинстве версий браузеров. Масштаби- рование изображения может вызывать нежелательные искажения, поэтому выполняйте его с чрезвычайной осторожностью. Глава 20. Объекты изображения, области и карты изображений 631
Пример Используйте приложение The Evaluator для изучения свойств height и width Начните с получения значений по умолчанию, введя в верхнее текстовое поле следующие выражения. document.mylMG.height document.mylMG.width Увеличьте высоту изображения в два раза. document .mylMG.height = 18'0 Если вы прокрутите страницу, то увидите, что изображение сохранило свои пропорции. Далее измените ширину изображения. document.mylMG.width = 400 Просмотрите полученный результат. См. также: свойства hspace, vspace. href См. src. hspace vspace Значение: целочисленное Чтение/Запись Совместимость: WiijIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Свойства hspace и vspace управляют полем в виде прозрачной границы, окружающей изображение; его значения задаются в пикселях. Свойство hspace управляет отображением полей в верхней и нижней частях изображения, vspace — в левой и правой. По умолчанию изображения имеют значение поля, равное нулю пикселей. Пример Приложение The Evaluator также позволяет ознакомиться и со свойствами hspace и vspace. Сначала изучите изображение в левой нижней части страницы — оно не имеет гранип и при- вязано к левому полю документа. Теперь установите отступ — 30 пикселей. document.mylMG.hspace = 30 Как видите, изображение сместилось вправо на 30 пикселей. См. также: свойства height, width. isMap Значение: булево Чтение/Запись Совместимость: WinIE4+, МасШ4+, NN6+, Mozl+, Safaril+ Свойство isMap позволяет определить, должно ли изображение восприниматься как кар- та изображения на стороне сервера. Когда свойство определяет рисунок в качестве карты изображения на стороне сервера, координаты пикселя, на котором производится щелчок мы- шью, передаются как параметры ссылке href, в которую включено изображение. Клиент- ские карты изображения описаны в свойстве useMap далее в этой главе. 632 Часть III. Объекты документа
Пример Изображение в приложении The Evaluator не настроено в качестве карты изображения. Поэтому если ввести в верхнее текстовое поле следующее выражение, то будет возвращено значение false. document.myIMG.isMap См. также: свойство img. useMap. longDesc Значение: URL-адрес Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safari 14- Свойство longDesc — это URL файла, который предназначен для предоставления де- тального описания изображения, вставленного в элемент img. NN64- распознает это свойство, однако браузер не применяет полученную информацию для решения определенных задач — независимо, от того задана она в сценарии или с помощью атрибута longdesc. loop Значение: целочисленное Чтение/Запись Совместимость: WinIE44-, Мас1Е4-ь, NN-, Moz-, Safari- Свойство loop определяет количество воспроизведений видеоклипа, отображаемого с помощью объекта элемента img. После воспроизведения клипа указанное количество раз в области изображения будет отображаться только первый его кадр. Значение свойства по умолчанию 1; но если установить значение -1, то видеоклип будет воспроизводиться непре- рывно. К сожалению, установка свойства в значение 0 до задания свойства dynsrc не пре- дотвращает воспроизведения видеофайла по крайней мере единожды (кроме браузеров для Мас, как отмечалось при описании свойства dynsrc ранее в этой главе). Пример Пример использования свойства loop приведен в листинге 20.3, который уже рассматри- вался при изучении свойства dynsrc. См. также: свойство dynsrc. lows ГС lowSrc Значение: строка URL Чтение/Запись Совместимость: WinIE44-, MacIE44-, NN34-, Mozl4-, Safaril4- Для файлов изображений, которые загружаются в течение десяти и более секунд, в по- следних версиях браузеров определяются копии с низким разрешением или быстро загру- жающиеся заполнители, которые “бронируют” место для изображения, в то время как оно само загружается в браузер. Это альтернативное изображение задается в атрибуте lowsrc дескриптора <img>. Такой атрибут представлен свойством lowsrc объекта изображения. Все поддерживающие его браузеры признают только версию этого свойства, введенную в нижнем регистре. Но W3C DOM спецификация гарантировано распознает только вариант lowSrc. NN6 также признает только эту версию. Помните, если вы назначаете URL атрибуту lowsrc, то свойство complete принимает значение true, и обработчик события onload активизируется, когда файл с альтернативным изображением завершает загрузку в браузер. Браузер не дожидается загрузки файла, заданно- го в атрибуте src. Глава 20. Объекты изображения, области и карты изображений 633
Пример В листинге 20.5 в обработчике onload объекта изображения используются операторы определения этим свойствам значений. См. также: свойства img. src, img.complete. mimeType Значение: строка Только для чтения Совместимость: WinIE6+, MacIE-, NN-, Moz-, Safari- Это свойство возвращает описание MIME-типа в формате простого текста, например, JPEG Image или GIF Image. Пример Вы можете использовать свойство mimeType для определения формата изображения. if (document.mylMG.mimeType.indexof("JPEG") != -1) { // Операторы обработки JPEG-изображения } В этом примере метод indexof О используется для поиска фразы "JPEG" в строке описания MIME-типа. name Значение: идентификатор Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство name возвращает значение, присвоенное атрибуту name элемента img. Начиная с IE4 и NN6, вы можете использовать ID элемента, чтобы сослаться на объект элемента img в document. al 1 и document. getElementByld (). Но ссылки в формате document. имя- Изображения и document. images [имяИзображения] принимают только значение, на- значенное атрибуту name. В некоторых случаях элементам img удобнее назначить упорядоченные в алфавитном по- рядке имена (imgl, img2 и т.д.). Как и любое другое имя объекта, идентификатор не может начинаться с цифры. На практике вы редко будете заменять имя объекта элемента img иден- тификатором. Пример Все то же приложение The Evaluator поможет вам изучить свойство name изображения. Введите в верхнее текстовое поле такое выражение. document.mylMG.name Конечно, это излишне, поскольку имя входит в состав ссылки на объект. См. также: свойство id. nameProp Значение: строка имени файла Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- B отличие от свойства src, которое возвращает полный URL в IE, свойство nameProp в IE возвращает только имя файла и путь к нему. Если ваш сценарий замены изображения 634 Часть III. Объекты документа
нуждается в получении имени файла текущего изображения (чтобы определить, какое изо- бражение отображать следующим), то свойство name Prop облегчит эту задачу, задав факти- ческое имя файла без необходимости проведения обширного синтаксического анализа URL. Пример Вы можете применить приложение The Evaluator для сравнения результатов, возвращае- мых свойствами src и name Prop (пример приведен на прилагаемом к книге компакт-диске в IE5+). Введите в верхнее текстовое поле следующие выражения. document. mylMG. src document.mylMG.nameProp См. также: свойство img. src. naturalHeight naturalwidth Значение: целое число Чтение/Запись Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Эти свойства возвращают исходную ширину и высоту изображения, выраженные в пиксе- лях. Они часто применяются при масштабировании изображения в сценарии или с помощью атрибутов элемента img. Пример Приложение The Evaluator позволяет изучить и свойства naturalHeight, naturalwidth. Начните с получения значений по умолчанию, введя в верхнее текстовое поле следующее выражение. document.mylMG.width Увеличьте ширину изображения со значения 120 до 200. document.mylMG.width = 200 Если вы прокрутите изображение, то увидите, что оно изменило свой размер. Чтобы озна- комиться с исходными размерами изображения, выполните такое выражение. document.mylMG.naturalwidth Как видите, The Evaluator возвращает значение 120, хотя текущая ширина равна 200. См. также: свойство img.height, img. width. protocol Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE5+, NN-, Moz-, Safari- Свойство protocol в IE содержит только часть полного URL, которое возвращается свойством src, описывающим протокол для передачи данных, что позволяет сценарию вы- яснить, например, где находится источник изображения: на локальном’жестком диске или на Web-сервере. Возвращенные значения не являются фактическими определителями протоко- ла; они, скорее, описывают используемое средство — Hyper Text Transfer Protocol или File Protocol. Глава 20. Объекты изображения, области и карты изображений 635
Пример И вновь вам на помощь придет приложение The Evaluator. Введите в верхнее текстовое поле следующее выражение. document.mylMG.protocol См. также: свойства img. src, img. nameProp. src Значение: строка URL Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Свойство src — это шлюз к предварительной загрузке изображений (в объекты Image, которые хранятся в памяти) и выполнению замены изображений (в элементах img). Задайте URL свойству src объекта изображения в памяти, и вы заставите браузер загружать указанное изображение в свой собственный буфер (если пользователь разрешил кэширование). Задание URL свойству src объекта элемента img заставляет элемент отображать новое изображение. Чтобы воспользоваться преимуществом этой мощной комбинации средств, необходимо пред- варительно загрузить альтернативные версии заменяющих изображений в объекты изображе- ний в памяти и затем приравнять свойство src объекта изображения к свойству src необхо- димого объекта элемента img. В NN3, NN4 (все OS платформы) и IE3 для Мас размер изображения, определенного ат- рибутами элемента img (или, если они не заданы, то вычисленный браузером в соответствии с размером изображения), определяет прямоугольную область, резервируемую для этого изо- бражения. Попытка назначить объекту элемента img изображения разного размера приводит к принудительному их масштабированию, что позволяет заполнить указанную ранее прямо- угольную область (обычно приводит к искажению изображений). Во всех более поздних браузерах, тем не менее, объект элемента img изменяет свои размеры, чтобы расположить изображение на странице в неискаженном виде; остальное содержимое страницы перерас- пределяется таким образом, чтобы приспособиться к новому размеру изображения. Обратите внимание, что при считывании свойство src возвращает полный URL файла изо- бражения, включая протокол и путь. Зачастую неудобно проводить замену одного изображения другим, указывая расположение файла последнего в сценарии. Некоторые другие способы (например, сохранение имени файла изображения в глобальной переменной) значительно по- вышают эффективность управления изображениями (см. свойство nameProp в WinIE5+). Пример В следующем примере (листинг 20.4) вы ознакомитесь со страницей, на которую добав- лено несколько графических изображений. Его главное предназначение — это сравнение до- кументов с предварительной загрузкой (кэшированием) изображений и без нее. Также вы научитесь через указанное время автоматически изменять изображения в объекте img. Чаще всего последняя возможность применяется при добавлении на Web-узлы баннеров. При загрузке страницы в глобальной переменной сохраняется массив объектов изображений. Элементы массива имеют строковые имена с числовыми индексами ("deskl", "desk2" и т.д.). Эти имена используются в ссылках на элементы массива. Каждый объект изображения в мас- сиве имеет связанный с ним URL, соответственно которому выполняется предварительная за- грузка изображения. Рассматриваемая страница (рис. 20.1) содержит два элемента img. Один из них отображает некэшируемое изображение, а второй — кэшируемое. Под каждым изображением располагается список (элемент select), который применяется для выбора одного из четырех графических 636 Часть III. Объекты документа
файлов. Обработчик onchange каждого списка вызывает отдельную функцию замены кэшируе- мого (loadCached ()) или некэщируемого файла (loadindividual ()). Обе функции при- нимают в качестве единственного аргумента ссылку на форму, содержащую элементы select. Для циклического отображения изображений с пятисекундным интервалом в функции checkTimer () выполняется проверка установки флажка. Если флажок установлен, то свойст- во selectedlndex элемента select кэшированного изображения увеличивается (или обну- ляется, если индекс принимает максимальное значение). Далее вызывается функция loadCached (), которая определяет текущий элемент и отображает соответствующее изобра- жение. Рис. 20.1. Страница документа с кэшируемыми изображениями С целью повышения удобства использования страницы в дескриптор <body> добавляется обработчик событий onunload, который вызывает функцию resetSelects О . Эта функ- ция общего назначения просматривает формы страницы и все элементы формы. Она устанав- ливает свойство selectedlndex всех элементов select в значение ноль. Таким образом, если пользователь перезагрузит страницу или возвратится к ней с помощью кнопки Назад (Back), то изображения начнут отображаться в исходной последовательности. Листинг 20,4. Лосладомлимю» нгибрпаиг» lijrfip.i WTinifi <html> <head> <title>Image Object</title> <script type="text/javascript"> // объявление глобального массива изображений var imageDB; I/ предварительное кэширование изображений Глава 20. Объекты изображения, области и карты изображений 637
if (document.images) { // установка индексных имен массива var deskimages = new Array("deskl", "desk2", "desk3", "desk4"); // создание и предварительная загрузка массива изображений imageDB = new Array(4); for (var i = 0; i < imageDB.length ; i++) { imageDB[deskimages[i]] = new Image(120,90); imageDB[deskimages[i]].src. = deskimages[i] + ".gif"; // изменение отдельных изображений function loadindividual(form) { if (document.images) { var gifName = form.individual.options[form. individual.selectedlndex].value; document.getElementByldCthumbnaill") .src = gifName + ".gif"; // изменение кэшированных изображений function loadCached(form) { if (document.images) { var giflndex = form^cached.options[form.cached, selectedlndex].value; document.getElementByld("thumbnail2").src = imageDB[giflndex].src; } } function checkTimerO { if (document.images && document.Timer.timerBox.checked) { var giflndex = document.selections.cached.selectedlndex; if (++gifIndex > imageDB.length - 1) { giflndex = 0; } document.selections.cached.selectedlndex = giflndex; loadCached(document.selections); var timeoutID = setTimeout("checkTimer()",5000); . } } // восстановление при выгрузке function resetSelects() { for (var i = 0; i < document.forms.length; i++) { for (var j =0; j < document.forms[i].elements.length; j++) { if (document.forms[i].elements[j].type == "select-one") { document.forms[i].elements[j].selectedlndex = 0; } } } // инициализация function init() { loadindividual(document.selections); loadCached(document.selections); setTimeout("checkTimer()",5000); } 638 Часть III. Объекты документа
</script> </head> cbody onload="init()" onunload="resetSelects ()"> <hl>Image Object</hl> chr /> ' <center> «table border="3" cellpadding="3"> <tr> <th>«/th> <th>Individually Loaded«/th> <th>Pre-cachedc/th> </tr> <tr> <td align="right"><b>Image:</b>«/td> «tdximg alt="image" src="cpul.gif" id=”thunibnaill" height="90" width="120" /x/td> «tdximg alt="image" src="deskl.gif" id="thumbnail2" height="90" width="120" /></td> </tr> <tr> <td align= "right"xb>Select image:</b>«/td> «form name="selections"> «tdxselect name= "individual" onchange="loadindividual(this.form)"> «option value="cpul">Wires«/option> «option value="cpu2">Keyboard«/option> «option value="cpu3">Disks«/option> «option value="cpu4">Cables«/option> «/select x/td> «tdxselect name="cached" onchange= "loadCached(this.form)"> «option value="deskl">Bands</option> «option value="desk2">Clips«/option> «option value="desk3">Lamp«/option> «option value="desk4">Erasers«/option> </select>«/td> </form> </tr> </table> «form name="Timer"> «input type="checkbox" name="timerBox" onclick="checkTimer()" />Auto-cycle through pre-cached images </form> </center> </body> </html> См. также: свойства img. lowsrc, img. nameProp. start Значение: строка Чтение/Запись Совместимость: WiriDE4+, MacIE4+, NN-, Moz-, Safari- Свойство start задается для файлов видеоклипов, воспроизводимых в области элементов img в IE4+. По умолчанию видеоклип начинает воспроизводиться (не в Мас) тогда, когда файл Глава 20. Объекты изображения, области и карты изображений 639
изображения отображается на экране. Такое поведение следует из настройки по умолчанию свойства start — fileopen. Другое распознаваемое значение — mouseover; оно указывает воспроизводить клип только в случае, когда пользователь наводит указатель на изображение. См. также: свойства img. dynsrc, img. loop. useMap Значение: идентификатор Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство useMap представляет атрибут usemap элемента img, указывая на имя, назна- ченное элементу area на странице (см. листинг 22.7). Этот элемент area содержит подроб- ные сведения о клиентской карте изображения (см. далее в этой главе). Значение свойства useMap должно включать символ решетки, который определяет внутреннюю HTML-ссылку на странице. Если необходимо выбрать одну из двух или большего количества карт изобра- жения для того же самого элемента img (например, изображение заменяется или пользова- тель находится в другом режиме), можно задать несколько map-элементов так, чтобы каждый из них имел собственное имя. Изменение свойства useMap объекта элемента img позволяет связать карту с изображением. См. также: свойство isMap. vspace См. hspace. width См. height. X У Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN4, Moz-, Safari- B NN4 сценарий может получать координаты х и у элемента img (верхний левый угол прямоугольной области, занятой изображением) с помощью свойств х и у. Эти свойства дос- тупны только для чтения. Они вытеснены в NN6 свойствами of f setLef t и of f setTop, за- даваемыми для любого элемента. Даже вне DHTML можно использовать значения этих свойств, чтобы прокручивать доку- мент в NN4 в строго определенное место (методом window. scrolITo ()). Поскольку все операционные системы отображают страницы и задают размеры окон браузера по-разному, изображение можно динамически перемести в необходимое положение (другими словами, прокрутить документ) в зависимости от действий пользователя. Пример Для прокрутки документа таким образом, чтобы ссылка располагалась на несколько пик- селей ниже верхнего края окна, выполните следующее выражение. window.scrollTo(document.images[0].x, (document.images[0].у - 3)); См.также::свойства img.offsetLeft, img.OffsetTop; методы img.scrolUntoViewO, window.scrollTo(). 640 Часть III. Объекты документа
Обработчики событий onabort onerror Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Иногда ваши сценарии должны будут реагировать на ситуацию, когда пользователь щелкает на кнопке Stop во время загрузки изображения или возникновения сбоев в сетевых соединени- ях, что сводит на нет весь процесс загрузки изображения. Для этого используйте обработчик со- бытий onabort, позволяющий активизировать определенную функцию в случае щелчка на кноп- ке Stop. Если возникает ошибка в передаче изображения, используйте обработчик onerror. Данные обработчики событий не позволяют решить всех проблем, с которыми вы можете столкнуться на практике. Например, они не позволяют получить имя файла загружаемого изображения. Если такая информация в сценарии необходима, ее нужно сохранить в отдель- ной переменной перед установкой свойства src изображения. У вас также нет возможности узнать природу ошибки, которая является причиной запуска соответствующего обработчика. С возникшими проблемами можно справиться, выполнив перезагрузку страницы либо пере- местившись в другое место Web-страницы. Пример В коде листинга 20.5 используется обработчик события onabort. Если изображение уже кэшировано, то необходимо завершить работу и загрузить браузер заново, чтобы предотвра- тить загрузку изображения. В Данном случае перезагружается сразу вся страница. Вы при не- обходимости можете сделать исключения, несколько изменив код. onload Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari! + Обработчик события onload объекта img активизируется, когда происходит одно из трех действий: файл lowsrc-изображения заканчивает загружаться; для изображения отсут- ствует lowsrc-копия, а изображение src заканчивает загружаться; при появлении каждого кадра анимационного GIF-изображения (GIF89a). Обратите внимание, что при определении lowsrc-файла внутри дескриптора <img> объект img не получает никакой информации о том, что изображение src закончило загружаться. Если эта информация применяется в сценарии, то специально проверьте текущий файл изо- бражения, проанализировав свойство src объекта изображения. Остерегайтесь того, что обработчик события onload элемента img может активизиро- ваться до завершения загрузки остальных элементов страницы. Если функция обработчика событий ссылается на другие элементы страницы, то она должна проверить существование других элементов до обращения к ним. Пример Чтобы в полной мере ознакомиться с листингом 20.5, перезагрузите браузер. При первой загрузке документа файл изображения lowsrc загружается вместо фотографии клавиатуры. После этого в текстовое поле выводится значение done (обработчиком onload), даже если основное изображение еще не загружено. Вы можете поэкспериментировать с другим изо- бражением — фотографией причудливой скалы. Глава 20. Объекты изображения, области и карты изображений 641
<html> <head> «title>«/title> «script type="text/javascript"> function loadlt(thelmage, form) { if (document.images) { form.result.value = ""; document.images[0].lowsrc = "deskl.gif"; document.images[0].src = thelmage; } } function checkLoad(form) { if (document.images) { form.result.value = document.images[0].complete; } } function signal() { if(confirm("You have stopped the image from loading. Do you want to try again?")) { location.reload(); } } «/script> </head> «body> «img alt="image" src="cpu2.gif" lowsrc="desk4.gif" width="120" height="90" onload="if (document.forms[0].result) document.forms[0].result.value='done'" onabort="signal()" /> «form> «input type="button" value="Load keyboard" onclick="loadlt('cpu2.gifthis.form)" /> «input type=“button" value="Load arch" onclick="loadlt('arch.gif',this.form)" /> «pxinput type="button" value="Is it loaded yet?" onclick="checkLoad(this.form)" /> «input type="text" name="result" /> «input type="hidden" /x/p> «/form> </body> </html> См. также: свойства img. src, img. lowsrc. Объект элемента area Свойства, методы, обработчики событий для этого HTML-элемента описаны в главе 15. Свойства Методы Обработчики событий alt coords hash 642 Часть III. Объекты документа
Окончание таблицы Свойства Методы Обработчики событий host hostname href noHref pathname port protocol search shape target Синтаксис Доступ к свойствам элемента area. (NN3+/IE4+) (IE4+) (IE4+) [window.]document.links[индекс] .свойство [window.]document.all.идентификатор.свойство | метод ([параметры]) [window.]document.all.идентификатор.areas[ивдекс]- свойство| метод([параметры] ) (IE5+/W3C) [window.]document.getElementByld("MAPElemID).areas[ивдекс]. свойство | метод ( [параметры] ) (IE5+/W3C) [window.]document.getElementByld("идентификатор").свойство| метод([параметры] ) Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Описание объекта Объектные модели документа определяют объект области карты изображения как один из объектов ссылки в документе (см. объект анкера в главе 19). Такое поведение не лишено здраво- го смысла, поскольку щелчок мышью на области карты приводит пользователя к другому доку- менту или анкеру в том же самом документе — создается гиперссылка внутри изображения. В HTML определение ссылок и областей карт изображения отличается довольно сущест- венно; а вот в самых ранних версиях сценариев оба вида объектов имели почти одни и те же свойства и обработчики событий. Чтобы детально ознакомиться с объектом ссылки, обрати- тесь к главе 19. Единственное отличие состоит в том, что в NN3 и NN4 для объекта области карты не определено полного набора обработчиков событий мыши — можно рассчитывать только на использование onclick (NN4+), onmouseover и onmouseout. Начиная с IE4 и NN6, все атрибуты элемента area доступны как свойства, используемые при написании сценария. Кроме того, с помощью объекта элемента тар можно изменить структуру клиентских областей карты. Объект элемента тар содержит массив объектов эле- ментов area. Существует возможность удалять, изменять или добавлять элементы area внутри элемента тар. Глава 20. Объекты изображения, области и карты изображений 643
Клиентские карты изображения использовать очень интересно. К тому же, они хорошо описаны в документации по HTML (с тех пор как впервые были представлены в NN2). По существу, вы определяете любое число прямоугольных областей в пределах изображения, за- давая координаты их углов. Помочь правильно задать координаты областей изображений в атрибуте coords дескриптора <агеа> вам помогут графические средства. Существует одна деталь, которая вводит в заблуждение многих HTML-разра- Смет ботчиков. Она заключается во взаимосвязи дескрипторов <тар> и <img>. Сна- ч. чала назначьте имя дескриптору <тар>. В дескрипторах <img> атрибут usemap ' * должен содержать символ решетки (#) и имя карты изображения. Если вы забу- дете ввести символ решетки, то не сможете присоединить изображение к соот- ветствующей карте. Листинг 20.6 содержит пример клиентской карты изображения, с помощью которой поль- зователь может перемещаться по Ближнему Востоку. При наведении указателя на отдельные части изображения его вид изменится, определив ссылки, на которых можно щелкнуть. Щел- чок на графической области приводит к выводу сообщения с названием выбранного геогра- фического региона. Листинг 20.6. Простая клиентская карта изображения <html> <head> <title></title> <script type="text/javascript"> function show(msg) { window, status = msg.- return true; function go(where) { alert("We're going to " + where + " ! ") ; function clearltO { window.status = ""; return true; } </script> </head> <body> <hl>Sinai and Vicinity</hl> <img alt="image" src="nile.gif" width="320" height="240" usemap="#sinai" /> <map id="sinai" name="sinai"> <area href="javascript:go('Cairo’)" coords="12,152,26,161" shape="rect" onmouseover="return show('Cairo')" onmouseout="return clearltO" /> <area href="javascript:go('the Nile River')" coords="l,155,6,162,0,175,3,201,61,232,109,227,167,238,274, 239,292,220,307,220,319,230,319,217,298,213,282,217,267,233, 198,228,154,227,107,221,71,225,21,199,19,165,0,149" shape="poly" onmouseover="return show('Nile River')" onmouseout=”return clearltO" /> <area href="javascript:go('Israel')" coords="95,69,201,91" shape="rect" onmouseover="return show('Israel')" onmouseout="return clearltO" /> <area href="javascript:go('Saudi Arabia')" 644 Часть III. Объекты документа
coords="256,57,319,121" shape="rect" onmouseover= "return show('Saudi Arabia')" onmouseout=" return clearltO" /> <area href="javascript:go('the Mediterranean Sea')" coords="l,55,26,123" shape="rect" onmouseover="return show('Mediterranean Sea')" onmouseout="return clearltO" /> «area href="javascript:go('the Mediterranean Sea')" coords="27,56,104,103"’ shape="rect" onmouseover^"return show('Mediterranean Sea')" onmouseout="return clearltO" /> </map> </body> </html> Свойства alt Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство alt представляет атрибут alt элемента area. Будущие браузеры могут ис- пользовать этот атрибут, чтобы обработать дополнительную информацию о ссылке, связан- ной с элементом area. См. также: свойство title. coords shape Значение: строка Чтение/Запись Совместимость: WintE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойства coords и shape управляют расположением, размером и формой изображения, заданными элементом area. Значения формы, которые вы можете использовать для этого свойства, определяют формат представления значений в свойстве coords. Форма Координаты Пример circ центр x, центр у, радиус "30, 30, 20" circle центр х, центр у, радиус "30, 30, 20" poly х1,у1,х2,у2,... "0, 0, 0, 30, 15, 30, 0, 0" polygon х1,у1,х2,у2,„. "0, 0, 0, 30, 15, 30, 0, 0" rect левая, верхняя, правая, нижняя "10, 20, 60, 40" rectangle левая, верхняя, правая, нижняя "10, 20, 60, 40" Заданная по умолчанию форма элемента area — rectangle. Глава 20. Объекты изображения, области и карты изображений 645
hash host hostname href pathname port protocol search target См. соответствующие свойства объекта ссылки (глава 19). shape См. coords. Объект элемента тар Свойства, методы, обработчики событий этого элемента HTML описаны в главе 15. Свойства Методы Обработчики событий areas [] name onscroll Синтаксис Доступ к свойствам объекта элемента тар. (IE4+) [window. ] document.all.идентификатор. свойство|метод( [параметры]) (IE5+/W3C) [window. ] document. getElementByld ("идентификатор”) . свойство | метод ( [параметры] ) Совместимость: WinIE4+, МасШ4+, NN6+, Mozl+, Safari 1+ Описание объекта Объект элемента тар — невидимый HTML-контейнер всех элементов area, каждый из которых определяет активную область изображения. Клиентская карта изображения назнача- ет ссылки для прямоугольных, круговых или многоугольных областей изображения. Намного более важные свойства объекта элемента тар — массив areas; в меньшей сте- пени— его свойство name. Маловероятно, что вы будете изменять имя элемента тар. (Лучше определить имена отдельным элементам тар, а затем задать соответствующие имена в качестве значения свойства useMap элемента img.) Вы можете использовать массив areas, чтобы изменить структуру объектов area внутри карты изображения на стороне клиента. 646 Часть III. Объекты документа
Свойства areas [] Значение: массив объектов area Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Используйте массив areas, чтобы просмотреть все объекты area в элементе тар. Если NN6 максимально точно поддерживает структуру узлов, принятую в W3C DOM, то IE4+ обеспечива- ет более прямой доступ к объектам area, вложенным в тар. Если необходимо перераспре- делить элементы area внутри объекта тар, удалите старые элементы, установив свойства length массива areas в нуль, а затем заново заполните этот массив элементами area. Пример Листинг 20.7 демонстрирует принципы замены элементов area в элементе тар. Страни- ца загружается с изображением клавиатуры. Это изображение связано с клиентской картой изображения keyboardMap, содержащей три активных области. Если впоследствии изме- нить изображение элемента img, то сценарий заменит его свойство useMap, соответствую- щее новой карте изображения. Наведите указатель мыши на каждое изображение и изучите URL-адреса их активных областей (отображаются в строке состояния). На странице также присутствует кнопка, которая вызывает функцию makeArea () (не под- держивается в Мас1Е5). Указанная функция создает четыре новых элемента area и настраи- вает их в контексте текущего изображения. На рис. 20.2 показана ссылка для четвертой ак- тивной области. ЦЛ.Ш.ИШ д.жтв— sggggggg;*аав • File Edit View Favorite* Tool* Help - о a sa & e; 0* «Oja w " map Element Object I* Л [ ' Lood Lamp Image j Write Map on tie Fly | I..Lund Layboardlmoga | Puc. 20.2. Создание клиентской карты изображения Глава 20. Объекты изображения, области и карты изображений 647
Листинг 20.7. Изменения активных областей “на лету” i <html> <head> <title>map Element Object</title> <script type="text/javascript"> // генерирование элементов области function makeAreasO { document.getElementByld("mylMG").src = "desk3.gif"; // создание объектов элементов области var areal = document.createElement("area"); areal.href = "Script-Made-Shade.html"; areal.shape = "polygon"; areal.coords = "52,28,108,35,119,29,119,8,63,0,52,28"; var area2 = document.createElement("area"); area2.href = "Script-Made-Base.html"; area2.shape = "rect"; area2.coords = "75,65,117,87"; var агеаЗ = document.createElement("area”); area3.href = "Script-Made-Chain.html";' агеаЗ.shape = "polygon"; агеаЗ.coords = "68,51,73,51,69,32,68,51"; var area4 = document.createElement("area"); area4.href = "Script-Made-Emptyness.html"; area4.shape = "rect"; area4.coords = "0,0,50,120"; // включение новых элементов в дочерние узлы МАР var mapObj = document.getElementByld("lamp_map"); while (mapObj.childNodes.length) { mapObj.removechild(mapObj.firstChild); } mapObj.appendChild(areal) ; mapObj.appendChild(area2); mapObj.appendChild(агеаЗ); mapObj.appendChild(area4); // обработка ошибки отображения в NN6 document.getElementByld("mylMG").style.display = "inline"; } function changeToKeyboard() { document.getElementByld("mylMG").src = "cpu2.gif"; document.getElementByldCmylMG") .useMap = "ttkeyboardMap"; } function changeToLamp() { document.getElementByldCmylMG").src = "desk3.gif"; document.getElementByldCmylMG").useMap = "#lampMap"; } </script> </head> <body> <hl>map Element Object</hl> <hr /> <img alt="image" id="myIMG" src="cpu2.gif" width="120" height="90" usemap="#keyboardMap" /> стар id="keyboardMap" name="keyboardMap"> carea href="AlpaKeys.htm" shape="rect" 648 Часть III. Объекты документа
coords="0,0,26,42" /> «area href="ArrowKeys.htm" shape="polygon" coords="48,89,57,77,69,82,77,70,89,78,84,89,48,89" /> «area href="PageKeys.htm" shape="circle" coords="104,51,14" /> </map> стар name="lampMap" id="lamp_map"> «area href="Shade.htm" shape="polygon" coords="52,28,108,35,119,29,119,8,63,0,52,2 8" /> «area href="Base.htm" shape="rect" coords="75,65,117,87" /> «area href="Chain.htm" shape="polygon" coords="68,51,73,51,69,32,68,51" /> c/map> cform> «pxinput type="button" value="Load Lamp Image" onclick="changeToLamp()" /> cinput type="button" value="Write Map on the Fly" onclick="makeAreas()" />c/p> cp>cinput type="button" value="Load Keyboard Image" onclick="changeToKeyboard()" />c/p> с/form> c/body> </html> См. также: объект элемента area. Глава 20. Объекты изображения, области и карты изображений 649
Объект form и вложенные в него объекты До появления динамических объектных моделей и ав- томатического изменения содержимого страницы сценарии в HTML-документе, как правило, управляли исклю- чительно формами. Несмотря на появление новых возможно- стей в DHTML, формы остаются первичными элементами пользовательского интерфейса HTML-документов, позво- ляющими вводить информацию и выбирать значения с по- мощью привычных элементов управления (кнопок, списков оп- ций и т.п.). Использование форм в сценарии и элементов форм часто требует создания ссылок на объекты. Ссылки могут стать довольно длинными к тому моменту, когда вы начнете использовать свойство элемента управления формы (дочернего объекта формы, являющейся дочерним объектом документа, который выступает дочерним объектом окна или фрейма). Расширенные объектные модели W3C предоставляют доступ в сценарии к элементам управления формой элементы и их свойствам, описанным в спецификации HTML 4.0. Эле- менты fieldset и legend объединяют в сценарии все элементы управления формы текущего документа. Еще один элемент— label — представляет собой контейнер тексто- вых надписей, которые часто прикрепляются к элементам управления форм. Если в сценарии не всегда возникает по- требность в этих объектах, браузеры предоставляют к ним доступ таким же образом, как к любому другому HTML- элементу, поддерживаемому браузером. Объект form в объектной модели Взгляните еще раз на иерархию объектов JavaScript в объектной модели; обратите внимание на самый низкий уровень (см. рис. 14.1), представленный на рисунке. Объект элемента form может содержать большое количество объектов
элементов формы (иногда их называют элементами управления формы) — см. главы 22-24. В этой главе речь пойдет о контейнерах. Хорошие новости для разработчика заключаются в том, что многие сценарии, выполняе- мые на стороне клиента и поддерживающие элементы управления форм, совместимы почти со всеми браузерами. Вполне вероятно, что вы будете использовать более новые способы об- ращения к формам и их вложенным элементам, предполагая, что большая часть посетителей ваших Web-страниц использует новые браузеры. Тем самым вы сможете избежать необходи- мости утомительной отладки “старого” синтаксиса в случае создания ссылок. Тем не менее, почти весь код примеров в этой и следующих трех главах использует синтаксис, который яв- ляется совместимым с самыми ранними версиями браузеров. Обратите внимание, что боль- шинство преобразований в характеристиках элементов форм (в новых браузерах) в первую очередь коснулось добавления свойств, общих для всех HTML-элементов. Элемент form Свойства, методы и обработчики событий этого HTML-элемента описаны в главе 15. Свойства Методы Обработчики событий acceptCharset handleEvent() onreset action 'reset() onsubmit autocomplete elements[] encoding enctype length method name target submit() Синтаксис Доступ к свойствам и методам объекта form. (Все) [window. ] document. имяФормы. свойство | метод ( [параметры] ) (Все) [window. ] document. forms [индекс] . свойство | метод ( [параметры] ) (Все) [window. ] document. forma [ "имяФормы" ] . свойство | метод ([параметры]) (IE4+) [window.]document.all.идентификатор.свойство|метод([параметры]) (IE5+/W3C) [window. ] document .getElementByld] "идентификатор") .свойство) | метод ( [параметры] ) Совместимость: WinIE3+, Мас!ЕЗ+, NN2+, Mozl+, Safaril+ Глава 21. Объект form и вложенные в него объекты 651
Описание объекта Формы и их элементы — наиболее общие двусторонние шлюзы между пользователями и сценариями JavaScript. Элемент управления формы — единственный способ предоставить пользователям возможность введения текстовой информации. Элементы управления формы также представляют максимально стандартизованные и знакомые опции пользовательского интерфейса, которыми посетитель может воспользоваться для выбора значений из предопре- деленного набора данных. Иногда этот выбор предоставляется в виде переключателя, флажка или элементов списка. Вы, очевидно, знаете, что форма — это пользовательское средство ввода информации, ко- торая отправляется на сервер. Какие действия сервер выполняет с этой информацией, зависит от CGI-программы, запущенной на нем. Если ваша Web-страница выполняется на сервере не- посредственно под вашим управлением, то вы можете определить все необходимые операции по сбору данных или программ поиска в базе данных, что позволит максимально эффективно взаимодействовать с пользователем. Но некоторые Intemet-провайдеры (ISP) не ориентиру- ются на предоставление серверных услуг и не обеспечивают поддержку CGI-программ — в лучшем случае вам предоставят ограниченный набор популярных, но малофункциональных CGI-программ, доступных всем клиентам. Клиентские базы данных или средства выполнения транзакций редко предусмотрены услугами Intemet-провайдера. Независимо от статуса Internet-сервера, вы можете найти формам разное применение в JavaScript- сценариях. Например, рекомендуется не сразу приступать к обработке данных на стороне серве- ра и интенсивному обмену данными, а с помощью JavaScript предварительно проанализировать необработанные данные, полученные от пользователя, на стороне клиента, чтобы удостове- риться, что используется формат данных, который конечная база данных или другие про- граммы сможет обработать без фатальных последствий. Любое подобное взаимодействие с данными происходит в браузере без единого лишнего бита, отправленного по сети. Глава 43 будет посвящена эффективным методам проверки данных, собранных с помощью форм. От того, как определяется элемент form (независимо от пользовательских элементов ин- терфейса, описанных в следующих главах), во многом зависит, как вы будете использовать информацию, полученную от элементов управления формы. Если вы намереваетесь исполь- зовать форму исключительно для обработки полученных данных в JavaScript-сценарии (отсутствуют запросы или регистрация на стороне сервера), то нет необходимости использо- вать в нем атрибуты action, target и method. Но если ваша Web-страница будет от- правлять информацию или запросы обратно, на сервер, то вы должны определить атрибуты action и method. Кроме того, необходимо определить атрибут target (если возвращенные с сервера данные нужно отобразить в окне, отличном от окна запроса) и атрибут enctype (если сценарий вашей формы отправляет на сервер данные в определенном формате MIME, а не в обычной кодировке ASCII). Ссылка на элементы управления формы Для большинства клиентских сценариев взаимодействие между пользователем и системой происходит с помощью элементов в пределах формы. Объект form— это обычный контей- нер для различных элементов управления. Если ваши сценарии выполняют проверку кор- ректности введенных пользователем данных до их отправки или обработки на сервере или клиенте, то многие операторы воспринимают объект формы как часть ссылки на элемент. Комплексный HTML-документ может содержать много объектов form. Каждая пара де- скрипторов <f orm>. . . </f orm> определяет одну форму. Вы никогда не проиграете (мы не учитываем потенциальное замешательство со стороны того, кто прочитает ваш сценарий), 652 Часть III. Объекты документа
если многократно определите имена элементов в каждой из форм документа. Например, если каждая из трех форм имеет набор переключателей с именем choice, то задание ссылки на каждый из них гарантирует, что JavaScript точно их не перепутает. Ссылка на первый пере- ключатель каждого из наборов задается следующим образом. document.forms[0].choice[0] document.forms[1].choice[0] document.forms[2].choice[0] Помните также, что можно создать формы (или любой объект HTML для описанного слу- чая) “на лету”, когда HTML-строки в процессе выполнения сценария записываются в другие окна или фреймы. В результате вы можете определить различные атрибуты формы на основе установок существующего документа. Передача форм и элементов в функции Если форма или элемент формы содержат обработчик события, который вызывает функ- цию, определенную в другой части документа, вы можете использовать дополнительные ключевые слова, чтобы упростить задачу обращения к объектам (в то время как функция вы- полняет свою работу). Непонимание этой концепции не только вынуждает создавать большее количество кода, чем необходимо, но также безнадежно запутывает при попытке анализа кода в JavaScript-документе другого разработчика. В параметрах обработчика событий часто встре- чается ключевое слово this, которое представляет ссылку на текущий объект, содержащий ат- рибут обработчика событий. Например, рассмотрите функцию и форму листинга 21.1. Полный пользовательский интерфейс состоит из элементов формы, показанных на рис. 21.1. Листинг 21.1. Передача объекта Corm в качестве параметра «html> «head> «title>Beatle Picker«/title> «script type="text/javascript"> function processData(form) { for (var i = 0; i < form.Beatles.length; i++) { if (form.Beatles[i].checked) { break; } } var chosenBeatle = form.Beatles[i].value; var chosenSong = form.song.value; alert("Looking to see if " + chosenSong + " was written by " + chosenBeatle + "..."); } function checkSong(songlitle) { var enteredSong = songTitle.value; alert("Making sure that " + enteredSong + " was recorded by the Beatles."); } </script> «/head> <body> «form name="Abbey Road"> Choose your favorite Beatle: «input type="radio" name="Beatles" value="John Lennon" checked="true" />John Глава 21. Объект form и вложенные в него объекты 653
<input type="radio" name="Beatles" value="Paul McCartney" /> Paul cinput type="radio" name="Beatles" value="George Harrison" />George <input type="radio" name="Beatles" value="Ringo Starr" />Ringo <p>Enter the name of your favorite Beatles song:<br /> •cinput type="text" name="song" value="Eleanor Rigby" onchange="checkSong(this)" /></p> cpxinput type="button" name= "process" value="Process Request..." onclick="processData(this.form)" /></p> </form> </body> </html> Функция processData (), которая считывает и записывает свойства многочисленных элементов управления формы, ссылается на элемент управления двумя способами. Первый способ состоит в том, чтобы определить обработчик событий onclick (кнопка в нижней части документа), вызвать функцию processData () и не передавать ей никаких парамет- ров. Внутри этой функции все ссылки на объекты (переключатели или поля указания песни) должны быть представлены в полном виде, чтобы получить значение, введенное в поле song. document.forms[0].song.value Рис. 21.1. Элементы управления передают различные ссылки в функцию, представленную в листинге 21.1 Более эффективный способ состоит в том, чтобы передать ссылку на объект form как па- раметр, в котором вызывается функция (см. листинг 21.1). Определив this. form как пара- метр, вы поручите JavaScript передать все, что он знает относительно формы, из которой вы- зывалась эта функция (form— это свойство каждого элемента управления формы; данное 654 Часть III. Объекты документа
свойство— ссылка на форму, которая содержит текущий элемент управления; поэтому this. form передает значение свойства form элемента управления). В функции ссылка на объект form присваивается имени переменной (произвольно устанав- ливается для значения form), которая задается в круглых Скобках после имени функции. Пара- метр имени переменной form в данном случае используется потому, что он представляет целую форму. Но вы можете применить любое достоверное имя переменной, которое вам нравится. Ссылка на форму содержит всю необходимую браузеру информацию, чтобы найти эту форму в пределах документа. Поэтому любые операторы в функции могут использовать зна- чение данного параметра вместо более громоздкой ссылки на форму. Таким образом, можно использовать form, чтобы заменить document. forms [0] в любой ссылке на объект фор- мы. Чтобы получить значение поля song, необходимо задать следующую ссылку. form.song.value Если бы был назначен объект формы переменной с именем Sylvester, ссылка выгляде- ла бы так. Sylvester.song.value Если параметр функции — это ссылка на объект, операторы в функции могут получать или устанавливать свойства этого объекта так же, как вызываются его методы. Другой способ использования ключевого слова this заключается в передаче его как па- раметра. В отличие от this. form, которая задает ссылку на форму, содержащую элемент, this определяет ссылку исключительно на сам элемент. В листинге 21.1 вы можете доба- вить обработчик событий к полю song, чтобы сделать возможной проверку вводимых дан- ных (и удостовериться, что введенный элемент присутствует в базе данных песен “Битлз”, созданных в другой части документа). Поэтому в функцию анализа данных советуем отпра- вить только объект field. cinput type="text" name="song" onchange "checkSong(this)" /> Затем создайте функцию, которая будет выполнять запрос обработчика событий. function checkSong(songTitle) ( var enteredSong = songTitle.value alert("Making sure that " + enteredSong + " was recorded by the Beatles.") } В пределах этой функции вы можете идти прямо к основе — свойству value элемента, избежав более длинной ссылки. В дальнейшем как параметр передается только свойство элемента управления формы. В последнем примере функции checkSong () требуется только свойство value этого по- ля, поэтому обработчик событий может передавать this. value как параметр. Поскольку this ссылается на тот же объект, в котором появляется обработчик событий, синтаксис this. имяСвойства позволяет извлекать и передавать свойство. cinput type="text" name="song" onchange="checkSong(this.value)" /> Преимущество этого способа передачи данных формы состоит в том, что функция не вы- полняет такого количества работы, как в предыдущем случае. function checkSong(songTitle) { alert("Making sure that " + songTitle + " was recorded by the Beatles.") } В отличие от передачи ссылок на объекты (подобно форме и текстовому полю, как пока- зано выше), при передаче значения свойства (например this. value) последнее задается без ссылки на объект, который оно представляет. Это вполне приемлемо, когда функция нуждается Глава 21. Объект form и вложенные в него объекты 655
в значении, чтобы выполнить свою работу. Однако, если часть этой работы сострит в изме- нении свойства объекта (например, преобразовании текста к верхнему регистру и повтор- ного отображения этого текста в поле), то значение, переданное в функцию, не обеспечи- вает “обратную связь” с породившим его объектом. Чтобы изменить свойство объекта, который вызывает функцию обработки событий, вам необходимо передать ссылку на опреде- ленный объект — и функция будет знать, где искать конечный объект. Многие разработчики с опытом написания программ на других языках ожидают, Сомт что параметры могут быть переданы либо по ссылке, либо по значению, но не X обоими путями. Эмпирическое правило в JavaScript, однако, является довольно ' У забавным исключением из написанных правил: ссылки на объекты передаются по ссылке, значения свойста — по значению. Ниже приведены принципы, которыми следует руководствоваться, чтобы правильно оп- ределить тип значения, передаваемого обработчику событий. Элемент управления формы (this) передается в том случае, если функция должна по- лучить последующий доступ к этому же элементу управления (возможно, с целью по- лучения свойства value объекта, преобразования текста к верхнему регистру и по- следующей записи результата обратно в значение свойства этого же объекта). Передается только одно свойство (this. propertyName), если функция нуждается в доступе исключительно для чтения к этому свойству. Передается полный объект form элемента (this. form), если функция обращается ко многим элементам внутри формы (например, щелчок мышью на кнопке указывает на то, что функция должна восстановить содержимое поля). Не забывайте, что вы можете передать в функцию несколько параметров (например onclick="someFunction (this. form, this name) ") или даже несколько объектов этой же самой формы (например onclick="someFunction(this.form, emailAddr.value)"). Главное— задать входящие параметры в соответствии с типом данных, воспринимаемым функцией. (В главе 33 подробно описаны пользовательские функции.) Отправка форм по электронной почте У разработчиков сценариев часто возникает вопрос, связанный с тем, как отправить фор- му в виде почтового сообщения автору страницы. Эта задача предполагает возможность от- правки “секретного” сообщения автору каждый раз, когда кто-то посещает его Web-страницу. Сначала мы узнаем, в чем же заключается “секретность” происходящего. Адрес электронной почты посетителя — ценная личная информация, к которой вы не по- лучаете доступа без разрешения владельца. Это и есть та причина, по которой в NN устранена возможность отправки почтовых сообщений разработчику (она поддерживалась в NN2 и раз- решала отправлять форму с помощью протокола mailto: без ведома владельца URL). Вы можете использовать средства NN3, но я не сторонник тайного использования адресов элек- тронной почты и поэтому не буду в этой книге предавать огласке “грязные” методы работы. Кроме того, поскольку многие пользователи переходят к новым версиям браузера, рано или поздно они осознают невозможность того, что ранее было доступно. Microsoft, с другой стороны, пошла слишком далеко в вопросе недопустимости отправки форм по электронной еще в самых ранних версиях браузера. Если браузеры Nescape показы- вают пользователю предупреждение, что отправляемое электронное сообщение содержит ад- рес разработчика (сохраненный в установках браузера), в котором можно одобрить этот не- продуманный поступок, ГЕЗ категорически отказывается отправлять содержимое формы в виде почтового сообщения. IE4 отправляет содержимое формы как вложение к сообщению, 656 Часть III. Объекты документа
созданному в Microsoft Outlook, но только после отображения окна создания сообщения. На- чиная с IE5, этот процесс становится более гибким, а результирующий эффект — лучше, чем в случае использования Outlook в качестве почтового клиента по умолчанию. Многие поставщики Intemet-услуг обеспечивают разработчиков CGI-программами, кото- рые могут получать почтовые сообщения, содержащие формы с любыми адресам электрон- ной почты. Этот способ управления данными формы, однако, не позволяет получить доступ к почтовому адресу посетителя (за исключением случая, когда ваша форма не содержит поля, где посетитель вводит такую информацию добровольно). Приведенное ниже описание методов отправки форм по электронной почте в первую оче- редь касается браузеров NN2+ и IE5+. Вы должны знать, что формы, отправленные по почте, в определенной степени не поддерживаются официальными Web-стандартами. С момента ее создания HTML-спецификация от W3C официально не поддерживает эти методы. Однако по- следние версии браузеров, тем не менее, их поддерживают, причем весьма эффективно. Ис- пользуйте эти средства предельно осторожно и только после тщательного тестирования во всех браузерах, которые будут использоваться для выполнения кода. Если вы будете создавать формы, отправляемые конечному получателю в виде почтовых сообщений, то вам придется ознакомиться с тремя атрибутами дескриптора <f orm>. Первый из них — method. Он инициализируется как POST. Следующий атрибут enctype. Если вы опустите его, то в почтовом сообщении данные формы будут содержаться в виде вложения, состоящего из закодированных пар имя-значения, как в следующем примере. name=Danny+Goodman&rank=Scripter+First+Class&serialNumber=042 Если вы устанавливаете атрибут enctype в значение text/plain, то пары имя- значения размещаются в теле сообщения в более простом и понятном формате. name=Danny Goodman rank=Scripter First Class serialNumber=042 Последний атрибут— action— это обычное место указания URL другого файла или сервера с CGI-программой. Замените URL на определенный адрес mail to: URL, указав по- сле него необязателен параметр темы сообщения. action="mailto:prez@whitehouse.gov?subject=Opinion%20Poll" Чтобы подвести итог, в следующем примере будет показан полный дескриптор <form>, предназначенный для отправки формы по электронной почте в NN. <form name="entry" method="POST" enctype-"text/plain" action="mailto:prez@whitehouse.gov?subject=Option Poll"> Описанный выше способ не требует применения средств JavaScript. Рассмотрев варианты использования атрибутов и учтя тот факт, что эти атрибуты представлены как свойства объекта элемента form, можно найти расширенные возможности управления формами в сценариях. Изменение атрибутов формы За исключением IE3 (где свойства объекта form доступны только для чтения), все брау- зеры, поддерживающие сценарии, представляют атрибуты элемента, form как свойства, ко- торые поддаются изменению. Поэтому вы можете изменять, скажем, реакцию формы в сце- нарии в ответ на действия пользователя на вашей странице. Например, у вас может быть установлено две различных CGI-программы, которые будут вызываться на сервере в зависи- мости от того, выставлен или снят флажок на форме. Глава 21. Объект form и вложенные в него объекты 657
Лучшая возможность изменить свойства объекта form — воспользоваться Совет функцией, вызванной обработчиком'события onsubmit формы. Изменения, вы- ... % полненные а последний момент перед фактической отправкой данных, не остав- ** ляют никакой возможности проявиться сбоям, вызванным пользователем. Кнопки на формах Обычная ошибка, которую делают начинающие разработчики сценариев, — это определе- ние в объекте input всех кнопок как submit (< input type=11 submit" >). Кнопка Submit отправляет форму. Если вы не установите атрибуты method или action в дескрипторе <form>, то браузер задаст их значения по умолчанию: method=GET и асП1оп=СЖЬстраницы. Когда вы отсылаете форму с этими атрибутами, страница перезагружается и устанавливает значения всех полей в их первоначальные значения. Используйте кнопку Submit только в том случае, когда необходимо, чтобы она отправля- ла форму. Если вы решили использовать кнопку для других целей, обратитесь к другому типу элемента (cinput type= “button" >). Обычная кнопка может вызывать функцию, которая выполняет дополнительные действия и затем вызывает метод submit () объекта элемента form, чтобы отправить форму на сервер. Перенаправление данных после отправки Несомненно, после отправки формы на узел вы получаете страницу с названием Thank you, которую сервер возвращает, чтобы подтвердить, что ваша форма была принята. Это простая и понятная, а также вполне логичная обратная связь с сервером, принимающим данные. Не удивительно, что вы захотите, чтобы этот эффект сопровождал отправку данных с помощью протокола mailto:. К сожалению, это невозможно. Здравый смысл в данной ситуации требует, чтобы сценарий выполнил отправку данных (с помощью метода form, submit ()), а затем переместился к другой странице, которая вы- дает пользователю благодарность Thank you. Ниже приведен фрагмент сценария внутренней функции, запускаемой щелчком на графической кнопке Submit со ссылкой. function doSubmitO { document.forms[0].submit(); location.href = "thanks.html"; } Проблема состоит в следующем: если сразу после метода form, submit () выполняется другой оператор, то отправка данных отменяется. Другими словами, сценарий не ждет окон- чания отправки данных и не проверяет в браузере завершения действия (даже при том, что браузер знает, как сделать это — анализируя состояние строки состояния во время отправки формы). JavaScript не имеет события, которое активизируется после проведения успешной отправки данных. Поэтому надежного способа отобразить вашу собственную страницу Thank you после отправки данных нет. Не пользуйтесь методом window.setTimeout (), чтобы изменить документ в окне браузера после истечения определенного интервала, отсчитываемого сразу после выполнения метода form, submit (). Вы не можете предсказать, насколько быстро передаются данные в сетевом соединении пользователя. Если отправка данных не завершается до окончания ин- тервала, то она отменяется (даже если уже завершена частично). Нет ничего положительного в том, что до сих пор не существует возможности управления подобными событиями. Вероятно, будущая версия объектной модели документа обеспечит нас средствами, которые позволят выполнять действия в случае успешной отправки данных. 658 Часть III. Объекты документа
Массивы элементов формы Начиная с NN2 и IE4, объектные модели документов обеспечивают разработчиков сред- ством, которое выгодно улучшает многие сценарии. Если вы создаете несколько одинаково названных объектов, они автоматически становятся массивом объектов, которые извлекаются с помощью синтаксиса, характерного для массивов (см. главу 7). Это особенно полезно, когда вы создаете формы со столбцами и строками (в форме заказа). Определяя то же самое имя всем ячейкам в столбце, вы можете использовать, циклы for, чтобы по очереди просмотреть каждую строку, используя индекс цикла как индекс массива. Например, следующий код представляет типичную функцию, которая вычисляет сумму на форме заказа (при этом вызывается другая пользовательская функция, применяемая для фор- матирования полученного значения). function extendRows(form) { for (var i = 0; i < Qty.length; i++) { var rowSum = form.Qty[i].value * form.Price[i].value; form.Total[i].value = formatNum(rowSum.2); } } Все ячейки в столбце Qty названы Qty. Элемент в первой строке имеет значение индекса массива, равное нулю; он задан как form. Qty [i]. Описание объекта элемента input Данная глава описывает элемент form как контейнер элементов управления; следующие три главы посвящены различным типам элементов управления, которые содержатся на фор- ме. Многие из этих элементов управления задаются с помощью одного и того же HTML- дескриптора: <input>. Только атрибут type дескриптора «inputs определяет, отображает ли браузер кнопку, переключатель, текстовое поле и т.д. Тот факт, что один элемент имеет так много обликов, заставляет задуматься о нелогичности структуры элементов управления. Элемент input имеет атрибуты (и соответствующие свойства объекта), специфичные для каждого типа элемента управления формы. Например, если свойство maxLength текстового поля вполне логично задает количество символов, которые пользователь может ввести в нем, для другого элемента управления формы (например, кнопки), оно вообще не используется. Точно так же вы можете изменять состояние флажка или переключателя, изменяя его свойст- во checked; однако это свойство не задается при использовании текстового поля. Поскольку объектные модели документа все еще развиваются, они постепенно прогресси- руют в объектно-ориентированном направлении. В результате все элементы управления, соз- данные с помощью дескриптора «inputs, имеют длинный список свойств, которые являются общими для всех объектов элементов типа input. Они наследуют свойства и методы, которые оп- ределены для любого элемента input. В следующих главах этой книги будут рассмотрены эле- менты input и описаны объекты по функциональным признакам (кнопки в одной главе, тексто- вые поля — в другой). Далее речь будет идти только о тех свойствах и методах элемента input, которые имеют непосредственное отношение к применению элемента управления на практике. Тем временем в этой главе мы продолжаем описывать объект элемента form. Глава 21. Объект form и вложенные в него объекты 659
Свойства acceptcharset Значение: строка Чтение/Запись Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safari 14- Свойство acceptCharset представляет собой атрибут acceptcharset элемента form в HTML 4.0. Его значение— это список одного или более наборов символов, ко- торые сервер, принимающий форму, должен поддерживать. Для просмотра списка зареги- стрированных имен наборов символов обратитесь по адресу http://www.iana.org/ assignments/character-sets. action Значение: строка URL Чтение/Запись (см. текст) Совместимость: WinIE34-, MacIE3+, NN2+, Mozl4-, Safari 14- Свойство action (наряду со свойствами method, и target) прежде всего представляет интерес для HTML-разработчиков, страницы которых связаны с серверными CGI-сцена- риями. Это свойство подобно значению, которое присваивается атрибуту action дескрип- тора <form>. Возвращаемое значение — это обычно URL сервера, на который отправляются запросы или обрабатываемые данные. Вводимые пользователем данные могут определять, как страница будет обращаться к сер- веру. Например, выставленный флажок в документе может изменить свойство action фор- мы так, что CGI-сценарий на сервере будет обрабатывать все входные данные; наряду с этим неустановленный флажок означает, что данные формы будут обрабатываться другим CGI- сценарием или CGI-сценарием, расположенным на другом сервере. Также может быть, что один установленный флажок будет отправлять данные по одному адресу mailto:, а дру- гой — по другому адресу mailto:. Технические требования для всех трех связанных свойств позволяют изменить их “на ле- ту”, однако подобные изменения эфемерны. Перезагрузка уничтожает любые установки, ко- торые вы делаете для других выставленных свойств; поэтому следует изменять эти свойства только в той же самой функции сценария, которая отправляет форму (см. form. submit ()). См. также: свойства form.method, form, target, form, encoding. autocomplete Значение: строка Чтение/Запись Совместимость: WinIE54-, MacIE-, NN-, Moz-, Safari- Microsoft добавила в формы, отображаемые в IE5, свойство, которое позволяет браузеру давать подсказки пользователям, чтобы облегчить заполнение элементов управления формы (если их имена представляют собой набор однострочных текстовых полей, которые определяются с помо- щью дополнительных атрибутов, задаваемых в XML-структуре vCard). Подробнее поддержка этого свойства в браузере описана на странице http:/ /msdn. microsof t. com/workshop/ author/forms/autocomplete_ovr.asp. Значения свойства autoComplete— это одна из двух строк: on или off. В любом случае, объект form не сообщает о том, какое зна- чение использовано, если не указать в дескрипторе формы атрибут autocomplete. elements [] Значение: массив элементов управления формы Только для чтения Совместимость: WinIE34-, МасШЗ-ь, NN24-, Mozl-r, Safaril-ь 660 Часть III. Объекты документа
Свойство elements включают в себя все элементы пользовательского интерфейса, опре- деленные на форме: текстовые поля, кнопки, переключатели, флажки, списки и т.д. Свойство elements — массив всех элементов управления формы, определенных в пределах текущей формы. Например, если на форме определены три элемента < inputs, то свойство elements для той же формы — массив, состоящий из трех объектов (один для каждого элемента в по- рядке расположения на странице). Каждый член массива — достоверная ссылка на элемент управления; таким образом, чтобы извлечь свойства или методы элементов, ваш сценарий должен производить более глубокий поиск в массиве. Если первый элемент формы — тексто- вое поле, и вы хотите извлечь строку, находящуюся в поле этого элемента в данный момент (свойство value текстового поля), то ссылка должна выглядеть так. document.forms[0].elements[0].value Обратите внимание на то, что эта ссылка содержит два свойства элементов массива: одно для forms и одно для elements. На практике я рекомендую обращаться к элементам управления формы по их именам, что придаст документу гибкости и предоставит возможность перемещать элементы управления по всей странице, улучшая дизайн документа. При этом вы не должны волноваться о порядке отображения текста в элементах управления. Массив elements удобен при просмотре всех элементов управления в пределах формы. Если ваш сценарий нуждается в цикле просмотра всех элементов формы, производимом с целью поиска определенных типов элементов управ- ления, используйте свойство type каждого объекта формы (NN3+ и IE4+), чтобы идентифи- цировать, каким видом объекта этот элемент является. Свойство type состоит из той же са- мой строки, которая задается в атрибуте type дескриптора < inputs. Обычно я предпочитаю употреблять смысловые имена элементов управления формы и ис- пользовать их в ссылках, встречающихся в сценариях. Массив elements также позволяет использовать имена элементов управления формы. Вместо числового индекса в массиве elements, вы можете применить имя элемента управления. Таким образом, можно создать универсальную функцию, которая обработает любое количество элементов управления фор- мы, и передать строку, содержащую имя элемента управления, как параметр функции. Ис- пользуйте этот параметр как индекс массива elements. function putVal(controlName, val) { document.forms[0].elements[controlName].value = val; } Если вы хотите изменить число элементов управления на форме, используйте средства управления элементом и/или узлом в браузере (браузерах) по вашему выбору. Например, в IE4+ и W3C вы можете создать HTML-строку для создания полностью нового набора элемен- тов управления формы, а затем присвоить эту строку свойству innerHTML элемента form. Пример Документ листинга 21.2 демонстрирует принципы использования свойства elements. Его форма содержит четыре текстовых поля и несколько других элементов (рис. 21.2). Первая часть функции, управляющая этими элементами, просматривает форму для поиска текстовых полей и определения пустых элементов. Обратите внимание, как свойство type используется для выделения на форму текстовых полей среди других элементов. Если поле не содержит данных, то на экран выводится сообщение; при этом поле повторно активизируется методом focus (), чтобы пользователь мог немедленно приступить к вводу необходимой информации. Глава 21. Объект form и вложенные в него объекты 661
ftftments Array Microsoft Internet Explorer 55 - ” • -r.- - *- •. e -- Ml#* fd«t Vfew F^voihes ГоеЬ Help jjff ©Back • S ® Й.\Р =«*☆'*«»*«<»« 0’1^ B ’□ g} '©*' Enter your first nameiTheodore Enter your last name:'Cleaver ©Male О Female Enter your address:; Biter your city. Mayfield □I am retired ¥*r~~ -J Puc. 21.2. Массив элементов формы применяется для поиска только текстовых полей <html> <head> <title>Elements Array</title> <script type="text/javascript"> function verifyltO { var form = document.forms[0]; for (i = 0; i < form.elements.length; i++) { if (form.elements[i]-type == "text" && form.elements[i].value == "") { alert("Please fill out all fields."); form.elements[i].focus(); break; } // другие тесты } // другие операторы } </script> </head> <body> <form> Enter your first name:<input type="text" name="firstName" /> <p>Enter your last name:<input type="text" name="lastName" /></p> <pxinput type="radio" name="gender" />Male <input type="radio" name="gender" />Female</p> <p>Enter your address:<input type="text" 662 Часть III. Объекты документа
name="address" /></р> <p>Enter your city:cinput type="text" name="city" /></p> <pxinput type="checkbox" name="retired" />1 am retired</p> </form> <form> cinput type="button" name="act" value="Verify" onclick="verifylt()" /> c/form> c/body> c/html> См. также: объекты text, textarea, button, radio, checkbox и select. encoding enctype Значение: строка типа MIME Чтение/Запись (см. текст) Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ С помощью формы можно предупредить сервер, если отправляемые ему данные пред- ставлены в формате другого типа MIME, а свойство encoding содержит значение атрибута enctype, задаваемого при определении формы. Свойство enctype определено для объек- тов элемента form в W3C DOM (в ней отсутствует свойство encoding), но NN6 поддержи- вает оба свойства, обеспечивая двустороннюю совместимость. При отправке данных в формате mailto:URL рекомендуется установить это свойство (в дескрипторе или в сценарии) в значение text/plain, чтобы отобразить содержимое формы в теле почтового сообщения. Если определение формы.не содержит атрибута enctype, то это свойство — пустая строка. См. также: свойства form, action, form.method. length Значение: целочисленное Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство length объекта элемента form обеспечит вас той же информацией, что и свойство length массива elements формы. Свойство предлагает удобный способ опре- деления количества элементов управления формы. См.также: свойство form.elements. method Значение: строка (GET или POST) Чтение/Запись (см. текст) Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Свойство method формы имеет значение GET или POST (независимо от регистра), назна- ченное атрибуту method дескриптора <form>. Терминология в обоих методах подобна, по- этому будьте внимательны и постарайтесь не перепутать атрибут формы передачи данных на сервер с объектно-ориентированным методом отправки формы, который используется во всех формах JavaScript. Свойство method имеет первостепенное значение важность для HTML-документов, кото- рые представляют данные формы для обработки в серверной CGI-программе, поскольку именно оно определяет способ передачи этой информации. Например, чтобы отправить форму с помощью Глава 21. Объект form и вложенные в него объекты 663
mailto:URL, свойство method должно иметь значение POST. Подробное описание способов отправки форм и вопрос их обработки в CGI-программе выходят за рамки рассматриваемого в этой книге материала (см. документацию к HTML или CGI), где вы узнаете, какую установку необходимо задать для этого атрибута в среде вашего Web-сервера. Если форма не имеет явно определенного атрибута method, то устанавливается значение по умолчанию — GET. См. также: свойства form, action, form, target, form, encoding. name Значение: идентификатор Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Присвоение имени форме в атрибуте name проводить не обязательно, однако рекоменду- ем это сделать, если ваши сценарии ссылаются на форму или ее элементы. Значение такого атрибута можно получить как свойство name формы. Существует немного случаев, когда вам понадобится использовать это свойство. Обычно без него сложно обойтись, если вы обра- щаетесь к другому документу, содержащему необходимую форму. var formName = parent.frameName.document.forms[0].name; По причине того, что CGI-программы часто полагаются на имя формы при проверке дан- ных, маловероятно, что вам необходимо будет изменить это свойство. target Значение: идентификатор Чтение/Запись (см. текст) Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Всегда, когда HTML-документ отправляет запрос на сервер для обработки, последний обычно возвращает назад HTML-страницу — это может быть стандартный ответ на получен- ные данные или, более вероятно, страница, содержащая результаты обработки данных. Вы часто сталкиваетесь с подобными ситуациями, выполняя поиск Web-страниц в сети. В мно- гофреймовой или многооконной среде вы можете представить часть возвращаемой страницы в поле зрения пользователя, отобразив ее в отдельном фрейме или окне для просмотра. Цель атрибута target дескриптора <form> состоит в том, чтобы позволить указать, где должен быть отображен ответ, получаемый с сервера. Значение свойства target — это имя окна или фрейма. Например, если вы определяете на- бор фреймов и назначаете им имена Frame 1, Frame2 и Frame3, то должны определить одно из этих имен в качестве параметра target дескриптора <form>. Браузеры также поддержива- ют четыре специальных имени целевых объектов, которые вы можете использовать в определе- нии формы: _top, _parent, _self, и _blank. Чтобы определить target как отдельное подокно, открываемое с помощью сценария, используйте имя окна, заданное во втором пара- метре метода window. open (), а не ссылку на объект окна, возвращаемую этим методом. См. также: свойства form, action, form.method, form, encoding. Методы handleEvent (событие) Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Смотрите описание метода window. handlerEvent () в главе 16. 664 Часть III. Объекты документа
reset () Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ В длинной форме часто добавляют кнопку, которая позволяет пользователю восстановить для всех элементов формы настройки по умолчанию. Стандартная кнопка reset (отдельный тип объекта, описанный в главе 22) отлично справляется с этой задачей. Но если вы хотите очистить форму, используя сценарий, то должны это сделать, вызвав метод reset () для формы. Наверняка, такой запрос будет инициализироваться вне формы, возможно в ре- зультате использования графической кнопки. В последнем случае удостоверьтесь, что на метод reset () формы, для которой вы задаете восстановление значений, задана полная ссылка, даже если текущая страница содержит только одну форму. Пример В листинге 21.3 сброс формы выполняется с помощью атрибута href связанного объекта (присоединен к графическому объекту reset.jpg). В сценарии используется оператор javascript :URL для непосредственного вызова метода reset О (для этого не создается отдельная функция). В нашем примере данные формы передаются на несуществующий узел. Поэтому по щелчку на кнопке Submit вы получите сообщение об ошибке нахождения сервера. Листинг 21.3, Методы form, гsssttJ и .() <html> chead> ctitle>Registration Form</title> с/head> <body> <form name="entries" method="POST" action="http://www. tr. edu/pub/cgi-bin/register"> Enter your first name:<input type="text" name="firstName" /> <p>Enter your last name:cinput type="text" name="lastName" /></p> <p>Enter your address:<input type="text" name="address" />c/p> cp>Enter your city:cinput type="text" name="city" />c/p> cpxinput type="radio" name="gender" checked="checked" /> Male cinput type="radio" name="gender" />Femalec/p> cpxinput type="checkbox" name="retired" />1 am retiredc/p> </form> cpxa href="j avascript:document.forms[0] .submit()"ximg alt="image" src="submit.jpg" height="25" width="100" border="0" />c/a> ca href="javascript:document.forms[0]. reset()">cimg alt="image" src="reset.jpg" height="25" width="100" border="0" /></ax/p> c/body> c/html> См. также: обработчик события onreset; объект reset. submi t() Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Глава 21. Объект form и вложенные в него объекты 665
Наиболее популярный способ отправить данные формы на сервер для обработки в CGI- программе состоит в щелчке мышью на кнопке Submit. Стандартная кнопка Submit в HTML предназначена для того, чтобы отправлять данные всех определенных элементов формы в со- ответствии со спецификациями, указанными в атрибутах дескриптора <form>. Но если вы хотите отправлять данные формы на сервер автоматически или использовать для этого гра- фическую кнопку, то вправе это сделать с помощью метода form, submit (). Вызов указанного метода — это почти то же, что щелчок на кнопке Submit формы (за ис- ключением того, что onsubmit обработчик события в этом случае не запускается). Поэтому вы можете создать изображение на вашей странице, которое будет представлять графическую кнопку отправки данных на север. Если это изображение заключить в объект ссылки, то по щелчку можно запустить специальную функцию, содержимое которой включает и метод submit () (см. листинг 21.3). В HTML-документе с несколькими формами вы должны сослаться на надлежащую форму или по имени, или согласно ее расположению в массиве document. forms. Старайтесь удостовериться, что ссылка, которую вы определяете в своем сценарии, ука- зывает на желаемую форму перед тем, как вы отправите с ее помощью данные на сервер. Соблюдая меры защиты от несанкционированных посягательств на данные пользователя- ми, посещающими ваш узел, JavaScript игнорирует все методы submit (), действия которых представлены в формате mail :URL. Многие разработчики Web-страниц пожелали бы полу- чить адреса посетителей их страниц. Но поскольку такая систематизация данных может рас- сматриваться как вторжение в личную жизнь любого человека, подобная возможность была устранена. Однако вы можете использовать кнопку Submit, чтобы получить форму в виде почтового сообщения от браузера. Поскольку метод form, submit () не запускает обработчик события onsubmit формы, проведите любую доступную обработку и проверку данных форм перед их отправкой на сер- вер в том же самом сценарии, который заканчивается оператором form, submit (). Но при этом не прерывайте процесс отправки данных, инициализированный вызовом метода form. submit (). Операторы сценария, которые следуют после вызова form. submit () — особенно те, которые перемещают пользователей к другим страницам или осуществляют по- пытку повторной отправки данных, — прерывают процесс первичной передачи данных. См. также: обработчик события onsubmit. Обработчики событий onreset Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Прежде чем кнопка Reset возвратит форму к настройкам по умолчанию, JavaScript генерирует в форме событие reset. Включив обработчик события onreset в определение формы, вы можете захватить это событие прежде, чем произойдет восстановление значений по умолчанию. Удачный вариант использования этой особенности состоит в том, чтобы подстраховать пользователя, который случайно щелкает на кнопке Reset после заполнения формы. Обра- ботчик события может вызвать функцию, которая запросит пользователя подтвердить выпол- ненное действие. Обработчик события onreset использует методику, представленную впервые в NN3: он должен содержать оператор return true, обеспечивающий продолжение выполне- ния функции в браузере. Это может напомнить вам обработчики событий onmouseover и onmouseout, заданные для ссылок и областей изображений. Данное требование гораздо важнее, потому что ваша функция может определить, будет операция обновления в конечном счете проведена или нет. 666 Часть III. Объекты документа
Пример В листинге 21.4 продемонстрирован пример предотвращения случайного сброса или от- правки данных формы. Если использовать в форме стандартные кнопки Reset (Сброс) и Submit (Подача запроса), то в описание элемента <form> будет добавлено оба обработчи- ка событий. Каждый обработчик будет вызывать собственную функцию, выводящую пользо- вателю сообщение о выполняемых действиях. Обратите внимание на использование ключе- вого слова return и применение булевых значений. chtml> chead> ctitle>Submit and Reset Confirmation</title> escript type="text/javascript"> function allowResetO { I return window.confirm("Go ahead and clear the form?"); } function allowSendO { return window.confirm("Go ahead and mail this info?"); } </script> c/head> <body> <form method="POST" enctype="text/plain" action="mailto:trash4@dannyg.com" onreset="return allowReset()" onsubmit="return allowSend()"> Enter your first name:<input type="text" name="firstName" /> <p>Enter your last name:cinput type="text" name="lastName" /></p> <p>Enter your address:cinput type="text" name="address" />c/p> cp>Enter your city:cinput type="text" name="city" />c/p> cp>cinput type="radio" name="gender" checked="checked" /> Male cinput type="radio" name="gender" />Femalec/p> cp>cinput type="checkbox" name="retired" />1 am retiredc/p> cp>cinput type="reset" /> <input type="submit" />c/p> c/form> c/body> c/html> onsubmit Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Независимо от того, как данные формы переданы на сервер (пользователем, щелкнувшим на кнопке Submit, или сценарием, вызвавшим метод form.submit О), вы можете поже- лать, чтобы ваш HTML-документ, допускающий использование JavaScript, провел проверку данных, полученных от пользователя (особенно из текстовых полей), перед отсылкой этой информации на сервер. Вы имеете возможность выполнить подобную проверку данных непо- средственно во время их введения пользователем (см. главу 43) или в пакетном режиме перед отправкой данных на сервер (а также обоими способами). Место, в котором можно запустить окончательную проверку данных,— обработчик события onsubmit. Обратите внимание, Глава 21. Объект form и вложенные в него объекты 667
что это событие генерируется только для исходного объекта Submit элемента типа <input>, а не благодаря методу submit () формы. Когда вы определяете обработчик события onsubmit как атрибут дескриптора <form>, JavaScript отправляет событие submit в форму непосредственно перед тем, как она передает свои данные на сервер. Поэтому любой сценарий или функция, которые являются парамет- ром onsubmit, выполняются прежде, чем данные фактически передаются на обработку. Об- ратите внимание, что этот обработчик события активизируется только в ответ на использова- ние кнопки Submit, а не в результате выполнения методом form, submit (). Любой код, выполненный из обработчика события onsubmit, должен содержать выра- жение, состоящее из слова return и булевого значения. Если булево значение равно true, передача данных выполняется, как обычно; если значение равно false, то отправка данных не выполняется. Поэтому, если ваш сценарий выполняет проверку данных перед их переда- чей на сервер, удостоверитесь, что обработчик события вызывает функцию проверки данных как часть оператора return (см. листинг 21.4). Даже после того, как обработчик события onsubmit перехватит передачу данных, сис- тема защиты данных JavaScript может отобразить дополнительные предупреждения пользо- вателю (что зависит от расположения конечного сервера). Объекты элементов fieldset и legend Свойства, методы и обработчики событий этих элементов описаны в главе 15. Свойства Методы Обработчики событий align form Синтаксис Доступ к свойствам или методам объектов элементов fieldset и legend. (IE4+) [window.]document.all.идентификатор.свойство|метод([параметры]) (IE5+/W3C) [window. ] document. getElementByld ( ”идентификатор”) . свойство | метод ( [параметры] ) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Описание объектов Элементы fieldset и legend используются совместно для обеспечения пользователя дополнительными контекстными данными о наборе элементов управления формы в пределах самой формы. Браузеры, которые поддерживают элемент fieldset, создают прямоуголь- ник вокруг области документа, который содержит элементы управления формы, вложен- ные внутрь этого элемента. Прямоугольная область занимает всю ширину формы, если ширина не задается в соответствующих свойствах стилей (например width). К этой пря- моугольной области добавляется текстовая надпись, которая определяется в элементе legend, вложенном внутрь элемента fieldset. Ни один из этих элементов группы не требуется, ес- ли в макете страницы уже содержатся графические элементы, которые позволяют группиро- вать элементы управления формы. 668 Часть III. Объекты документа
Правильность вложения элементов имеет первостепенное значение для получения в брау- зере необходимого вида документа. Типичный HTML-код этих элементов выглядит следую- щим образом. <form> <fieldset> <legend>Legend Text</legend> Элементы управления и их подписи. </fieldset> </form> Вы можете иметь больше одного элемента fieldset внутри формы. Каждый набор име- ет прямоугольник, добавленный вокруг него. Это помогает организовать длинную форму в четко разграниченные для пользователей разделы элементов управления — одна-единствен- ная форма сохраняет свою целостность для отправки на сервер. Элемент fieldset управляется подобно любому другому HTML-контейнеру, в котором поддерживаются стили и принцип наследования. Например, если вы устанавливаете стиль color свойства элемента fieldset, то цвет задается для текста элементов, расположенных внутри него; однако цвет границы, нарисованной браузером, остается неизменным. При из- менении стиля color-border свойства элемента fieldset в указанный цвет окрашивает- ся только граница, а не текстовое содержимое вложенных элементов. Обратите внимание, что содержимым элемента legend может быть любой HTML-код. Вы можете задать любое правило таблицы стилей для элемента legend. Если в ваших сце- нариях необходимо изменить текст подписи, то это можно выполнить с помощью свойства innerText (IE4+), innerHTML (IE4+, NN6+) или nodeValue (IE5+, NN6+) объектов элементов. Только два действительно специфических свойства элементов имеет эта пара объектов. Первое— это align— свойство объекта legend. Это свойство соответствует атрибуту align этого элемента, как определено в описании HTML 4.0 (хотя свойство осуждается в пользу правил таблиц стилей). IE5+ для Мас и IE5.5+ для Windows позволяют изменить это свойство “на лету” (задавая выравнивание по правому или левому краю). В результате вы можете изменить расположение надписи в верхней части раздела элементов управления. Поскольку эти элементы — дочерние объекты элемента form, неудивительно, что в специ- фикации DOM 2 для них определяется доступное только для чтения свойство form. Это свойст- во возвращает ссылку на объект элемента form, который включает любой из указанных элемен- тов. Свойство form для объектов fieldset и legend реализовано только в Мас1Е5 и NN6. Объект элемента label Свойства, методы и обработчики событий этих элементов описаны в главе 15. Свойства Методы Обработчики событий form htmlFor Синтаксис Доступ к свойствам или методам объекта элемента label. (IE4+) [window. ] document .all .идентификатор, свойство \ метод [параметры] ) (IE5+/W3C) [window. ] document .getElementByld ("идентификатор") . свойство | метол ( [параметры] ) Глава 21. Объект form и вложенные в него объекты 669
Описание объекта Чтобы обеспечить контекстные дескрипторы для каждого бита содержимого страницы, рабочая группа W3C по развитию HTML заполнила пробел, который представлял текст, ото- бражаемый на/или возле элементов управления input, select и textarea формы. Этот текстовый фрагмент используется в большинстве случаев как надпись, описывающая назна- чение элемента управления. Только элемент input, который имеет специальный атрибут для представления надписи, относится к кнопочному типу элементов ввода. Элемент label позволяет заключить текст надписи элемента управления в контекстный дескриптор. Кроме того, один из атрибутов элемента — for — позволяет связать надпись со специфическим элементом управления формы. В HTML атрибуту for назначен идентифика- тор элемента управления, с которым связана надпись. Элемент label связывается с элемен- том управления формы, если дескриптор элемента управления формы содержится между от- крывающим и закрывающим дескрипторами элемента label. На первый взгляд, браузеры не делают ничего специального (с точки зрения представле- ния данных) для отображения элемента label. Но для некоторых типов элементов, особенно для переключателя и флажка, они помогают сохранить жизненно важное удобство пользова- тельского интерфейса: щелчок кнопкой мыши на надписи означает то же самое, что и щелчок на элементе управления. Для текстовых полей события активизации, которые добавляются к ним, также добавляются и для надписи. Фактически, все события, которые определены для надписи, передаются элементу управления формы, связанному с ней. Следующий фрагмент страницы демонстрирует, как элементы fieldset, legend и label выглядят на форме, со- стоящей из двух переключателей. <form ...> <fieldset id="formlsetl"> <legend id=,,formlsetllegend">Choose the Desired Per£ormance</legend> <input type="radio" name="speed" id="speedl" /> clabel for="speedl">Fastest (lower-quality)</labelxbr /> <input type="radio" name-"speed" id="speed2" /> clabel for="speed2">Slower (best quality)</label> </fieldset> </form> Даже в этом случае label и связанный с ним элемент управления формы не обязательно должны быть смежными в исходном коде. Например, вы можете задать надпись в одной ячейке строки таблицы, а сам элемент управления формы — в другой (в той же самой или другой строке таблицы). Свойства htmlFor Значение: ссылка на объект элемента Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство htmlFor — сценарный эквивалент атрибута for элемента label. Допустимое значение — полная ссылка на элемент управления формы (объект элемента input, textarea или select). Маловероятно, что вы будете изменять это свойство для существующего эле- мента label. Однако, если ваш сценарий создает новый элемент label, используйте это свойство, чтобы связать надпись с элементом управления формы. 670 Часть III. Объекты документа
Объект кнопки Зта глава посвящена таким элементам, как кнопки, которые позволяют пользователям активизиро- вать с помощью щелчка определенные действия. К этой ка- тегории относятся стандартные кнопки системы, содержащие надписи, а также переключатели и флажки. Однако словарь свойств, методов и обработчиков события для этих инст- рументов форм HTML является довольно ограниченным. Я сгруппировал вместе объекты button, submit и reset по одной важной причине: функционально они выглядят одина- ково, хотя и предназначены для выполнения различных задач. Важно научиться правильно использовать кнопки, а особен- но— понимать различия между объектами button и submit. Многие начинающие разработчики путают эти два объекта и сталкиваются со множеством проблем. Этого не случится, если вы внимательно изучите материал данной главы. Объект элемента button, объекты button, submit и reset Свойства этого элемента, его методы и обработчики со- бытия описываются в главе 15. Свойства Методы Обработчики события form 'Пате type value click() onclick onmous edown onmouseup Синтаксис Доступ к свойствам и методам объекта button. (Все) [window.]document. имяФормы.имяКнопки. свойство | метод ( [параметры] ) (Все) [window.]document.имяФормы.elements [индекс].свойство|метод([параметры])
(Все) [window. ] document. forms [индекс] . имяКнопки. свойство | метод ( [параметры]) (Все) [window.]document.forms["имяФормы”] .имяКнопки.свойство]метод ( [параметры] ) (Все) [window.]document.forms["имяФормы” ] .elements[индекс] .свойство] метод([параметры] ) (IE4+) [window. ]document. all. идентификатор, свойство] метод ( [параметры]) (IE5+/W3C) [window. ] document .getElemeritBylD ("идентификатор”) . свойство | метод ( [параметры] ) Описание объектов В зависимости от операционной системы, с которой запускается браузер, объекты button генерируют на странице стандартные элементы интерфейса в виде знакомых пользователю кно- пок. Раньше для генерации этих стандартных элементов интерфейса браузер обращался к опе- рационной системе. Предыдущие версии браузеров самостоятельно определяли внешний вид кнопок, хотя он и отличался в разных операционных системах. Сравнительно недавно на вид кнопок стали влиять особенности настроек браузера, которые заложены в него разработчика- ми. Но несмотря на все это, любой пользователь компьютера легко узнает на странице кнопку. Начиная с IE4 и NN6, существует два способа использования кнопок на странице. Первый, обеспечивающий полную обратную совместимость, заключается в использовании элементов input, вложенных в контейнер form. Новый элемент HTML, button, предоставляет несколь- ко отличный способ задания на странице кнопки; он включает параметр, который позволяет ис- пользовать кнопку внутри контейнера form (возможно, для выполнения некоторых клиентских сценариев, не зависимых от операции отправки данных формы). С точки зрения HTML, разли- чие между этими двумя подходами касается способа определения надписи кнопки. С помо- щью элемента input строка, присвоенная атрибуту value, становится надписью кнопки. Во втором случае элемент button является контейнером (имеющим закрывающий дескриптор), содержимое которого становится надписью кнопки. Тем не менее, в последнем случае вы можете задать атрибуту value определенное значение, которое (если форма содержит кноп- ку) впоследствии отправляется на сервер как часть данных и независимо от текста надписи. Прежде чем присвоить кнопке надпись, хорошо все продумайте. Поскольку использование кнопки подразумевает выполнение определенного действия, убедитесь, что термин, содержа- щийся в тексте надписи, четко определяет действие, совершаемое после щелчка на ней. Кроме того, прислушайтесь к советам профессиональных дизайнеров интерфейсов, которые разраба- тывают операционные системы и коммерческое программное обеспечение: будьте лаконичны. Если надпись на кнопке содержит более двух-трех слов, пересмотрите дизайн своей страни- цы, чтобы посетитель мог четко уяснить назначение каждой кнопки из более краткого текста. Браузеры автоматически изменяют размер кнопки в соответствии с длиной текста надпи- си. Но только браузеры, которые поддерживают таблицы стилей (IE4+ и NN6+), позволяют управлять другими параметрами внешнего вида кнопок (например, шрифтом надписи, его размером и цветом). Что касается положения кнопки на странице, то она, как и все внедрен- ные на форму элементы, размещается там, где задается исходный код. Конечно, можно ис- пользовать свойство позиционирования, поддерживаемое последними версиями браузеров (глава 39), чтобы поместить кнопку там, где необходимо. Но если просмотреть ваши Web- страницы в различных операционных системах и в разных версиях браузеров, то можно легко убедиться, что вид (и размер) кнопки не будет одинаковым. Постарайтесь просмотреть ре- зультаты на максимально доступном количестве платформ. 672 Часть III. Объекты документа
Кнопки в среде Windows ведут себя стандартно, т.е. активизируются при выделении тек- ста надписи (обычно заключаются в пунктирный прямоугольник). Некоторые новые версии браузеров, работающие в операционных системах, отличных от Windows, предлагают этот вид выделения и подсвечивания как пользовательский параметр. IE5 поддерживает дополни- тельное средство элемента input, которое не позволяет кнопке при активизации выделяться пунктирным прямоугольником. Обработчик события для отдельной кнопки, который выполняется во всех версиях браузеров и запускает назначенное действие, когда пользователь щелкает на кнопке,— это onclick. Фактически все действия, относящиеся к объекту button, связаны с этим обработчиком со- бытия. Вряд ли вам придется задавать значения свойств или вызывать метод click (этот ме- тод некорректно работает в браузере NN3) данного объекта. Браузеры NN4 и IE4 поддержи- вают дополнительные события составляющих щелчка: mousedown и mouseup; а браузеры IE4+ и NN6+ обеспечивают кнопки рядом других инициируемых пользователем событий. Два специальных варианта объекта button — это submit и reset. Появились они в ран- них версиях HTML. Эти две кнопки предназначены для выполнения специальных операций. Кнопка submit автоматически отправляет данные из текущего объекта формы по адресу URL, указанному в атрибуте action дескриптора <form>. Атрибут method описывает формат, в котором данные отправляются с помощью кнопки. Следовательно, это действие не следует изменять, если вы предусматриваете обмен данными между HTML-страницей и CGI- программой, которая находится на сервере. Бели для атрибута формы action задается значение mailto :URL, то на странице необ- ходимо разместить кнопку Submit (Отправить), которая будет выполнять необходимое дей- ствие. Заданное для атрибута enctype значение plain/text также часто используется для отправки данных из формы в более доступной форме, чем обычные кодированные пары зна- чений. Подробно об отправке данных из формы в виде почтового сообщения рассказывалось в предыдущей главе. Рядом с кнопкой Submit (Подача запроса) часто встречается кнопка Reset (Сброс). Эта кнопка также имеет специфическую функцию. Щелчок на ней восстанавливает заданные по умолчанию значения для всех элементов формы. Это действительно для текстовых объектов, групп переключателей, флажков и выделенных в списке элементов. Чаще всего такая кнопка используется для очистки введенных пользователем значений полей. Все три типа кнопок, используемых в дескрипторе < input > или <button>, отличаются друг от друга значением атрибута type. Для кнопок, которые не предназначены для отправки данных на сервер, используется тип button (задаваемое по умолчанию значение для элемен- та button). Значения submit и reset применяются для выполнения специальных задач. Если вы хотите, чтобы во всех поддерживаемых браузерах роль кнопки выполняло графи- ческое изображение, свяжите с ним соответствующую ссылку (см. описание объекта link в главе 19) или создайте клиентскую карту изображения (см. описание объекта area в гла- ве 20). Но в браузерах IE4+ и NN6+ можно использовать элемент input, для атрибута type которого задано значение image (см. далее в этой главе). Вероятно, самая большая ошибка при написании сценариев с использованием этих кно- пок— применение кнопки Submit для выполнения обычных задач, возлагаемых на пользова- тельскую кнопку. Поскольку эти две кнопки выглядят одинаково, а тип submit элемента input имеет более длинную историю, их очень легко перепутать между собой. Но если вы хотите раз- местить на странице кнопку, которая запускает на выполнение серверную часть сценария, ис- пользуйте пользовательский вариант. Кнопка Submit предназначена исключительно для от- правки данных формы. Если не задается атрибут action, то страница перезагружается, а все заданные значения полей очищаются. Обычная же кнопка выполняет возложенные на нее обязанности без перезагрузки страницы (если это специально не предусмотрено сценарием). Глава 22. Объект кнопки 673
Свойства form Значение: ссылка на объект form Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойство каждого объекта элемента input является ссылкой на элемент form, который содержит элементы управления. Это свойство может быть очень удобным при написании сценария, в котором вы управляете одним элементом управления формы, передаваемым в ка- честве параметра функции, и хотите получить доступ к другому элементу управления в этой же форме или вызвать метод управления формой. Обработчик события любого элемента input может передавать в качестве параметра ключевое слово this, а функция получает доступ к форме без задания в сценарии полной формы именной ссылки. См. также: объект form. name Значение: идентификатор Чтение/Запись (см. текст) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Имя кнопки фиксируется в атрибуте name элемента input или button и может быть изменено в сценарии только в новых версиях браузеров. Возможно, вам понадобится извлечь это свойство для использования в универсальной функции обработчика событий, которая вы- зывается в документе несколькими кнопками. Такая функция может проверить имя кнопки и выполнить для данной кнопки соответствующий оператор. Если изменить имя этого объекта, то перезагрузка страницы или задание нового целевого окна восстановит его исходное имя. См. также: свойство value текстового объекта. type Значение: строка Только для чтения Совместимость: WinIE44-, MacIE44-, NN64-, Mozl-t, Safaril4- Значение свойства type аналогично значению атрибута type дескрипторов <input* и <button>, которое определяет тип элемента управления формы: button, submit или reset. value Значение: строка Чтение/Запись (см. текст) Совместимость: WinIE44-, MacIE44-, NN64-, Mozl4-, Safari 14- Оба объекта (input и button) имеют атрибут value, который представляет свойство value в объектной модели документа. Но назначение этого атрибута-свойства в каждом объекте разное. В элементе input свойство value представляет надпись, отображаемую на' кнопке. В элементе button текст надписи представлен содержимым соответствующего де- скриптора. В обоих случаях при задании элементу атрибута name пара имя-значение отправ- ляется на сервер вместе с другими данными- формы (предполагается, что элемент button расположен на форме). Если не задать значение атрибута value для кнопок отправки данных и обновления пара- метров формы, то этим кнопкам автоматически будут назначены надписи Reset и Submit. I В качестве значения атрибута допускается использовать строку, состоящую из нескольких слов. I 674 Часть III. Объекты документ»
Значение свойства value можно изменить “на лету” в ходе выполнения сценария. При этом будьте предельно внимательны. Браузеры, вышедшие ранее NN6 и IE4, не позволяют изменить размер кнопки в соответствии с новым значением, определенным в сценарии. Тем не менее, перезагрузка документа или определение для него нового целевого окна обеспечи- вают необходимое изменение размеров элемента. NN6 и IE4+ изменяют размер кнопки при замене надписи без дополнительной перезагрузки формы. При этом размер страницы изменя- ется соответствующим образом. В IE4 для Мас это свойство также поддерживается, на поль- зоваться им часто не приходится. См. также: свойство value текстового объекта. Методы clickO - Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Метод clickO кнопки с помощь сценария имитирует щелчок пользователя на кнопке. К сожалению, этот метод не выполняется в ранних версиях браузеров, вышедших до IE4 и NN4. См. также: обработчик события onclick. Обработчики события onclick Совместимость: WinIE34-, МасГЕЗ-ь, NN24-, Mozl4-, Safari 14- Почти все действия кнопок выполняются в ответ на обработчик события onclick. Щел- чок подразумевает нажатие и последующее отпускание кнопки мыши, когда указатель нахо- дится над кнопкой. Событие для кнопки наступает только после того, как пользователь от- пустит кнопку мыши. Для кнопки Submit, вероятно, следует опустить обработчик события onclick и позво- лить обработчику события on submit позаботиться о проверке введенных данных перед от- правкой их на сервер. При запуске процедуры проверки данных с помощью обработчика со- бытия onsubmit ваши сценарии могут отменить отправку данных формы, если данные формы введены некорректно (см. описание объекта form в главе 21). Пример В листинге 22.1 продемонстрировано не только использование обработчика onclick, но и свойств name и values кнопки. Обработка всех этих программных элементов выполняет- ся в функции общего назначения, которая управляет сразу несколькими кнопками. В данном случае каждая кнопка передает в функцию displayTeamO собственное значение. Резуль- тат функция выводит в диалоговом окне сообщения. В примерах из реальной жизни исполь- зуются более совершенные конструкции if.. .else, поскольку реакция на щелчок мышью на кнопке в них несколько сложнее. (В браузерах DE44- и W3C также применяется оператор switch по отношению к выражению btn. value.) Глава 22 Объект кнопки 675
«htmls <head> «titlesButton Click</title> «script type="text/javascript"s function displayTeam(btn) { if (btn.value == "Abbott") { alert("Abbott & Costello"); } if (btn.value == "Rowan") { alert("Rowan & Martin"); } if (btn.value == "Martin") { alert("Martin & Lewis"); </scripts </head> «bodys Click on your favorite half of a popular comedy team: <forms «input type="button" value="Abbott" onclick="displayTeam(this)" /s «input type="button" value="Rowan" onclick="displayTeam(this)" /s «input type="button" value="Martin" onclick="displayTeam(this)" /s «/forms </bodys «/htmls См. также: обработчики события button, onmousedown, button. onmouseup, form.onsubmit. onmousedown onmouseup Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Более современные версии браузеров поддерживают обработчики события для компонен- тов события click— onmousedown и onmouseup. Вместе они представляют единый об- работчик события onclick. Системные кнопки, отображаемые операционной системой, при щелчке на них изменяют свой вид. Тем не менее, захват компонентов события щелчка не поможет вам изменить вид кнопки с помощью сценария. Запомните, что при нажатии кнопки пользователь может свести с нее указатель мыши. Когда указатель смещается за область кнопки, ее вид изменяется на исходный (в отжатом положении). Но далеко не все настройки, выполняемые в обработчике события onmousedown, будут восстанавливаться соответствующим обработчиком события onmouseup (даже после того, как пользователь отпустит кнопку мыши в произвольном мес- те документа). С другой стороны, если вы загрузите в кэш-память звуки, воспроизводимые при нажатии и отпускании кнопки, то использовать эти события для их воспроизведения в ответ на действия мыши вполне возможно. См. также: обработчики событий button, onclick. 676 Часть III. Объекты документа
Объект checkbox Свойства, методы и обработчики события этого HTML-элемента описываются в главе 15. Свойства Методы Обработчики события checked click()* onclick* form* name* type value * См. объект Button Синтаксис Доступ к свойствам и методам объекта checkbox. (Все) [window. ] document. имяФормы. имяФлажка. свойство | метод ([параметры]) (Все) [window.]document.имяФормы. elements[индекс].свойство|метод ( [параметры] ) (Все) [window. ] document. forms [индекс] . имяФлажка. свойство | метод ( [параметры] ) (Все) [window.]document.forms["имяФормы"].имяФлажка.свойство]метод ( [параметры] ) (Все) [window. ] document. forms ["имяФормы" ] . elements [индекс] .свойство | метод ( [параметры] ) (IE4+) [window. ]document. all. идентификатор, свойство] метод ( [параметры] ) (IE5+/W3C) [window. ] document. getElementByld (" идентифика тор” ) . свойство | метод( [параметры] ) Описание объекта Элемент checkbox (флажок) выполняет особую задачу при разработке современного пользовательского интерфейса: он является переключателем между состояниями “включено” и “выключено”. Как и флажок на стандартной анкете, галочка в квадратике указывает на то, что данный параметр верен или его следует включить для данного конкретного случая. Если флажок не установлен или квадратик пуст, соответствующий параметр не верен или этот па- раметр следует исключать. Если группируются два или более флажков, они не должны взаи- модействовать: каждый из них задается независимо друг от друга (см. описание объекта radio для переключателей). Я применяю эти элементы пользовательского интерфейса в самом начале формы для того, чтобы обеспечить Web-страницу унифицированным' интерфейсом, к которому пользователь привык, работая с другими программами. Объекты checkbox необходимо использовать только для включения или выключения выбранных пользователем параметров. Например, не рекомендуется использовать флажки в качестве кнопок, которые загружают другой адрес URL. Как и в диалоговых окнах Windows или Мас, с помощью флажков или переключателей Глава 22. Объект кнопки 677
пользователи устанавливают параметры, а при щелчке на стандартной кнопке или карте изо- бражения инициируют выполнение необходимых действий. Это не значит, что объект checkbox может выполнять только некоторые ограниченные действия в ответ на щелчок пользователя, но подобные действия обычно относятся к контек- сту самой формы. Например, в некоторых диалоговых окнах Windows и Мас установка флажка может активизировать несколько других неактивных параметров, указанных в этом же диалоговом окне. Браузеры IE4+ и NN6+ позволяют сделать недоступными или скрыть элементы формы. В подобных случаях объект checkbox применяется для управления атри- бутами отображения соответствующих элементов управления. Кроме того, в окне, состоящем из двух фреймов, объект checkbox одного фрейма может управлять представлением данных в другом. При этом содержимое другого фрейма может детализироваться до необходимого уровня сложности. Установка флажка изменяет уровень насыщенности данными документа другого фрейма (для каждого уровня сложности загружается свой документ с другого адреса URL). Таким образом, в нижней части окна можно использовать флажки для переключения между несколькими состояниями страницы. Для инициализации обработки заданных настро- ек добавьте на страницу обычные кнопки. В дескрипторе <input» для объекта checkbox можно указать выставлять флажок при загрузке страницы. Для этого в его определении укажите атрибут checked. Если по умолча- нию опустить этот атрибут, то будут отображаться пустые квадратики флажков. Текст надпи- си задается содержимым дескриптора <input». Если проанализировать поведений объекта checkbox в браузерах HTML, то такое положение вещей имеет определенный смысл: текст надписи не является активной частью объекта checkbox (как это обычно бывает в стандарт- ном пользовательском интерфейсе Windows или Macintosh, где щелчок на тексте надписи равносилен выставлению флажка). Задание имени для объекта checkbox является важной частью определения объекта (в зависимости от того, как вы хотите использовать в сценарии или документе эту информа- цию). Для форм, содержимое которых используётся в CGI-программе на сервере, имя объекта необходимо задать таким образом, чтобы программа могла проанализировать данные из формы и извлечь значение указанного объекта. Для использования в клиентском JavaScript- сценарии можно присвоить не только понятные имена, описывающие этот объект, но и ука- зывать значения, которые используются в условных конструкциях if. . .else или включа- ются в строки, которые впоследствии будут отображаться в окне или фрейме. Свойства checked Значение: булево Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Простейшее свойство объекта checkbox указывает (или позволяет задать), установлен ли флажок. Для установленного флажка задается значение true, а для неустановленного — false. Для того чтобы установить флажок с помощью сценария, следует просто присвоить значение true для свойства checked объекта checkbox. document.forms[0].имяФлажка.checked = true; Задание свойства checked с помощью сценария не запускает событие click для объек- та checkbox. Возможно, вам понадобится сделать так, чтобы установка одного флажка автоматически выставляла другой флажок в Другой области этой же или другой формы определенного документа. 678 Часть III. Объекты документа
Для выполнения этой задачи следует задать обработчик события onclick для одного объек- та checkbox и написать оператор обработки события одного флажка, в котором для другого задается значения true соответствующего свойства. Однако этим не следует увлекаться чрезмерно: для труппы связанных, взаимно исключающих параметров лучдте использовать группу переключателей. Если дизайн вашей страницы подразумевает, что флажок будет установлен после загрузки страницы, не следует специально писать сценарий для выполнения этого действия. Просто добавьте к дескриптору < input > атрибут checked. Поскольку свойство checked является булевым значением, его результаты можно использовать в качестве аргумента оператора if, как показано в следующем примере. Пример Простой пример использования свойства checked приведен в листинге 22.2. В единст- венную функцию документа подставляется ссылка на объект формы. Функция же считывает свойства checked объекта флажка (checkThis. Checked) и использует полученное булево значение как условие в конструкции if. . . else. <html> <head> <title>Checkbox Inspector</title> <script type="text/javascript"> function inspectBox(form) { if (form.checkThis.checked) { alert("The box is checked."); } else { alert("The box is not checked at the moment."); </script> , </head> <body> <form> cinput type="checkbox" name="checkThis" />Check here «pxinput type="button" name="boxChecker" value="Inspect Box" onclick= "inspectBox(this.form) " /x/p> </form> </body> </html> См. также: свойства def aultChecked, value. defaultChecked Значение: булево Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Если добавить в дескриптор < input > определения объекта checkbox атрибут checked, то свойство defaultChecked для данного объекта будет иметь значение true; в противном случае, для свойства будет использоваться значение false. Полученный доступ к этому свойству позволит сценарию изменить состояние флажков (или пользователем, если сценарий не задает этого свойства). Глава 22. Объект кнопки 679
Пример Функция в листинге 22.3 используется для сравнения текущего значения флажка со значе- нием по умолчанию. Для этого была применена конструкция if. Оба сравниваемых значения имеют булев тип, поэтому в представленной операции нет ничего противоречивого. Если теку- щее значение и значение по умолчанию не совпадают, то функция изменяет свое поведение. function compareBrowser(thisBox) { if (thisBox.checked != thisBox.defaultChecked) { // операторы разных HTML-страниц } } См. также: свойства checked, value. type Значение: строка (checkbox) Только для чтения Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Используйте свойство type для идентификации объекта checkbox в неизвестной группе элементов формы. См. также: свойство form, elements. value Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Свойство value объекта checkbox представляет собой строку произвольного текста, который можно связать с соответствующим флажком. Обратите внимание, что свойство value объекта checkbox является не надписью, как в случае использования обычной кнопки, а скрытым текстом, связанным с данным флажком. Например, надпись объекта checkbox не несет важной информации, которую можно использовать в сценарии. Но если присвоить нужные данные атрибуту value соответствующего дескриптора, то эту строку можно из- влечь с Помощью свойства value. При отправке данных объекта checkbox в CGI-программу свойство value отправляется как часть пары имя-значение установленного флажка (если флажок не установлен, то никакая информация не передается). Если опустить атрибут value при задании объекта checkbox, то при установленном флажке это свойство всегда будет наследовать строку on, которая отправля- ется в программу CGI. При работе с JavaScript не следует пугать эту строку с параметрами объекта checkbox: on и off; для определения состояния флажка используйте свойство checked. Пример Сценарий листинга 22.4, создающий основу HTML-страницы, отображает форму с един- ственным флажком, состояние Которого определяет, какой из вариантов отправки данных на сервер реализуется в текущий момент. После щелчка на кнопке Подача запроса (Submit) функция JavaScript определяет значение свойства checked флажка. Если оно равно true (флажок установлен), то сценарий устанавливает свойство action всей формы в значение свойства value. Если вы протестируете этот листинг в локальном компьютере, то получен- ный результат будет зависеть от используемого браузера. В большинстве случаев на экран 680 Часть III. Объекты документа
(или в диалоговое окно) будет выведено сообщение о том, что имен primaryURL или alternativeURL не существует. Тем не менее, IE5.5 не отображает имя файла, который не- возможно открыть. По возможности не используйте этот браузер для изучения приводимого примера. Все сообщения и названия в ошибках выдуманы специально для данного примера. Листинг 22.4. Настройка действия отправки данных на сервер <html> <head> <title>Checkbox Submission«/title> «script type="text/javascript"> function setAction(form) { if (form.checkThis.checked) { form.action = form.checkThis.value; } else { form.action = "file://primaryURL"; } return true; } </script> </head> «body> «form method="POST" action=""> «input type="checkbox" name="checkThis" value="file://alternateURL" />Use alternate «p>«input type="submit" name="boxChecker" onclick="return setAction(this.form)" />«/p> </form> </body> «/html> См. также: свойство checked. Методы click () Возвращаемое значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Назначение метода click () состоит в выполнении с помощью сценария физического действия установки флажка (но без вызова обработчика события onclick). К сожалению, этот метод не выполняется должным образом в браузерах NN2 или NN3. Даже если описываемый метод работает безупречно, при написании сценария рекомендуется использовать свойство checked, чтобы абсолютно точно знать, какой параметр установлен для данного флажка. См. также: свойство checked, обработчик события onclick. Обработчики события onclick Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Поскольку пользователи регулярно устанавливают и снимают флажки, эти объекты обла- дают обработчиком события для события click. Используйте такой обработчик события Глава 22. Объект кнопки 681
только в том случае, если хотите, чтобы ваша страница (или скрытые значения переменной) тем или иным образом реагировала на установку флажка. Многие действия пользователя, как уже отмечалось ранее, инициируются не выставлением флажков, а щелчком на стандартных кнопках, поэтому будьте внимательны и не увлекайтесь использованием обработчиков собы- тий для объектов checkbox. Пример Пример захвата события щелчка объекта флажка приведен в листинге 22.5. Обработчик данного события позволяет отображать и скрывать другие элементы формы. После установки флажка Monitor на странице появится список переключателей, которые указывают размер монитора. Подобным образом, флажок Communications позволяет ознакомиться с двумя пе- реключателями используемого сетевого соединения. Выбор одного из двух последних вари- антов приводит к дальнейшему расширению формы на четыре переключателя (рис. 22.1). Рис. 22.1. Щелчок на элементе управления приводит к отображению дополнительных элементов управления Обратите внимание на универсальность функции toggle (). Она принимает ссылку на любой объект флажка и любой связанный с ним элемент span. Если в таблице использовать не более пяти групп флажков, то вполне можно обойтись одной этой функцией. В функции swap () для преобразования булевого значения свойства checked в строко- вое значение (принимает свойство display) используются вложенные конструкции if.. .else. Вложенность конструкций обеспечивает соблюдение двух условий в одном операторе: обработка сразу двух элементов управления и вызов функции в свойстве checked. Эта функция далеко не универсальная, поскольку она содержит явные ссылки на объекты документа. Чтобы сделать ее универсальной, вам понадобится ввести много допол- нительного кода в ссылках. 682 Часть III. Объекты документа
<html> <head> <title>Checkbox Event Handler«/title> <style type="text/css"> #monGroup {visibility:hidden} #comGroup {visibilityihidden} </style> «script type=11 text/javascript" > function toggle(chkbox, group) { var visSetting = (chkbox.checked) ? "visible" : "hidden"; document.getElementByld(group).style.visibility = visSetting; } function swap(radBtn, group) { var modemsVisSetting = (group == "modems") ? ((radBtn.checked) ? "" : "none") : "none"; var netwksVisSetting = (group == "netwks") ? ((radBtn.checked) ? "" : "none") : "none"; document.getElementByld("modems").style.display = modemsVisSetting; document.getElementByld("netwks").style.display = netwksVisSetting; } </script> «/head> «body> <form> <h3>Check all accessories for your computer:</h3> «table border="2" cellpadding="5"> <tr> «tdxinput type="checkbox" name= "monitor" onelick="toggle(this, 'monGroup')" />Monitor«/td> «tdxspan id="monGroup"><input type="radio" name="monitorType" />15" «input type="radio" name="monitorType" />17" «input type="radio" name="monitorType" />21" «input type="radio" name= "moni torType " / >&gt; 21" < /spanx/ td> «tdxinput type="checkbox" name="comms" onclick="toggle(this, 'comGroup')" /> Communications«/td> «tdxspan id= "comGroup"><p><input type="radio" name="commType" onelick="swap(this, 'modems')" /> Modem «input type="radio" name="commType" onclick="swap(this, 'netwks')" />Network«/p> <p>«span id="modems" style="display:none">«input type="radio" name="modemType" />&lt;56kbps «input type="radio" name="modemType" />56kbps «input type="radio" name="modemType" />ISDN (any speed) «input type="radio" name="modemType" />Cable«/span> «span id="netwks" style="display:none">«input type="radio" name="netwkType" />Ethernet 10Mbps (10-Base T) «input type="radio" name="netwkType" /> Ethernet 100Mbps (10/100) «input type="radio" name= "netwkType" />T1 or greater«/span> &nbsp; </px/spanx/td> Глава 22. Объект кнопки 683
</table> </form> </body> </html> См. также: обработчики событий мыши. Объект radio Свойства Методы Обработчики события См. объект checkbox Синтаксис Доступ к свойствам или методам объекта radio. (Все) [window.]document.имяФормы. имяГруппыПереключателей[индекс]. свойство | метод ( [параметры]) (Все) [window.]document.имяФормы.elements[индекс].свойство|метод ( [параметры] ) (Все) [window. ] document. forms [индекс] .имяГруппыПереключателей[индекс] . свойство] метод ( [параметры] ) (Все) [window.]document.forms["имяФормы”].имяГруппыПереключателей [индекс] .свойство|метод([параметры] ) (Все) [window.]document.forms["имяФормы"].elements[индекс] .свойство] метод([параметры] ) (IE4+) [window. ] document. all. идентификатор [индекс] . свойство | метод ( [параметры] ) (IE5+/W3C) [window.] document. getElementByld ("идентификатор") [индекс] . свойство | метод ( [параметры] ) Совместимость: WinIE3+, МасЕЗ+, NN2+, Mozl+, Safaril+ Описание объекта Объект radio достаточно нестандартный в языке JavaScript. При использовании любого, другого элемента управления формы одному объекту на экране соответствует один графиче- ский элемент. Но объект radio состоит из группы элементов radio. Поскольку природа элементов radio — взаимно исключающие параметры в группе двух или более элементов, то группа всегда имеет несколько графически представленных в документе элементов. Все элементы в группе обладают одинаковым именем, чтобы браузер мог сгруппировать элемен- ты вместе и обеспечить при выделении одного параметра отмену выделения других выделен- ных в данный момент параметров. Однако, помимо этого, каждый элемент группы может иметь уникальные свойства (например, значение свойства checked). Для получения информации об отдельных элементах группы используется синтаксис мас- сива JavaScript. Рассмотрите приведенный ниже пример задания группы элементов и обратите 684 Часть III. Объекты документа
внимание на определение каждого элемента группы. Эта группа элементов позволяет пользо- вателю выбрать один из трех заданных параметров. <form> <t»Select your favorite Stooge: </bxbr /> cinput type="radio" name="stooges" value="Moe Howard" checked />Moe cinput type="radio" name="stooges" value="Larry Fine" />Larry cinput type="radio" name="stooges" value="Curly Howard" />Curly cinput type="radio" name="stooges" value="Shemp Howard" />Shemp c/form> После отображения группы элементов на странице первый элемент radio для пользова- теля будет выделенным. Для всех элементов группы применимо только одно общее свойство объекта radio— length. Однако другие свойства применяются к отдельным элементам группы. Для получения доступа к элементу группы воспользуйтесь значением индекса масси- ва как частью имени группы элементов. firstBtnValue = document.forms[0].stooges[0].value // "Moe Howard" secondBtnValue = document.forms[0].stooges[1].value // "Larry Fine" При получении доступа к свойствам def aultChecked, type или value нужно указать специфический элемент группы, в соответствии с порядковым номером массива (в JE4+ и NN6+ каждый элемент обладает уникальным ID). Порядок элементов в группе зависит от последо- вательности расположения отдельных элементов группы в указанном элементе HTML. Дру- гими словами, для выявления текущего выделенного элемента группы ваш сценарий должен последовательно просмотреть все элементы radio в группе (см. далее). Задание атрибута value для элемента группы может стать очень важной задачей в сцена- рии. Несмотря на то, что текстовая надпись для элемента задается за пределами дескриптора < input >, только атрибут value позволяет хранить для использования в сценарии любую строку. В приведенном ранее примере надписи элементов radio содержали только имена, в то время как свойствам value были присвоены полные имена актеров. В качестве значений мож- но использовать любые данные, которые необходимо обработать в сценарии, например, даты рождения, размер обуви, адреса URL или просто имена (поскольку сценарий может извлекать надписи только с помощью свойства innerHTML или'свойства node в большинстве современ- ных браузеров). Смысл заключается в том, что атрибут value может содержать любую строку, которая требуется сценарию для извлечения выбранного пользователем параметра. Содержимое атрибута value также отправляется в CGI-программу на сервер при передаче данных формы. • Расположить группу переключателей в документе вы вправе по своему усмотрению. Можно расположить их в строке по горизонтали (как показано ранее); для того чтобы раз- местить их в одном столбце, добавьте дескриптор <Ьг> после каждого элемента переключа- теля или после каждого следующего переключателя, чтобы создать двойной столбец. Индек- сы массива определяются только порядком расположения переключателей в исходном коде, а не способом их отображения на экране. Для того чтобы определить, какой переключатель из группы является выделенным перед началом обработки после выбора элемента пользова- телем, следует создать цикл просмотра переключателей в группе (см. следующий пример). Для каждого переключателя в сценарии следует проверить свойство checked. Свойства checked Значение: булево Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Чтение/Запись Глава 22. Объект кнопки 685
Только один переключатель в группе может быть выделен (checked) — за выделение переключателя в группе отвечает браузер. При этом для одного свойства checked переклю- чателя будет установлено значение true, в то время как для всех остальных элементов в группе устанавливается значение false. Начиная с NN3 (и IE3), можно спокойно использовать для переключателей свойство checked. При задании для одного переключателя группы свойства checked со значением true все остальные переключатели автоматически перестанут быть активными. Пример В листинге 22.6 в одной из функций циклически просматриваются все установленные элементы управления формы. Как только функция найдет переключатель, свойство которого имеет значение true, она возвратит его индекс. Далее значение индекса используется для определения значения value, которое впоследствии отображается в диалоговом окне. Кроме того, индекс необходим для определения следующего устанавливаемого элемента управления. <html> <head> <title>Extracting Highlighted Radio Button</title> <script type="text/javascript"> function.getSelectedButton(buttonGroup){ for (var i = 0; i < buttonGroup.length; i++) { if (buttonGroup[i].checked) { return i; } } return 0; } function fullName(fprm) { var i = getSelectedButton(fofc-m.stooges); alert("You chose " + form.stooges[i].value + "."); } function cycle(form) { var i = getSelectedButton(form.stooges); if (i+1 == form.stooges.length) { form.stopges[0].checked = true; } else { form.stooges[i+1].checked = true; } } </script> </head> <body> <form> <b>Select your favorite Stooge:</b> <pxinput type="radio" name="stooges" value="Moe Howard" checked="checked" />Moe <input type="radio" name="stooges" value="Larry Fine" />Larry <input type="radio" name="stooges" value="Curly Howard" /> Curly <input type="radio" name="stooges" value="Shemp Howard" />Shemp</p> <pxinput type= "button" name = "Viewer" value="View Full Name..." onclick="fullName(this.form)" 686 Часть III. Объекты документа
/></р> <p><input type="button" name="Cycler" value="Cycle Buttons" onelick="cycle(this.form)" /></p> </form> </body> </html> См. также: свойство def aultChecked. defaultChecked Значение: булево Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Если при задании переключателей к дескриптору < input > добавить атрибут checked, то для этого объекта свойство def aultChecked будет иметь значение true; в противном случае ему будет присвоено значение false. Предоставьте доступ к этому свойству, и вы по- зволите сценариям проанализировать отдельные переключатели, чтобы просмотреть, были ли изменены их значения (предположительно пользователем, если ваш сценарий не выполняет автоматическую проверку). Пример В коде, показанном в листинге 22.7, функция устанавливает ссылку на форму, содержа- щую переключатели. Задача очень проста — определить (группа переключателей имеет соб- ственное имя), изменил ли пользователь настройки по умолчанию. Функция просматривает в цикле все переключатели и определяет, какой из них имеет атрибут checked в дескрипто- ре <input>. Получив соответствующий индекс (i), можно легко проверить, установлен ли переключатель до сих пор. Если нет (обратите внимание на оператор отрицания !), то на эк- ране появится сообщение о внесенных изменениях. for function groupChanged(form) { (var i = 0; i < form.stooges.length; i++) { if (form.stooges[i].defaultChecked) { if ('form.stooges[i].checked) { alert("This radio group has been changed."); См. также: свойства checked, value. length Значение: целочисленное Только для чтения Совместимость: WinE3+, MacIE3+, NN2+, Mozl+, Safari 14- Группа переключателей имеет длину — количество отдельных переключателей, заданных для данной группы. Попытка извлечь значение длины отдельных переключателей приводит к возвращению значения null. Свойство length используется для задания максимального количества значений в цикле, который выполняет проверку каждого переключателя в данной Глава 22. Объект кнопки 687
группе. Если задать свойство length вручную (а не с помощью сценария), то управлять цик- лом будет намного проще. Также будет упрощено решение других насущных задач, напри- мер, изменение количества элементов группы (в процессе выполнения пользователем действий). name Значение: идентификатор строки Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ При использовании для переключателей свойство name задается только для отдельного переключателя в группе. btnGroupName = document.forms[0].groupName[2].name; В данном представлении каждый переключатель в группе наследует имя всей группы. Как правило, для сценария не требуется извлекать свойство name отдельного элемента группы. Чаще придется использовать в сценарии имя труппы переключателей, чтобы извлечь другие свойства отдельных элементов. Очевидно, что извлекать свойство name объекта, имя которо- го вам известно, — это лишняя трата времени. Но понять, какое место занимает имя группы переключателей в структуре объектов JavaScript, важно для всех программистов. См. также: свойство value. type Значение: строка (radio) Только для чтения Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safari 14- Свойство type используется для идентификации объекта radio в незнакомой группе элементов формы. См. также:свойство form. elements. value Значение: строка Чтение/Запись Совместимость: WinTE3-b, MacIE3+, NN24-, Mozl4-, Safaril4- Как отмечалось ранее в этой главе, для объекта checkbox свойство value содержит про- извольную информацию, которую вы присваиваете при задании дескриптора < input > для от- дельного элемента radio. Это свойство используется для установки соотношения между над- писью переключателя и полной или относительной информацией, отправляемой в сценарий или CGI-программу на сервере. Свойству value можно присвоить тот же текст, что и надписи. См. также: свойство name. Методы clickO Возвращаемое значение: отсутствует Совместимость: WinIE34-, Мас1ЕЗч-, NN24-, Mozl-h, Safari 14- Назначение метода click () — с помощью сценария имитировать физическое действие выбора переключателя. К сожалению, этот метод не выполняется в браузере NN2 или NN3. Даже если описываемый метод работает безупречно, при написании сценария рекомендуется использовать свойство checked для всех элементов в группе, чтобы абсолютно точно знать, какой параметр установлен для данного флажка. См. также: свойство checked, обработчик события onclick. 688 Часть III. Объекты документа
Обработчики события onclick Совместимость: WinIE3+, МасЕЗ+, NN2+, Mozl+, Safari 14- Переключатели предназначены для предоставления возможности выбора (в отличие от ос- тальных объектов, например, кнопки Submit или стандартной пользовательской кнопки). Воз- можно, вам приходилось работать с программами Windows или Мас, где выбор переключателя активизирует или отображает дополнительные, связанные с ним параметры (см. листинг 22.5). Настойчиво рекомендуем не использовать обработчики событий, которые при выборе пе- реключателя выполняют действия в сценарии. Возможно, вам захочется использовать знания об изменении глобальной переменной или параметра document. cookie, который влияет на последующую обработку (что выполняется при выборе пользователем переключателя). Однако будьте внимательны: если вы примените для одного элемента из группы такое дейст- вие, вам придется применить подобные действия и для других элементов группы. Пример При щелчке на одном из переключателей, создаваемых в листинге 22.8, глобальная пере- менная примет значение true или false. Это действие не зависит от действий, выполняемых при щелчке на кнопке View Full Name. Обработчик onunload в дескрипторе <body> вызыва- ет функцию, которая отображает сообщение перед удалением страницы с экрана. В данном примере используется функция инициализации, которая вызывается в обработчике onload. Листинг 22.8. Обработчик onclick пчремжмггелвй <html> <head> <title>Radio Button onClick Handler</title> «script type="text/javascript"> var ShempOPhile = false function initValue() { ShempOPhile = document.forms[0].stooges[3].checked; function fullName(form) { for (var i = 0; i < form.stooges.length; i++) { if (form.stooges[i].checked) { break; ' } alert("You chose " + form.stooges[i].value + "."); } function setShemp(setting) { ShempOPhile = setting; function exitMsgO { if (ShempOPhile) { alert("You like SHEMP?"); </script> </head> «body onload="initValueO" onunload="exitMsg()"> <form> <b>Select your favorite Stooge:</b> Глава 22. Объект кнопки 689
«pxinput type=“radio" name="stooges" value="Moe Howard" checked="checked" onclick="setShemp(false)" />Moe «input type="radio" name="stooges" value=”Larry Fine" onclick="setShemp(false)" />Larry «input type="radio" name="stooges" value="Curly Howard" onclick="setShemp(false)" />Curly «input type="radio" name="stooges" value="Shemp Howard" onclick="setShemp(true)" />Shemp«/p> «pxinput type="button" name="Viewer" value=”View Full Name..." onclick="fullName(this.form) " /x/p> </form> «/body> </html> Объект image Свойства, методы и обработчики события этого элемента описываются в главе 15. Свойства Методы Обработчики события complete form* name* src type * См. объект button Синтаксис Доступ к свойствам или методам объекта image. (Все) [window.]document.имяФормы.имяИзображения.свойство|метод([па- раметры] ) (Все) [window. ] document .имяФормы. elements [индекс] . свойство (метод ([па- раметры] ) (Все) [window.]document.forms[индекс] .имяИзображения.свойство | метод ( [параметры] ) (Все) [window.]document.forms["имяФормы"].имяИзображения.свойство|ме- тод( [параметры] ) (Все) [window. ] document. forms [ "имяФормы" ] . elements [индекс] . свойство] метод ( [параметры] ) (IE4+) [window. ] document. all. идентификатор, свойство] метод ([параметры]) (IE5+/W3C) [window. ] document.getElementByld ("идентификатор") . свойство | ме- тод ( [параметры] ) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ 690 Часть III. Объекты документа
Описание объекта Браузеры с полной объектной моделью документа предоставляют для использования в сце- нарии элемент image. Объект image напоминает объект button, но для него свойство value (которое определяет надпись кнопки) заменяется свойством его. Это свойство задает адрес URL изображения, которое должно быть отображено на форме. Это более простой способ за- дания изображения, реагирующего на щелчок, чем, например, способ, используемый при обеспечении совместимости со браузерами старых версий (речь идет о заключении элемента img внутрь элемента а, что позволяет воспользоваться обработчиками события последнего). Этот элемент загружает в документ обычное Web-изображение, однако вы не сможете управлять им, что позволяет сделать элемент IMG. Убедитесь, что отображение выполняется именно так, как вы рассчитывали. Свойства complete Значение: булево Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Mozl+, Safaril+ Свойство complete выполняется так же, как и для элемента img; значение true присваи- вается только после окончания загрузки. В противном случае свойство возвращает значение false. Интересно, что для этого объекта не существует обработчика события onload. См. также: свойство image. complete. src Значение: строка URL Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Подобно объекту элемента img, свойство src элемента image управляет адресом URL изображения, отображаемого в элементе. Это свойство можно использовать для замены изо- бражения в элементе управления формы так же, как и для обычного элемента img. Поскольку элемент image обладает всеми необходимыми и доступными (например onmouseover, onmouseout, onmousedown) обработчиками события мыши, вы можете использовать в своем сценарии изображения, реагирующие на перемещения указателя мыши, щелчки, нажатия кнопки мыши или любой другой метод управления элементами пользовательского интерфей- са. Для того чтобы адаптировать исходный код, который написан для ссыпок, содержащих изображения, переместите обработчик события из элемента а в элемент image, и убедитесь, что имя элемента image является таким же, как и у старого элемента img. Более ранние версии браузеров загружают изображения в элемент image, но обработчики события для них не распознаются. См. также: свойство image .src. type Значение: строка (image) Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Используйте свойство type для идентификации объекта image в неизвестной группе элементов. См. также: свойство form, elements. Глава 22. Объект кнопки 691
Текстовые объекты формы Объектная модель документа для форм включает четы- ре объекта пользовательского интерфейса, связанных с управлением текстом, — текстовое поле, поле пароля, скрытый объект элемента input и элемент textarea. Все четыре объекта используются для ввода, отображения или временного хранения текстовых данных. Все эти объекты по умолчанию содержат текст при загрузке страницы, однако сценарии в процессе выполнения также могут изменить их содержимое. Важно отметить, что все объекты, кроме скры- тых полей, сохраняют содержимое, измененное пользовате- лем или сценарием при перезагрузке (например, при щелчке на кнопке Reload), кроме браузера IE3. Скрытые объекты при перезагрузке во всех браузерах возвращаются к парамет- рам, заданным по умолчанию. Очевидная разница между скрытыми объектами и всеми остальными заключается в невозможности обработки их со- бытий и управления ими пользователями. Таким образом, возможностей по управлению скрытыми объектами в сцена- рии несколько меньше. Постоянство текста и данных в объекте textarea при пе- резагрузке (и изменении размеров окна) способствует тому, что они являются превосходными хранилищами (неотображаемых) данных, которые, помимо этого, можно сохранять в файлах cookie. При создании фрейма без определенного размера (например, параметры cols или rows в дескрипторе <f rameset> для всех видимых фреймов задаются равными 100%, а для другого, скрытого фрейма, — равными *) его полям можно определить поведение, аналогичное заполните- лям или таблицам на коммерческих узлах, которые расширя- ются по мере заполнения данными. В случае, когда пользова- тели пренебрегают использованием cookie или не отвечают утвердительно на предложение использовать файлы cookie, ваше приложение может воспользоваться временно сохранен- ными пользовательскими данными. Содержимое поля иногда остается прежним при перезагрузке страницы, но произойдет ли это, зависит от того, насколько эффективно пользователь
использует кэш-память браузера для сохранения временных данных (если используется брау- зер IE3, то в этом случае данные не сохраняются при перезагрузке). Если пользователь закро- ет браузер или окно браузера, то данные поля будут безвозвратно потеряны. Объект text Свойства этого HTML-элемента, его методы и обработчики события описываются в главе 15. Свойства Методы Обработчики события defaultvalue form maxLength name readonly size type value select() onaf terupdate onbeforeupdate onchange onerrorupdate onselect Синтаксис . Доступ к свойствам или методом объекта text. (Все) [window.]document.имяФормы.имяПоля.свойство|метод([параметры] ) (Все) [window.]document.имяФормы.elements[индекс] .свойство|метод ( [параметры] ) (Все) [window. ] document.forms[индекс] .имяПоля.свойство|метод([пара - метры]) (Все) [window.]document.forms["имяФормы”].имяПоля.свойство|метод ( [параметры] ) (Все) [window.]document. forms["имяФормы"].elements[индекс].свойство| метод ( [параметры] ) (IE4+) [window. ] document .all .идентификатор, свойство\метод([параметры] ) (IE5+/W3C) [window. ] document. getElementBylD ("идентификатор” ) . свойство | метод ( [параметры] ) Описание объекта Объект text является основным инструментом получения введенного пользователем текста, состоящего из одной строки. По умолчанию браузеры отображают введенный текст моноширинным шрифтом (как правило, Courier или производными от него), поэтому вы обя- зательно должны задать ширину (атрибут size) поля, указав максимальное количество сим- волов, которые пользователь может ввести в поле. Если вы не разрабатываете страницу спе- циально для браузеров IE3+ или NN6+, то у вас шрифт будет иметь фиксированный размер, а строка выравнивается по левому краю. В более поздних версиях браузеров каскадные Глава 23. Текстовые объекты формы 693
таблицы стилей могут изменять параметры шрифта текстового поля. Если вы собираетесь исполь- зовать текстовое поле, состоящее из нескольких строк, воспользуйтесь объектом textarea, о котором рассказывается далее в этой главе. До того, как объектные модели документов браузеров W3C позволили динамически изме- нять содержимое поля, текстовые объекты использовались для отображения результатов вы- числений, выполняемых сценарием, или другого вида обработки данных. Подобные поля мо- гут использоваться на странице отдельно или входить в состав таблицы. Также до появления браузеров W3C эти поля нельзя было полностью защитить от записи, поэтому легко представить, в какое неловкое положение попадали неопытные пользователи, активизировавшие (с помощью указателя мыши или клавиши <ТаЬ>) поля, использовавшиеся исключительно для вывода информации. Для методов текстовых объектов и обработчиков событий применяется терминология, с которой, возможно, знакомы пользователи Windows, но не Macintosh. Считается, что поле становится активным, если пользователь щелкнул на нем или перешел в него с помощью клавиши <ТаЬ>. Когда поле активизируется, в нем либо мерцает курсор, либо находящийся в данном поле произвольный текст оказывается выделенным. Противоположное действие пользователя — щелчок за пределами поля или переход от этого поля к другому элементу таблицы с помощью клавиши <ТаЬ> — называется деактивизацией. Щелчок на другом объекте (другом поле или любой кнопке) приводит к тому, что поле становится неактивным. Если вы не хотите, чтобы пользователь изменил содержимое поля, у вас есть три возмож- ности (в зависимости от типа поддерживаемого браузера): сделать поле неактивным; сделать поле недоступным; задать для поля свойство readonly. Для достижения полной обратной совместимости в поле, которое следует защитить, ис- пользуется следующий обработчик события. onFocus="this.blur() Начиная с IE4 и NN6, объектная модель содержит свойство disabled для элементов управления формы. Установка этого свойства в значение true оставляет элемент отобра- женным на странице, но пользователь не сможет получить к нему доступ. В этих же брау- зерах задано свойство readonly, которое не блокирует поле, но и не позволяет ввести в него информацию. Текстовые поля и события События focus и blur также соответствуют дополнительным действиям пользователя, выполняемым по отношению к текстовому объекту: выделение и изменение. Выделение про- исходит, когда пользователь щелкает мышью вначале поля и перетаскивает указатель вдоль тек- ста поля; изменение происходит, когда пользователь вносит изменения в содержимое поля, а за- тем уходит от этого поля, щелкнув на любом другом элементе или нажав клавишу <ТаЬ>. При использовании обработчиков события для поля учтите, что взаимодействие пользова- теля с полем может привести к генерированию более одного события. Например, щелчок на поле для выделения текста может запустить оба события: focus ц select. Если у вас воз- никают проблемы при использовании обработчиков событий onf ocus и onselect, то ваши сценарии, скорее всего, будут выполнять непонятные для посетителя страницы действия. На- пример, отображение диалоговых окон с предупреждениями также запускает событие blur, поэтому поле, для которого заданы обработчики событий onselect (отображающее преду- преждение) и onblur, взаимодействуют самым необъяснимым образом. Будьте внимательны, задавая для текстового объекта несколько обработчиков событий. По возможности выберите одно действие пользователя, которое хотите использовать для вы- полнения определенного фрагмента исходного кода JavaScript, и последовательно используй- те его на странице. Не для всех полей необходимо задавать обработчики событий, — только 694 Часть III. Объекты документа
для тех, которые будут выполнять определенные операции в результате воздействия пользо- вателя на данное поле. Многие неопытные разработчики не понимают поведения события change. Любые изме- нения в поле считаются выполненными только после того, как поле будет деактивизировано, т.е. пользователь щелкнет за пределами поля или уйдет от него с помощью клавиши <ТаЬ>. Таким образом событие не передается после ввода в поле каждого следующего символа од- ного слова. При этом вместо события blur используется событие change, которое при из- менении значения поля вызывает обработчик события onchange. Необходимое действие (щелчок за пределами поля или использование клавиши <ТаЬ>) вызывает соблазн присвоить обработчик события onchange отдельной кнопке, на которой пользователь должен щелк- нуть, чтобы инициировать определенное действие над содержимым поля. Начиная с браузеров NN4 и IE4, текстовым полям также свойственны обработчики собы- тий клавиатуры — onkeydown, onkeypress и onkeyup. С помощью этих обработчиков событий можно перехватывать нажатие клавиши до того, как символ отобразится в тексто- вом поле. Следовательно, события для работы с клавиатурой можно использовать, чтобы при вводе информации в текстовое поле, например, не допустить ввода чисел. Для извлечения текущего содержимого текстового объекта вызовите свойство document. имяФормы. имяОбъекта. value. После извлечения значения строки можно использовать строковый объект JavaScript для анализа или другого вида обработки данного текста, предусмотренного в сценарии. Если поле содержит числовое значение, а вам нужно передать это значение в методы, использующие числовые данные, следует преобразовать текст в число с помощью глобальных функций parselnt () или parseFloat (). Текстовые поля и клавиша <Enter> В ранних версиях браузеров использовались общепринятые соглашения, которые действуют и по сей день. Если форма состоит только из одного текстового поля, нажатие клавиши <Enter> действует точно так же, как и щелчок на кнопке Submit для формы. Возможно, вы не- однократно убедились в этом при вводе значения в простое поле формы, используемое для проведения поиска. Стоит нажг^ь клавишу <Enter>, и запрос отправится на сервер. С другой стороны, если форма содержит более одного текстового поля, то при нажатии кла- виши <Enter> (<Retum>) данные ни из одного текстового поля отправлены не будут (исключением является браузер IE4 для Мас: он отправляет данные независимо от того, сколько текстовых полей содержит форма). Но при наступлении событий, связанных с кла- вишами, можно запрограммировать это действие (или инициировать серверную часть сце- нария) для любых текстовых полей формы. Чтобы они выполнялись во всех браузерах, раз- личающих события клавиатуры, необходимо использовать небольшую функцию ветвления, которая при нажатии клавиши будет выполнять соответствующий фрагмент исходного кода, свойственный для данной объектной модели документа. Приведенный ниже код представля- ет фрагмент страницы, в которой применяется функция, анализирующая каждое нажатие клавиш в текстовом поле, и запускающая обработку данных при нажатии клавиши <Enter>. <html> <head> <title>Enter/Return Event Trigger</title> «script type="text/javascript"> // Обрабатывает объекты событий в NN4, IE4+, NN6 function isEnterKey(evt) { evt = (evt) ? evt : (window.event) ? window.event : var theKey; if (evt) { theKey = (evt.which) ? evt.which : evt.keyCode; } return (theKey == 13) ; Глава 23. Текстовые объекты формы 695
} function processOnEnter(fid, evt) { if (isEnterKey(evt)) { alert("Ready to do some work with the form."); return false; } return true; } </script> </head> <body> <hl>Enter/Return Event Trigger</hl> <hr /> <form onsubmit=" return false"> Field 1: cinput type="text" name="fieldl” onkeydown="return processOnEnter(this, event)" /> Field 2: cinput type="text" name="field2" onkeydown="return processOnEnter(this, event)" /> Field 3: cinput type="text" name="field3" onkeydown="return processOnEnter(this, event)" /> </form> c/body> </html> Обратите внимание на то, что для удобства работы с моделями событий в браузерах NN4+ и W3C ссылка на объект event передает в качестве параметра в обрабатывающую функцию (см. главу 25). Свойства de f aultValue Значение: строка * Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Пользователи и сценарии могут свободно управлять содержимым объекта text, присваи- вая свойство value строкам, однако вы всегда сможете извлечь (и, следовательно, при необ- ходимости восстановить) строку, присвоенную текстовому объекту при задании дескриптора <input>. Свойство defaultvalue извлекает строковый параметр атрибута value. / Листинги 23.1-23.3 описывают форму, содержащую всего один элемент input. /На заметку Правила управления формами на HTML-страницах гласят, что данные формы ’ отправляются на сервер при нажатии клавиши <Enter> даже при активном тексто- вом поле или текстовой области. Такое поведение формы предполагает переза- грузку страницы, в форму которой не введены данные, что вызывает прекращение выполнения текущего сценария. В текущем примере элементы form содержат об- работчик onsubmit, который в подобных ситуациях блокирует отправку данных и вызывает обработчик onchange текстового поля, выполняющий демонстрацион- ный сценарий. В отдельных браузерах, например MaclE5, чтобы вызвать обработ- чик onchange, вам придется щелкнуть за пределами поля или нажать <ТаЬ>. Листинг 23.1 содержит простую форму с единственным полем, в которое введено значе- ние по умолчанию. Функция resetFieldO восстанавливает содержимое этого поля до значения по умолчанию (задается в дескрипторе < input >) после того, как оно было изменено. В странице с одним текстовым полем, подобной этой, определение кнопки type="reset” 696 Часть III. Объекты документа
и вызов метода form, reset () приводят к одинаковым результатам, поскольку подобная кнопка восстанавливает значения по умолчанию всех элементов управления формы. Если же вам необходимо восстановить значения только отдельного набора полей, то рассмотрите пример функции в листинге 23.1. Листинг 23,1. Восстановление значения по умолчанию текстового объекта <html> <head> <title>Text Object DefaultValue</title> <script type="text/javascript"> function upperMe(field) { field.value = field.value.toUpperCase(); } function resetField(form) { form.converter.value = form.converter.defaultvalue; } </script> </head> <body> <form onsubmit="window.focus(); return false"> Enter lowercase letters for conversion to uppercase: <input type="text" name="converter" value="sample" onchange="upperMe(this)" /> cinput type="button" value="Reset Field" onclick="resetField(this.form)" /> </form> </body> </html> См. также: свойство value. form Значение: ссылка на объект form Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство каждого объекта элемента input представляет собой ссылку на элемент form, который содержит элемент управления. Это свойство удобно использовать в сценарии при работе с одним элементом управления формой, которое передается функции в качестве пара- метра, из которого вам нужно получить доступ к другому элементу управления той же формы или вызвать метод формы. Обработчик события элемента input может принимать в качестве параметра ключевое слово this, а функция получает доступ к форме без дополнительного об- ращения к именованным объектам и громоздким иерархическим ссылкам в пределах документа. Следующая функция получает в качестве аргумента ссылку на текстовый объект. Эта ссылка определяет, какая из ветвей функции будет в дальнейшем выполняться (в данном слу- чае определяется способ отправки данных формы). function setAction(fid) { if (fid.value.indexOf("®") != -1) { fid.form.action = "mailto:" + fid.value; } else { fid.form.action = "cgi-bin/normal.pl"; } fid.form.submit(); } Глава 23. Текстовые объекты формы 697
Обратите внимание, что сама функция не привязывается к конкретной форме, поскольку в данном случае форма определяется как контейнер текстового поля, вызвавшего функцию. См. также: объект form. maxLength Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство maxLength определяет максимальное количество символов, которые можно ввести в поле. Свойства maxLength и size не зависят друг от друга. Это значение обычно задается с помощью атрибута maxlength элемента input. Пример Приложение The Evaluator (глава 13) позволяет экспериментировать со свойством maxLength. Верхнее текстовое поле приложения не имеет значения по умолчанию, но вы можете временно назначить его равным неким символам, чтобы узнать, как следующее вы- ражение скажется на нем. document.forms[0].input.maxLength = 3; Введя это выражение в верхнее поле, вы увидите, что результат изменился. Чтобы восста- новить значение по умолчанию, перезагрузите страницу. См. также: свойство size. name Значение: идентификатор Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Имена текстовых объектов имеют важное значение по двум причинам. Во-первых, если ваша HTML-страница отправляет информацию в CGI-сценарии, то устройство ввода передает имя текстового объекта вместе с данными, чтобы помочь программе на сервере идентифици- ровать информацию, полученную из формы. Во-вторых, имя текстового объекта можно ис- пользовать в ссылках в сценарии JavaScript.'EcnH вы присвоите для ваших полей понятные имена, то они помогут вам разобраться (а другим пользователям понять структуру сценария) в выполняемых действиях и отладить листинги JavaScript. Задавая имена для текстовых объектов, постарайтесь использовать понятные имена. Ко- пирование текста надписи поля, отображаемой на странице, поможет вам найти в сценарии ссылку на его физическое расположение. Подобно всем именам объектов в JavaScript, имена текстовых объектов должны начинаться с буквы, за которой может следовать любое количе- ство символов или чисел. Избегайте использования в именах знаков пунктуации, за исключе- нием безопасного символа подчеркивания. Рекомендуется использовать понятные имена для всех объектов, которые задаются в до- кументе, однако может оказаться так, что вы присвоите одно и то же имя для набора взаимо- связанных полей, — и здесь JavaScript придет вам на помощь. В пределах одной формы лю- бое повторно использованное имя для объекта того же типа помещается в индексированный массив, созданный для этого имени. Например, при задании трех полей с одинаковым именем для каждого поля свойство value можно извлечь с помощью следующих инструкций. data = document, f orms [0] .entry [0] .value data = document.forms[0].entry[1].value; data = document.forms[0].entry[2].value; Такую конструкцию удобно использовать, если вы хотите задать цикл просмотра всех по- лей формы для поиска пустого элемента. Кроме того, в процессе выполнения сценария, воз- можно, понадобится узнать, какой тип информации содержит каждое поле (чтобы выполнить 698 Часть III. Объекты документа
соответствующую обработку данных). Я не рекомендую повторно использовать одни и те же имена объектов, но вам следует знать, как представлено объектная модель в этом случае. К сожалению, ВЕЗ не поддерживает использования подобных объектов text в массивах. Бо- лее подробная информация по этому вопросу приведена в главе 21. Пример Изучите листинг 23.2 далее в этой главе, в котором использовался текстовый объект convertor. Имя этого объекта применялось в операторе присвоения полю значения. Чтобы извлечь имя текстового поля, использовалась ссылка на свойство name. var objectName = document.forms[0].elements[О].name; См. также: свойство form, elements, свойства name других элементов объектов формы. readonly Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Для отображения текста в текстовом поле без предоставления пользователю возможности его изменения новые версии браузеров предлагают свойство readonly (и атрибут дескрип- тора). При задании параметра true это свойство не позволяет пользователю изменять или удалять содержимое текстового поля. В отличие от недоступных текстовых полей, эти поля, предназначенные только для чтения, выглядят точно так же, как и редактируемые. В браузерах старых версий можно частично сымитировать такое поведение, добавив в элемент input следующий обработчик события. onfocus="this.blur()" Однако добавление этого обработчика события нельзя считать полноценным заменителем (некоторые пользователи могут намеренно изменить содержимое поля еще до того, как обра- ботчик события завершит свою работу). Для NN можно заблокировать события, связанные с клавиатурой, и предотвратить ввод символов в поле. Пример Приложение The Evaluator позволяет сделать нижнее текстовое поле доступным только для чтения. Сначала введите в него произвольный текст. Затем введите в верхнее поле сле- дующее выражение. document.forms[0].inspector.readonly = true; Теперь вы можете выделить текст в нижнем поле, однако изменить его не представляется возможным. См. также: свойство disabled. size Значение: целочисленное Чтение/Запись Совместимость: WinfE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Если размер текстового поля не указан при создании этого элемента, то оно будет ото- бражать около 20 символов для шрифта с размером, указанным в таблице стилей элемента. Вы можете дополнительно указать максимальное количество символов, всего вводимого в поле текста (если атрибута size дескриптора не достаточно). Однако помните, что браузе- ры не всегда корректно оценивают пространство, необходимое для отображения определен- ного количества символов. Если вы задаете для текстового поля атрибут maxlength, то укажите для атрибута size размер на один-два символа больше. Глава 23. Текстовые объекты формы 699
Пример Измените размер нижнего текстового поля приложения The Evaluator, введя в верхнее по- ле следующие выражения. document.forms[0].inspector.size = 20; document.forms[0].inspector.size = 400; Перезагрузите страницу, чтобы вернуться к исходным размерам поля (80). См. также: свойство maxLength. type Значение: строка (text) Только для чтения Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Используйте свойство type для идентификации объекта text в неизвестной группе эле- ментов формы. См. также: свойство form, elements. value Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Свойство value текстового объекта является двузначным по отношению к содержимому поля. Ссылка на свойство value объекта возвращает строку, отображаемую в данный мо- мент в поле. Обратите внимание на то, что все значения, извлекаемые из объекта text, яв- ляются строковыми. Если пользователю предлагается ввести в поле число, возможно, вашему сценарию следует преобразовать данные в текстовое значение, в котором числа воспринима- ются как строки (“42” вместо старого доброго 42), чтобы сценарий смог выполнить операцию сравнения. JavaScript пытается по возможности сделать это автоматически, соблюдая некото- рые внутренние правила (см. главу 27). Если выводится сообщение об ошибке, в котором го- ворится, что некоторое значение не является числовыми (в математических операциях), то это значение точно является строковым. Ваш сценарий помещает в поле текст, который отображается для пользователя в резуль- тате присвоения строки свойству value текстового объекта. Для этого используется обыч- ный оператор присвоения. document.forms[0].ZIP.value = "90210"; При присвоении значений текстовому объекту JavaScript является более снисходитель- ным. JavaScript делает все возможное для преобразования значения в строковое при отобра- жении текстового объекта. Даже булевы значения преобразуются в свои строковые эквива- ленты true или false. Сценарии могут без проблем помещать числовые значения в поля. Но помните: если позже сценарий извлечет эти значения из текстового объекта, они будут иметь строковый тип. Единственными значениями, которые не преобразуются, являются объек- ты. Обычно они отображаются в текстовых полях как [object], или — в некоторых брау- зерах — более описательную надпись объекта. Хранение массивов в поле требует дополнительной обработки данных. Для преобразова- ния массива в строку следует использовать метод array. j oin (). Каждый элемент массива отделяется символом, заданным в методе array. j oin (). Позднее для преобразования этой разделенной строки в массив можно использовать обратный метод string. split (). 700 Часть III. Объекты документа
Пример Демонстрация принципов назначения и получения значения в текстовом поле приведена в листинге 23.2, в котором действия выполняются в обработчике onchange. Введите любой строчный символ в поле и щелкните за пределами поля. В обработчик события подставляется ссылка на объект формы. Функция извлекает значение, преобразует его символы в прописные (для этого используются методы управления строчными данными JavaScript) и обратно на- значает его в качестве значения поля. Листинг 23.2. Получение инШрйвм вмчеи* тактового поля «html» <head> «title»Text Object DefaultValue</title> «script type="text/javascript"» function upperMe(field) { field.value = field.value.toUpperCase(); } function resetField(form) { form.converter.value = form.converter.defaultvalue; } </script> «/head» <body> «form onsubmit="window.focus(); return false"» Enter lowercase letters for conversion to uppercase: «input type="text" name="converter" value="sample" onchange="upperMe(this)" /» «input type="button" value="Reset Field" onclick="resetField(this.form)" /> «/form» «/body» «/html» Ниже показано еще два способа выполнения этой же задачи, каждый из которых эффек- тивнее предыдущего. В обоих применяется сокращенная ссылка на текстовый объект. В лис- тинге 23.3 текстовый объект определяется ссылкой, содержащей всего одно ключевое слово this. Поскольку текстовый объект полностью описывается этим ключевым словом (хотя это и не очевидно на первый взгляд), вы можете получить доступ к его свойству value и назна- чить ему строковое значение, воспользовавшись оператором присвоения. «html» «head» «title»Text Object Value«/title» «script type="text/javascript"» function upperMe(field) { field.value = field.value.toUpperCase(); } «/script» «/head» «body» «form onsubmit="window.focus(); return false"» Enter lowercase letters for conversion to uppercase: Глава 23. Текстовые объекты формы 701
<input type="text" name="converter" value="sample" onchange="upperMe(thi s)" /> </form> </body> </html> Еще один способ управления значением в поле заключается в использовании внедренного обработчика событий (вместо вызова внешней функции). Подобный подход проще реализо- вать, поскольку сценарии обычно содержатся в заголовке HTML-страницы. Если в документе не использовать функцию, то обработчик события элемента < input > примет следующий вид. <input type="text" name="converter" value="sample" onchange="this.value = this.value.toUpperCase()" /> Правая часть оператора присвоения извлекает текущее содержимое поля и (с помощью метода toUpperCase () строкового объекта) преобразует исходную строку в символы верх- него регистра. В результате выполнения этой операции свойство value принимает изменен- ное исходное значение. Ключевое слово this в предыдущем примере в данном случае может вас ввести в заблуж- дение, хотя в его применении нет ничего удивительного. Это ключевое слово может применять- ся в качестве аргумента обработчика событий, представляя текущий объект (см. листинг 23.3). Ес- ли вы хотите обратиться к объектам, содержащимся в текущем объекте, то введите их имена наряду с ключевым словом this. В листинге 23.2 ссылка на всю форму была представлена ссыл- кой this. form. В результате сценарий получал доступ к форме, содержащей текущий объект. С другой стороны, вы можете подобный синтаксис для получения свойств объекта this. В последнем примере я использовал только свойство value текущего объекта— this .value. Выражения this .value и this. form выглядят похожими, однако необходимо четко разли- чать, что первое— это значение, подставляемое в функцию, а второе— ссылка на объект (вызывающий функции). Когда вы создаете ссылку на объект, функции могут получать и изме- нять свойства этого объекта. Если вы подставите в функцию значение свойства, то вы не сможе- те изменить его, пока не создадите полную ссылку на объект и его значение. См. также: свойство defaultvalue. Методы blur () Возвращаемое Значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Когда пользователь щелкает на другом объекте или с помощью клавиши <ТаЬ> переходит к другому полю, текущее поле становится неактивным. Под управлением сценария метод blur () отменяет выделение любого фрагмента содержимого поля, и из поля исчезает мер- цающий курсор. При этом курсор не переходит к следующему полю, как это происходит при нажатии клавиши <ТаЬ>. Пример Следующий оператор вызывает метод blur () текстового поля vanishText. document.forms[0].vanishText.blur О; См. также: метод focus (), обработчик события onblur. 702 Часть III. Объекты документа
focus ( ) Возвращаемое Значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Для текстового объекта быть активным означает заключать в себе мерцающий курсор, го- товый к вводу текста (для кнопок в среде Windows активизация имеет несколько другое зна- чение). Активизировать текстовое поле — означает предоставить его для редактирования. При активизации поля, содержащего некоторую информацию, курсор не обязательно по- мещается в любое заданное место поля. Как правило, курсор отображается в начале текста (хотя в браузерах ВЕ4+ для размещения курсора в определенной точке поля можно использо- вать объект textRange— см. главу 35). В случае, когда при вводе информации сущест- вующий текст удаляется, используются оба метода — focus () и select (). Пример В листинге 23.4 приведен пример совместного использования методов focus О и select О. См. также: метод select (), обработчик события onf ocus. select() Возвращаемое Значение: отсутствует Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Выделение поля под управлением сценария означает выделение всего текста данного тек- стового объекта. В обычном приложении, как правило, содержится сценарий, предназначен- ный для проверки введенных пользователем данных на предмет наличия ошибок. После пре- дупреждения пользователя о найденной ошибке (в диалоговом окне window.alert ()) сценарий завершает свою работу, выделяя в поле фрагмент текста, вызывающий сомнения. Это не только привлекает внимание пользователя (что особенно важно, если подобный сце- нарий выполняет проверку нескольких полей), но также и сохраняет исходный текст, позво- ляя пользователю приступить к поиску возможной ошибки. Когда текст выделен, при нажа- тии любой клавиши он удаляется, замещаясь вводимыми символами. Выделить содержимое текстового объекта с помощью щелчка на нем не всегда удается. Од- на из проблем заключается в том, что щелчок на поле приводит к его активизации, а процесс выделения при этом не инициализируется. Для корректного выполнения этого процесса необходи- мо для поля использовать в сценарии оба метода (focus () и select ()) в указанном порядке. Использовать одновременно оба метода не запрещается, а дополнительная подстраховка вторым методом предоставляет пользователю более широкие возможности при работе со страницей. В Internet Explorer для Windows после отображения диалогового окна с предупреждением выполнение обоих методов текстового поля проходит аномально. Эту ситуацию можно ис- править: с помощью метода setTimeout О вставьте искусственную задержку перед тем, как запускать отдельную функцию, отвечающую за активизацию поля и выделение его со- держимого. Другие браузеры, не имеющие подобного дефекта, выполняют описанную выше задачу без особых проблем. Выделение текстового объекта с помощью сценария не вызывает тот же обработчик со- бытия onselect для данного объекта (как это происходит при выделении текста в поле са- мим пользователем). Следовательно, когда пользователь вызывает метод select О, обра- ботчик события в сценарии не запускается. Пример Щелчок на кнопке Verify (листинг 25.4) вызывает проверку содержимого текстового поля. Введенное значение должно содержать только цифры. Все необходимые действия выполня- ются в функции checkNumeric (), которая получает в качестве аргумента ссылку на прове- Глава 23. Текстовые объекты формы 703
ряемое поле. Поскольку функция deselection() вызывается с задержкой, различные части ссылки на форму получаются из свойств поля и формы. Если проверка данных приводит к полу- чению негативного результата, то deselection () вызывается с нулевой задержкой. По- скольку первый аргумент метода setTimeout () строковый, то в данном примере выраже- ние вызова функции deselection () представлено в строковом формате. Задача последней функции сводится к активизации и выделению поля, ссылка на которое указана как аргумент. <html> <head> <title>Text Object Select/Focus</title> <script type="text/javascript"> // общая функция проверки введенного значение //на принадлежность к числам function isNumber(inputstr) { for (var i = 0; i < inputstr.length; i++) { var oneChar = inputstr.charAt(i); if (oneChar < "0" || oneChar > ”9") { , alert("Please make sure entries are numbers only."); return false; } } return true; } function checkNumeric(fId) { var inputstr = fId.value; var fldName = fid.name; var formName = fid.form.name; if (isNumber(inputStr)) { // операторы, выполняемые в случае true } else { setTimeout("deselection(document." + formName + ". " + fldName + ")", 0) ; } } function deselection(fid) { fid.focus(); fid.select () } </script> </head> <body> <form name="entryForm" onsubmit="return false"> Enter any positive integer: <input type="text" name="numeric" /> <pxinput type="button" value= "Verify" onclick="checkNumeric(this.form.numeric)" /></p> </form> </body> </html> См. также: метод focus (), обработчик события onselect. 704 Часть III. Объекты документа
Обработчики событий onafterupdate onbeforeupdate onerrorupda te Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Если в WinlE вы проводите объединение данных в текстовом элементе, то его объект становится целью для трех событий, связанных с обновлением данных в поле. События onbeforeupdate и onafterupdate вызываются немедленно (соответственно) перед и по- сле обновления данных. Если при извлечении информации из базы данных возникает ошибка, то вызывается событие onerrorupdate. Все три события можно использовать в целях обучения. Например, обработчик события onafterupdate может временно изменять характеристики шрифта элемента, чтобы обозна- чить обновленные данные. Обработчик события onerrorupdate может заполнить поле сим- волами дефиса, если для данного поля отсутствует корректно заданное значение. Эти события применяются только для элементов input текстового поля (не для password или hidden). См. также: свойства dataFld, dataSrc (глава 15). onblur onfocus onselect Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Все три этих обработчика события следует использовать только после того, как вы четко уясните взаимодействие событий, которые связаны с текстовыми объектами. Перед тем как применять для текстового объекта более одного из этих событий, следует выполнить предва- рительное тестирование и проанализировать все возможные ситуации. Поскольку некоторые события не выполняются без непосредственного наступления других событий перед или после текущих (например, событие onfocus наступает непосредственно перед событием onselect, если, конечно, поле исходно не было активизировано), то любое действие вашего сценария для данных событий должно быть максимально явным, чтобы избежать возможного конфликта. / Обработчик события onselect не поддерживается в NN для Windows до версии 4. /на заметку В частности, будьте предельно внимательны при отображении модального диалогового окна (например диалоговые окна window. alert ()) в ответ на обработчик события onfocus. По- скольку текстовое поле при отображении диалогового окна становится неактивным, а затем снова активизируется при закрытии окна, то легко запустить циклическое действие, которое трудно разорвать. Если вы оказались в подобной ситуации, воспользуйтесь специальной ком- бинацией клавиш для перезагрузки страницы (<Ctrl+R>) при закрытии диалогового окна. Часто возникает вопрос, каким обработчиком событий (onblur или onchange) следует запускать проверку введенных данных. Проверку данных нельзя выполнить в обработчике события onblur, а вот onchange позволяет это сделать (пользователь не изменяет непра- вильно введенные данные, а переходит к другому полю с помощью клавиши <ТаЬ>). Что мне ие нравится при управлении событием onblur — это вероятность возникновения проблемы Глава 23. Текстовые объекты формы 705
у пользователя, который, вероятно, захочет перейти к другому полю с помощью клавиши <ТаЬ>, а затем вернуться к исходному полю (предполагается, что перед отправкой данных из формы требуется ввести их в поле). Как описывается в главе 43, при отправке данных из формы рекомендуется использовать событие onchange для немедленной проверки данных, а затем применить обработчик события onsubmit для вызова функции отправки данных. Пример В листинге 23.5 продемонстрирован пример использования обработчиков onblur, onf ocus, onselect. С их помощью строка состояния окна преобразуется в область вывода информационных сообщений. Как только пользователь переходит к полю (по щелчку или в результате нажатия клавиши <ТаЬ>), в строке состояние отображается сообщение, связан- ное с текущим полем. На рис. 23.1 показано, что пользователь перешел к первому полю. Рис. 23.1. Обработчик on focus изменяет содержимое строки состояния <html> <head> <title>onfocus Event Handler</title> <script type="text/javascript"> function prompt(msg) { window.status = "Please enter your " + msg + } </script> </head> <body> <form> Enter your first name:<input type="text" name="firstName" onfocus="prompt('first name')" /> <p>Enter your last name:<input type="text" name="lastName" onfocus="prompt('last name1)" /></p> 706 Часть III. Объекты документа
<p>Enter your address:<input type="text" name="address" onfocus="prompt(’address1)" /></p> <p»Enter your city:cinput type="text" name="city" onfocus="prompt('city')" /></p> </form> </body> </html> onchange Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Из всех обработчиков событий, предназначенных для работы с текстовым объектом, вы чаще всего будете использовать onchange (см. листинг 23.6). Я предпочитаю применять это Событие для немедленной проверки введенных пользователем данных в поле. Дело в том, что при выполнении единой проверки всех данных перед отправкой информации из формы вни- мание пользователя сосредоточено уже не на данном поле. При проверке данных сразу после введения информации в поле пользователь не отвлекается от вводимых данных. Более под- робно о выполнении проверки при введении данных рассказывается в главе 43. I В браузере NN4 (только в нем) при задании для текстового поля и обработчика /Не заметку события onchange, и обработчика события клавиатуры, первый игнорируется. * Этого не происходит в браузере IE4+, NN6+ и W3C, где поддерживаются любые события. <html> <head> <title»Text Object Select/Focus</title> <script type="text/javascript"» // общая функция проверки введенного значения // на принадлежность к числам function isNumber(inputStr) { for (var i = 0; i < inputStr.length; i++) { var oneChar = inputStr.substring(i, i + 1) ; if (oneChar < "0" || oneChar > "9") { alert("Please make sure entries are numbers only."); return false; } } return true; } function checklt(form) { inputStr = form.numeric.value; if (isNumber(inputStr)) { // операторы, выполняемые в случае true } else { form.numeric.focus(); form.numeric.select(); </script> </head» <body onsubmit="checklt(this); return false"» Глава 23. Текстовые объекты формы 707
<form> Enter any positive integer: <input type="text" name="numeric" onchange="checklt(this.form)" /> </form> </body> </html> Объект password Свойства Методы Обработчики события См. объект text Синтаксис См. объект text Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Описание объекта Поле для пароля выглядит так же, как и текстовое поле, но когда пользователь вводит в него данные, то в этом поле отображаются только звездочки или маркеры (в зависимости от вашей операционной системы). В целях безопасности любой обмен паролями следует обра- батывать серверной частью CGI-программы. Сценарии могут рассматривать объект password как текстовый объект input. При этом создатель сценария может сохранить пароль посетителя Web-страницы в свойстве document. cookie на компьютере пользователя. Свойство value объекта password воз- вращается в текстовом формате, поэтому подобные пароли можно также хранить в файле cookie. Поскольку файл cookie пользователя можно просмотреть на локальном компью- тере (например, слишком любопытным коллегой в обеденный перерыв), то хранение пароля в обычном виде представляет собой потенциалъную опасность. Вместо этого вам следует разработать для вашей страницы закодированный алгоритм чтения и записи паролей в файл cookie. На большинстве Web-узлов, защищающих пароли, обычно имеется специальная программа CGI, которая кодирует пароль перед его отправкой в файл cookie. Свойства, методы и обработчики объекта password совпадают с объектом text. Свой- ство type для данного объекта возвращает password. Скрытый объект input Свойства Методы Обработчики события См. объект text Синтаксис См. объект text Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ 708 Часть III. Объекты документа
Описание объекта Объект скрытого поля представляет собой простой контейнер строки объекта формы на Web-странице, содержимое которого скрыто от пользователя. Несмотря на длинный список свойств, методов и обработчиков событий, которыми обладает этот тип элемента, для скры- того элемента обычно применяют только операции чтения и записи свойства value. Скрытый объект играет важную роль в приложениях, которые работают с CGI-програм- мами, выполняемыми на сервере. Очень часто сервер получает данные, которые ему необхо- димо передать самому себе при следующей отправке данных формы (например, ID пользова- теля, сохраненного на регистрационной форме приложения). CGI-программа может генери- ровать HTML-страницу, содержащую необходимые данные, скрытые от пользователя, но передаваемые на сервер при отправке остальной информации. Наряду с этими строками, страница, предназначенная для приложения на сервере, может содержать дружественный для пользователя интерфейс, который упрощает ввод данных. Но для базы данных или другого серверного приложения необходимо, чтобы данные представ- лялись в более удобном формате. В сценарии, добавленном на клиентскую страницу для пре- образования введенной в скрытом поле информации в требуемый для базы данных формат можно использовать обработчик события onsubmit. Когда CGI-программа получает запрос от клиента, она передает его вместе со значением скрытого поля в базу данных. - Я не являюсь сторонником использования скрытых полей в полностью клиентских при- ложениях JavaScript. Если вместе со страницами, на которых используются сценарии JavaScript, нужно отправить некоторые предварительно заданные наборы данных или значений, я делаю это с помощью переменных и массивов, которые обрабатываются в сценарии. Поскольку изменение содержимого скрытого поля с помощью сценария является нена- дежной операцией (например, мягкая перезагрузка удаляет проведенные изменения), то без- боязненно вносить подобные изменения можно только в сценарии, который отправляет дан- ные из формы в CGI-программу, или в функции, запускаемой обработчиком события onsubmit. На самом деле вы используете скрытые поля как хранилища данных сценария, которые впо- следствии будут отправлены на сервер. Для более надежного хранения данных используйте свойство document.cookie или уникальные текстовые поля, содержащиеся вскрытых фреймах, даже если это увеличивает продолжительность загрузки страницы. Свойства, методы и обработчики скрытого объекта совпадают с характеристиками объек- та text. Свойство type данного объекта возвращает значение hidden. Объект textarea Свойства элемента HTML, его методы и обработчики события описываются в главе 15. Свойства Методы Обработчики события cols « createTextRange() onafterupdate* form* select()* onbeforeupdate* name* onchange readonly* onerrorupdate* rows type* wrap * См. объект text Глава 23. Текстовые объекты формы 709
Синтаксис Доступ к свойствам или методам объекта textarea. (Все) [window. ] document. имяФормы. имяОбласти. свойство | метод ([параметры]) (Все) [window.]document.имяФормы.elements[индекс].свойство|метод ( [параметры] ) (Все) [window.]document.forms[индекс].имяОбласти.свойство|метод ( [параметры] ) (Все) [window.]document.forms["имяФормы"].имяОбласти.свойство | метод ( [параметры] ) (Все) [window.]document.forms["имяФормы"].elements[индекс].свойство | метод([параметры] ) (IE4+) [window.]document.all.идентификатор.свойство|метод([параметры]) (IE5+/W3C) [window. ] document .getElementBylD ("идентификатор”) . свойство) метод([параметры] ) Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Описание объекта Несмотря на то, что объект textarea не входит в тот же синтаксический раздел HTML, что и другие элементы < input >, он является элементом формы, предоставляя возможности ввода текста, состоящего из многих строк. Некоторые браузеры позволяют использовать эле- мент textarea в любой части документа, однако старайтесь применять его исключительно в элементе form. Объект textarea напоминает текстовый объект, за исключением атрибутов, которые за- дают его физический вид на странице. Поскольку объект textarea предназначен для ввода текста, состоящего из многих строк, его атрибуты отвечают за определение высоты (количество строк) и ширины (количество символов моноширинного текста) объекта на эк- ране. Какой размер вы зададите, не имеет значения: в старых браузерах отображается тексто- вая область, содержащая горизонтальную и вертикальную полосу прокрутки; более современ- ные браузеры стараются отображать полосы прокрутки только, когда это необходимо (хотя это все еще исключение, а не правило). Если задать для атрибута wrap значение virtual или physical в NN и soft или hard в ЕЕ, то текст, введенный в текстовую область, будет пе- ренесен в пределах видимого прямоугольного поля элемента; в противном случае текст про- кручивается на значительное расстояние по горизонтали (горизонтальная полоса прокрутки появляется, когда перенос строк не задан). Конечно, это поле является примитивным тексто- вым элементом по стандартам графического интерфейса, поскольку в современных версиях браузеров параметры шрифта обладают большими возможностями благодаря таблицам сти- лей, задаваемым для всего текста в поле. Используйте приложение The Evaluator (глава 13) для изучения свойств cols и rows об- ласти вывода результатов. Измените ширину области, введя следующее выражение в верхнее текстовое поле. document.forms[0].output.cols = 30; Затем сделайте область выше на строку. document.forms[0].output.rows++ 710 Часть III. Объекты документ!)
Все свойства, методы и обработчики события текстовых полей применимы к объекту textarea. Они действуют точно так же (конечно, кроме свойства type, значением которо- го является textarea). Следовательно, подробно о написании сценариев с использованием этого объекта можно узнать из описанных выше листингов. Далее рассматривается набор до- полнительных свойств, которые являются уникальными для объекта textarea. Возврат каретки в текстовых областях Три класса операционных систем, поддерживаемых браузером Netscape Navigator — Win- dows, Macintosh и UNIX — не однозначно интерпретируют символ возврата каретки в тек- стовой строке. Это разногласие платформ касается объекта textarea и его содержимого. После того, как пользователь введет текст и воспользуется клавишей <Entei> (<Retum>), в строку добавляется один или более скрытых символов. В соответствии со строковыми сим- волами языка JavaScript символ возврата каретки состоит из комбинации символов новой строки (\п) и возврата (\г). В приведенной ниже таблице показаны символы, вставляемые в строку, для каждой из операционных систем. Операционная система Символ строки Windows \r\n Macintosh \r Unix \n Этот вопрос становится чрезвычайно важным, если вам необходимо удалить из текстовой области символы возврата каретки, чтобы обрабатывать данные в CGI-программе или в ло- кальном сценарии. Проблема заключается в том, что для каждой платформы вам придется выполнить отдельную операцию. В случае, когда вам необходимо сохранить символы возвра- та каретки, но база данных на сервере не может принять этих значений, рекомендуется ис- пользовать метод string. escape () для кодирования строки (он применяется при задании URL). Символ возврата каретки преобразуется в значение %0D, а символ новой строки — в % О А. Конечно, эти символы занимают дополнительное место в базе данных, что также сле- дует учитывать при разработке документов (и баз данных). Когда проблема символа возврата каретки рассматривается исключительно в пределах тек- стовой области, ситуация значительно упрощается. Начиная с NN3 и IE4, при задании любой из комбинаций, указанных в предыдущей таблице, все платформы могут автоматически преобра- зовывать данные в формат, свойственный для текущей операционной системы. Следовательно, для объекта textarea на всех платформах можно задать значения 1\г\п2\г\пЗ, и в этих полях появится список столбцов 1, 2 и 3. Если кодированный текст предназначен для хране- ния в базе данных, то вы можете преобразовать соответствующий символ перед формирова- нием значения текстовой области, отправляемого на сервер. Независимо от того, на какой платформе работает пользователь, символ возврата каретки будет преобразовываться кор- ректно. При получении этих значений сценарием вы также можете наблюдать в форме сим- волы возврата каретки, которые преобразуются корректно для указанной платформы (показаны в предыдущей таблице). Глава 23. Текстовые объекты формы 711
Свойства cols rows Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Отображаемый размер элемента textarea определяется атрибутами COLS и ROWS, ко- торые представлены в объектной модели документа, соответственно, свойствами cols и rows. Значениями для данных свойств являются целые числа. Для свойства cols число представляет количество символов, которые отображаются без применения горизонтальной полосы прокрутки; для свойства rows — количество строк текста, который отображается без применения вертикальной полосы прокрутки. См. также: свойство wrap. wrap Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство wrap представляет атрибут wrap, который не входит в стандарт HTML 4.0, разработанный консорциумом W3C. В любом случае, браузер IE4+ позволяет задать это свойство с помощью сценария. Допустимые строковые значения — soft, hard и off. Брау- зер задает мягкий перенос (по умолчанию в IE) для содержимого текста, но на самом деле в текст не добавляются символы возврата каретки. Второй параметр, hard, отвечает за до- бавление к тексту символов возврата каретки (которые будут отправлены на сервер в CGI- программу вместе со значением). При задании параметра off текст вводится в одну строку, распространяющуюся в правую сторону текстовой области до тех пор, пока пользователь са- мостоятельно не нажмет клавишу <Enter>. См. также: свойство cols. Методы createTextRange() Возвращаемое Значение: объект createTextRange Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Метод createTextRange О для объекта textarea действует точно так же, как и ме- тод document’. createTextRange (), за исключением того, что данный диапазон состоит из текста, содержащегося в элементе textarea, помимо обычного содержимого. Эту версию объекта createTextRange удобно использовать, когда требуется, чтобы сценарий управ- лял положением курсора внутри элемента textarea вместо пользователя. См. также: объект createTextRange (глава 35). 712 Часть III. Объекты документа
Объекты select, option и fileupload Списки отображаются на форме в виде всплывающих меню или прокручивающихся перечней. Это самые информативные и экономные элементы HTML-страницы. Они позволяют дизайнерам представить достаточный объем информации, занимающей сравнительно немного места. Пользователи хорошо знакомы с этими элементами интер- фейса по работе с диалоговыми окнами операционных сис- тем и различных приложений. Однако программировать списки достаточно тяжело, особенно в ранних версиях браузеров, поскольку сами по себе они являются сложными конструкциями. Все данные, связанные с элементами списков, представлены в элемен- тах option, вложенных в элементы select. Как будет видно из этой главы, ссылки, поддерживающие совмести- мость снизу вверх, для получения информации из объекта элемента select и его объектов option могут быть доста- точно длинными. Тем не менее, старания, приложенные для создания списков, стоят затраченных усилий. Кроме того, в этой главе рассматривается объект элемен- та ввода fileupload, возможности которого зачастую пре- увеличены. К сожалению, он не обеспечивает отдельного способа отправки файлов, о котором мечтают многие разра- ботчики Web-страниц. Объект элемента select Свойства, методы и обработчики событий этого HTML- элемента описаны в главе 15.
Свойства Методы Обработчики событий form* length multiple name* options selectedlndex size type value add() options[i].add() item() namedltem() remove() options[i].remove() onchange * См. объект текстового поля (предыдущая глава). Синтаксис Доступ к свойствам объекта элемента select. (Все) [window.]document.имяФормы.имяСписка.свойство|метод([параметры]) (Все) [window. ] document. имяФормы. elements [индекс] . свойство | метод ([па - раметры] ) (Все) [window.] document. forms [индекс] .имяСписка. свойство | метод( [пара- метры] ) (Все) [window.]document.forms["имяФормы"].имяСписка.свойство|метод ( [параметры] ) (Все) [window. ] document. forms ["имяФормы" ] . elements [индекс] . свойство| метод( [параметры] ) (IE4+) [window.]document.all.идентификатор.свойство\метод([параметры]) (IE5+/W3C) [window. ] document. getElementByld ("идентификатор") . свойство | ме- тод ( [параметры] ) Описание объекта Объекты элементов select представляют собой, возможно, самые интересные элементы пользовательского интерфейса среди стандартных объектов. В одном формате они принима- ют вид всплывающих, а в другом — прокручивающихся списков. Всплывающие списки, в ча- стности, позволяют эффективно использовать рабочую площадь страницы. Более того, толь- ко элемент, выбранный пользователем, отображается на странице, что позволяет избежать пустого заполнения страницы ненужными данными. По сравнению с другими объектами JavaScript, элементы select трудно программиро- вать, в основном, из-за сложности представления данных, включенных в список элементов. То, что пользователь видит на странице как элемент select, состоит из самого элемента, а также элементов option, которые содержат конечные данные, выбираемые пользователями. Одни свойства, задаваемые программистам, принадлежат объекту select, другие — объек- там option. Например, индекс текущей выбранной опции в списке является свойством объекта select. Однако, чтобы получить отображаемый текст, необходимо обратиться к свойству text объекта выбранного элемента option. 714 Часть III. Объекты документа
При определении объекта select в форме следует внимательно задать конструкцию, состоя- щую из пары дескрипторов <select>.. . </select>. Прежде всего, большинство атрибутов, определяющих объект целиком (name, size, а также обработчики событий), принадлежат откры- вающему дескриптору <select>. Между ним и закрывающим дескриптором </select> находятся дополнительные дескрипторы, задающие каждую опцию списка. Приведенное ни- же определение объекта создает всплывающий список с тремя опциями выбора цвета. <form> <seiect name="RGBColors" onchange="changecolor(this)"> <option selected="selected">Red</optidn> <option>Green</option> <option>Blue</option> </select> </form> Форматирование дескрипторов в документе HTML не является важной операцией. Я сде- лал отступ в строках с опциями списка лишь для повышения читаемости кода. По умолчанию элемент select отображается как всплывающий список. Чтобы он ото- бражался как прокручивающийся список, атрибуту size необходимо присвоить значение, большее 1. Это значение определяет, сколько строк будет отображаться в списке без про- крутки (попросту говоря, это высота списка, выраженная в строках). Поскольку полосы про- крутки в графическом интерфейсе занимают определенную площадь (при отображении раз- личных областей для щелчка мышью), не следует делать высоту таких списков меньше 4. Если это слишком много для текущей страницы, то воспользуйтесь всплывающим меню. Способы отображения всплывающих меню на различных графических платформах раз- ные. Поскольку каждый браузер при выводе всплывающего меню практически всецело пола- гается на операционную систему (иногда, правда, разработчики браузеров идут своим путем), между размером всплывающего меню в ОС и браузерах существует большая разница. То, что отлично помещается в окне стандартной ширины в одной ОС, может отображаться совсем по-другому в ином браузере в другой ОС. Другими словами, на точные размеры объекта select полагаться нельзя (если вы, например, пытаетесь выровнять объект select и рас- положенное рядом с ним изображение). На форме объект select позволяет выбрать одновременно несколько расположенных рядом опций. Обычно этого можно достичь, одновременно нажав клавиши-модификаторы (<Shift>, <Ctrl> в зависимости от операционной системы) и щелкнув мышью на нужных оп- циях. Для предоставления этой возможности в элемент select необходимо добавить ат- рибут multiple. Для каждой записи в списке дескриптор <select> должен содержать дескриптор <option>, а также текст, представленный в качестве надписи элемента. Если при загрузке страницы необходимо, чтобы в списке отображался элемент по умолчанию, в соответствую- щем дескрипторе <option> задайте атрибут selected. Без этого атрибута элемент по умолчанию будет или пустым, или первым в списке, что зависит от браузера (см. описание объекта option далее в этой главе). Кроме того, в каждом дескрипторе option атрибуту value можно присвоить строковое значение. Как и в случае переключателей, им это строко- вое значение может отличаться от приведенного в списке текста. Таким образом, сценарий работает со “скрытым” значением, а не с отображаемым текстом, что позволяет заменить сложный URL простой строкой. Это строковое значение пересылается CGI-программе (как часть пары имя-значение), когда пользователь отправляет форму с объектом select. Одна из характеристик объекта select существенно влияет на дизайн страницы. Обра- ботчик события onchange запускается сразу же после того, как пользователь выбирает но- вый элемент из всплывающего списка (за исключением ситуации, когда в браузере NN2 для Windows возникает ошибка). Если вы предпочитаете, чтобы действия выполнялись после Глава 24. Объекты select, option и fileupload 715
того, как пользователь проведет все установки в форме, опустите обработчик события onchange в объекте select, но обязательно создайте кнопку, которая позволит пользова- телю выполнить действие на основании проведенных настроек. Изменение опций объекта select (NN3+, IE4+) Средства JavaScript обладают достаточной гибкостью для изменения содержимого объекта select. Однако они доступны лишь в браузерах NN3+ и IE4+. Причем некоторые из них впол- не прямолинейны: например, изменение свойства selectObj .options [i] .text, отвечаю- щего за отображение отдельной записи в списке. Ситуация усложняется, когда изменяется коли- чество опций в объекте select. В данном случае сценарий имеет следующие возможности. Удаление отдельной опции (приводит к сжатию списка). Изменение элементов списка в меньшую сторону. Удаление всех опций. Добавление новых опций к объекту. Для удаления опции из списка следует установить соответствующий элемент массива в значение null. Например, если в списке содержится пять элементов и третий необходимо удалить (сократив, таким образом, список до четырех элементов), используется следующий синтаксис (со ссылкой на объект select). selectObj.options[2] = null; После выполнения этого оператора свойство selectObj . options. length становится равным 4. Предположим, что в сценарии объект select имеет пять опций, и его нужно заменить дру- гим объектом с тремя опциями. Вначале свойству length необходимо присвоить значение 3. selectObj.options.length = 3; Затем установите свойства text и value для каждой опции с индексом от 0 до 2. Можно начать строить новый список, полностью удалив предыдущий (однако не изменять сам объект select). Для этого достаточно установить его свойство length в значение 0. selectObj.options.length = 0; Теперь можно создать новые опции (как при расширении списка, скажем, от трех до семи элементов). Механизм создания новых опций состоит в использовании конструктора объекта: new Option (). Он имеет четыре аргумента, эквивалентных атрибутам дескриптора < options. Текст, отображаемый в списке. Значение свойства value опции. Опция def aultSelected (булевого типа) элемента. Параметр выделения элемента в списке (булевого типа). Часть параметров можно установить в конструкторе, а часть — отдельно в других опера- торах (конструктор можно вызывать и без аргументов). Рекомендуем установить два первых параметра (оставив другие пустыми), а свойству selected присвоить значение отдельно. Ниже приведен пример оператора, создающего новый (пятый) элемент в списке объекта select. Этот оператор устанавливает свойства text и value. selectObj.options[4] = new Option("Yahoo","http://www.yahoo.com"); Все представленные методы демонстрируются в листинге 24.1, позволяющем изменить текст объекта select (вначале корректируя его при фиксированном числе опций, а затем 716 Часть III. Объекты документа
создавая новый набор элементов). Обработчики события onclick переключателей вызыва- ют функции, выполняющие нужные операции, — редкий пример, когда переключатели логи- чески инициируют какое-либо видимое действие. Листинг 24.1. Изменение олции^в <html> <head> <title>Changing Options On The Fly</title> <script type="text/javascript" language="JavaScript"> // флаг перезагрузки страницы в старых браузерах NN var isPreNN6 = (navigator.appName == "Netscape" && parselnt(navigator.appVersion) <= 4); // инициализация массива цветов plainList = new Array(6); hardList = new Array(6); plainList[0] = "cyan"; hardList[0] = "tfOOFFFF"; plainList[1] = "magenta"; hardList[1] = "#FF00FF"; plainList[2] = "yellow"; hardList[2] = "#FFFF00"; plainList[3] = "lightgoldenrodyellow"; hardList[3] = "#FAFAD2"; plainList[4] = "salmon"; hardList[4] = “#FA8072"; plainList[5] = "dodgerblue"; hardList[5] = "#1E9OFF"; 11 изменение набора цветов function setLang(which) { var listobj = document.forms[0].colors; // фильтрация старых браузеров if (listobj.type) { // проверка количества элементов: 3 или 6 var listLength = listobj.length; // сохранение выбранного индекса var currSelected = listobj . selectedlndex,- // замена отдельных записей for (var i = 0; i < listLength; i++) { if (which == "plain") { listobj.options[i].text = plainList[i]; } else { listobj.options[i].text = hardList[i]; } } if (isPreNN6) { history.go(0); } else { listobj.selectedlndex = currSelected; } } } // создания нового списка опций function setcount(choice) { Глава 24. Объекты select, option и fileupload 717
var listObj = document.forms[0].colors; // фильтрация старых браузеров if (listObj.type) { // получение настроек названий цветов var lang = (document.forms[0].geekLevel[0].checked) ? "plain" : "hard"; II очистка списка listObj.length = 0; // создания новых объектов для опций списка for (var i = 0; i < choice.value; i++) { if (lang == "plain") { listObj.options[i] = new Option(plainList[i]); } else { listObj.options[i] = new Option(hardList[i]); } } listObj.options[0].selected = true; if (is₽reNN6) { history.go(0); «/scripts </head> <body> <hl>Flying Select Options«/hls «forms Choose a palette size: «input type="radio" name="palettesize" value="3" onclick="setcount(this)" checked="checked" />Three «input type="radio" name="paletteSize" value="6" onclick="setCount(this)" /sSix <p>Choose geek level: «input type="radio" name="geekLevel" value="" onclick="setLang('plain')" checked="checked" /> Plain-language «input type="radio" name="geekLevel" value="" onclick="setLang('hard')" />Gimme hex-triplets! </p> <p>Select a color: «select name="colors"> «option selected="selected"scyan</options «option>magenta</options <optionsyellow</options </selects«/ps «/forms «/bodys </htmls Чтобы упростить поддержку этого кода, списки для выбора цветов (названия и шестна- дцатеричные триплеты) выделены в два отдельных массива. Циклы в обеих функциях обра- батывают эти массивы, независимо от их длины. Два первых переключателя (см. рис 24.1) запускают функцию setLang (). Ее первичной задачей является получение ссылки на объект select для сокращения выражения обраще- ния к объектам (просто listObj). С помощью свойства length она определяет, сколько элементов будет отображаться, в списке. После этого в цикле свойству text каждой опции объекта select присваивается значение, взятое из одного массива. Во второй паре переключателей каждый из них указывает количество отображаемых эле- ментов, когда пользователь раскрывает список. Эго количество передается функции setCount () и используется как число итераций цикла. Функция определяет выбранный переключатель, 718 Часть III. Объекты документа
с помощью которого задается формат опций списка, и полностью обнуляет объект select. Опции создаются заново с помощью конструктора new Option (). Его параметрами явля- ются строки текста, взятые из массивов. Новые опции не имеют других свойств, поэтому вы- бираемая по умолчанию функция устанавливает первый элемент списка. Рис 24.1. Выбор переключателя динамически изменяет содержимое объекта select Обратите внимание, что обе функции после установки свойств объекта select в браузе- рах NN3 и NN4 вызывают метод history .до (0). Это дает возможность ранним версиям NN изменить размер объекта select, чтобы правильно отобразить содержимое списка. Раз- ница хорошо заметна при переключении от списка с шестью цветами к любому другому списку. Если не изменить размер объекта, некоторые длинные названия не поместятся в от- веденной области. Браузеры IE4+ и NN6 перерисовывают страницу автоматически после из- менения элемента формы. Изменение опций объекта select (IE4+) Браузеры компании Microsoft IE4+ поддерживают и другой способ изменения опций эле- мента select, использующий два собственных метода свойства-массива options объекта select. Они называются add () и remove (). Метод add () имеет один обязательный и один допол- нительный параметр. Обязательным параметром является ссылка на объект элемента option, ко- торый сценарий создает в другом операторе (с помощью метода document. createElement ()). Если опустить второй параметр метода add(), то новый элемент option будет добавлен к текущему набору элементов. Если же во втором аргументе указан индекс, новый массив оп- ций будет вставлен в указанную позицию. Листинг 24.2 показывает, как можно изменить функции из листинга 24.1, воспользовав- шись средствами исключительно IE (изменения и дополнения выделены полужирным шрифтом). Глава 24, Объекты select, option и fileupload 719
В сценарии подразумевается, что страница будет загружаться только в браузерах IE (другими словами, сценарий не осуществляет проверки имени браузера). При замене одного набора оп- ций другим демонстрируются два подхода. В первом (функция set Lang ()) заменяется то же количество элементов, поэтому длина существующего массива используется в качестве счетчика и индексного значения в методах remove () и add (). Если количество элементов изменяется (как в функции set Count ()), то сначала в цикле удаляются все опции, и только после этого с помощью метода add () без второго параметра (т.е. в конец списка) добавля- ются новые опции. Способ, приведенный на листинге 24.2, не имеет никаких преимуществ по сравнению с тем, который применялся в листинге 24.1. . ИзменемиеммЫ ябммнвефХесь (Е4+) function setLang(which) { var listobj = document.forms[0] .colors; var newOpt; // проверка ранних версий браузеров IE if (listobj.type) { // проверка числа элементов массива: 3 или 6 var listLength = listobj.length; I/ сохранение выбранного индекса var currSelected = listobj.selectedlndex; I/ замена отдельных элементов ' for (var i = 0; i < listLength; i++) { newOpt = document.createElement("option"); newOpt.text = (which == "plain")TplainList[i]:hardList[i]; listobj.options.remove(i); listobj.options.add(newOpt, i); } listobj.selectedlndex = currSelected; } } I/ создание нового списка опций function setCount(choice) { var listobj = document.forms[0].colors; var newOpt; // проверка ранних версий браузеров if (listobj.type) { // получение настроек названий цветов var lang - (document.forms[0].geekLevel[0].checked) ? "plain" : "hard"; // очистка опций while (listobj.options.length) { listobj.options.remove(0); } I/ создание нового объекта опции для элементов списка for (var i = 0; i < choice.value; i++) { newOpt = document.createElement("option"); newOpt.text = (lang == "plain")?plainList[i]:hardList[i]; listobj.options.add(newOpt); } listobj.options[0].selected = true; } j 720 Часть III. Объекты документа
Изменение опций объекта select (W3C DOM) Еще один подход возможен в браузерах, поддерживающих стандарт W3C DOM 2. В NN6, например, также можно воспользоваться методами add () и remove () объекта элемента select. Они напоминают методы массива options в IE4+, однако принадлежат непосред- ственно объекту элемента select. Другое отличие — в синтаксисе: в NN6 метод add О в ка- честве второго аргумента использует не индекс, а ссылку на объект элемента option, перед которым нужно вставить новый элемент. Этот аргумент является обязательным. Для добав- ления элемента в конец текущего списка необходимо указать значение null. Сценарий, из- мененный для поддержки объектной модели W3C, приведен на листинге 24.3. Полужирным шрифтом выделены отличия между версиями IE4+ и W3C DOM. Ямскммг 24.3.Имм«аа0е опций обмжт| t (ММ*) function setLang(which) { var listObj = document.forms[0].colors; var newOpt; // проверка ранних версий браузеров IE if (listObj.type) { // проверка количества элементов: 3 или 6 var listLength = listObj.length; // сохранение выбранного индекса var currSelected = listObj.selectedlndex; // замена отдельных элементов for (var i = 0; i < listLength; i++) { newOpt = document.createElement("option"); newOpt.text = (which == "plain")?plainList[i]:hardList[i]; listObj .removed) ; listObj.add(newOpt, listObj.options[i]); } listObj.selectedlndex = currSelected; } } // создание нового списка опций function setcount(choice) { var listObj = document.forms[0].colors; var newOpt; // проверка ранних версий браузеров if (listObj.type) { // получение настроек названий цветов var lang = (document.forms[0].geekLevel[0].checked) ? "plain" : "hard"; // очистка списка while (listObj.options.length) { listObj . remove (0)'; } // создание объектов опции для элементов списка for (var i = 0; i < choice.value; i++) { newOpt = document.createElement("option"); newOpt.text = (lang == "plain")PplainList[i]zhardList[i]; listObj.add(newOpt, null); } Глава 24. Объекты select, option и fileupload 721
listObj.options[0].selected = true; Как и в случае с IE4, версия для W3C не имеет никаких преимуществ по сравнению с ис- ходной. Свойства length Значение: целочисленное Чтение/Запись (см. текст) Совместимость: WinIE3+, МасЕЗ+, NN2+, Mozl+, Safaril+ Как и все массивы в JavaScript, options имеет свойство length. Однако вместо него используется свойство length самого объекта select. Его значение представляет собой число опций в объекте. Свойство length объекта select с тремя опциями равно 3. В браузерах NN3+ и IE4+ это свойство можно уменьшать после загрузки документа для сокращения количества элементов в списке. Задание значения 0 делает объект Select пус- тым, однако не заставляет его исчезнуть. Пример В листинге 24.1 приведен пример использования свойства length. С его помощью в цикле просматриваются все элементы списка. Поскольку счетчик (i) в качестве начального значе- ния принимает число 0, то цикл выполняется до тех пор, пока счетчик не станет равен значению свойства length. См. также: свойство options. multiple Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство multiple соответствует значению атрибута multiple объекта элемента select. Если оно равно true, элемент позволяет выделить несколько опций списка од- новременно (в Windows, например, для этого используется комбинация <СШ+щелчок>). Если требуется преобразовать всплывающий список в список select с поддержкой выделения нескольких элементов, измените свойство size для отображения максимального набора оп- ций в списке. Пример Следующее выражение изменяет значение свойства multiple на противоположное, но только в тех списках, свойство size которых установлено в значение, большее 1. document.forms[0].mySelect.multiple = 'document.forms[0].mySelect.multiple; См. также: свойство size. options [индекс] Значение: массив элементов option Только для чтения Совместимость: WinIE3+, МасПЗЗ+, NN2+, Mozl+, Safaril+ 722 Часть III. Объекты документа
Как правило, это свойство не используется само по себе. Чаще оно является частью ссыл- ки на свойства (или метода в современных версиях браузеров) определенной опции в составе объекта select. Другими словами, свойство options — это шлюз к другим свойствам, на- пример, значениям в списке. В ранних версиях браузера NN, в предупреждении, выводимом на экран в результате ссылки на массив options, отображался HTML-код опции. Современ- ные версии просто сообщают, что значение является объектом. В последних версиях браузеров (IE4+ и NN6+) на опции можно ссылаться как на отдель- ные объекты элементов HTML. Такие ссылки не требуют префикса объекта элемента form или select. Но для обеспечения совместимости снизу вверх рекомендуется использовать длинные ссылки, содержащие объект select. Несколько следующих опций включены в описание объекта select, так как они совмес- тимы даже с теми версиями браузеров, в которых элемент option не выделен в отдельный объект. Помните, что все перечисленные свойства, включающие и префикс options [индекс], в браузерах IE4+ и NN6+ являются также свойствами объекта элемента option. Пример В листингах 24.1-24.3 приведен пример использования массива options. С его помо- щью сценарий получает информацию об элементах списка См. также: все элементы options [index] .property. options[индекс].defaultSelected Значение: булево Только для чтения Совместимость: WinIE3+, МасПЗЗ+, NN2+, Mozl+, Safari 1+ Если определение объекта select включает опцию с атрибутом selected, ее свой- ство defaultSelected содержит значение true. Для всех остальных опций свойство defaultSelected равно false. Если объект select поддерживает выделение несколь- ких опций (причем его атрибут size больше 1), то атрибут selected может быть задан для нескольких опций. После загрузки страницы все элементы с этим атрибутом будут предвари- тельно выделены (включая даже несмежные позиции). Пример Следующее выражение сохраняет в переменной булево значение, указывающее на выбор в качестве элемента по умолчанию первого элемента списка. var zeroIsDefault = document.forms[0].listName.options[0]. defaultSelected; См. также: свойство options [индекс] . selected. options[индекс].index Значение: целочисленное Только для чтения Совместимость: WinIE3+, MacIE3+, NN6+, Mozl+, Safaril+ Значение index любой опции объекта select,-скорее всего, окажется лишним в сценарии. Поскольку к опции можно обратиться без индекса (используя как часть ссылки options [индекс]), в его использовании нет необходимости. Глава 24. Объекты select, option и fileupload 723
Пример Приведенное ниже выражение назначает целочисленный индекс первого элемента списка listName переменной itemindex. var itemindex = document.forms[0].listName.options[0].index; См. также: свойство options. options [ивделс] .selected Значение: булево Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari! + Как уже отмечалось, существуют более удобные методы поиска опции, которую выбрал пользователь, чем просмотр в цикле всех опций и проверка их свойств selected. Исключе- нием является список с поддержкой нескольких выделений. В этой ситуации свойство selectedlndex возвращает индекс самой первой выбранной опции в списке. Поэтому сценарию необходимо проверить значение свойства selected (true или false) каждой опции. Пример Для учета выбранных в списке опций функция seeList () листинга 24.4 анализирует свойство option [индекс] .selected каждого элемента. Текст выбранного элемента до- бавляется в переменную result после символа \п, указывающего на возврат каретки в строке. Эта переменная выводится в отдельном диалоговом окне. <html> «head> <title>Accessories List«/title> «script type="text/javascript"> function seeList(form) { var result = ""; for (var i = 0; i < form.accList.length; i++) { if (form.accList.options[i].selected) { result += "\n " + form.accList.options[i].text; } } alert("You have selected:" + result); } </script> </head> <body> <form> <p>Control/Command-click on all accessories you use: «select name="accList" size="9" multiple="multiple"> «option selected=11 selected" >Color Monitor«/option> <option>Modem«/option> <option>Scanner«/option> <option>Laser Printer«/option> <option>Tape Backup«/option> <option>MO Drive«/option> <option>Video Camera«/option> </select>«/p> «pxinput type="button" value="View Summary..." 724 Часть III. Объекты документа
onclick="seeList(this.form)" /></p> </form> </body> </html> См. также: свойства options [индекс] .text, options [индекс] .value, selected- index. options [индекс] . text Значение: строка Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 14- Свойство text содержит текст, отображаемый в опции списка. Если этот текст применя- ется для выполнения определенных задач, то вам нужно извлечь его с помощью данного свойства. Однако, если сценарию требуется не текст опции, а сама опция, то в сценарии луч- ше воспользоваться атрибутом value, а потому и свойством options [индекс] .value (см. листинг 26.6). Пример Чтобы продемонстрировать практическую ценность свойства text, в листинге 24.5 текст выделенного элемента списка назначается свойству document .bgColor документа в окне браузера. Поскольку значения последнего свойства чувствительны к регистру символов, то имена цветов перед присвоением необходимо преобразовать в прописные символы. <html> «head> <title>Color Changer l</title> «script type="text/javascript"> function seeColor(form) { var newColor = (form.colorsList.options [form.colorsList.selectedlndex] .text) ; document.bgColor = newColor; } </script> </head> <body> <form> «p>Choose a background color: «select name="colorsList"> «option selected="selected">Gray</option> <option>Lime«/option> < opt i on > I vor у« / opt i on > <option>Red«/option> </select>«/p> «pxinput type= "button" value="Change It" onclick="seeColor(this.form)" /></p> </form> </body> </html> См. также: свойство options [index] . value. Глава 24. Объекты select, option и fileupload 725
options [индекс] .value Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Во многих случаях, названия опций в списке представляются в удобной для пользователей форме, но неудобной для управления в сценариях. Вы можете либо создать процедуру поиска, сверяющую значения свойств selectedlndex или options [индекс] . text с теми значе- ниями, которые требуются сценарию, либо просто сохранить значения в атрибутах value эле- ментов «options объекта select. Затем при необходимости к ним можно легко обратиться. Атрибуту value допускается присваивать любое строковое выражение, включая URL, свойства объекта или даже описание страницы целиком, задаваемое, например, в методе parent.frames[индекс].document.write(). Начиная с браузеров IE4 и NN6, объект элемента select имеет свойство value, которое возвращает значение свойства value выбранной опции. Для совместимости снизу вверх ре- комендуется, все же, использовать подход, приведенный в примере. Пример В листинге 24.6 текст элементов списка представлен простыми описательными выражения- ми, а не стандартными названиями цветов. Чтобы корректно назначить цвет фона страницы, не- обходимо использовать одно слово, а не все выражение. Это слово сохраняется в атрибуте value дескриптора <option>. Единственная функция сценария считывает значение этого атри- бута и назначает его свойству bgColor текущего документа. Если вы предпочитаете работать с шестнадцатеричными числовыми идентификаторами цветов, то можете также использовать их в коде дескрипторов <options. Например, «option value="#e9967a"sDark Salmon. <html> <head> «titlesColor Changer 2</title> «script type="text/javascript"> function seeColor(form) { var newColor = (form.colorsList.options [form.colorsList.selectedlndex].value); document.bgColor = newColor; } «/scripts «/heads «bodys «forms «psChoose a background color: «select name="colorsList"s «option selected="selected" value="cornflowerblue"s Cornflower Blue«/options «option value="darksalmon"sDark Salmon«/options «option value="lightgoldenrodyellow"sLight Goldenrod Yellow</options «option value="seagreen"sSea Green</options </selects«/ps <ps<input type="button" value="Change It" onclick="seeColor(this.form)" /s«/ps «/forms «/bodys «/htmls См. также: свойство options [индекс] . text. 726 Часть III. Объекты документа
selectedlndex Значение: целочисленное Чтение/Запись Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Когда пользователь выбирает элемент из списка, свойство selectedlndex изменяет свое значение на индекс этого элемента. Индекс первого элемента равен 0. Он необходим сценарию для извлечения информации о выбранной опции из списка. Индексом можно воспользоваться для доступа к свойствам выбранной опции. Чтобы про- верить свойство selected объекта select, вместо циклического прохождения по всем оп- циям нужно воспользоваться свойством selectedlndex и создать ссылку на выбранный элемент. Ссылка получится длинной, однако, с точки зрения выполнения, такая методика яв- ляется наиболее эффективной. Если объект select поддерживает выделение нескольких оп- ций, свойство selectedlndex содержит индекс первого выбранного элемента. Чтобы запрограммировать выбор определенной опции, необходимо присвоить целочис- ленное значение свойству selectedlndex объекта элемента select, как показано в лис- тингах 24.1-24.3. Пример В функции inspect (), приведенной в листинге 24.7, значение в квадратных скобках, кото- рое определяет индекс, задано свойством selectedlndex. Поскольку это свойство всегда возвращает целочисленное значение, оно полностью удовлетворяет требования к индек- су свойства options. Таким образом, если вы выберете в списке опцию Green, то вы- ражение' form.colorsList.selectedlndex возвратит значение 1. В результате ссылка form. colorsList. options [1] .text будет соответствовать текстовому значению Green. Листинг 247, ИмоМЯВ** нойстм и«1исс edlJa 4чх •. . “ -Е? " • <html> <head> <title>Select Inspector</title> «script type="text/javascript"> function inspect(form) { alert(form.colorsList.options[form.colorsList. selectedlndex].text); } </script> </head> <body> <forni> «pxselect name="colorsList"> «option selected="selected">Red«/option> «option value="Plants">Green«/option> <option>Blue«/option> </select>«/p> «pxinput type= "button" value="Show Selection" onclick="inspect(this.form)" /></p> </form> «/body> </html> См. также: свойство options. Глава 24. Объекты select, option и fileupload 727
size Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство size соответствует значению атрибута size объекта элемента select. Это целочисленное значение показывает, сколько опций отображено в списке без прокрутки. Пример В следующем выражении свойство size задает количество отображаемых элементов равным 5. document.forms[0].mySelect.size = 5; См. также: свойство multiple. type Значение: строка Только для чтения Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Свойство type позволяет идентифицировать объект select среди группы неизвестных элементов формы. Значение строки зависит от того, как был определен объект select: вы- бирается один элемент (select-one) или несколько (select-multiple). См. также: свойство form, elements. value Значение: строка Чтение/Запись (см. текст) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Последние версии браузеров (и W3C DOM) поддерживают свойство value объекта эле- мента select. Оно содержит строку, присвоенную атрибуту value (или свойству value) текущего выбранного элемента option. Если атрибуту не присвоено значение, это свой- ство возвращает пустую строку. В браузерах нового поколения свойство value объекта элемента select используется вместо более длинной версии, требующей ссылки на свойство selectedlndex и массив options. Если этому свойству присвоить новую строку (причем, если она не совпадает с сущест- вующим значением опции), IE создаст пустую опцию в списке. Несмотря на то, что формаль- но в NN6 это свойство предназначено для чтения/записи, присвоение новой строки не вызы- вает изменения значения свойства. Пример Функция seeColorO в листинге 24.6 получает доступ к значению выбранного элемента. Используемую в ней ссылку можно упростить, если сценарий выполняется в новых версиях браузеров. function seeColor(form) { document.bgColor = form.colorsList.value; } См. также: свойство options [индекс] . value. 723 Часть III. Объекты документа
Методы add(ссылкаНаНовыйЭлемент[, индекс] ) add(ссылкаНаНовыйЭлементf ссылкаНаЭлемент) remove(индекс} Возвращаемое Значение: отсутствует Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Эти методы используются в W3C для вставки и удаления элементов списка. Первый атри- бут метода add О — это новый элемент option, добавляемый в список. Второй аргумент .зависит от используемого браузера. В IE второй атрибут метода add () представляет собой индекс добавляемого элемента в списке. Элемент будет вставлен перед элементом с указан- ным индексом или в конец списка, если второй аргумент метода не указан. В W3C второй ар- гумент представляет ссылку на элемент списка, перед которым вставляется новый элемент. Если второй аргумент метода add () равен null, то новый элемент вставляется в конец списка, options[индекс].add(ссылкаНаЭлемент[, индекс]) options [индекс] . remove () Возвращаемое Значение: отсутствует Совместимость: WinIE4+, МасВЕ4+, NN-, Мог-, Safari- Оба поддерживаемых в IE метода принадлежат свойству-массиву options объекта элемен- та select (см. описание этого объекта ранее в этой главе, где рассказано, как нужно исполь- зовать эти и эквивалентные им методы в других браузерах и объектных моделях). i t em (индекс) () narnedl tern (11 идентификатор") () Возвращаемое Значение: ссылка на элемент option Совместимость: WinIE5+, MacIE5+, NN-, Мог-, Safari- Методы item () и namedltem () поддерживаются только в браузерах компании Netscape. Они предназначены для быстрого доступа к объектам элементов option, вложенных в объект select (вместо массива options с индексацией элементов). Аргументом метода item () является целочисленный индекс. Например, два следующих оператора указывают на один и тот же объект элемента option. document.forms[0].mySelect.options[2] document.forms[0].mySelect.item(2) Если в сценарии известен идентификатор элемента option (являющийся строкой), им можно воспользоваться как аргументом метода namedltem (). Пример В следующем выражении ссылка на элемент опции сохраняется в переменной. var oneOption = document.forms[0].mySelect.namedltem("option3_2"); См. также: свойство options. Глава 24. Объекты select, option и fileupload 729
Обработчики событий onchange Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Когда пользователь выбирает новый элемент в списке объекта select, происходит событие onchange. В примерах, приведенных ранее в этом разделе (в частности, листинги 24.6 и 24.7), действие связано с отдельной кнопкой. Такой подход оказывается удобным при определен- ных обстоятельствах, особенно в списках select, поддерживающих групповое выделение, или любых всплывающих списках. (Обычно щелчок на опции во всплывающем списке не производит никакого видимого для пользователя действия.) Однако в большинстве всплы- вающих меню желательно, чтобы действие осуществлялось при выборе элемента. Для этого в определение объекта <select> необходимо включить обработчик события onchange. Если пользователь вторично выберет один и тот же элемент, событие onchange не запустит. В этом случае действие все равно можно выполнить, воспользовавшись обработчиком события onclick, которое, однако, доступно для объекта select лишь в браузерах IE4+ и W3C. Пример Листинг 24.8 представляет собой измененный листинг 24.6. Сценарий этого документа выполняет все свои действия после выбора пользователем элементов в раскрывающемся спи- ске. В данном случае обработчик события onchange дескриптора <select> заменяет кнопку выполнения действий. Рассматриваемое приложение позволяет выполнить все необ- ходимые операции “немедленно”, не прибегая к услугам командных кнопок. Обратите внимание на некоторые изменения. Теперь элемент select в качестве первой опции содержит пустую строку. Таким образом, когда пользователь открывает страницу, ни- чего не происходит. Функция в обязательном порядке проверяет, что выбрал пользователь перед тем, как изменить фоновый цвет. Второе изменение касается элемента body. Теперь он содержит обработчик onunload, восстанавливающий форму. Его назначение очень простое — когда пользователь откроет в те- кущем окне новую страницу, а затем возвратится обратно с помощью кнопки Back (Назад), он не увидит цветной заливки — форма возвратится к исходному состоянию. В связи с внутрен- ней ошибкой в браузерах IE4 и IE5 восстановление не выполняется. В качестве альтернатив- ного варианта можно предложить запускать функцию seeColor () в обработчике onload, подставив в нее ссылку на элемент select в качестве аргумента. Листинг И Цве^фс^) выборе, алмйнтй сптям <html> <head> <title>Color Changer 2</title> «script type="text/javascript"> function seeColor(list) { var newColor = (list.options[list.selectedlndex].value); if (newColor) { document.bgColor = newColor; } } . </script> </head> «body onunload="document.forms[0].reset()"> «form> 730 Часть III. Объекты документа
<p>Choose a background color: <select name="colorsList" onchange="seeColor(this)"> «option selected="selected" value=""></option> «option value="cornflowerblue">Cornflower Blue«/option> «option value="darksalmon">Dark Salmon«/option> «option value="lightgoldenrodyellow">Light Goldenrod Yellow«/option> «option value="seagreen">Sea Green«/option> </select>«/p> </form> </body> </html> Объект элемента option Свойства, методы и обработчики событий этого элемента описаны в главе 15. Свойства Методы Обработчики событий defaultSelected form* label selected text value * См. объект текстового поля (глава 23). Синтаксис Доступ к свойствам объекта option. (All) [window. ] document. имяФормы. имяСписка. options [индекс] . свойство | метод ( [параметры]) (Все) [window. ] document. имяФормы. elements [индекс] . options [индекс] . свойство | метод ([параметры] ) (Все) [window. ] document. forms [индекс] . имяСписка. options [индекс] . свойство | метод ([параметры] ) (Все) [window.]document.forms["имяФормы"].имяСписка.options[индекс]. свойство | метод ( [параметры] ) (Все) [window. ] document. forms ["имяФормы"] .elements [индекс] .options [индекс] . свойство | метод ( [параметры] ) (IE4+) [window. ] document .all. идентифика тор. свойство | метод ( [параметры]) (IE5+/W3C) [window. ] document.getElementByld ("идентификатор") . свойство | метод ([параметры] ) Глава 24. Объекты select, option и fileupload 731
(W3C) [window. ] document. forms [индекс] .имяСписка.item(индекс) .свойство! метод( [параметры] ) (W3C) [window. ] document. forms [”имяФормы" ] . имяСписка. namedltem (иденти- фикатор) . свойство!метод([параметры] ) Совместимость: WinIE3+, МасПзЗ-ь, NN2+, Mozl+, Safari 14- Описание объекта Элементы option являются вложенными в элементы select. Каждая опция представ- ляет собой элемент в списке, отображаемом элементом select. Свойства объекта option позволяют проверить, является ли данная опция выбранной в текущий момент или по умол- чанию. Кроме видимого текста, объекту можно присвоить и скрытое значение. Подробная информация о взаимодействии объектов элементов select и option, а также о свойствах и методах массива options была изложена ранее при описании объекта select. Все свойства объекта option, совместимые снизу вверх (defaultSelected, selected, text и value), были рассмотрены в разделе, посвященном объекту select. Далее мы на- зовем уникальные свойства, поддерживаемые только в современных версиях браузерор. В браузерах NN3+ и IE4+ для создания нового объекта opt ion предназначена функция- конструктор Option, поддерживающая следующий синтаксис. var newOption = new Option("текст","значение”); В данном случае текст является надписью, отображаемой в списке, а значение— стро- кой, присваиваемой свойству value новой опции. Новый объект option не добавляется к объекту select. Для этого его необходимо включить в массив options. Пример того, как можно изменять опции, приведен в листинге 24.1. Свойства label Значение: строка > Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safari 14- Свойство label соответствует атрибуту label элемента option (стандарт HTML 4.0). Этот атрибут (и свойство) позволяет присвоить опции новый текст. Свойство поддерживает- ся в браузерах МасЕ5 и NN6. В Мас1Е5 любая строка, присваиваемая атрибуту label или соответствующему свойству, заменяет текст, находящийся между открывающим и закрывающим дескрипторами элемента option. Поэтому определенное содержимое можно присвоить и атрибуту, и дескриптору, но только браузеры, поддерживающие стандарт HTML 4.01, будут отображать значение свойст- ва label. Несмотря на то, что это свойство поддерживается в NN6, браузер не изменит ото- бражаемого текста после изменения значения свойства. Пример Следующее выражение изменяет текст, отображаемый в списке элементов. document.forms[0].mySelect.options[3].label = "Widget 9000"; Если текущая опция выбрана, то ее текст принимает указанный в подписи вид. См. также: свойство text. 732 Часть III. Объекты документа
Объект элемента optgroup Свойства, методы и обработчики событий этого элемента описаны в главе 15. Свойства Методы Обработчики событий form* label * См. объект текстового поля (глава 23). Синтаксис Доступ к свойствам объекта optgroup. (IE) [window. ] document. all. "идентификатор” . свойство | метод([параметры]) (NN6) [window. ] document .getElementByld("идентификатор" ) Зсвойство!ме- тод ( [параметры] ) Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Описание объекта Элемент optgroup (стандарт HTML 4.0) позволяет разработчикам группировать опции в списке select. Надпись, присваиваемая элементу optgroup, отображается в списке как невыбираемая опция. В NN6 элементы optgroup по умолчанию отображаются полужирным курсивным шрифтом. Обычные элементы option внутри группы отображаются обычным шрифтом и начертанием. Объект элемента optgroup имеет гораздо меньше свойств, мето- дов и обработчиков событий, чем другие элементы, поскольку (на момент написания этой кни- ги) он не был включен в объектную модель документа браузера WinlE, хотя и поддерживался в браузере MacDE5, позволяя создавать иерархически правильно форматированные меню. Браузеры, не распознающие этот элемент, попросту игнорируют его. Опции отображают- ся так, будто элементы optgroup отсутствуют. Свойства label Значение: строка Чтение/Запись Совместимость: WinIE6+, MacDE5+, NN6+, Mozl+, Safaril+ Свойство label соответствует атрибуту label элемента optgroup (стандарт HTML 4.0). Этот атрибут (и свойство) позволяет присвоить текст надписи, выделяющей группу вложен- ных элементов opt ion во всплывающем списке. / В Мас1Е5 присвоить значения последнему элементу optgroup внутри элемента /на заметку select невозможно из-за внутренней ошибки программы. Глава 24. Объекты select, option и fileupload 733
Пример Приводя листинг 24.9, мы надеемся, что Microsoft и Netscape, наконец-то, исправят все ошибки, связанные с использованием в сценариях свойства label. При правильном выпол- нении этого кода в списке цветов отображаются имена групп элементов. Будьте готовы к то- му, что далеко не все браузеры справятся с выполнением этого сценария. <html> <head> <title>Color Changer 3</title> «script type="text/javascript"> var regularLabels = ["Reds","Greens","Blues"]; var naturalLabels = ["Apples","Leaves","Sea"]; function setRegularLabels(list) { var optGrps = list.getElementsByTagName("optgroup"); for (var i = 0; i < optGrps.length; i++) { optGrps[i].label = regularLabels[i]; } } function setNaturalLabels(list) { var optGrps = list.getElementsByTagName("optgroup"); for (var i = 0; i < optGrps.length; i++) { optGrps[i].label - naturalLabels[i]; } } function seeColor(list) { var newColor = (list.options[list.selectedlndex].value); if (newColor) { document.bgColor = newColor; } } </script> </head> «body onunload="document.forms[0].reset))"> <form> <p>Choose a background color: «select name="colorsList" onchange="seeColor(this)"> «optgroup id="optGrpl" label="Reds"> «option value="#ff9999">Light Red«/option> «option value="#ff3366">Medium Red«/option> «option value="#ff0000">Bright Red«/option> «option value="#660000">Dark Red«/option> </optgroup> «optgroup id="optGrp2" label="Greens"> «option value="#ccff66">Light Green«/option> «option value="#99ff33">Medium Green«/option> «option value="#00ff00">Bright Green«/option> «option value="#006600">Dark Green«/option> </optgroup> «optgroup id="optGrp3" label="Blues"> «option value="#ccffff">Light Blue«/option> «option value="#66ccff">Medium Blue«/option> «option value="#0000ff">Bright Blue«/option> «option value="#000066">Dark Blue«/option> </optgroup> 734 Часть III. Объекты документа
</selectx/p> <pxinput type="radio" name="labels" checked="checked" onclick="setRegularLabels(this.form.colorsList)" />Regular Label Names cinput type="radio" name="labels" onclick="setNaturalLabels(this.form.colorsList)" /> Label Names from Nature</p> </form> </body> </html> См. также: свойство option. label. Объект элемента ввода файла Свойства, методы и обработчики событий этого элемента описаны в главе 15. Свойства Методы Обработчики событий defaultvalue* select()* onchange* form* name* readonly* size* type* value* * См. объект текстового поля (глава 23). Синтаксис Доступ к свойствам файлового объекта input. (NN3+/IE4+) [window. ] document. имяФормы. имяПоля. свойство | метод ([параметры] ) (NN3+/IE4+) [window.]document. имяФормы.elements[индекс] .свойство|метод ( [параметры] ) (NN3+/IE4+) [window.]document.forms[индекс] .имяПоля.свойство|метод([пара- метры] ) (NN3+/IE4+) [window. ] document. forms [" имяФормы” ] . имяПоля. свойство | метод ( [параметры] ) (NN3+/IE4+) [window. ] document. forms [ "имяФормы” ] . elements [индекс] . свойство | метод ( [параметры] ) (IE4+) [window. ] document. all. идентификатор. свойство | метод ([параметры]) (IE5+/W3C) [window. ] document. getElementByld ("идентификатор") . свойство | метод ( [параметры] ) Глава 24. Объекты select, option и fileupload 735
Описание объекта Некоторые Web-узлы позволяют выгружать файлы с клиентской стороны на серверную. Для этого, как правило, используется форма, пересылающая файл CGI-программе на сервере. Эле- мент input, тип которого определен как file (известный также как объект fileUpload), представляет собой пользовательский интерфейс, необходимый для указания выгружаемого файла. Без сервера, принимающего файл, этот элемент не осуществляет никаких действий. Кроме того, два атрибута элемента form необходимо установить следующим образом. method="POST" enctype="multipart/form-data" Этот элемент отображает поле и кнопку Browse (Обзор). С ее помощью вызывается стан- дартное диалоговое окно открытия файла (его вид зависит от операционной системы), в ко- тором пользователь указывает файл. После этого в поле ввода появляется имя файла (или путь к нему, в зависимости от операционной системы). При этом имя файла содержится в свойстве value объекта. С клиентской стороны для этого объекта не требуется дополнительного программирова- ния. Свойство value, например, в ранних версиях браузеров предназначено Только для чте- ния. Кроме того, форма не может выгрузить файл на сервер без согласия пользователя. Пример Увидеть, как выглядит данный элемент, позволяет листинг 24.10. Листинг 2* ЛО Злами* амм НИж <html> <head> <title>FileUpload Object</title> </head> <body> <form method="POST" action="yourCGIURL" enctype="multipart/form-data">File to be uploaded: cinput type="file" size="40" name="fileToGo" /> cpxinput type= "button" value="View Value" onclick="alert(this.form.fileToGo.value)" /></p> </form> </body> </html> Для использования этого кода в реальных проектах в атрибуте action дескриптора <f orm> необходимо обозначить кнопку Submit и указать реальный URL. 736 Часть III. Объекты документа
Объекты событий о браузерах D34+ и NN4+ любое действие пользовате- ля или системы — событие — передается обработчи- ку событий, описанному в виде атрибута внутри дескриптора HTML. Например, когда пользователь щелкает мышкой, со- бытие щелчка запускает обработчик события onclick. При этом выполняете^ отдельная функция или встроенный сце- нарий JavaScript (т.е. само событие ничего не делает: оно или происходит, или нет). Событие (например, изменение коор- динаты указателя в тот момент, когда пользователь щелкнул кнопкой мыши) и связанное с ним действие (например, на- жатие клавиши-модификатора в момент запуска события) — это не одно и то же (хотя до четвертой версии браузеров эти понятия были эквивалентны). Сохранив полную обратную совместимость со старыми обработчиками событий, браузеры четвертой версии под- держивают первую модель событий, согласно которой каж- дому событию соответствует объект определенного класса. Когда происходит событие свойства этого объекта, они автоматически получают всю информацию о нем. Такие свой- ства полностью доступны сценарию, что позволяет страни- цам более “интеллектуально” реагировать на действия поль- зователя с самой страницей и ее элементами. Другое новшество модели событий четвертого поколения браузеров— возможность передачи событий. Таким обра- зом, стала возможной обработка события несколькими объектами, расположенными на разных уровнях иерархии; в результате обеспечивается обработка событий многими объектами. То, что обрабатываемое событие содержит ин- формацию о целевом объекте и другие полезные данные, га- рантирует высокую интеллектуальность функций, которые могут обрабатывать событие, не ссылаясь на дополнитель- ные источники информации. Как бы то ни было, наибольшее преимущество указанно- го нововведения заключается в урегулировании несовмести- мости между различными моделями событий. На сегодняш- ний день существует три модели объектов событий: NN4 (значимость которой с каждым днем уменьшается, поскольку пользователи переходят на более новые браузеры), модель событий IE4+ и стандартизованная модель W3C DOM, реа-
лизованная в браузере NN6+. Многие отличия между разными моделями событий были опи- саны во вступлении к описанию модели событий в главе 15. В этой главе вы найдете исчер- пывающие сведения о моделях событий и о большинстве объектов событий. Там, где это возможно, описываются межбраузерные решения. Понятие события Создать графический пользовательский интерфейс гораздо труднее, чем “старомодный” интерфейс с использованием командной строки. При использовании командной строки или системы управляющих меню набор действий, которые могут выполнятся в каждый момент времени, весьма ограничен. Эта возможность часто применяется в программировании, по- скольку позволяет направлять пользователя по пути, ограниченному структурой программы. Совсем другой подход применяется при создании графических пользовательских интерфей- сов, например, в операционных системах Windows, MacOS, X Window System и других, начиная с первой системы, использующей графический интерфейс XeroxStar. Задача программиста при создании действительно удобного графического интерфейса состоит в предоставлении поль- зователю возможности выполнять любое действие в любой момент времени: перемещать мышь, вводить команды с клавиатуры, выделять текст, выбирать опции в выпадающем меню и т.д. Для этого программа (или, точнее говоря, операционная система) должна отслеживать любые действия устройств ввода (мышь, клавиатура) и сигналы, поступающие из сети. Таким образом, операционная система регистрирует все события: как вызванные дейст- виями пользователя, так и работой активных программ. Впоследствии система или текущая программа будет следить, как протекает каждое событие. Для этого события должны содер- жать определенную информацию о себе: как и в какой области экрана они происходят. Свойства событий Несмотря на большое разнообразие объектов событий, существует всего три модели со- бытия. Согласно первой модели объект событий создается в тот момент, когда происходит событие. Например, когда вы щелкаете мышью, в памяти браузера создается объект события. Когда объект создан, браузер присваивает значения свойствам события. Свойства отражают многочисленные характеристики конкретного события. Для события click — это координа- ты на экране и информация о том, какая кнопка мыши была использована. Чтобы облегчить задачу обработчику событий, браузер производит вычисления и устанавливает, на каком эле- менте экрана произошло событие click (например, на кнопке). Таким образом, одно из свойств объекта события содержит ссылку на элемент, на котором вы щелкнули мышью. Большинство свойств объекта события (для некоторых моделей событий — все свойства) доступны только для чтения. В том, что модель события позволяет изменять свойства объек- та события, есть как преимущества, так и недостатки. Например, если пользователь вводит текст в текстовое поле, но там появляются совсем не те символы, которые он ввел, — ему вряд ли это понравится. С другой стороны, иногда может принести пользу изменение регист- ра вводимого текста (заглавные на строчные буквы) или замена одних символов другими. Каждая модель события предлагает свою концепцию управления. Модель события IE4 пре- доставляет возможность изменять событие — нажатие клавиши на клавиатуре в модели со- бытий NN4 и W3C DOM оказывается безрезультатным. Пожалуй, наиболее важное свойство объекта события состоит в том, что он хранится в памяти ровно столько времени, сколько требуется сценарию для обработки события. Каж- дое событие запускает обработчик события— обычно функцию. Эта функция, разумеется, может вызывать другие функции. Пока выполняются операторы обработчика события, 738 Часть ///. Объекты документа
объект события и его свойства остаются доступными вашему сценарию в памяти, выделен- ной браузеру. Но когда выполняется последний оператор сценария, объект события возвра- щается в исходное состояние (пустой объект). Короткий срок жизни объекта — это следствие того, что в определенный момент времени существует только один объект события. Другими словами, независимо от того, насколько сложны функции обработчика событий, все они выполняются последовательно (для опытных программистов: один выполняемый поток). Операционная система заносит запущенные со- бытия в буфер. В редких случаях, когда буфер системы оказывается заполненным многими обработчиками событий, они выполняются в том порядке, в каком заносились в буфер. Статичные объекты событий Прежде мы говорили об объектах event (с маленькой е), которые являются экземпляра- ми конкретных событий, со всем набором свойств, связанных с определенным действием. В моделях событий NN4 и W3C DOM присутствуют статичные объекты событий event. В мо- дели событий W3C DOM представлена дополнительная подкатегория объектов. Эта подкате- гория будет рассматриваться позже в данной главе, в настоящий момент нам важно показать различие между событием event и объектом event. Первое событие является временным объектом с информацией о конкретном действии пользователя; основное назначение второ- го — хранить значения констант-значений событий, которые могут быть использованы в сце- нарии. Статический объект также доступен для сценария из любого окна или фрейма. Если вы хотите увидеть список свойств объекта event в NN4 или NN6+, используйте приложение The Evaluator (описанное в главе 13); введите event в нижнее текстовое поле (можете также проверить свойства объекта KeyEvent в NN6+). Статический объект event используется и как родительский объект, т.е. на его основе могут создаваться другие объекты событий. Объект event имеет набор свойств и методов, которые передаются или наследуются другими объектам, созданным в результате определен- ного события. Наследование наиболее заметно проявляется в модели событий W3C DOM, при реализации которой использовались объектно-ориентированные принципы DOM. Передача событий В браузерах до 4 версии любое событие инициирует объект. Если для этого события и объекта задан обработчик события, то он выполняется; если обработчик не существует, со- бытие игнорируется. Современные браузеры в любом случае отправляют событие в долгий путь, передавая его через объектную модель. Как уже отмечалось, на сегодняшний день су- ществует три модели передачи события: NN4, IE4 и W3C DOM, реализованная в NN6. Кон- цепции моделей передачи событий в NN4 и IE4 диаметрально противоположны. В модели W3C DOM реализованы обе модели одновременно, но с новым синтаксисом, который не по- вторяет ни одну из предыдущих моделей. В основу всех трех объектных моделей положено утверждение, что каждое событие имеет конкретную цель. Для действий, инициализированных пользователем, это очевидно. Если вы щелкаете мышью на кнопке или вводите текст в текстовое поле, то целью сгенерированного вами события являются, соответственно, кнопка или текстовое поле. Для событий, вызванных действиями системы, это не столь очевидно. Например, после завершения загрузки страницы возникает событие onload. Во всех моделях событий это событие запускает объект window. Различие между моделями передачи событий состоит в том, как событие достигает цели и что происходит с событием после того, как обработчик события заканчивает выполняться. Глава 25. Объекты событий 739
Передача событий в NN4 Несмотря на то, что популярность браузеров NN4 продолжает уменьшаться, эта модель передачи использует некоторые концепции, которые применяются в более современной мо- дели W3C DOM. Название модели передачи событий в NN4 — захват события. В этой модели событие передается от верхнего в иерархии объекта window к объекту, представляющему цель события. Например, когда вы щелкаете на кнопке формы, событие щелчка проходит через объекты window и document (если возможно, то и объект layer) прежде, чем достигает объекта button (кнопка) (объект form не входит в цепочку переда- чи). Несмотря на кажущуюся сложность, эта передача происходит мгновенно, без потери производительности. Событие, которое проходит через объекты window, document и layer, само является полноценным объектом с полным набором свойств, описывающих действие пользователя или системы. Таким образом, если событие обрабатывается на уровне объекта window, одно из свойств объекта события содержит ссылку на объект, являющийся целью события. Благодаря этому сценарий обработчика событий, работающий на уровне объекта window, может получить необходимую информацию (например, имя кнопки) и создать ссылку на содержащую ее форму. Йо умолчанию захват события отключен. Чтобы события, проходящие через объекты window, document и layer, обрабатывались на уровне текущих объектов, включите для каждого из них захват события. Захват события в NN4 Все три описанных выше объекта— window, document и layer — имеют метод captureEvents О . С его помощью обеспечивается захват события на уровне любого из этих объектов. Данный метод требует наличия одного или нескольких параметров — имена типов событий (константы, содержащиеся в объекте Event), которые будут захвачены объек- том. Остальные события пройдут через объект без изменений. Например, если вы хотите, чтобы объект window захватывал все события keyPress (нажатие клавиши на клавиатуре), включите в сценарий, выполняемый при загрузке страницы, следующую команду. window.captureEvents(Event.KEYPRESS); Желательно определить обработчик события в предполагаемом целевом объекте. Даже если он будет пустым (например onkeypress=""), это поможет быстрее сгенерировать со- бытие. Если нужно, чтобы объект захватывал несколько типов событий, перечислите их все, используя в качестве разделителя вертикальную черту. window. captureEvents (Event. KEYPRESS | Event .CLICK) ; Далее определите, какие действия будут выполняться на уровне window над каждым ти- пом события. Вам нужно создать функции для обработки события. Создайте ссылки на соот- ветствующие функции, установив свойства обработчика событий объекта window следую- щим образом. window, onkeypress = processKeyEvent; window, onclick = processClickEvent; Теперь если пользователь введет текст в текстовое поле или щелкнет мышью в окне (window), эти события будут обработаны соответствующими функциями обработчика событий уровня объекта window. Отключение захвата события Выше мы рассмотрели захват события определенного типа. Но иногда (например, когда страница выгружается из браузера) требуется отключить захват события. Вы можете отключить захват события определенного типа, воспользовавшись методом releaseEvents О объектов 740 Часть III. Объекты документа
window, document и layer. Метод releaseEvents (), как и метод captureEvents (), требует в качестве параметров задать типы событий — константы объекта Event. Действие освобождения определенного типа события означает, что событие не обрабаты- вается в объектах верхнего уровня, а передается без изменений в целевой объект события (даже если в объектах верхнего уро’вня определены обработчики данного типа события). Вы можете освободить события определенного типа, указав соответствующие параметры метода releaseEvents О . События остальных типов, для которых захват события остался вклю- ченным, по-прежнему будут захватываться. Для демонстрации методов releaseEvents (), captureEvents (), а также методов других моделей событий мы представляем серию из нескольких версий одного документа HTML со встроенным сценарием JavaScript. Каждая последующая версия содержит дополни- тельные возможности, которые дополняют уже существующие. Также в них применяются различные типы взаимодействий между событиями и методами обработчиков событий. До- кумент содержит несколько кнопок и флажков, позволяющих выбирать методы, которые бу- дут применяться. Объект layer также активно используется, поскольку многие директивы о захвате и модификации событий поступают от элементов уровня объекта layer. Листинг 25.1 — это первый пример, который демонстрирует захват и освобождение со- бытий верхним в иерархии объектом document. Флажок позволяет устанавливать или от- ключать захват события cl ick на уровне объекта document (все флажки в данном примере используют обработчик события onmouseup, так как событие click может быть изменено). Поскольку событие может захваливаться объектом верхнего уровня, в результате применения метода captureEvents О каждый щелчок на кнопке слоя приведет к обработке события объектом верхнего уровня. pfciCtoe МЛ. й ПГЛЙИЦЙИ1 во&дей в ЙМ <html> <head> <titlex/title> «script type="text/javascript"> function setDocCapture(enable) { if (!enable) { document.captureEvents(Event.CLICK); } else { document.releaseEvents(Event.CLICK); } } function doMainClick(e) { if (e.target.type == "button") { alert("Captured in top document"); } } document.captureEvents(Event.CLICK); document.onclick=doMainClick; </script> </head> <body> <b>Basic document-level capture of Event.CLICK«/b> «hr / > <form> «input type="checkbox" onmousedown = "setDocCapture(this.checked)" checked^"checked" />Enable Document Capture Глава 25. Объекты событий 741
<hr / > «input type="button" value="Button 'mainl'" name="mainl" onclick="alert('Event finally reached Button:' + this.name)" /> </form> «layer id="layerl" left="200" top="150" bgcolor="coral"> <form> <br /> «pxinput type="button" value="Button 'layerButtonl'" name="layerButtonl" onclick="alert(1 Event finally reached Button:’ + this.name)" /x/p> «pxinput type="button" value="Button 1 layerButton2 1 " name="layerButton2" onclick="alert('Event finally reached Button:' + this.name)" /></p> </form> </layer> </body> </html> Когда включен захват события на уровне объекта document (по умолчанию он включен), все события click захватываются обработчиком события объекта document — функцией, которая извещает пользователя о том, что событие было захвачено верхним в иерархии объек- том. Следовательно, все события click кнопок слоя захватываются, не доходя до цели. Но если вы отключите захват, тогда события будут передаваться объекту-цели. ! Если логика функции setDocCapture О кажется вам ошибочной, вспомните, что /На заметку при генерировании события для флажка, сам флажок переходит в противопо- * ложное состояние. В листинг 25.2 мы внесли некоторые дополнения, которые позволят захватить событие click объекту layer (но только тогда, когда выключен захват события объектом document). За- хват события click объектом layer устанавливается с помощью JavaScript внутри деск- риптора <layer>. Следовательно, если захват события верхним объектом иерархии отклю- чен, то событие передается непосредственно кнопке и захватывается обработчиком событий слоя. Захват события объектом layer препятствует передаче событий от других объектов кнопкам слоя.. Эта операция становится возможной только в том случае, если вы отключите захват событий в обоих объектах: document и layer. IAmctw ЭД. Змагг и осаобождеммв cOJk/ntf | <html> <head> <title>«/title> «script type="text/javascript"> function setDocCapture(enable) { if (!enable) { document.captureEvents(Event.CLICK); } else { document.releaseEvents(Event.CLICK); } } function setLayerCapture(enable) { if (tenable) { document.layer1.captureEvents(Event.CLICK); 742 Часть ///. Объекты документа
} else { document.layerl.releaseEvents(Event.CLICK); } } function doMainClick(e) { if (e.target.type == "button") { alert("Captured in top document"); } } document.captureEvents(Event.CLICK); document.onclick=doMainClick; </script> </head> <body> <b>Document-level and/or Layer-level capture of Event.CLICK</b> <hr /> <form> <input type»"checkbox" onmousedown = "setDocCapture(this.checked)" checked="checked" />Enable Document Capture cinput type = "checkbox" onmousedown»"setLayerCapture(this.checked)" checked = "checked" />Enable Layer Capture chr /> cinput type="button" value="Button 'mainl'" name="mainl" onclick="alert('Event finally reached Button:' + this.name)" /> c/form> clayer id="layerl" left="200" top="150" bgcolor="coral"> cscript type»"text/javascript"> function doLayerClick(e) { if (e.target.type == "button") { alert("Captured in layerl"); } } layerl.captureEvents(Event.CLICK); layerl.onclicksdoLayerClick; c/script> cform> &#160;layerlcbr /> cp>cinput type="button" value="Button 'layerButtonl'" name="layerButtonl" onclick="alert('Event finally reached Button:' + this.name)" /></p> <p>cinput type="button" value="Button 'layerButton2'" name="layerButton2" onclick="alert('Event finally reached Button:' + this.name)" />c/p> c/form> с/layer> c/body> </html> Глава 25. Объекты событий 743
Передача событий целевым объектам Если объект захватывает событие определенного типа, сценарий объекта может выполнять определенные действия с событием перед отправкой события к цели. Например, вам нужно вы- полнить определенное действие, когда пользователь щелкает на элементе интерфейса, удержи- вая нажатой клавишу <Shift>. В этом случае функция, обрабатывающая событие на уровне объекта document, изменяет свойства события. Если же клавиша <Shift> не была нажата, событие просто продолжит свой путь к элементу, на котором пользователь щелкнул мышью. Для передачи событий через всю объектную иерархию к целевому элементу используется метод rout eEvents (), который получает в качестве параметра объект события, обрабаты- ваемый текущей функцией. Метод routeEvents () не гарантирует того, что событие будет сразу же передано по назначению, поскольку в промежуточных объектах может быть вклю- чен захват событий данного типа и событие будет перехвачено. Эти объекты, разумеется, мо- гут передать событие по назначению, используя собственный метод routeEvents (). Листинг 25.3 представляет собой документ, рассмотренный в предыдущих примерах, с добавлением средств передачи события. Целевые элементы события (кнопки) остаются без изменений, а функции обработчиков событий объектов получают дополнительные парамет- ры. Для каждого из этих объектов, захватывающих события, создается флажок, который оп- ределяет, будет ли событие обрабатываться перед передачей объекту уровнем ниже. По умолчанию флажки установлены так же, как и в листинге 25.2, т.е. захват события click включен для обоих объектов: document и layer. Щелчок на любой из кнопок приводит к тому, что событие обрабатывается только обработчиком событий объекта document. Но если вы включите передачу событий на уровень ниже, то обнаружите, что щелчок на кнопках слоя вызывает два сообщения: событие обрабатывается и объектом document, и объектом layer. Если вы включите передачу событий ниже объекта layer, то щелчок на кнопке при- ведет к появлению трех окон сообщений. Это означает, что событие достигло конечной цели — кнопки. Поскольку кнопка mainl не является частью слоя, обработчики событий объектов слоя игнорируют связанные с ней события. <html> <head> <titlex/title> «script type="text/javascript"> function setDocCapture(enable) { if (!enable) { document.captureEvents(Event.CLICK); } else { document.releaseEvents(Event.CLICK); document.forms[0].setDocRte.checked = false; docRoute = false; } } function setLayerCapture(enable) { if (!enable) { document.layerl.captureEvents(Event.CLICK); } else { document.layerl.releaseEvents(Event.CLICK); document.forms[0].setLyrRte.checked = false; layerRoute = false; } 744 Часть III. Объекты документа
} var docRoute = false; var layerRoute = false; function setDocRoute(enable) { docRoute = tenable; } function setLayerRoute(enable) { layerRoute = !enable; } function doMainClick(e) { if (e.target.type == "button") { alert("Captured in top document"); if (docRoute) { routeEvent(e); } } } document.captureEvents(Event.CLICK); document.onclick=doMainClick; </script> </head> <body> <b>Capture, Release, and Routing of Event.CLICK</b> <hr / > <form> <input type»"checkbox" name="setDocCap" onmousedown="setDocCapture(this.checked)" checked = "checked" />Enable Document Capture&#160; <input type»"checkbox" name="setDocRte" onmousedown»"setDocRoute(this.checked)" /> And let event continuecbr /> <input type="checkbox" name="setLyrCap" onmousedown»"setLayerCapture(this.checked)" checked»"checked" />Enable Layer Capture&#160; <input type»"checkbox" name="setLyrRte" onmousedown="setLayerRoute(this.checked)" /> And let event continuecbr /> <hr /> «input type="button" value="Button 'mainl'" name="mainl" onclick="alert('Event finally reached Button:' + this.name)" /> </form> «layer id="layerl" left="200" top="150" bgcolor»"coral"> «script type»"text/javascript"> function doLayerClick(e) { if (e.target.type == "button") { alert("Captured in layerl"); if (layerRoute) { routeEvent(e); } } } layerl.captureEvents(Event.CLICK); layerl.onclick=doLayerClick; </script> «fOrm> Глава 25. Объекты событий 745
&#160;layerl<br /> <pxinput type="button" value="Button ’layerButtonl’" name=”layerButtonl" onclick="alert(’Event finally reached Button:' + this.name)" /></p> <pxinput type="button" value="Button ’layerButton2’" name=’’layerButton2" onclick= "alert ('Event finally reached Button:’ + this.name)" /></p> </form> </layer> </body> </html> В некоторых случаях сценарию требуется знать, было ли событие передано следующему объекту с помощью метода routeEvents О . Этот метод запускает функцию, которая воз- вращает значение true, если событие было передано с его помощью, и false — если нет. Возвращаемое значение используется тогда, когда объект “знает” о том, что первоначальное состояние события было изменено, и реагирует соответствующим образом (например, щел- чок на ссылке может переместить или не переместить пользователя по ссылке href, в зави- симости от того, что обнаруживает обработчик события— оператор return true или return false). Когда функция запускается с помощью метода routeEvents О, значе- ние, возвращаемое конечной функцией, обратно возвращается методу routeEvents (). Это значение может обратно передавать объекту, который первоначально захватил событие. Отслеживание перемещения событий В следующем примере (последнем для модели событий NN4) объект верхнего уровня за- хватывает событие и передает его любому объекту в иерархии. Например, вы можете создать функцию обработчика событий объекта document, проверяющую свойство modifiers со- бытия; если оно содержит информацию о нажатии клавиши <Alt>, то функция передает со- бытие объекту кнопки Help, обработчик события которого отображает панель справочной информации (или другой предварительно скрытый слой). Вы можете переадресовать любое событие, используя метод handleEvent (). Этот ме- тод отличается от других методов, рассмотренных в данной главе, поскольку он ссылается на объект, обрабатывающий событие (имя объекта события передается в качестве параметра, как и в других методах). Пока в целевом объекте определен обработчик для данного типа со- бытия, он (объект) обрабатывает это событие так, если бы оно генерировалось системой (даже если свойство target объекта события содержит совсем другой объект). Продемонстрируем, как выполняется переадресация событий. Листинг 25.4 содержит окончательную версию документа, который мы так долго создавали и неоднократно описы- вали в данной главе. В этом примере описан механизм, который позволяет направлять все события click второй кнопке слоя (в листинге layerButton2). Рассмотренные выше ме- тоды (захват события, освобождение и передача событий) продолжают работать, хотя невоз- можно одновременно осуществить передачу и переадресацию события. Чтобы проанализировать, как работает переадресация событий, включите захват событий для объектов document и layer (по умолчанию включена для обоих). Когда вы щелкаете на кнопке ma ini, событие достигает только захватывающего событие обработчика объекта document. Но если вы выставите флажок Send event to 'layerButtonZ, связанный с объектом document, и щелкните на кнопке mainl, событие достигнет обработчиков событий объек- тов document и layerButton2 (объект связан со второй кнопкой слоя), несмотря на то, что кнопка mainl не является кнопкой слоя. Попробуйте поэкспериментировать с другими флажками и посмотреть, как выполняется захват, передача и переадресация событий. 746 Часть III. Объекты документа
<html> <head> <titlex/title> <script type="text/javascript"> function setDocCapture(enable) { if (!enable) { document.captureEvents(Event.CLICK); } else { document. releaseEvents (Event. CLICK)'; document.forms[0].setDocRte.checked = false; docRoute = false; } function setLayerCapture(enable) { if (!enable) { document.layerl.captureEvents(Event.CLICK); } else { document.layerl.releaseEvents(Event.CLICK); document.forms[0].setLyrRte.checked = false; layerRoute = false; var docRoute = false; var layerRoute = false; function setDocRoute(enable) { docRoute = ienable; document.forms[0].setDocShortCircuit.checked = false; docShortCircuit = false; function setLayerRoute(enable) { layerRoute = ienable; document.forms[0].setLyrShortCircuit.checked = false; layerShortCircuit = false; } var docShortCircuit = false; var layerShortCircuit = false; function setDocShortcut(enable) { docShortCircuit = (enable; if (docShortCircuit) { document.forms[0].setDocRte.checked = false; docRoute = false; } } function setLayerShortcut(enable) { layerShortCircuit = (enable; if (layerShortCircuit) { document.forms[0].setLyrRte.checked = false; layerRoute = false; } } function doMainClick(e) { if (e.target.type == "button") { alert("Captured in top document"); if (docRoute) { routeEvent(e); Глава 25. Объекты событий 747
} else if (docShortCircuit) { document.layerl.document.forms[0].layerButton2. handleEvent(e); document.captureEvents(Event.CLICK); document.onclick=doMainClick; </script> </head> <body> <b>Redirecting Event.CLICK</b> «hr /> <form> «input type="checkbox" name="setDocCap" onmousedown="setDocCapture(this.checked)" checked = ' "checked" />Enable Document Capture&#160; «input type="checkbox" name = "setDocRte" onmousedown="setDocRoute(this.checked)" /> And let event continue «input types"checkbox" names"setDocShortCircuit" onmousedown="setDocShortcut(this.checked)" />Send event to *layerButton21<br /> «input type="checkbox" name="setLyrCap" onmousedown="setLayerCapture(this.checked)" checked="checked" />Enable Layer Capture&#160; «input type="checkbox" name="setLyrRte" onmousedown = "setLayerRoute(this.checked)" />And let event continue «input types"checkbox" names"setLyrShortCircuit" onmousedown="setLayerShortcut(this.checked)" /> Send event to *layerButton21«br /> «hr I > «input type="button" value="Button 'mainl’" name="mainl" onclick="alert('Event finally reached Button:' + this.name)" /> </form> «layer id="layerl" left="200" top="200" bgcolor="coral"> «script type="text/javascript"> function doLayerClick(e) { if (e.target.type == "button") { alert("Captured in layerl"); if (layerRoute) { routeEvent(e); } else if (layerShortCircuit) { document.forms[0].layerButton2.handleEvent(e) ; layerl.captureEvents(Event.CLICK) layerl.onclick=doLayerClick </script> <form> &#160;layerl«br /> «pxinput type="button" value="Button 'layerButtonl'" name="layerButtonl" onclick="alert('Event finally reached Button:' + this.name)" /></p> «pxinput type="button" value="Button ' layerButton2 ' " names"layerButton2" onclick="alert('Event finally 74ff Часть III. Объекты документа
reached Button:’ + this.name)" /></p> </form> </layer> </body> </html> Передача событий в IE4 Передача событий в IE4 базируется на других принципах, отличных от принципов модели захвата событий в NN4. Модель передачи называется всплыванием события — в ней собы- тия, словно пузырьки в воде, поднимаются от целевого объекта вверх через все элементы ие- рархии. Вам следует ощутить разницу между старой моделью иерархической структуры объек- тов (принятой в модели захвата событий NN4) и более современным ее представлением — HTML-контейнеров, концепция которых принята в модели W3C DOM. Лучший способ продемонстрировать всплывание событий (поведение, которое включено по умолчанию), состоит в создании простого документа с несколькими обработчиками собы- тий (посмотрите, как запускается каждый из них). Листинг 25.5 содержит обработчики события onclick, определенные для кнопки внутри формы, самой формы и каждого объекта элемен- та иерархии, вплоть до window. chtml onclick="alert('Event is now at the HTML element.')"> «head> <title>Event Bubbles</title> «script type="text/javascript"> function init() { window.onclick = winEvent document.onclick = docEvent; document.body.onelick = docBodEvent; } function winEvent() { alert("Event is now at the window object level."); } function docEvent() { alert("Event is now at the document object level."); } function docBodEvent() { alert("Event is now at the BODY element."); } «/script> </head> «body onload="init()"> «hl>Event Bubbles«/hl> «hr /> «form onclick="alert('Event is now at the FORM element.')"> «input type="button" value="Button 'mainl'" name="mainl" onclick="alert('Event started at Button: ' + this.name)" /> </form> </body> </html> Глава 25. Объекты событий 749
Этот документ будет корректно работать в IE4 и NN6, поскольку эти браузеры поддержи- вают всплывающие события. Но выполнение кода в различных браузерах и на различных платформах будет иметь свои особенности (например, в WinIE4+, Мас1Е4+ и W3C). После того, как вы щелкнете на кнопке документа, описанного в листинге 25.5, событие достигнет цели — кнопки. Потом событие начнет “всплывать” через элементы HTML: вначале через содержащий кнопку элемент form, потом через элемент body и т.д. Различия в поведении события начинают проявляться после элемента body. В табл. 25.1 можно увидеть, для каких элементов определены обработчики событий (речь идет о документе, описанном в листинге 25.5) и как событие всплывает через эти элементы в различных браузерах. Я" АЛТ APWWHfe, TAMil cLti РЯМИЧМШ khmimiimn вофын i nwiruro ЭРЛ Расположение обработчика событий WinlE4+ MadE4+ NN6+/Moz1+/Safari button Да Да Да form Да . да да body да да да html да нет да document да да да window нет нет да Несмотря на отображенные в табл. 25.1 различия, события всплывают через элементы HTML одинаковым образом. Уровень объекта самой глобальной области рассмотрения, который представлен во всех браузерах (табл. 25.1), — это document. Предотвращение всплывания событий в IE Поскольку по умолчанию события всплывают,. вам может потребоваться блокировать всплывание события к верхнему элементу иерархии. Например, вы определили событие click на уровне объекта document, связанное с группой кнопок, но любой другой объект, генери- рующий событие click, тоже будет передавать его через все элементы иерархии, пока он не достигнет объекта document. Всплывающее событие и событие, переданное непосредствен- но обработчику, могут конфликтовать между собой. В IE4 каждое событие имеет свойство canc el Bubble (отменить всплывание события). По умолчанию значение этого свойства false, что означает следующее: событие всплывает через элементы иерархии, пока не достигнет обработчика. После того как событие достигнет обработчика, свойство cancelBubble изменится на true, выполнение обработчика завер- шается, но событие не всплывет далее по иерархии. Для того чтобы отключить всплывание событий, добавьте приведенный ниже код в функцию обработчика. event.cancelBubble=true; Вы можете включить этот код в документ, описанный в листинге 25.5, для отключения всплывания на любом уровне. Например, если вы измените обработчик события элемента form, добавив в него код, отключающий всплывание событий, событие не сможет подняться выше элемента form (речь идет о браузере IE4, в NN6 существуют некоторые отличия в синтакси- се — см. далее). <form onclick="alert('Event is now at the FORM element.'); event.cancelBubble=true"> 750 Часть III. Объекты документа
Предотвращение действия по умолчанию Во времена, когда события только начали добавляться в объекты, они настраивались в ат- рибутах дескрипторов. Методика блокирования действия по умолчанию для события заклю- чалась в выполнении в обработчике события оператора return false. Таким образом, например, обработчик onsubmit элемента form делал невозможной отправку данных на сервер при вводе пользователем неправильных данных. Чтобы реализовать подобное поведение (особенно при настройке событий нестандартны- ми способами, например, с помощью свойств элементов), в объект event (в IE) было вклю- чено свойство retumValue. Если назначить этому свойству в обработчике события значе- ние false, то действие по умолчанию для данного события будет блокировано. event.returnvalue = false; Такой метод блокировки событий в IE более совершенный, чем применение оператора return false. Переадресация событий Начиная с версии IE5.5, появилась возможность переадресации события любому элементу HTML (правда, с некоторыми ограничениями). Эта задача выполняется с помощью метода fireEvent(), которым обладают все элементы HTML (см. главу 15). К сожалению, переадресация со- бытия с помощью этого метода не эквивалентна генерированию нового события. Но боль- шинство свойств текущего объекта event передается новому объекту event, если в качестве параметра метода f ireEvent () указать имя оригинального объекта event. Серьезный недостаток этого метода состоит в том, что при переадресации событий теря- ется ссылка на объект, являющийся целью события. Свойство scrElement исходного собы- тия, содержащее ссылку на целевой объект, заменяется ссылкой на целевой объект метода f ireEvent (). Приведем пример — обработчик события содержится внутри элемента form. function buttonEvent() { event.cancelBubble=true; document.body.fireEvent("onelick", event); } После того как всплывание событий отключается, событие не передается вверх по иерар- хии элементу form. Вместо этого текущий объект event переадресовывается элементу body (второй параметр метода f ireEvent ()). Когда запускается обработчик события эле- мента body, объект event предоставляет информацию об исходном событии (например о том, какая кнопка мыши использовалась для щелчка) и о координатах указателя. Но свойст- во event. scrElement указывает на объект event. После того как событие достигнет эле- мента, свойство event. scrElement продолжит указывать на объект event. Вы можете убедится в этом, запустив документ, описанный в листинге 25.6, в IE5.5+. <html onclick="revealEvent('HTML', event)"> <head> <title>Event Cancelling & Redirecting</title> «script type="text/javascript"> // отображение сообщения co сведениями об объекте события function revealEvent(elem, evt) { var msg = "Event (from " + evt.srcElement.tagName + " at msg += event.clientx + + event.clientY + ") is now at the "; Глава 25. Объекты событий 751
msg += elem + " element."; alert(msg); } function init() { document.onclick = docEvent; document.body.onclick = docBodEvent; } function docEvent() { revealEvent ("document", event) } function docBodEvent() { revealEvent("BODY", event); } function buttonEvent(form) { revealEvent (11 BUTTON", event) // отмена при установке (IE4+) event.cancelBubble = form.bubbleCancelState.checked; // перенаправление при установке (IE5.5+) if (form.redirect.checked) { document.body.fireEvent("onelick", event); } } </script> </head> «body onload="init()"> <hl>Event Cancelling &amp; Redirecting</hl> <hr /> <form onclick="revealEvent(1 FORM', event)"> «pxbutton name="mainl" onclick="buttonEvent(this.form)"> Button ' mainl1 </buttonx/p> «pxinput type="checkbox" name="bubbleCancelState" onclick="event.cancelBubble=true" />Cancel Bubbling at BUTTON«br /> «input type="checkbox" name="redirect" onclick="event.cancelBubble=true" /> Redirect Event to BODY«/p> </form> </body> </html> Листинг 25.6 является модифицированной версией листинга 25.5. В первую очередь из- менения коснулись обработчиков событий каждого уровня, таким образом, теперь вы можете видеть имя дескриптора события, имеющего отношение к свойству srcElement () (как и ко- ординаты указателя мыши в событии click). Если оба флажка сняты, то событие начинает всплывать от кнопки, и элемент button является целью события в течение всего процесса всплы- вания вверх по иерархии. Если вы выставите флажок Cancel Bubbling, то событие не про- двинется далее элемента button, поскольку всплывание событий отменяется. Если вы вы- ставите флажок Redirect Event to BODY, то исходное событие будет отменено на уровне элемента button, но на уровне элемента BODY будет запущено новое событие. Заметьте, что при передаче объекта в качестве второго параметра метода revealEvent () свойства, опи- сывающие щелчок мышью (событие click), исходного события наследуются новым собы- тием, запущенным на уровне элемента body. Это событие начинает всплывать вверх по ие- рархии, начиная от элемента body. И последний вариант: если вы выставите флажок Cancel Bubbling, а флажок Redirect Event to BODY оставите неснятым, то сможете увидеть, что переадресация происходит только 752 Часть III. Объекты документа
тогда, когда заканчивает выполняться обработчик события элемента button. Исходное со- бытие никак не проявляется, пока переадресованное событие всплывает вверх по иерархии. Как только цепочка обработки переадресованного события заканчивается, исходное событие начинает всплывать к элементу form. Обратите внимание: пока объект события “знает” свою цель, элемент button и остальные его свойства тоже остаются неизменными. Это означает, что в определенный момент времени в памяти браузера может существовать два объекта event, но только один из них является “активным”. Пока передается переадресованное со- бытие, объект window. event ссылается только на этот объект event. Захват событий в IE Браузеры WinIE5 и выше в некой степени поддерживают захват событий, который доми- нирует над передачей событий. Разработанный изначально для захвата событий мыши, этот механизм был реализован с помощью методов setcapture () и releseCapture () объектов всех HTML-элементов (см. главу 15). При переходе в режим захвата все события мыши передаются объекту элемента, который вызывает метод setCapture О, независимо от конечной цели события. Такое поведение события требуется реализовать при выполнении операции перетаскивания элемента (событие генерируется за пределами текущего объекта, но все же приходит в целевой объект). Как только такая обработка событий станет не нужна, выполните метод releasecapture О. Таким образом вы вернетесь к стандартному режиму управления событиями. Передача событий в NN6+ Каждая из рассмотренных выше моделей (всплывающие события и захват событий) имеет свои преимущества. Поэтому создатели модели события W3C DOM объединили в ней обе модели передачи. Страницы с новым синтаксисом работают в старых браузерах, поскольку модель захвата событий реализована так же, как и в NN4, а всплывание — как в IE4+. Другими словами, по умолчанию событие всплывает, но в то же время вы можете вклю- чить захват события. При этом событие вначале достигнет целевого элемента, а затем всплывет в обратном направлении. По умолчанию события всплывают так же, как и в IE4+. Для того чтобы события захваты- вались в W3C DOM, объекту или элементу нужно определить приемник событий. Для этого используется метод addEventlistener () (детально о его использовании рассказано в гла- ве 15). Один из параметров метода указывает, будет ли запускаться функция-приемник собы- тия в то время, как событие всплывает или захватывается. Листинг 25.7 — это простой пример, который демонстрирует, как событие щелчка (click), назначенное кнопке, может всплывать и захватываться одновременно. Большинство функций обработчика событий определено внутри функции init О. Позаимствуем код из листинга 25.5 — в нем определены обработчики событий для объектов window, document и всех объектов, расположенных внутри дескриптора body. Они автоматически назначаются приемниками событий всплывающего типа. Далее два объекта — document и form— оп- ределяются приемниками события захватываемого типа для события click. Приемник со- бытий объекта document вызывает функции, инициализированные в обработчике событий всплывающего типа (выводимое на экран сообщение содержит символ *, чтобы напомнить вам о том, что один и тот же текст может выводиться и при захвате события, и при всплыва- нии). Для объекта form приемник событий захватываемого типа запускает одну функцию, а приемник событий всплывающего типа того же объекта запускает совсем другую функцию. Другими словами, объект содержит одну функцию для события, которое движется к целевому элементу, и совершенно другую функцию — для события, которое начинает всплывать. Многие Глава 25. Объекты событий 753
функции обработчика события могут динамически считывать значение свойства eventPhase объекта события с целью установить, в какой фазе передачи находится событие и какой обработчик события включен. <html> <head> <title>W3C DOM Event Propagation</title> <script type="text/javascript"> function init() { // использование старого синтаксиса обработки всплывания window.onclick = winEvent; document.onclick = docEvent; document.body.onclick = docBodEvent; // включение захвата щелчков для двух объектов document.addEventListener("click", docEvent, true); document.forms[0].addEventListener("click", formCaptureEvent, true); // установка приемников события при всплывании document.forms[0].addEventListener("click" , formBubbleEvent, false); } function winEvent(evt) { alert("Event is now at the window object level (" + getPhase(evt) + ")."); } function docEvent(evt) { alert("Event is now at the **document** object level (" + getPhase (evt) + ")."),- } function docBodEvent(evt) { alert("Event is now at the BODY level (" + getPhase(evt) + ") -") ; } function formCaptureEvent(evt) { alert("This alert triggered by FORM only on CAPTURE."); } function formBubbleEvent(evt) { alert("This alert triggered by FORM only on BUBBLE."); } I/ определение режима обработки события function getPhase(evt) { swi t ch (evt.event Phase) { case 1: return "CAPTURING"; break; case 2: return "AT TARGET"; break; case 3: return "BUBBLING"; break default: return ""; } } 754 Часть III. Объекты документа
</script> </head> cbody onload="ini t()"> <hl>W3C DOM Event Propagation»:/hl> <hr / > <form> cinput type="button" value="Button 'mainl'" name="mainl" onclick="alert('Event is now at the button object level (' + getPhase(event) + ')')" /> </form> </body> </html> Если вы хотите отменить захват события после того, как он был включен, используйте метод removeEventListener () любого объекта так же, как вы использовали метод addEventListener () для добавления захвата события (см. главу 15). Поскольку в одном объекте может быть определено несколько приемников событий, точно укажите три пара- метра метода removeEventListener () в соответствии с используемыми параметрами ме- тода addEventListener(). Предотвращение всплывания и захвата событий в W3C Поставим в соответствие свойству cancelBubble объекта event в IE4+ метод объекта события в модели событий W3C DOM. Метод, который предотвращает передачу события, называется stopPropagation (). Этот метод может вызываться в любом месте функции- обработчика приемника событий. Текущая функция будет полностью выполняться, но собы- тие никуда не передается. Листинг 25.8 повторяет листинг 25.7, однако в него добавлено два флажка, которые не допускают возможность остановки передачи события на уровне элемента form для захваты- ваемых или всплывающих событий. <html> <head> <title>W3C DOM Event Propagation</title> <script type="text/javascript"> function init() { // старый синтаксис обработки всплывающих событий window.onclick = winEvent; document.onclick = docEvent; document.body.onelick = docBodEvent,- // включение обработки щелчков для двух объектов document.addEventListener("click", docEvent, true); document.forms[0].addEventListener("click", formCaptureEvent, true); // установка приемников событий при всплывании document.forms[0].addEventListener("click", formBubbleEvent, false); function winEvent(evt) { if (evt.target.type == "button") { alert("Event is now at the window object level (" + getPhase (evt) + ")."),- } Глава 25. Объекты событий 755
} function docEvent(evt) { if (evt.target.type == "button") { alert ("Event is now at' the “document** object level (" + getPhase(evt) + ")."); } } function docBodEvent(evt) { if (evt.target.type == "button") { alert("Event is now at the BODY level ('' + getPhase(evt) function formCaptureEvent(evt) { if (evt.target.type == "button") { alert("This alert triggered by FORM only on CAPTURE."); if (document.forms[0].stopAllProp.checked) { evt.stopPropagation(); function formBubbleEvent(evt) { if (evt.target.type == "button") { alert("This alert triggered by FORM only on BUBBLE."); if (document.forms[0].stopDuringBubble.checked) { evt.preventBubble(); // определение режима обработки события function getPhase(evt) { switch (evt.eventphase) { case 1: return "CAPTURING"; break; case 2: return "AT TARGET"; break; case 3: return "BUBBLING"; break default: return ""; </head> cbody onload="init()"> <hl>W3C DOM Event Propagation</hl> chr /> <form> cinput type="checkbox" name="stopAllProp" />Stop all propagation at FORMcbr /> cinput type="checkbox" name="stopDuringBubble" />Prevent bubbling past FORM chr /> cinput type="button” value="Button 'mainl'" name=''mainl" onclick="alert('Event is now at the button object level (' + getPhase(event) + ').')" /> 756 Часть III. Объекты документа
</form> </body> </html> Кроме метода stopPropagation (), в NN6+, Mozl+ и Safari поддерживается свойство cancelBubble. Предотвращение действия по умолчанию в W3C Свойство returnValue (в IE) в W3C DOM заменено методом preventDef ault (). Он выполняется в обработчике события и блокирует действие по умолчанию для события. evt.preventDefaultО ; Переадресация событий в W3C Существует еще один механизм отправки события объекту, который отличается от стандартно- го, — с помощью переадресации, принятой в IE4+. Он использует другой синтаксис. Вместо метода IE4+ f ireEvent (), в NN6 применяется метод W3C DOM dispatchEvent (). Единствен- ный параметр этого метода — объект события, например текущего. Листинг 25.9 повторяет листинг 25.6, однако в него внесены незначительные изменения для адаптации к модели со- бытий W3C DOM. Заметьте, что метод dispatchEvent () получает в качестве единствен- ного параметра объект текущего события. cljtml onclick="revealEvent('HTML', event) "> <head> <title>Event Cancelling & Redirecting</title> < script type="text/javascript”> // отображение сообщения co сведениями о событии function revealEvent(elem, evt) { var msg = "Event (from 11 + evt.target.tagName + " at msg += evt.clientx + + evt.clientY + ") is now at the msg += elem + " element."; alert(msg); function init() { document.onclick = docEvent; document.body.onclick = docBodEvent; function docEvent(evt) { revea1Event("document", evt); function docBodEvent(evt) { revealEvent("BODY", evt); function buttonEvent(form, evt) { revealEvent("BUTTON", evt); // перенаправление при установке if (form.redirect.checked) { document.body.dispatchEvent(evt); } // отмена при установке if (form.bubbleCancelState.checked) { evt.stopPropagation(); } Глава 25. Объекты событий 757
</script> </head> cbody onload="init()"> <hl>Event Cancelling & Redirecting*:/hl > <hr /> <form onelick="revealEvent(1 FORM', event)"> <pxbutton name="mainl" onclick="buttonEvent(this.form, event) ">Button 'mainl1 c/buttonx/pxpx input type="checkbox" name="bubbleCancelState" onclick="event.stopPropagation()" />Cancel Bubbling at BUTTONcbr /> <input type="checkbox" name="redirect" onelick="event.stopPropagation()" /> Redirect Event to BODY</p> </form> </body> </html> Ссылки на объект события Несмотря на то, что на сегодняшний день существует три различных модели событий, есть всего два способа доступа сценария к их объектам: принятый в IE и в NN (также в W3C). Начнем с более простого способа, принятого в ЛЕ. Ссылки на объект события в IE4+ В IE4 объект event доступен как свойство объекта window. window.event Как вы уже знаете, окно является необязательной частью ссылки, т.е. ваши сценарии бу- дут рассматривать объект события как глобальную ссылку. event.имяСвойства Таким образом, любой оператор в обработчике событий имеет доступ к объекту события без предварительного объявления или инициализации. Ссылки на объект события в W3C Несколько сложнее ситуация с моделью событий в NN4. В некоторых случаях вы должны явным образом задать объект как параметр функции обработчика событий. В то же время существуют ситуации, когда объект автоматически назначается как параметр. Разница состо- ит в том, каким образом обработчик событий связывается с объектом. Если вы используете обычный способ привязки обработчика событий к объектам (с по- мощью свойства дескриптора элемента), то вам необходимо задать объект события как пара- метр event. onclick="doSomething(event)" Это единственный случай в модели NN4, когда вы увидите явную ссылку на объект event (е в нижнем регистре) как на глобальный элемент. Эта ссылка не используется ни в каком другом контексте — только как параметр функции обработчикахобытий. Если в функ- ции используется несколько параметров, то event можно указывать любым по счету, но я пред- почитаю вводить его последним. 758 Часть III. Объекты документа
onclick="doSomething(this, event)" В определении функции должен задаваться параметр-переменная, описывающий объект события. function doSomething(widget, evt) {...} Этому параметру-переменной можно давать любое имя. В настоящей книге используется и event, и evt. Однако в процессе разработки сценариев для разных браузеров избегайте применения event как имени для параметра-переменной, поскольку это название идентично имени свойства event в IE4. Существует еще несколько способов привязки функции обработчика событий к объек- там — с помощью специальных свойств и метода addEventListener () в NN6-I-в об- работчиках событий можно назначить ссылки на необходимые объекты в документе, как это показано ниже. document.forms[0].someButton.onclick = doSomething; document.getElementByld("my Button").addEventListener("click", doSomething, false); Привязка событий подобным образом не допускает передачи ваших собственных пара- метров вызываемым функциям. Но браузеры NN4+ автоматически воспринимают ссылку на объект события (который создается в ответ на действия пользователя или системы) как пара- метр. Это означает, что ваши функции “получают” обработанный объект события в качестве параметра-переменной. function doSomething(evt) {...} Вспомните: объект события содержит ссылку на объект, который был целью события. Исходя из этого, вы можете управлять любыми функциями целевого объекта, например, реально су- ществующего объекта формы, содержащего элементы управления. Листинг 25.9 показывает, каким образом объект события обрабатывается как параметр. Для всех обработчиков событий, вызванных ссылкой (как на свойство объекта обработчика собы- тий, так и на метод addEventListener ()), у функций есть параметр, который рассматрива- ется как ссылка на объект события в пределах данной функции. Если вам необходимо вызвать оттуда другие функции, вы можете использовать в них ссылку на объект события. Объект собы- тия сохраняет свои свойства до тех пор, пока выполняется цепочка команд, запущенная событием. Совместимость объектов event Несмотря на несовместимость способов, с помощью которых в IE и NN объект события попадает в функцию обработчика события, вы можете легко использовать одну переменную таким образом, что оба браузера ее поймут. Например, следующий фрагмент кода использу- ется для получения события в NN, но при этом задает и объект event в IE. function doSomething(evt) { evt = (evt) ? evt : ((window.event) ? window.event : null); if (evt) { // специальная обработка события } Если объект события представлен как параметр, он и далее будет доступен как evt; в про- тивном случае функция определяет объект window. event и присваивает его значение пере- менной evt. И наконец, если браузер не находит объект event, переменной evt присваивается пустая строка. Обработка осуществляется только тогда, когда evt содержит объект события. Глава 25. Объекты событий 759
Но это только цветочки Ягодки начнутся при более детальном рассмотрении — при по- пытке разобраться в свойствах объект события. Имена свойств разные в трех моделях событий. Далее в этой главе будут детально описаны все свойства событий и способы построения всех трех моделей. Чтобы помочь вам разобраться, сравним их. В табл. 25.2 представлена основ- ная информация об объекте события, а также имена свойств и методов, использующихся в трех моделях событий. ы Л лЯ/ЛкЯпл иАшмгп'.епйьи'ям Свойство/Действие NN4 IE4+ W3C DOM Целевой объект target srcElement target Тип события type type type X координата в элементе * offsetx * Y координата в элементе It offsetY —* X координата в позиционируемом элементе layerX X layerX Y координата в позиционируемом элементе layerY У layerY X координата на странице pageX —* pageX Y координата на странице pageY * pageY X координата в окне — clientx clientx Y координата в окне — clientY clientY X координата на экране screenX screenX screenX Y координата на экране screenY screenY screenY Кнопка мыши which button button Клавиша на клавиатуре which keyCode keyCode Нажатая клавиша <Shift> modifiers shiftKey shiftKey Нажатая клавиша <Alt> modifiers altKey altKey Нажатая клавиша <Ctrl> modifiers ctrlKey ctrlKey Предыдущий элемент — fromElement relatedTarget Следующий элемент — toElement re1at edTarge t Отменить всплывание — cancleBubble preventBubble() Предотвратить действие по умолчанию return false returnValue preventDefault() * Значение может быть получено в результате преобразований других параметров Как видно из табл. 25.2, свойства объектов событий в NN6+/W3C DOM и IE4+ во многом схожи. Это хорошая новость, особенно если учитывать то, что людей, использующих NN4, становится все меньше. Основное разногласие состоит в том, как ссылаться на элемент, кото- рый является целью события. В результате возникает необходимость задания в коде перемен- ной, которая ссылается на необходимый элемент. Например, в предыдущую функцию можно встроить следующий фрагмент кода. var elem = (evt.target) ? evt.target : evt.srcElement; Каждая модель события имеет дополнительные уникальные свойства. Именно им посвя- щена вторая часть этой главы. 760 Часть III. Объекты документа
Сравнение моделей событий Несмотря на то, что модели объектов событий существенно отличатся в обработке свойств, приспособить разные браузеры к управлению событиями довольно просто. В этом разделе рассматриваются два сценария, которые демонстрируют основные свойства событий. Первый сценарий определяет, нажата ли во время возникновения события клавиша- модификатор (и если да, то какая). Второй сценарий извлекает коды для обеих кнопок мыши и клавиш клавиатуры. Оба сценария работают со всеми браузерами, поддерживающими объ- екты событий, включая NN4. Если ваша аудитория больше не использует NN4, то вы можете удалить из сценария часть кода, выполняемого только в нем. Межплатформенное определение клавиш-модификаторов Листинг 25.10 демонстрирует технику определения клавиши-модификатора, которая' нажата во время наступления события. Детально свойства объекта события (modifiers и altKey) будут рассмотрены в этой главе несколько позже. Чтобы увидеть эту страницу в действии, щелкните на ссылке, введите какую-либо информацию в текстовом поле и щелк- ните кнопкой мыши, нажав комбинацию клавиш-модификаторов. Внизу представлен набор четырех флажков, соответствующих четырем клавишам-модификаторам. После того, как вы щелкнете мышкой и введете в поле данные при нажатом модификаторе, соответствую- щий флажок обозначит это. Листинг 25.10. Изменение свйммвс <html> <head> <title>Event Modifiers</title> «script type="text/javascript"> function checkMods(evt) { evt = (evt) ? evt : ((window.event) ? window.event : null); if (evt) { var elem = (evt,target) ? evt.target : evt.srcElement; var form = document.output; if (evt.modifiers) { form.modifier[0].checked = evt.modifiers & Event.ALT_MASK; form.modifier[1].checked = evt.modifiers & Event.CONTROL_MASK; form.modifier[2].checked = evt.modifiers & Event.SHIFT_MASK; form.modifier[3].checked = evt.modifiers & Event.METAMASK; } else { form.modifier[0].checked = evt.altKey; form.modifier[1].checked = evt.ctrlKey; form.modifier[2].checked = evt.shiftKey; form.modifier[3].checked = false; } } Глава 25. Объекты событий 761
return false; } «/script> «/head> «body> «hl>Event Modifiers«/hl> «hr /> «p>Hold one or more modifier keys and click on «a href="javascript:void(0)" onmousedown="return checkMods(event)">this link«/a> to see .which keys you are holding.«/p> < f orm name ="output"> «p>Enter some text with uppercase and lowercase letters: «input type="text" size="40" onkeyup="checkMods(event)" /> </P> <p><input type="button" value="Click Here With Modifier Keys" one 1 ick= "checkMods (event) " /></p> <p><input type="checkbox" name="modifier" />Alt «input type = "checkbox" name="modifier" />Control «input type="checkbox" name="modifier" />Shift «input type="checkbox" name="modifier" />Meta«/p> «/form> «/body> «/html> Разветвление задается только в функции checkMods (), т.к. все три обработчика собы- тий совместно используют только ее одну. Заметьте также, что при ветвлении предпочтение отдается определению объекта, а не navigator .userAgent. В данном случае этот метод предпочтительнее, поскольку его функционирование основывается на существовании опре- деленных объектов и свойств. Для NN4 объект события обрабатывается как параметр, свой- ство modifier которого остается постоянным для каждой клавиши-модификатора. Для Ш4+ и NN6 сценарий проверяет свойства объекта события для каждого из трех модификаторов. Межплатформенное определение клавиш Чтобы продемонстрировать управление клавиатурой в обоих браузерах, мы представили листинг 25.11, который определяет тип клавиши, введенной в текстовом поле, а также кнопку мыши, используемую для щелчка на кнопке. Как и в листинге 25.10, NN4 по поведению су- щественно отличается от IE4+ и NN6+. Но так или иначе, NN6 все еще поддерживает синтак- сис NN4, т.е. в нем вы можете использовать как старый, так новый синтаксис. В то время как NN4 комбинирует щелчок мыши и нажатие клавиши в одном свойстве объекта события, но- вые браузеры используют абсолютно разные свойства для этих значений. Листинг 25.11 на- писан таким образом, что NN6+ следует синтаксису NN4, но если этот синтаксис исчезнет в будущих версиях NN, браузер без всяких последствий будет использовать новый. Лслммг 25.i1. Огсмжимммгс^гШ, вызжвиних нматявм «html> «head> «title>Button and Key Properties«/title> «script type="text/javascript"> 762 Часть III. Объекты документа
function checkwhich(evt) { evt = (evt) ? evt : ((window.event) ? window.event : null); if (evt) { var thingPressed = ""; var elem = (evt.target) ? evt.target : evt.srcElement; if (elem.type == "textarea") { thingPressed = (evt.charCode) ? evt.charCode : ((evt.which) ? evt.which : evt.keyCode); } else if (elem.type == "button") { thingPressed = (typeof evt.button != "undefined") ? evt.button : ((typeof evt.which != "undefined") ? evt.which : "n/a"); } window.status = thingPressed; } return false; } </script> </head> <body> <hl>Button and Key Properties</hl> (results in the status bar) <hr /> <form> <p>Mouse down atop this «input type="button" value="Button" onmousedown="checkwhich(event)" /> with either mouse button (if you have more than one). </p> <p>Enter some text with uppercase and lowercase letters: ctextarea cols="40" rows="4" onkeypress = "checkwhich(event)" wrap="virtual"></textarea> </p> </form> </body> </html> Коды клавиш клавиатуры соответствуют ASCII-значениям символов. Если вам необходи- 'мы коды других клавиш, обработчики событий onkeydown и onkeyup предоставят вам Unicode-значения любых клавиш клавиатуры. Подробно свойство keyCode описывается да- лее в этой главе. Типы событий Браузеры до версии 4 не поддерживали возможности управления объектом события; несмотря на это, мы рассмотрим свойство type. Объектные модели в IE4+ и NN6+/W3C предоставляют обработчик событий практически для каждого элемента HTML, таким образом возможно, например, назначить обработчик событий onclick не только для кнопки, на кото- рой можно щелкнуть, но и для элемента р или произвольных span-элементов. К современным версиям браузеров мы скоро вернемся. Если вам необходимо создать сценарий, который будет выполняться в старых браузерах, определите, какие их элементы и какими обработчиками событий поддерживаются. Эта информация поможет определить общие свойства обработ- чиков событий, которые можно воплотить в ваших страницах, рассчитанных на те браузе- ры, с помощью которых, по вашим прогнозам, будут просматриваться эти страницы. Глава 25. Объекты событий 763
Старые версии браузеров Создатели старых браузеров стремились к уменьшению количества обработчиков собы- тий, предоставляя их только тем элементам, которые, по их мнению, должны ими обладать. При этом увеличение количества объектов требовало все большего количества обработчиков. Прежде чем это было воплощено в IE4+ и NN6+, разработчики попытались узнать пределы объектного моделирования. Табл. 25.3 показывает доступные для объектов обработчики со- бытий в трех поколениях браузеров. Каждый столбец представляет версию браузера, в кото- рой встречается определенный тип события. Например, объект window оснащен четырьмя типами событий, с появлением NN4 к ним было добавлено еще три. С другой стороны, объект area был впервые представлен в NN3, именно в нем для этого объекта впервые был пред- ставлен собственный обработчик события. объект NN2/IE3 NN3 NN4 window layer blur focus load unload dragdrop move resize blur focus load mouseout mouseover mouseup link click mouseover mouseout dblclick mousedown onmouseup area image mouseout mouseover abort error load click form submit reset text, textarea. password blur ' change focus select keydown keypress keyup allbuttons click mousedown mouseup За исключением объекта layer в NN4, все объекты, перечисленные в табл. 25.3, сохра- нились в более новых версиях браузеров — вы с уверенностью можете использовать их обра- ботчики событий. Также имейте в виду, что из всех браузеров, перечисленных в таблице, только NN4 имеет все объекты событий, используемые в сценариях. 764 Часть III. Объекты документа
Типы событий в IE4+ и NN6+/W3C К настоящему моменту вы уже должны были познакомиться с обработчиками событий, определенных для наиболее часто используемых элементов. Этот список огромен. Каждый браузер — IE4, IE5, IE5.5/6 — имеет уникальный список типов поддерживаемых событий. Если вы создаете страницы как для IE4+, так и для NN6+/W3C, то вам необходимо знать их общие типы событий. Типы событий в NN6+/Mozl+/Safari базируются, в основном, на спецификации W3C DOM второго уровня; они включают в себя события клавиатуры, кото- рые формально не являются частью этой спецификации. Табл. 25.4 представляет список со- вместных типов событий для современных браузеров, а также объектов, которые их поддер- живают. Как видите, многие типы событий и соответствующих объектов так и не изменились. Наиболее существенные перемены заключаются в том, что события мыши стали доступны для любого отображаемого элемента. Табл. 25.4 имеет небольшой размер, поэтому она вместила в себя не полный список событий IE (таким образом, она является только тем минимумом, который вам необходимо знать для управления браузерами). Таблица 25.4. Ой»ШС Тип события Элементы abort obj ect blur window, button, text, password, label, select, textarea change text, password, select, textarea click Bee error window, frameset, object focus window, button, text, password, label, select, textarea keydown text, password, textarea keypress text, password, textarea keyup text, password, textarea load window, frameset, object mousedown Bee mousemove Bee mouseout Bee mouseover Bee mouseup Bee preset resize form window scroll window select text, password, textarea submit form unload window, frameset Глава 25. Объекты событий 765
Объект события в NN4 Свойства Методы Обработчики событий data layerX layerY modifiers pageX pageY screenX screenY target type which Синтаксис Доступ к свойствам объекта события в NN4. объектСобытия.свойство Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Описание объекта Детальные сведения об этом объекте были приведены при рассмотрении сравнительных характеристик объектов событий. Однако отметим, что уменьшение популярности NN4 дела- ет эти объекты и их свойства менее важными. Свойства data Значение: массив строк Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Событие dragdrop содержит информацию о строке URL, которая помещается в окно браузера. Поскольку в окне браузера могут размещаться различные объекты (в некоторых операционных системах это могут быть значки, представляющие URL), значение этого свой- ства— совокупность строк, где каждая строка содержит один URL (включая file:// — URL для файлов локального компьютера). Учитывая то, что такая информация, как URL, является частной, она применяется только для защищенных сценариев — только тогда, когда пользователь дает разрешение на чтение данных браузера. Если вы хотите, чтобы ваш сценарий получал эту информацию, не загружая URL в окне, обработчик событий должен вернуть значение false. Пример На странице листинга 25.12 содержится текстовое поле, в котором отображаются URL адреса перетаскиваемых элементов. Чтобы запустить этот защищенный сценарий, вам потре- буется настроить доверителя (см. главу 46). 766 Часть III. Объекты документа
Загрузите страницу и перетащите в текстовое поле любой ярлык с рабочего стола, кото- рый представляет файлы, папки и приложения. Выделите и перетащите несколько элементов сразу. Поскольку обработчик ondragdrop выполняет оператор return false, файлы в окно браузера не загружаются. Если вы хотите просматривать URL-адреса и загружать только некоторые из них, то создайте конструкцию if. . . else, возвращающую в обработ- чик значение true или false. Выполнение оператора return true приводит к обработке события dragdrop стандартным образом — после завершения работы обработчика события. <html> <head> <title>Drag and Drop</title> <script type="text/javascript"> function handleDrag(evt) { netscape.security.PrivilegeManager. erfablePrivilege("UniversalBrowserRead"); var URLArray = evt.data; netscape.security.PrivilegeManager. disablePrivilege("UniversalBrowserRead"); if (URLArray) { document. forms [0] .output .value = URLArray. join("\n") } else { document.forms[0].output.value = "Nothing found."; } return false; } «/script> </head> «body ondragdrop="return handleDrag(event)"> <b>Drag a URL to this window (NN4 only). «/b> <hr /> <form> URLs:<br /> ctextarea name="output" cols="70" rows="4"x/textareaxbr /> «input type="reset" /> </form> </body> </html> layerX layerY pageX pageY screenX screenY Значение: целое Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Для многих (но не всех) связанных с мышью событий в обработчике NN4 предоставляется достаточное количество информации о координатах указателя во время наступления события. Глава 25. Объекты событий 767
В усложненном варианте щелчок мышью на объекте слоя имеет три четко определенных па- ры координат: слоя, страницы и всего экрана. Если для документа не заданы слои, то системы координат страницы и слоя совпадают. Заметьте, что эти значения, по сути, являются физи- ческими; сами по себе они никакой информации об объекте не несут (информация содержит- ся в свойстве eventobject. target). Указанные свойства координат указателя устанавливаются только для специфических со- бытий. В случае объекта ссылки событие click и четыре остальных события мыши отправ- ляют эти значения объекту события. Для кнопок только события мыши (mousedown и mouseup) получают эта координаты. Каждый из двух типов событий окна (move и resize) использует одну из этих пар свойств, чтобы передать результаты действий пользователя. Например, когда пользователь изменяет размер окна, событие resize использует свойства объектСобытия. layerX и объектСобытия. layerY, в которых содержатся значения размеров окна браузера (если хоти- те, можете также использовать свойства объектСобытия .width и объектСобытия .height). Когда пользователь перемещает окно, экранные координаты верхнего левого угла окна ото- бражаются в свойствах объектСобытия. screenX и объектСобытия.screenY. Пример Ознакомиться с координатной системой и связанными с ней свойствами вы можете, изучив листинг 25.13. В верхней части страницы вы найдете три поля для пар свойств layerX-layerY, pageX-pageY и screenX-screenY. Два объекта, на которых можно щелкнуть (кнопка и изображение), добавлены, чтобы показать разницу между объектами на слое и объектами вне слоя. Объект за пределами слоя располагается в той же координатной системе, что и сам слой, а также остальные объекты страницы. Два не упомянутых выше поля отображают координаты перемещения и изменения разме- ра окна. Если вы максимально увеличите окно браузера в Windows, то его левый верхний угол выйдет за края экрана на четыре пикселя в каждом направлении. Именно поэтому свой- ства screenX и screenY принимают значения - 4. <html> <head> <title>X and Y Event Propertiesc/title> «script type="text/javascript"> function checkCoords(evt) { var form = document.forms[0] ; form.layerCoords.value = evt.layerX + "," + evt.layerY; form.pageCoords.value = evt.pageX + "," + evt.pageY; form.screenCoords.value = evt.screenX + "," + evt. screenY retum false; function checksize(evt) { document.forms[0].resizeCoords.value = evt.layerX + + evt.layerY; } function checkLoc(evt) { document.forms[0].moveCoords.value = evt.screenX + + evt.screenY; } </script> </head> 768 Часть III. Объекты документа
«body onresize="checksize(event)" onmove="checkLoc(event)"> «hl>X and Y Event Properties (NN4)«/hl> «hr /> «p>Click on the button and in the layer/image to see the coordinate values for the event object.«/p> «form name="output"> «table> «tr> «td colspan="2">Mouse Event Coordinates:«/td> «/tr> «tr> «td align="right">layerX, layerY:«/td> «td>«input type="text" name="layerCoords" size="10" />«/td> «/tr> <tr> «td align="right">pageX, pageY:«/td> «td>«input type="text" name="pageCoords" size="10" />«/td> «/tr> «tr> «td align="right">screenX, screenY:«/td> «td>«input type="text" name="screenCoords" size="10" />«/td> «/tr> «tr> «td align="right">«input type="button" value="Click Here" onmousedown = "checkCoords(event)" />«/td> «/tr> «td colspan="2">«hr />«/td> «/tr> «tr> «td colspah="2">Window Resize Coordinates:«/td> «/tr> «tr> «td align="right">layerX, layerY:«/td> «td>«input type="text" name="resizeCoords" size="10" />«/td> «/tr> «tr> «td colspan="2">«hr />«/td> «/tr> «tr> «td colspan="2">Window Move Coordinates:«/td> «/tr> «tr> «td align="right">screenX, screenY:</td> «td>«input type="text" name="moveCoords" size="10" />«/td> «/tr> «/table> «/form> «layer name="display" bgcolor="coral" top="140" left="300" height="250" width="330"> «a href="javascript:void(0)" onclick="return checkCoords(event)"><img alt="image" src="nile.gif" Глава 25. Объекты событий 769
width="320" height="240" border="0" /></a> </layer> </body> </html> См. также: методы перемещения и изменения размера объектов layer и window. modifiers Значение: константа Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Свойство modifier в NN4 обращается к клавишам-модификаторам, которые могут быть нажаты во время щелчка мышью или работы с клавиатурой. К клавишам-модификаторам от- носятся <Alt> (<Option> на клавиатуре Macintosh), <Ctrl>, <Shift>, а также мета-клавиша (например, клавиша <Command> на клавиатуре Macintosh). Вы можете использовать это свой- ство, чтобы определить, нажимались ли какие-либо клавиши-модификаторы во время выпол- нения события. Значения для этих клавиш являются целочисленными величинами, разработанными таким образом, что любая комбинация клавиш имеет уникальное значение. К счастью, вам не обяза- тельно знать что-либо об этих значениях, так как модель события поддерживает некоторые константы обычного языка (свойства глобального объекта Event всегда доступны), которые сценарий может использовать в качестве значения свойства обрабатываемого объекта. Кон- станта состоит из имени клавиши (в верхнем регистре), за которым следует символ подчер- кивания и слово MASK (все в верхнем регистре). Например, если клавиша <Alt> нажата от- дельно или в сочетании с другой клавишей-модификатором, то вы можете использовать логический оператор AND (&) и константу Event. ALT_MASK, чтобы узнать, присутствует ли клавиша <Alt> в значении свойства. function handleMyEvent(evt) { if (evt.modifiers & Event.ALT_MASK) { //Установка обработчика событий для клавиши <Alt> } } Модификаторы доступны не в каждом событии. Вы можете привязать их к событиям mousedown и mouseup для кнопок и ссылок. Щелчок мыши позволяет привязать модифи- каторы только к объектам кнопок. События клавиатуры в текстовых объектах также включа- ют эти модификаторы. Но будьте аккуратны с комбинациями клавиш (<Ctrl>+<Q> для выхо- да) — они не воспринимаются моделями событий JavaScript, так как зарезервированы для использования в качестве команд браузера. Пример Обратитесь к листингу 25.10 выше в этой главе, в котором описано, как клавиши-модифи- каторы управляются в NN4. target Значение: ссылка на объект Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Каждый объект имеет свойство, содержащее ссылку на объект, на котором щелкнули мышью, что-то ввели или совершили другое действие. Обычно это свойство проверяется, когда вы задаете на странице обработку событий на уровне окна, документа или слоя, как 770 Часть III. Объекты документа
описывалось выше в этой главе. Свойство target позволяет вам точнее задать расположе- ние события, сразу проводя обработку для всех его типов. Имея ссылку на объект target, ваш сценарий может непосредственно извлечь и/или установить свойства этого объекта. type Значение: строка Только для чтения Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Тип объекта события — это имя события, которое сгенерировало объект события. Имя события — то же, что и у обработчика, только без приставки on. Таким образом, если обра- ботчик события onclick кнопки запускается в результате щелчка, то он соответствует со- бытию click (все в нижнем регистре). Если вы создаете многоцелевую функцию для обра- ботки событий, то можете воспользоваться свойством объектСобытия. type, чтобы помочь функции решить, каким образом обрабатывать событие. Эту задачу выполняет управ- ляющая структура switch (см. главу 31). which Значение: целое Только для чтения , Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- Значение свойства which зависит от типа события: индикатор кнопки мыши для событий мыши и символ клавиши для событий клавиатуры. Для событий мыши свойство объектСобытия. which содержит следующие значения: 1 — для левой (основной) кнопки мыши и 3 — для правой (дополнительной) кнопки мыши. Большинство компьютеров Macintosh оборудовано однокнопочной мышью — избегайте раз- работки страниц, управляемых второй кнопкой мыши. Даже в Windows и других платформах необходимо запрограммировать обработчик событий onmousedown объекта на задание опе- ратора return false для дополнительной кнопки мыши, чтобы на экране не появлялось всплывающее меню браузера. События клавиатуры генерируют код ISO-Latin нажатой клавиши. Это целое значение в диа- пазоне от 0 до 255. Если сценарий требует просмотреть истинный символ, который был введен, а не код клавиши, можно воспользоваться методом строка. f romCharCode () (см. главу 27), чтобы провести обратное преобразование. Если у вас возникают трудности с получением кода из событий клавиатуры, попробуйте использовать обработчики событий onkeyup и onkeydown вместо onkeypress. В любом случае, функциональные клавиши не имеют кодов символов. Пример Пример использования свойства объектСобытия. which приведен в листинге 25.10. Объект события в IE4+ Свойства Методы Обработчики событий altKey altLeft behaviorCookie behaviorPart bookmarks Глава 25. Объекты событий 771
Окончание таблицы Свойства Методы Обработчики событий boundElements button cancelBubble clientx clientY contentoverflow ctrlKey ctrlLeft dataFld dataTransfer fromElement keyCode nextPage offsetx offsetY propertyName , qualifier reason recordset repeat returnvalue saveType screenX screenY shiftKey shiftheft srcElement srcFilter srcUrn toElement type X У Синтаксис Доступ к свойствам объекта event в IE4+. [window.]event.свойство Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Описание объекта Объект event является свойством объекта window в описывались выше в этой главе. IE4+. Основные операции с ним / 772 Часть III. Объекты документа
С объектом event можно ознакомиться с помощью приложения The Evaluator (см. гла- ву 13). Если вы введете event в нижнем текстовом поле, то сможете исследовать свойства объекта event для событий, которые запускают функцию, отображающую свойства объекта event. Нажав клавишу <Enter>, вы увидите свойства события keypress, которое запустило внутренний сценарий. Щелкните мышью на кнопке List Properties, чтобы увидеть свойства события click, генерируемого кнопкой. Щелкните мышью одновременно с нажатием кла- виши-модификатора, чтобы узнать, как это влияет на некоторые свойства. Просматривая свойства объекта event, обратите внимание на таблицу совместимости для каждого свойства. Список свойств для этого объекта значительно увеличился в результа- те совершенствования модели событий в IE4+. Он также расширился в результате развития объектной модели IE4+. Преимущественно свойства, перечисленные в этом списке, имеют статус Только для чтения. Но для IE5+ они представлены как Чтение/Запись, если были соз- даны вручную с помощью таких методов IE5+, как document. createEventObj ect О . Объекты событий, которые были созданы пользователем или системой, имеют всего не- сколько свойств, что не позволяет вашим сценариям изменить действия пользователя. Свойства altKey ctrlKey shiftKey Значение: булево Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Когда объект event создается в ответ на действия пользователя или системы, то эти три свойства определяют, нажаты ли клавиши-модификаторы в момент выполнения дейст- вия (например, <8ЫЙ-нцелчок мышью>). Если клавиша нажата, свойству присваивается зна- чение true, если нет— false. Обычно эти выражения используются в составе условной конструкции if. Так как это бу- левы величины, в одном условии можно комбинировать различные свойства. Например, в той части функции, которая будет выполняться только тогда, когда во время выполнения события нажаты клавиши <Ctrl> и <Shift>, условие должно выглядеть следующим образом. if (event.shiftKey && event.ctrlKey) { // выполняемые функции } Также можно создать более простую запись функции, которая будет выполняться по- другому, если нажата одна из клавиш-модификаторов. if (event.shiftKey || event.ctrlKey || event.shiftKey) { // выполняемые функции } Суть представленных выше выражений — предложить пользователю упрощенное реше- ние, но не заставлять его при этом запоминать специфические комбинации клавиш- модификаторов . Пример В листинге 25.10 значения этих трех свойств используются для установки свойств checked соответствующих типов событий. См. также: свойства altLeft, ctrlLeft, shif theft. Глава 25. Объекты событий 773
altLeft ctrlLeft shlftLeft Значение: булево Только для чтения Совместимость: WinIE5.5, MacIE-, NN-, Moz-, Safari- Некоторые версии Windows (особенно Windows NT и Windows 2000) во время использо- вания Ш5.5+ позволяют модифицировать события только с помощью левых клавиш <Alt>, <Ctrl>, <Shift>. Чтобы эти модификаторы были восприняты объектом event, должен быть активным сам документ (тело), а не элемент управления формы. Если свойство для левой клавиши возвращает значение false, а для обоих — true, то сценарий “знает”, что во вре- мя генерирования события нажимается правая клавиша-модификатор. См. также: свойства altKey, ctrlKey, shif tKey. behaviorCookie behaviorPart Значение: целочисленное Только для чтения Совместимость: WinE6+, МасЕ-, NN-, Moz-, Safari- Эти два свойства относятся к технологии Windows, которую Microsoft называет поведением отображения. В отличие от поведений, описанных при обсуждении метода addBehavior () (см. главу 15), поведения отображения написаны на C++; они предостав- ляют возможность рисования на ваших Web-страницах. Подробно о них можно узнать в до- кументе Implementing Rendering Behaviors на узле http:/ /msdn. mi crosof t. com/workshop/ browser/edi t ing/imprendbehav.asp. bookmarks boundElements dataField qualifier reason recordset Значение: см. текст Только для чтения Совместимость: WinE6+, МасЕ-, NN-, Moz-, Safari- Эта группа свойств объектов event связана с использованием технологии Data Binding (связывание данных) в Е4+ для Windows. Детальные сведения о связывании данных мы при- водить не будем, но табл. 25.5 предоставляет информацию об этом объекте в контексте рас- сматриваемого в этой книге материала (большая часть терминологии используется в Data Binding, но не относится к сценариям). Подробные сведения о ней вы можете узнать на узле ActiveX Data Objects (ADO) по адресу http: / /msdn. microsof t. com/workshop/. button Значение: целочисленное Только для чтения Совместимость: WinE4+, МасЕ4+, NN6+, Moz-, Safari- 774 Часть ///. Объекты документа
nJ. АМ-сктвь >5ъеГ.а *-» •' • г F'-. ' Свойство Значение Впервые Описание параметра представлен bookmarks Массив IE4 Массив закладок ADO (сохраненных позиций) для записей, которые связаны с объектом, получившим событие boundElements Массив IE5 Массив ссылок на все элементы, которые связаны с одним набором данных, затронутым текущим событием dataFld Строчный IE5 Имя столбца с данными, который связан с ячейкой таблицы, получившей событие cellchange qualifier Строчный IE5 Имя члена данных, который связан с источником данных, получающего событие. Доступно только в том случае, если объект — источник данных (data source object — DSO) — разрешает существование членов данных со многими именами или если классификатор был явным образом установлен с помощью атрибута datasrc элемента. ВIE5 доступно для чтения и записи reason Целый IE4 Устанавливается только из события ondatasetcompiete; представляет код результата загрузки данных (О=успешный; 1=передача прервана; 2=другая ошибка) recordset Объект IE4 Ссылка на текущую запись в источнике данных Свойство button показывает, какая кнопка или кнопки были нажаты для активизации события мыши. Если не была нажата ни одна кнопка мыши, то значение параметра равно 0. Целые числа от 1до 7 определяют нажатые кнопки или комбинации кнопок (в том числе и для трехкнопочной мыши) в случае, если та распознается операционной системой. Целые значе- ния этого параметра соотносятся с кнопками в соответствии со следующей схемой. Значение Описание 0 Кнопки не нажаты 1 Левая (основная кнопка) 2 Правая кнопка 3 Одновременно левая и правая кнопки 4 Средняя кнопка 5 Левая и средняя 6 Правая и средняя 7 Левая, средняя и правая Все кнопки мыши, за исключением основной, проще просматривать в событиях mouseup, чем в onclick. Помните: когда пользователь нажимает несколько кнопок, каждая запускает событие mousedown. Таким образом, если пользователь сначала нажимает левую кнопку, за- пускается событие со значением свойства event .button, равным 1. Затем, когда нажимается другая кнопка, событие mousedown запускается снова, но на этот раз со значением event .button, равным 3. Если ваш сценарий подразумевает выполнение особых действий в ответ на нажатие обоих клавиш, он должен игнорировать нажатие отдельных кнопок, т.к. со- бытие одной кнопки запустит свой процесс, который будет мешать правильной работе сценария. Глава 25. Объекты событий 775
Внимание! При написании сценариев со свойством event .button для обоих браузеров NN6+ и IE4+ примите к сведению, что модель событий W3C DOM определяет иные значения для отдельно используемых кнопок мыши (0, 1 и 2 для, соответственно, левой, средней и пра- вой) и никаких значений для комбинаций кнопок. Пример В листинге 25.11 свойство event .button используется для управления строкой состоя- ния. Проверьте кнопки на странице, щелкнув на них разными кнопками мыши. Затем протес- тируйте комбинации кнопок — результаты можно увидеть в строке состояния. cancelBubble Значение: булево Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойство cancelBubble (которое звучит, скорее, как метод) определяет, будет ли теку- щий объект события всплывать выше по иерархии документа. По умолчанию значение этого свойства false — если событие может всплывать, то сделает это автоматически. Чтобы предотвратить всплывание текущего события, установите в функции обработчика событий параметр в значение true. Также можно отменить всплывание непосредственно в атрибутах обработчика событий. onelick="doButtonClick(this); event.cancelBubble = true" Отмена всплывания применяется только для текущего события. У каждого события, за- пущенного позже, это свойство будет включено. Пример В листинге 25.6 описано свойство cancelBubble. Несмотря на то, что некоторые части листинга предназначены для выполнения в IE5.54-, это свойства прекрасно поддерживается и в IE4. См. также: свойство returnvalue alientX clientY offsetX offsetY screenX screenY x У Значение: целочисленное Только для чтения Совместимость: WinIE44-, MacIE44-, NN64-, Mozl-ь, Safaril-b ,В IE4 объект event предоставляет четыре набора координат: элемента, родительского элемента целевого элемента, доступной для обозрения части окна браузера и всего экрана. К несчастью, некоторые свойства, отвечающие за эти наборы координат, могут возвращать неверные значения, о чем и пойдет речь далее. Заметьте, что свойства не предопределяют яв- ной позиции события по отношению к странице, если пользователь прокручивает документ. Начнем с самого первого набора координат — для элемента, который является целью события,— свойства offsetx, offsetY представляют координаты целевого элемента 776 Часть III. Объекты документа
в пикселях. Пользуясь ими, можно определить место щелчка на изображении, в зависимости от того, каким образом оно присоединено: в элементе body или div. IE6 для Windows в болыпрнстве случаев возвращает корректные значения свойств. Но для некоторых дочер- них объектов элемента body вертикальное (у) значение может зависеть от размеров окна, а не самого элемента. Пример вы можете увидеть при изучении листинга 25.14, щелкнув мы- шью на элементах hl или р вначале страницы. Эта проблема не затронула IE для Мас, но в данной версии браузера существует другая проблема: если страница прокручивается за пре- делы своих исходных размеров, то в качестве значений прокрутки используются значения clientx и clientY. Необходимо принять в расчет эту ошибку несовместимости при зада- нии координат щелчка для объекта на странице, которую можно прокручивать. Исправлять эту ошибку необходимо только для Мас, так как в Windows она отсутствует. Свойства х и у в IE5+ для Windows возвращают координаты смещения относительно роди- тельского элемента (элемента, который можно обнаружить с помощью свойства offsetParent). Для большинства элементов без строго заданного расположения эти значения соответствуют значениям свойств clientx и clientY, поскольку смещение элемента относительно его родительского элемента— body— нулевое. Примите к сведению также, что в WinIE4 и Мас1Е5 свойства х и у допускают смещение только относительно body. Даже в IE5+ для Windows в некоторых случаях это свойство может выдавать ложные значения. В целом этими двумя свойствами пользоваться не стоит. Следующий набор координат, clientx и clientY, относится к видимой части окна браузера. Если документ прокручивается до конца в пределах окна (или не прокручивается вообще), эти координаты будут такими же, что и у всей страницы. Но из-за того, что страни- ца может прокручиваться “за” видимую часть окна, координаты страницы могут изменяться. В IE для Windows можно регистрировать события мыши на расстоянии двух пикселей за пре- делами элемента body. Таким образом, в WinlE щелчок мышью на фоне элемента body за- пустит событие для элемента body, но значения clientX/clientY будут на два пикселя больше, чем of f setX/of f setY (в MacIE они равны). Несмотря на эти небольшие расхожде- ния, на описываемые свойства можно положиться, задавая координаты для события, которое определяется для позиционируемого элемента. Но лучше, чтобы эти координаты были привяза- ны ко всему доступному для обзора окну, чем просто к позиционируемому содержимому. Обычно очень важно при работе с координатами принять во внимание возможность про- крутки. Не создав для пользователя окна с фиксированными размерами, вы не сможете уга- дать, как это окно будет заполнено данными. Если вы собираетесь обрабатывать щелчок мы- шью на специальном месте страницы, то необходимо принять во внимание возможность прокрутки. Фактор прокрутки может быть получен из свойств document .body. scrollLeft и document .body. scrollTop. Работая co свойствами clientx и clientY, убедитесь, добавлены ли соответствующие координаты прокрутки. var coordX = event.clientx + document.body.scrollLeft; var coordY = event.clientY + document.body.scrollTop; Наконец, свойства screenX, screenY возвращают координаты места события в пиксе- лях относительно всего экрана. Это свойство может быть полезно, если IE предоставляет до- полнительные свойства размеров окна. По причине того, что события мыши запускаются только в том случае, когда указатель находится в пределах окна браузера, вы не получите значения за пределами обозначенной области. Если это объяснение вам кажется несколько туманным, не отчаивайтесь. Добавьте в любой программный продукт несколько ошибок — и вы получите полнейшую неразбериху. Но заду- майтесь над тем, как вы можете использовать координаты места событий в сценариях. Как пра- вило, вам необходимо знать одну из двух координат события: в самом элементе и на странице. Воспользуйтесь of f setX/of f setY в первом случае и clientX/clientY — во втором. Глава 25. Объекты событий 777
Как известно, свойства координат используются, в основном, для событий мыши. Суще- ствует небольшая уловка, позволяющая определить, каким образом пользователь изменил размер окна: с помощью кнопки в строке заголовка окна или потянув за правый нижний угол окна. Координаты указателя в момент возникновения события мыши записываются в объект event для события resize. При использовании кнопки разворачивания окна в строке заго- ловка свойство clientY принимает отрицательное значение (кнопка располагается над ра- бочей областью окна), a cl ientx — имеет значение на 45 пикселей больше исходной шири- ны окна (document.body.clientwidth). Значения свойств, конечно же, назначаются после изменения размера окна. Пример В листинге 25.14 приведен пример чтения всех “координатных” свойств: clientX, clientY, of f setx, offsetY, screenX, screenY, x, у. Реакция на все события задается в обработ- чике onmousedown. Пощелкайте на странице, чтобы увидеть результат выполнения обработчика. Изображение располагается в элементе div, чтобы продемонстрировать, что же происходит с отдельными свойствами, когда событие нацелено на позиционируемый элемент. i ^стмиг 2&-.1 Я. еьойстм, смймйме a WJ+ <html> <head> <title>X and Y Event Properties (IE4+ Syntax)</title> <script type="text/javascript"> function checkCoords(evt) { evt = (evt) ? evt : ((window.event) ? window.event : null); if (evt) { . var elem = (evt.target) ? evt.target : evt.srcElement; var form = document.forms[0] ; form.srcElemTag.value = "<" + elem.tagName + ">"; form.clientCoords.value = evt.clientX + + evt.clientY; if (typeof document.body.scrollLeft != "undefined") { form.pageCoords.value = (evt.clientX + document.body.scrollLeft) + "," + (evt.clientY + document.body.scrollTop); } form.offsetCoords.value = evt.offsetx + "," + evt.offsetY; form.screenCoords.value = 'evt.screenX + "," + evt.screenY; f orm. xyCoords. value = evt .-x + + evt.y; if (elem.offsetParent) { form.parElem.value = "<" + elem.offsetParent.tagName + " > " • } return false } } function handlesize(evt) { evt = (evt) ? evt : ((window.event) ? window.event : null); if (evt) { document.forms[0].resizeCoords.value = evt.clientX + "," + evt.clientY; } } </Script> </head> <body onmousedown="checkCoords(event)" onresize = 7П Часть III. Объекты документа
"handlesize(event)"> chl>X and Y Event Properties (IE4+ Syntax)</hl> chr /> cp>Click on any element to see the coordinate values for the event object.c/p> cform name="output"> <table> <tr> <td colspan="2">!E Mouse Event Coordinates:c/td> c/tr> <tr> <td align="right">srcElement:</td> ctdxinput type="text" name="srcElemTag" size="10" /> </td> </tr> <tr> <td align="right">clientX, clientY:c/td> ctdxinput type="text" name="clientCoords" size="10" /x/td> ctd align="right">...With scrolling:</td> ctdxinput type="text" name="pageCoords" size="10" />c/td> c/tr> ctr> ctd align="right">offsetX, of fsetY:c/td> ctdxinput type="text" name="offsetCoords" size="10" />c/td> c/tr> ctr> ctd align="right">screenX, screenY:c/td> ctdxinput type="text" name="screenCoords" size="10" />c/td> c/tr> ctr> ctd align="right">x, y:c/td> ctdxinput type="text" name="xyCoords" size="10" /> c/td> ctd align="right..Relative to:c/td> ctdxinput type="text" name="parElem" size="10" /> c/td> c/tr> ctr> ctd align="right"xinput type="button" value="Click Here" /x/td> </tr> ctr> ctd colspan="2"xhr />c/td> c/tr> <tr> ctd colspan="2">Window Resize Coordinates:c/td> c/tr> ctr> ctd align="right">clientX, clientY:c/td> ctdxinput type="text" name="resizeCoords" size="10" />c/td> c/tr> c/table> c/form> cdiv id="display" style="position:relative; left:100"> Глава 25. Объекты событий 779
<img alt="image" src="nile.gif" width="320" height="240" border="0" /> </div> </body> </html> Чтобы лучше понять взаимосвязь между “координатными” свойствами, с помощью доку- мента, представленного листингом 25.14, выполните следующие задачи. 1. Щелкните на точке над буквой i в кнопке Click Label. Целевой элемент в данном слу- чае представлен объектом input (кнопка), свойство которого offsetParent уста- новлено равным элементу ячейки таблицы. Значение свойства of f setY небольшое, поскольку указатель располагается совсем рядом с началом отсчета системы коорди- нат элемента. Клиентские координаты (а также х и у) связаны, тем не менее, с види- мой областью документа. Если окно браузера максимально расширено, то свойства screenX и clientx равны. Разница между свойствами screenY и clipntY равна расстоянию, на которое документ прокручен в окне браузера. Если документ вообще не прокручивать, то указанные пары свойств всегда будут равны. 2. Ознакомьтесь с приведенными в документах значениями свойств, а затем слегка про- крутите документ (щелчок на полосе прокрутки приведет к возникновению события). Далее снова щелкните на точке, расположенной на кнопке. Свойство cl ientY умень- шилось, поскольку при прокрутке вниз расстояние между кнопкой и верхним краем отображаемой в окне части документа стало меньше. Все offset-свойства в Windows продолжают рассчитываться правильно — во внутренней системе координат элемен- та. В Мас, тем не менее, для их получения из глобальных координат вычитается про- крученное расстояние. 3. Щелкните на большом изображении. Клиентские свойства (как и screen-свойства в Windows и Мас) вычисляются весьма точно. Но в Windows свойства х и у возвра- щают координаты события относительно значения свойства offsetParent элемента img, который помещен в элемент div. Обратите внимание, что браузер рассматривает элемент div как начинающийся на 10 пикселей левее от левого края изображения. В WinIE5.5 вы можете щелкнуть в пределах этих 10 прозрачных пикселей, чтобы вы- звать событие элемента div. Это поле учитывается автоматически, что отражается в значениях свойств х и у. Все сказанное выше в полной мере справедливо и для МасЕ, но до тех пор, пока страница не начнет прокручиваться. 4. Щелкните на верхнем элементе hr под заголовком. На это у вас может уйти некоторое время. Убедитесь, что клиентская система координат изменилась (в Мас это справед- .ливо только до прокрутки документа). Щелкните в левой части разделителя, чтобы найти начало отсчета внутренней системы координат элемента. Если вы пользуетесь Windows, то можете ознакомиться с неожиданным проявлением “координатных” свойств. 1. Не прокручивая страницу, шелкните в произвольном месте правой части страницы (вдалеке от текста, чтобы элемент body был представлен объектом srcElement). Поскольку теоретически элемент body занимает всю площадь окна браузера, то все пары координатных свойств должны быть равны, за исключением свойств screen. Вы заметите, что свойства offset на 2 пикселя меньше остальных свойств. В большин- стве случаев эта разница особо не повлияет на результаты выполнения сценариев, но ее нужно учесть при отладке сложных приложений. По неизвестной мне причине, система 780 Часть III. Объекты документа
координат для свойств offset смещена на 2 пикселя вправо и вниз относительно ле- вого верхнего угла окна браузера. В Мас эта ошибка никак не проявляется. 2. Щелкните на тексте элементов hl и р (над и под горизонтальным разделителем в верхней части документа). Теоретически свойства offset должны измеряться в системе координат самих элементов. Вместо этого они измеряются в той же системе координат, что и клиентские свойства (плюс 2 пикселя). Это поведение никак не связано с установ- кой текстового курсора в элементах. В Мас подобного поведения не наблюдается. Многие описанные выше свойства представлены в W3C DOM, а потому поддерживаются браузерами этой спецификации. Неподдерживаемые свойства в W3C-6pay3epax принимают значения undefined. Вы можете ознакомиться с другими примерами “координатных” свойств в главе 39, в ко- торой описываются методы перетаскивания элементов. См. также: свойства f romElement, toElement. dataTransfer Значение: объект Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Свойство dataTransfer является ссылкой на объект dataTransfer (только в WinlE). Можно использовать этот объект в операциях перетаскивания не только для контроля передачи данных, но и для определения формы указателя мыши во время выполнения этих действий. Табл. 25.6 предоставляет список свойств и методов объекта dataTransfer. Таблица 25.6. Qmcwfciiiiimini Свойство/метод ^ип B03BPau*aeM0r0 Описание значения dropEf feet string (строка) Элемент, являющийся потенциальным приемником отдельного действия, может использовать обработчики событий ondragenter, ondragover или ondrop, ДЛЯ установки типа указателя, отображенного поверх элемента. Прежде, чем это сможет работать, обработчик события ondragstart элемента источника должен задать значение свойства eventEf f ectAilowed. Возможные строковые значения для обоих свойств — copy, link, move или none. Эти значения соответствуют системным указателям Windows, которые обычно используются при управлении файлами или документами. Следует также отметить действие по умолчанию (речь идет об установке свойства event.ReturnValue в значение false) для всех обработчиков события: ondragenter, ondragover И ondrop eff ectAilowed string (строка) Вызывается как реакция на событие dragstart элемента источника. Это свойство определяет тип действия перетаскивания, которое будет происходить, сору, 1 ink, move или none — это возможные строковые значения. Значение должно соответствовать значению свойства dropEf feet объекта event целевого элемента и отменять действия по умолчанию (речь идет об установке свойства event. Returnvalue В значение false) в обработчике события ondragstart Глава 25. Объекты событий 781
Окончание табл. 25.5 Свойство/метод Тип возвращаемого значения Описание clearData ( [формат] ) нет Переносит данные в буфер обмена. Если данные не имеют форматирования, все они будут уничтожены. Форматирование данных задается одним или несколькими следующими значениями: Text, URL, File, HTML, image getData (формат) string (строка) Восстанавливает (извлекает) данные указанного формата из буфера обмена. Формат представлен одним из значений: Text, URL, File, HTML, Image. Буфер обмена не освобождается после извлечения данных, поэтому его можно использован в нескольких последовательных операциях setData (формат, данные) Boolean (булев) Поставляет данные строки в буфер обмена. Формат — это одно из следующих значений: Text, url, File, html, image. Для нетекстовых форматов данные представлены строкой, которая определяет путь или URL содержимого. Возвращение значения true возникает в случаях, если передача в буфер обмена проведена успешно Объект dataTransf er действует как проводник и контролер данных, которые сценарии передают при перетаскивании пользователем объекта от одного элемента к другому. Следует придерживаться четкой последовательности действий, запущенных группой обработчиков событий. Это означает, что объект event вызывается при возникновения любого события перетаскивания как отдельный экземпляр. Последовательность начинается в элементе источника, где обработчик события ondragstart обычно задает значение свойства dropEf feet. Метод getData () используется для фикса- ции данных объекта источника, которые перемещаются к конечной цели. Например, при пе- ретаскивании изображения может перемещаться его URL — данные, извлекаемые свойством event. srcElement. src данного события (src — это свойство изображения). В целевом элементе/элементах присутствует три обработчика события: ondragenter, ondragover и ondrop. Как правило, первые два из них выполняют лишь подготовку элемента непосредственно для события dropEf feet (должно соответствовать ef fectAllowed в эле- менте источнике перед началом перетаскивания) и задают свойство event. returnValue равным false, чтобы указатель соответствовал необходимым требованиям. Эти задачи так- же выполняются в ondrop; кроме них, он также обрабатывает действия, заданные для целе- вого элемента при вызове метода getData О объекта dataTransf er для приобретения данных, “сохраненных” getData () в начале перетаскивания. Убедиться, что данные слу- чайно не вызываются другим событием, можно, используя метод clearData О для удале- ния их из памяти. Заметьте, что Tjm перетаскивания, описываемый в данном случае, не характерен для эле- мента, перетаскиваемого на экране (хотя можно создать сценарий и таким образом). Целью является обработка операции перетаскивания таким же образом, как это осуществляется в окне программы Windows Explorer. Для пользователя перетаскивание связано с указателем мыши. Именно поэтому свойство dataTransf er объекта обеспечивает появление курсора в точке отпускания содержимого, что является способом передачи потребителю типа дейст- вия, которое произойдет в конечном счете. 782 Часть III. Объекты документа
Пример Детальный пример использования свойства dataTransfer на практике можно найти в листинге 15.37 в разделе, в котором описан обработчик события ondrag. См. также: обработчики события ondragend, ondragenter, ondragleave, ondragover, ondragstart, ondrop. fromElement toElement Значение: объект элемента Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойства fromElement и toElement позволяют элементу установить, где указатель появился или исчез. Эти свойства расширяют область действия обработчиков события onmouseover и onmouseout, увеличивая ее с внешней стороной текущего элемента (обычно соседним элементом). Когда для элемента запускается обработчик события onmouseover, указатель еще рас- полагается на другом элементе, а свойство fromElement задает ссылку на этот элемент. На- оборот, когда возникает событие onmouseout, указатель уже располагается на другом эле- менте, а свойство toElement задает на него ссылку. Пример , В листинге 25.15 приведен пример использования свойств fromElement, toElement. При наведении указателя на центральную ячейку в строке состояния указывается текст ячей- ки, с которого переместился указатель. ; Листинг ..25.15 pwAcn fwnt и toBieaaot <html> <head> <title>fromElement and toElement Properties</title> <style type="text/css"> .direction {backgrQund-color:#OOFFFF; width:100; height:50; text-align:center} #main {background-color:#FF6666; text-align:center} </style> <script type="text/javascript"> function showArrival() { var direction = (event.fromElement.innerText) ? event.fromElement.innerText : "parts unknown"; status = "Arrived from: " + direction; } function showDeparture() { var direction = (event.toElement.innerText) ? event.toElement.innerText : "parts unknown"; status = "Departed to: " + direction; } </script> </head> <body> <hl>fromElement and toElement Properties</hl> <hr /> Глава 25. Объекты событий 783
<p>Roll the mouse to the center box and look for arrival information in the status bar. Roll the mouse away from the center box and look for departure information in the status bar.</p> ctable cellspacing="O” cellpadding="5"> <tr> <tdx/td> <td class="direction">North</td> <tdx/tdx/tr> <tr> <td class="direction">West</td> <td id="main" onmouseover="showArrival()" onmouseout="showDeparture()">Roll</td> <td class="direction">East</td> </tr> <tr> <tdx/td> <td class="direction">South</td> <tdx/td> </tr> </table> </body> </html> Это весьма полезный пример, поскольку он выявляет потенциальные ограничения, заданные в браузере. Элементы, представленные свойствами fromElement и toElement, должны ге- нерировать события мыши, чтобы быть зарегистрированными. Каждый следующий элемент в последовательности в обязательном порядке представлен одним из этих свойств. Например, если вы наведете указатель на центральную ячейку, а затем быстро сведете его в нижнюю часть окна, то нижняя ячейка может не успеть зарегистрироваться в браузере. Таким образом, текст в строке состояния будет представлен содержимым элемента body, т.е. элементом, который воспринял событие мыши, зарегистрированное свойством toElement для центральной ячейки. См. также: свойство srcElement. keyCode Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Для событий клавиатуры свойство keyCode возвращает целые числа, соответствующие значению кодов символов в системе Unicode (для событий keypress) или клавиш на кла- виатуре (для событий keydown и keyup). Эти системы кодирования символов существенно отличаются друг от друга. Значения кода Unicode (такие же, как значения ASCII для латинского набора символов) нажатой пользователем клавиши можно узнать, используя свойство KeyCode обработчика события onkeypress. Например, а в нижнем регистре возвращает 97, в то время как в верхнем регистре А возвращает 65. Небуквенные символы (стрелки, символы цифровой кла- виатуры, функциональные знаки) в обработчике событий onkeypress для свойства keyCode возвращают значение null. Другими словами, свойство keyCode для событий keypress — это, скорее, код буквы, чем код клавиши. Чтобы фиксировать клавишу на клавиатуре, нажи- маемую пользователем, используются обработчики события onkeydown или onkeyup. Для них объект event определяет числовой код, связанный с определенной клавишей клавиату- ры. Для клавиш букв он определяется используемым языком, назначенным в качестве сис- темного. Важно, что никакого различия между верхним и нижним регистрами клавиш букв 784 Часть III. Объекты документа
теперь нет. Клавиша А в режиме латинского языка возвращает значение 65, независимо от состояния клавиши <Shift>. В то же время, однако, нажатие клавиши <Shift> генерирует ее собственные события onkeydown и onkeyup, задающие значение keyCode. Другие небук- венные символы — стрелки, символы цифровой клавиатуры, функциональные знаки и т.д. — также имеют свои собственные коды. Все они детализированы (включая специальные коды клавиш цифровой клавиатуры, которые отличаются от соответствующих им чисел верхней строки алфавитно-цифровой клавиатуры). Вы можете ознакомиться с детальным описанием событий клавиатуры в главе 15, а с приме- рами применения свойства keyCode — в соответствующих приложениях. Пример Листинг 25.16 предоставляет вам возможность детально изучить свойство keyCode для всех трех событий клавиатуры при вводе текста в область textarea. Впоследствии вы смо- жете использовать эту страницу для получения кодов клавиш. 4? И)- ' - 4- Яисгинг 25.16. Отображение кодоь клмвви » chtml> <head> <title>keyCode Propertyc/title> <style type="text/css"> td {text-align:center} </style> <script type="text/javascript"> function showCode(which) { document.forms[0].elements[which].value = event.keyCode function clearEmO { for (var i = 1; i < document.forms[0].elements.length; i++) { document.forms [0] .elements [i] .value = " 11 } } </script> </head> <body> <hl>keyCode Property*:/hl > chr /> <form> cpxtextarea name="scratchpad" cols="40" rows="5" wrap="hard" onkeydown="clearEm(); showCode(1 down’)" onkeyup="showCode('up1)" onkeypress="showCode('press')">c/textarea>c/p> ctable cellpadding="5"> <tr> <th>Eventc/th> <th>event.keyCode</th> </tr> ctr> <td>onKeyDown:</td> ctdxinput type="text" name="down" size="3" /x/td> c/tr> ctr> ctd>onKeyPress:c/td> ctdxinput type="text" name="press" size="3" />c/td> c/tr> Глава 25. Объекты событий 785
<td>onKeyUp:</td> ctdxinput type="text" name="up" size="3" /></td> </tr> </table> </form> </body> </html> Ниже описаны специальные задачи, которые решаются с помощью документа, представ- ленного листингом 25.16. Если вы используете кодировку, отличную от English или Latin, то получите совершенно другой результат. 1. Введите символ а в нижнем регистре. Обработчик onkeypress отображает код 97. Это значение представляет код Unicode (и ASCII) первой буквы нижнего регистра ла- тинского алфавита. Два других обработчика отображают код 65. 2. Введите символ А в верхнем регистре. Если вы были внимательны, то знаете, что кла- виша <Shift> представлена кодом 16 (в событиях onkeydowm и onkeyup). Но для всех трех событий в данном случае отображаются значения 65, поскольку ASCII-код символа в верхнем регистре совпадает с кодом символа для этой буквы. 3. Нажмите и отпустите клавишу со стрелкой “вниз” (убедитесь, что текстовый курсор все еще находится в текстовой области, иначе события клавиатуры не будут регистри- роваться). Поскольку эта клавиша не представляет символ, то событие onkeypress не генерируется. Остальные события возникают и возвращают код 40. 4. Понажимайте другие несимвольные клавиши. Некоторые из них выводят на экран диалоговые окна и меню, поэтому их коды (если таковые отображаются) вам мало пригодятся. Обратите внимание, что в Windows и Мас коды символов далеко не всегда одинаковы. См. также: обработчики события onkeydown, onkeypress, onkeyup. nextPage Значение: строка Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Свойство nextPage применяется в том случае, если документ в WinIE5.5 использует поведение Templateprinter. К значениям этого свойства относятся следующие: left, right или пустая строка. Чтобы получить дополнительную информацию о поведении TemplatePrinter в WinIE5.5 посетите узел http://msdn.microsoft.com/workshop/browser/hosting/printpreview/ reference/ behaviors/TemplatePrinter.asp propertyName Значение: строка Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Свойство propertyName принимает значение только после возникновения события onpropertychange. Если сценарий изменяет свойство, запускается обработчик события onpropertychange, а строчное значение свойства сохраняется в свойстве event.propertyName. Если это 786 Часть III. Объекты документа
свойство оказывается принадлежащим объекту style, связанному с элементом, то свойство propertyName— это полная ссылка на определенное свойство, например style.back- groundColor. Пример В листинге 15.46 описан обработчик события onpropertychange, который представля- ет пример значений, возвращаемых этим свойством. См. также: обработчик события onpropertychange (глава 15) repeat Значение: булево Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Свойство repeat задается для события onkeydown только тогда, когда клавиша нахо- дится в режиме повторного нажатия (как определено параметрами настройки папки Панель управления для клавиатуры). Благодаря этой информации, можно предотвратить автоматиче- ское повторное введение символов, распознаваемых браузером. Это свойство можно вызвать вручную, если удерживать клавишу нажатой слишком долго. Следующий фрагмент сценария — обработчик события onkeydown для текстового поля или объекта textarea; он предот- вращает появление различных символов, даже если система работает в режиме повтора. if (event.repeat) { Event.returnValue = false; } Отключите действие по умолчанию во время работы в режиме повтора, и вы не допустите повторного появления символов в текстовом поле до отключения режима (нажатия другой клавиши). Эго свойство не предназначено для Мас1Е5. См. также: обработчик события onkeydown. returnValue Значение: булево Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Если IE4+ продолжает следовать первоначальному способу предотвращения действия по умолчанию для обработчика события (т.е. задает в качестве последнего оператора обработ- чика события выражение return false), то модель событий IE4+ предоставляет свойство, которое позволяет аннулировать действие по умоЛчанию, полностью происходящее в преде- лах функции, вызванной обработчиком события. По умолчанию свойство returnValue объекта event имеет значение true. Это означает, что элемент обрабатывает событие после того, как запрограммированный обработчик завершает выполнение всех задач (так, если бы сценария не было вообще). Обычная обработка (по умолчанию), например, приводит к ото- бражению введенного символа, перемешению по ссылке href после щелчка на ней или пе- редаче данных формы после щелчка на кнопке Submit. Но не всегда необходимо, чтобы действие по умолчанию произошло. Например, в тексто- вом поле предполагается вводить только числа. Обработчик события onkeypress может вызвать функцию, рассматривающую каждый введенный символ. Если символ — не цифра, то он не достигает текстового поля. Подобная функция проверки правильности данных может вызываться обработчиком события onkeypress только этого текстового поля. function checklt () j var charCode = event.keyCode; if (charCode <48 || charCode >57) { Глава 25. Объекты событий 787
alert ("Please make sure entries are numerals only."); event.returnvalue = false; } Используйте этот обработчик события, и вы не допустите появления ошибочного символа в текстовом поле. Заметьте, что это свойство — не заменитель выражения return в функции обработчика. Если необходимо, возвращаемое значение можно использовать, применив оператор return в дополнение к определению значений свойств event. returnvalue. Пример Вы найдете несколько примеров использования свойства returnvalue в главе 15. Вни- мательно изучите листинги 15.30, 15.33, 15.36, 15.37, 15.38 и 15.45. См. также: оператор/выражение return. saveType Значение: строка Только для чтения Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Свойство saveType приобретает значение только тогда, когда событие oncontentsave привязывается к поведению WinlE, определяемому DHTML, (. htc). Для получения дополни- тельной информации о поведениях посетите узел по адресу http: / /msdn. microsof t. com/ workshop/author/behaviors/overview.asp См. также: метод addBehavior (). srcElement Значение: ссылка на объект элемента Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство srcElement — это ссылка на элемент объекта HTML, который является целью исходного события. Событие может проходить через иерархическую структуру объектов и обрабатываться на любом уровне. Поэтому оно имеет свойство, указывающее на элемент, который инициировал событие. Когда ссылка на этот элемент задана, можно получить, а также изменить любое его свойство или вызвать любые его методы. Пример В качестве простейшего примера возможностей свойства srcElement я привел лис- тинг 25.17. В нем в элементе body настроено два обработчика события, каждый из кото- рых вызывает отдельную функцию. Идея сценария очень проста: события onmousedown и onmouseup всплывают независимо от целевого элемента, а функции определяют послед- ние и изменяют их цвет стиля. В каждой функции проверяется свойство className целевого элемента. Если это свой- ство имеет значение bold (имя класса общее для всех трех элементов span абзаца), то пра- вило таблицы стилей для этого класса изменяется. В собственных сценариях вы можете за- дать более сложные операции форматирования документа Обратите внимание на то, что сценарий может ничего не "знать” об объектах страницы, чтобы правильно обратиться к ним. Причина состоит в том, что свойство srcElement пре- доставляет всю необходимую информацию о целевом элементе. 788 Часть III. Объекты документа
Листинг 25.17. Использование свойства srcKl «Rent «html> <head> «title>srcElement Property</title> «style type="text/css"> .bold {font-weight:bold} .ital {font-style:italic} </style> «script type="text/javascript"> function highlight() { var elem = event.srcElement; if (elem,className == "bold") { document.styleSheets[0].rules[0].style.color = "red"; } else { elem.style.color = "flFFCCOO"; function restore() { var elem = event.srcElement; if (elem.className == "bold") { document.styleSheets[0].rules[0].style.color = } else { elem.style.color = ""; </script> </head> «body onmousedown="highlight()" onmouseup="restore()"> «hl>srcElement Property«/hl> «hr /> «p>One event handler...</p> «ul> «li>Can«/li> «li>Cover«/li> «li>Many«/li> «li>Objects«/li> «/ul> «p>Lorem ipsum dolor sit amet, consectetaur adipisicing elit, «span class="bold">sed do«/span> eiusmod temper incididunt «span class="ital">ut labore et«/span> dolore magna aliqua. Ut enim adminim veniam, «span class="bold">quis nostrud exercitation«/span> ullamco laboris nisi ut aliquip ex ea «span class="bold">commodo consequat«/span>.«/p> «/body> </html> См. также: свойства f romElement, toElement. srcFilter Значение: строка Только для чтения Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Согласно концепции Microsoft, свойство srcFilter должно возвращать строку с име- нем фильтра, который был применен для вызова обработчика события onf i Iter change. Если свойство существует в объекте event, его значение всегда null, по крайней мере в IE6. См. также: обработчик события onf ilterchange; объект style. filter. Глава 25. Объекты событий 789
srcUrn Значение: строка Только для чтения Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Если событие используется в WinlE при подключении к элементу поведения, для которого определен идентификатор URN, свойство srcUrn возвращает строку с URN-идентификато- ром. Для получения дополнительной информации о поведениях посетите узел http://msdn.microsoft.com/workshop/author/behaviors/overview.asp См. также: метод addBehavior (). toElement Cm. fromElement type Значение: строка Только для чтения Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Всегда можно выяснять, какое событие запускается при создании объекта event с помо- щью свойства type. Его значение — строковая версия имени события, только без префикса on, который обычно ассоциируется с именем обработчика события в IE. Это свойство приме- няется для определения одного обработчика события в качестве функции обработки различ- ных видов событий. Например, и onmousedown, и onclick — обработчики события для объекта; они вызывают одну функцию. Внутри функции задано ветвление в зависимости от способа ее вызова (mousedown или click) и события, которое генерируется. Вам не обяза- тельно использовать подобные обработчики, но знать о возможности совместного использо- вания функции просто необходимо. Данное свойство и его значения полностью совместимы с моделями событий NN4 и NN6+/W3C. Пример Используйте приложение The Evaluator для ознакомления со значениями, которые воз- вращаются свойством type. Введите следующее имя объекта в нижнее текстовое поле и на- жмите <Entei>. event Если необходимо, прокрутите область Results, чтобы найти свойство type, имеющее значение keypress. Щелкните на кнопке List Properties. Значение свойства type изме- нится на click. Причина такого “поведения” приложения очень проста. Объект event, свойства которого мы определяем, представляет событие, которое запускает функцию отобра- жения свойств. В текстовой области это обработчик onkeypress, а у кнопки — onclick. См. также: все обработчики события (глава 15). Объект события в NN6+ Свойства события Методы Обработчики события altKey bubbles initEvent()* initKeyEvent()* 790 Часть III. Объекты документа
Окончание таблицы Свойства события Методы Обработчики события button cancelBubble cancelable charCode clientX clientY ctrlKey currentTarget detail eventphase isChar keyCode layerX layerY metaKey originalTarget pageX pageY relatedTarget screenX initMouseEvent()* initMutationEvent()* initUIEvent()* preventDefault() stopPropagation() screenY shiftKey target timestamp type view Синтаксис Доступ к свойствам и методам объекта события в NN6+. объектСобытия. свойство I метод( [параметры] ) Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Описание объекта Несмотря на то, что данный объект базируется в значительной мере на объекте события, определенном в W3C DOM 2, объект события NN6+/Moz также имеет некоторые характери- стики, присущие его версии в NN4. Ряд свойств добавлен прежде всего для обеспечения со- вместимости. Поскольку разработки для NN6, скорее всего, будут игнорировать особенности Глава 25. Объекты событий 791
NN4 DOM и ее модель событий, то использовать их на практике следует чрезвычайно осто- рожно (см. ниже). Везде, где возможно, используйте и поддерживайте положения модели со- бытий W3C DOM. Подобно IE4+, модель событий NN6+ обеспечивает разработчика всплывающими собы- тиями, однако несовместимость ссылок на объекты в обработчиках событий все еще присут- ствует. В W3C (как в NN4) объект события явно передается как параметр функции обработ- чика (или, скорее, приемника) события. Но после назначения специфичного для браузера объекта события, определенного как переменная внутри функции, несколько свойств приоб- ретают одинаковые имена в моделях событий IE4 + и NN6+. Если Microsoft в своих будущих разработках обратит больше внимания на модели обработки событий в W3C DOM, то со- вместимость IE4+ с другими браузерами только улучшиться. Объект события, описываемый в этом разделе, — экземпляр события, который получен в результате действий пользователя или системы. NN6 DOM включает дополнительный ста- тический объект Event. Многие свойства статического объекта Event наследуются экземп- ляром события, поэтому детальное описание этих свойств также будет приведено в настоя- щем разделе (именно этот объект события используется для написания сценариев). Во многих фрагментах кодов в следующих подразделах, будут присутствовать ссылки, ко- торые начинаются с evt. Это предполагает, что оператор или операторы, заданные внутри функции, оперируют объектом события в виде переменной evt. function myFunction (evt) {...} Как отмечалось ранее в этой главе, ссылки на объекты событий в NN6 и IE4+ с помощью этого метода можно сделать одинаковыми, так как спенарии управляют идентичными (или по- добными) свойствами объекта события. Свойства altKey ctrlKey metaKey shiftKey Значение: булево Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Когда объект события создается в ответ на действие пользователя или системы, эти четы- ре свойства вызываются в зависимости от того, удерживались ли соответствующие клавиши- модификаторы в момент щелчка. Если клавиша удерживалась, свойству присваивается значе- ние true; иначе — значение false. Свойство metaKey соответствует клавише <Command> клавиатуры Macintosh, но не соответствует ни одной клавише в системе Windows. Обычно выражения, содержащие это свойства, используются в условной конструкции if. Поскольку им присвоен булев тип данных, различные свойства можно комбинировать в отдель- ном условии. Например, при ветвлении функции, которая выполняется, если событию щелчка предшествует нажатие клавиш <Shift> и <Ctrl>, условия будут выглядеть следующим образом. if (evt.shiftKey && evt. ctrlKey) { // выполняемые операторы } Наоборот, можно избрать более удобный для пользователей метод для указания варианта действия в случае использования одной из четырех клавиш-модификаторов. 792 Часть III. Объекты документа
if (evt.shiftKey || evt.ctrlKey || evt.metaKey || evt.altKey) { // выполняемые операторы } Цель этого метода — предоставить возможность быстро выполнить необходимое дейст- вие, а не заставить вас запомнить названий всех клавищ-модификаторов. Пример В листинге 25.10 значения этих свойств используются при задании свойства checked со- ответствующих флажков для событий самых разных типов. bubbles Значение: булево Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ He каждое событие является всплывающим. Например, событие submit не распростра- няется далее объекта формы, с которым связано событие. События, не являющиеся всплы- вающими, имеют свойство bubbles объекта события, равное false. Все другие объекты событий имеют свойства bubbles, равные true. Используйте это свойство в редких случа- ях, когда обработчик события управляет огромным количеством событий. Для всплывающих событий можно выполнить один набор действий, а все остальные обрабатывать в каждом от- дельном случае по-разному. Для реализации этого подхода необходимо использовать конструкцию if в качестве ус- ловного оператора. if (evt.bubbles) { // специальная обработка всплывающего события } Нет необходимости задавать ветвление только для отмены всплывания. Нераспростра- няемые события не вступят в конфликт с браузером, если запретить им распространяться. См. также: свойство cancelBubble. button Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство button определяет кнопку, которая была нажата при инициализации события мыши. Левая (основная) кнопка возвращает значение 1. Если мышь трехкнопочная, средняя кнопка возвращает 2. Правая кнопка (любой многоклавишной мыши) возвращает значение 3. Заметьте, что эти значения отличаются от сформулированных в W3C DOM (0, 1 и 2, соответ- ственно), но они обратно совместимы со свойством which в NN4. " Кнопки мыши, отличные от основной (первой), проще обрабатывать в событиях mousedown или mouseup, чем в click. В случае нажатия пользователем нескольких кно- пок учитываться будет значение только самой последней. Будьте осторожны при создании сценариев с использованием свойства button в IE4+ и NN6+. Соответствующие модели событий определяют различные значения для кнопок мыши. Пример В листинге 25.11 значение свойства button отображается в строке состояния. Щелкните разными кнопками мыши на графической кнопке на экране, чтобы увидеть результат. Глава 25. Объекты событий 793
cancelBubble Значение: булево Чтение/Запись Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ Свойство cancelBubble является недоработанным образцом свойства события IE4+, реа- лизованного в NN6+/Moz/Safari, даже при том, что оно не определено в W3C DOM. Свойство функционирует так же, как и в IE4+, в котором определяет, будет ли объект текущего события всплывать выше в иерархии объектов документа. По умолчанию это свойство имеет значение false; если событие способно к всплыванию, то эта операция выполняется автоматически. - Чтобы не допустить всплывания текущего события, задайте в пределах функции обработ- чика события значение true. Альтернативным решением может быть отмена всплывания непосредственно в атрибуте обработчика события элемента. onclick = "doButtonClick (this); event.cancelBubble = true" Отмена всплывания события выполняется только для текущего события. Следующее иниции- рованное событие будет по умолчанию способно к всплыванию (имеет свойство всплывания). Если вам необходимо в максимально возможной степени совместить ваш код с поддерживае- мым в W3C DOM, то используйте метод stopPropagation (), а не свойство cancelBubble. Для обеспечения совместимости браузеров предпочтительнее использовать cancelBubble. Пример В листинге 25.6 можно увидеть свойство cancelBubble в действии в среде IE. Даже при том, что листинг представляет код со специфичными для IE5.5+ операторами, демонстрация отмены всплывания выполняется и в IE4. См. также: метод stopPropagation (). cancelable Значение: булево Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Если событие отменяемое, то его поведение по умолчанию может быть изменено с помощью сценария. Большинство событий являются отменяемыми, однако некоторые из них — все еще нет. Свойство отмены события позволяет запрашивать сведения о специфическом событии, чтобы убе- диться, присутствует ли у объекта свойство cancelable. Значения свойства— булевы. Вы мо- жете использовать в сценарии только отменяемые события, если необходимо обеспечить воз- можность ветвления. Для ветвления удобно использовать свойство в условной конструкции if. if (evt.cancelable) { // специальная обработка всплывающего события } Однако не обязательно выполнять ветвление только для предотвращения действий собы- тия по умолчанию. Неотменяемое событие не входит в конфликт с браузером, если для него отменить поведение по умолчанию. См. также: метод preventDefault (). charCode keyCode Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ 794 Часть III. Объекты документа
Модель событий в W3C четко различает символы Unicode, задаваемые алфавитно-цифро- вым клавишам клавиатуры, и код, определенный каждой клавише на клавиатуре (независимо от ее символа). Чтобы получить символ клавиши, сначала используйте событие onkeypress — так вы создадите объект события. Затем примените свойство charCode объекта event. Это свойство возвращает 97 для а и 65 для А, так как оно определяет символ, связанный с клави- шей. Его значение нулевое для событий onkeydown и onkeyup. Напротив, свойство keyCode при нажатии алфавитно-цифровых клавиш имеет ненулевые значения для событий onkeydown и onkeyup (для onkeypress это свойство имеет нулевое значение). Для большинства других небуквенньк символов все три события используют свойст- во keyCode. С его помощью можно получить коды небуквенных клавиш — клавиш со стрел- ками, функциональных клавиш и т.д Для буквенных клавиш верхний и нижний регистр в свой- стве не различается: клавиша А латинской раскладки клавиатуры возвращает значение 65, независимо от состояния клавиши <Shift>. Однако в это же время нажатие клавиши <Shift> ге- нерирует ее собственные события onkeydown и onkeyup, присваивающие свойству keyCode значение 16. Другие небуквенные символы также имеют свои собственные коды. Все коды кла- виш детализированы, включая специальные клавиши цифровой клавиатуры, которые отличают- ся от соответствующих им цифр в верхней строке алфавитно-цифровой клавиатуры. / Safari 1.0 не поддерживает свойство charCode. Вместо него в данном браузере /на заметку используется свойство keyCode, которое возвращает коды алфавитно-цифровых * клавиш, и не возвращает коды для остальных клавиш клавиатуры. Детальное описание событий клавиатуры приведено в специальном разделе главы 15. Там же вы узнаете об использовании свойства в приложениях. Пример В листинге 25.18 приведен пример использования свойств keyCode и charCode для трех событий клавиатуры при вводе текста в область textarea. В дальнейшем это прило- жение можно использовать в качестве справочника по кодам клавиш и символов. Листинг Z& li. Оюбра женив свойств charCode и keyCode <html> <head> <title>qharCode and keyCode Properties</title> «style type="text/css"> td {text-align:center} </style> «script type="text/javascript"> function showCode(which, evt) { document.forms[0].elements[which + "Char"].value = evt.charCode; document.forms[0].elements[which + "Key"].value = evt.keyCode; } function clearEmO { for (var i = 1; i < document.forms[0].elements.length; i++) { document:forms[0] .elements [i] .value = ""; } } </script> < /head> Глава 25. Объекты событий 795
<body> <hl>charCode and keyCode Properties</hl> chr /> <form> cpxtextarea name="scratchpad" cols="40" rows="5" wrap="hard" onkeydown="clearEm(); showCode(’down', event)" onkeyup="showCode(* 1 2 3 4up1, event)" onkeypress="showCode('press', event)"></textarea>c/p> «table cellpadding="5"> <tr> <th>Event</th> <th>event.charCodec/th> <th>event.keyCode«/th> </tr> <tr> <td>onKeyDown:</td> ctdxinput type="text" name="downChar" size="3" /x/td> ctdxinput type="text" name=”downKey" size="3" /x/td> </tr> <tr> <td>onKeyPress:</td> ctdxinput type="text" name= "pressChar" size="3" /x/td> ctdxinput type="text" name="pressKey" size="3" /x/td> </tr> ctr> <td>onKeyUp:</td> ctdxinput type="text" name="upChar" size="3" /x/td> ctdxinput type="text" name="upKey" size="3" /x/td> c/tr> </table> c/form> </body> </html> Ниже описаны специальные задачи, которые решаются с помощью документа, представ- ленного листингом 25.18, в NN6+ZMozl+. Если вы используете кодировку, отличную от Eng- lish или Latin, то получите совершенно другие результаты. 1. Введите символ а в нижнем регистре. Обработчик onkeypress отображает код 97. Это значение представляет код Unicode (и ASCII) первой буквы нижнего регистра ла- тинского алфавита. Два других обработчика отображают код 65. 2. Введите символ А в верхнем регистре. Если вы были внимательны, то знаете, что кла- виша <Shift> представлена кодом 16 (в событиях onkeydowm и onkeyup). Но для всех трех событий в данном случае отображаются значения 65, поскольку ASCII-код символа в верхнем регистре совпадает с кодом символа для этой буквы. 3. Нажмите и отпустите клавишу со стрелкой “вниз” (убедитесь, что текстовый курсор все еще находится в текстовой области, иначе события клавиатуры не будут регистри- роваться). Поскольку эта клавиша не представляет символ, то событие onkeypress не генерируется. Остальные события возникают и возвращают код 40. 4. Понажимайте другие несимвольные клавиши. Некоторые из них выводят на экран диало- говые окна и меню, поэтому их коды (если таковые отображаются) вам не пригодятся. См. также: обработчики события onkeydown, onkeypress, onkeyup. 796 Часть III. Объекты документа
clientx clientY layerX layerY pageX pageY screenX screenY Значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Объект события NN6 включает свойства координат указателя мыши как в модели NN4, так и IE4+. Для управления указателем мыши в W3C вам не требуется специальных знаний, если вы уже имеете опыт работы с другими браузерами. Подобно объекту события в IE4+, свойства clientx и clientY объекта события в W3C DOM задают координаты относительно просматриваемой области содержимого окна. Эти значения заданы для окна браузера, а не самого документа. Но, в отличие от IE4 +, вам не обязательно вычислять координаты указателя в документе, .так как другая пара свойств — pageX и pageY — предоставляет необходимую информацию автоматически. Если страница не прокручивалась, то значения для окна браузера и документа остаются одинаковыми. По- скольку координаты указателя мыши в момент возникновения события важнее знать для до- кумента, чем для окна, свойства pageX и pageY используются чаще. Другая пара свойства, layerX и layerY, происходит от уже не существующих объектов слоев NN4, которые, тем не менее, будут служить еще достаточно долго. Эти координаты за- даются относительно содержимого позиционируемого элемента, который’принимает событие. Как правило, непозиционируемые элементы-в разделе body документа более распростране- ны, чем позиционируемые. Для последних элементов значения координат относительно стра- ницы и слоя будут одинаковыми. Но при создании позиционируемого элемента координатное пространство измеряется от верхнего левого угла соответствующего объекта. Так, при ис- пользовании координат для определения расположения перетаскиваемых элементов можно задать соответствующие свойства только для позиционируемых объектов. Недостаток системы координат в NN6+/Moz — цтсутствие целевого элемента как такового (сопоставимого со свойствами offsetX и offsetY в IE4+). Эти значения, однако, могут быть вычислены путем вычитания из координат страницы значений offsetLeft и offsetTop как целевого элемента, так и его позиционируемого содержимого. Например, для получения координат указателя в событии щелчка на изображении обработчик события вычисляет необ- ходимые значения следующим образом. ' var clickOffsetXvar = evt.pageX — evt.target.offsetLeft — document.body.offsetLeft; var clickOffsetY — evt.pageY — evt.target.offsetTop — document.body.offsetTop; Последний набор свойств, screenX и screenY, предоставляет разработчику значения, соответствующие координатному пространства экрана монитора. Из всех представленных свойств только координатные пространства окна браузера и экрана монитора определены в стандарте W3C DOM 2. Помните, что в NN6 к целевым объектам события также относят текстовые узлы внутри элементов. Поскольку эти узлы не обладают всеми свойствами полноценного элемента (например, Глава 25. Объекты событий 797
они не имеют свойств смещения, отражающих их размещение в документе), то управлять ими приходится из родительского узла; именно родительский узел предоставляет все необходи- мые свойства, которые задают “геометрию” элемента страницы. Подобное решение исполь- зуется только для ситуаций, когда в сценарии необходимо обработать события, инициирован- ные щелчком на тексте. Пример Вы можете ознакомиться с “координатными” свойствами NN6+ZMoz в листинге 25.19. На странице, представленной этим листингом, отображаются значения во всех четырех системах координат. Чтобы нагляднее представить разницу между объектом на слое и объектом вне слоя, на страницу было добавлено два элемента, на которых можно щелкать. На рис. 25.1 по- казан результат щелчка на позиционируемом слое. В одном из полей указываются значения, в которых учитывается величина прокрутки до- кумента в окне. Но, как нетрудно заметить, эти значения совпадают с другими значениями (группы раде). Остальные поля представляют координаты в системе измерений, связанной с целевым элементом. Обратите внимание: если целевой элемент имеет свойство nodeType, равное text, то в вычислениях принимает участие родительский элемент текстового узла. Рис. 25.1. Координаты места щелчка в NN6+/Moz ACtMHr И.». "КммммШв” Оййстм в Wifi+/M*ry9ehirt <html> <head> <title>X and Y Event Properties (NN6+)</title> <script type="text/javascript"> function checkCoords(evt) { 798 Часть III. Объекты документа
var form = document.forms["output"]; var targText, targElem; if (evt.target.nodeType == 3) { targText = "[textnode] inside c" + evt.target.parentNode.tagName + ">"; targElem = evt.target.parentNode; } else { targText = "c" + evt.target.tagName + ">"; targElem = evt.target; } form:srcElemTag.value = targText; form.clientCoords.value = evt.clientx + "," + evt.clientY; form.clientScrollCoords.value = (evt.clientx + window.scrollX) + "," + (evt.clientY + window.scrollY); form.layerCoords.value = evt.layerX + + evt.layerY; form.pageCoords.value = evt.pageX + + evt.pageY; form.inElemCoords.value = (evt.pageX - targElem.offsetLeft - document.body.offsetLeft) + "," + (evt.pageY - targElem.offsetTop - document.body.offsetTop); form.screenCoords.value = evt.screenX + "," + evt.screenY; return false; } c/script> </head> <body onmousedown="checkCoords(event)"> chl>X and Y Event Properties (NN6+)c/hl> chr / > <p>Click on the button and in the DIV/image to see the coordinate values for the event object.c/p> «form name="output"> ctable> ctr> <td colspan="2">NN6 Mouse Event Coordinates:</td> </tr> ctr> ctd align="right">target:c/td> ctd colspan="3"xinput type="text" name="srcElemTag" size="25" />c/td> ctr> <td align="right">clientX, clientY:</td> ctdxinput type="text" name="clientCoords" size="10" /x/td> ctd align="right">...With scrolling:</td> ctdxinput type="text" name="clientScrollCoords" size="10" />c/td> c/tr> ctr> ctd align="right">layerX, layerY:c/td> ctdxinput type="text" name="layerCoords" size="10" /> c/td> c/tr> ctr> ctd align="right">pageX, pageY:c/td> ctdxinput type="text" name="pageCoords" size="10" /> c/td> ctd aligh="right">Within Element:c/td> ctdxinput type="text" name= " inElemCoords" size="10" />c/td> Глава 25. Объекты событий 799
<td align="right">screenX, screenY:</td> ctdxinput type="text" name="screenCoords" size="10" /></td> </tr> <tr> ctd align="right"xinput type="button" value="Click Here" />c/td> c/tr> c/table> c/form> cdiv id="display" style="position:relative; left:100"> cimg alt="image" src="nile.gif" width="320" height="240" border="0" /> c/div> c/body> c/html> См. также: свойство target. currentTarget Значение: ссылка на объект элемента ' Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Приемник события может обрабатывать событие в процессе всплывания, поскольку оно проходит по строго определенному пути. Так как событию известна его цель, очень часто в функции приемника события необходимо указать, какой из объектов в данный момент об- рабатывает событие. Свойство currentTarget задает ссылку на объект элемента, в кото- ром приемник события выполняется в текущий Момент. Это позволяет одной функции при- емника потенциально обработать событие на различных уровнях, разветвляя код для согласования действий на разных уровнях, обрабатывающих событие. Зачастую в подобных операциях важно знание еще одного свойства события — eventphase. Оно помогает функции приемника события определить, в каком состоянии находится собы- тие: в состоянии сбора данных, режиме всплывания или в цели. Это свойство демонстрирует- ся в одном из следующих разделов. Пример В листинге 25.20 приведен пример практического применения свойства currentTarget. С его помощью определяется элемент, обрабатывающий событие в процессе его передачи. Подобно листингу 25.7, этот пример несколько упрощен, чтобы позволить свойствам объекта event выполнить большинство операций по обработке события. Получатели событий в различ- ных режимах передачи настроены для самых различных узлов документа. После щелчка на кнопке каждый из них последовательно получает событие. В диалоговом окне отображается, ка- кой из узлов в данный момент обрабатывает событие. Как и в листинге 25.7, свойство event phase применяется для отображения режима передачи в процессе обработки события каждым узлом. <html> <head> <title>currentTarget and eventPhase Properties</title> «script type="text/javascript"> 800 Часть III. Объекты документа
function init() { // старый синтаксис обработки всплывающих событий document.onelick = processEvent; document.body.onelick = processEvent; // включение,обработки щелчков для документа и формы document.addEventListener("click", processEvent, true); document.forms[0].addEventListener("click", processEvent, true) ,- // установка приемника события для формы document.forms[0].addEventListener("click", processEvent, false); } function processEvent(evt) { var currTargTag, msg; if (evt.currentTarget.nodeType == 1) { currTargTag = "<" + evt.currentTarget.tagName + ">"; } else { currTargTag = evt.currentTarget.nodeName; } msg = "Event is now at the " + currTargTag + " level "; msg += "(" + getPhase(evt) + ")."; alert(msg); } // определение режима обработки события function getPhase(evt) { switch (evt.eventPhase) { case 1: return "CAPTURING"; break; case 2: return "AT TARGET"; break; case 3: return "BUBBLING"; break; default: return ""; } } </script> </head> cbody onload="init()"> <hl>currentTarget and eventPhase Propertiesc/hl> <hr /> <form> cinput type="button" value="A Button" name="mainl" onclick="processEvent(event)" /> </form> </body> </html> Вы можете щелкать не только на кнопке. Например, если вы наведете указатель на место справа от кнопки, то щелкнете на элементе form. Обработка события будет выполнена соот- ветствующим образом. См. также: свойство eventphase. Глава 25. Объекты событий 801
detail Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойство detail включено в W3C DOM как дополнительное, цель которого может быть определена создателем браузера. Теоретически целочисленное значение этого свойства мо- жет передавать дополнительную информацию о событии. Пока свойство присутствует только в объекте события NN6 (значения возвращаются далеко не для всех событий), оно не содер- жит никаких полезных данных, но может содержать их в будущем. eventPhase Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Событие постоянно находится в одной из трех возможных фаз: сбор данных события, целе- вой объект или всплывание. Поскольку одна -и та же функция приемника события может обра- батывать событие в нескольких фазах, в ней можно задать значение свойства eventPhase объекта события для определения, в какой фазе событие находится при вызове функции. Это свойство имеет целочисленные значения — 1 (сбор данных), 2 (в целевом объекте) и 3 (всплывание). Пример Пример использования свойства eventPhase был приведен ранее в листинге 25.20. В нем применялась конструкция switch для выбора операторов обработки события, что зависело от фазы текущего события. См. также: свойство currentTarget. isChar Значение: булево Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Для каждого события клавиатуры можно определить, соответствует ли нажимаемая кла- виша символу, изучая значение свойства isChar. Чаще всего для сбора данных о символь- ных и несимвольных клавишах используются обработчики событий, применяемые для захва- та событий клавиатуры: onkeypress для клавиш символов; onkeydown или onkeyup для несимвольных клавиш. Свойство isChar возвращает несогласованные значения (даже для той же самой клавиши) в первом выпуске NN6. См. также: свойства charCode, keyCode. originalTarget Значение: ссылка на объект узла Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Это свойство содержит ссылку на объект узла, который выступает первой целью события. Возвращаемое значение зависит от внутренней структуры элементов. Во многих случаях оно равно значению свойства target. relatedTarget Значение: объект элемента Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ 802 Часть III. Объекты документа
Свойство relatedTarget позволяет выявить элементы, с которых наводится указатель мыши на текущий элемент, и на которые он сводится с текущего элемента. Это свойство расширяет возможности обработчиков событий onmouseover и onmouseout, распростра- няя их на соседние с текущим объекты. Данное свойство в NN6 выполняет те же задачи, что и свойства f romElement и toElement объекта event в IE4+. Когда событие onmouseover инициируется в элементе, указатель все еще находится в другом элементе. Свойство relatedTarget задает ссылку на этот элемент. Наоборот, ко- гда возникает событие onmouseout, указатель уже расположен на другом элементе; свойст- во relatedTarget также задает ссылку на него. Пример Листинг 25.21 содержит пример использования свойства relatedTarget. С его помо- щью определяется расположение указателя до и после наведения его на центральный эле- мент. При наведении указателя на центральный элемент (ячейка таблицы) обработчик onmouseover отображает текст из ячейки, в которой указатель находился перед этим (свойство nodevalue текстового узла, расположенного в ячейке). Если же указатель пере- местился в центр из угла таблицы (нелегкая задача), то отображается специальное сообщение. Две функции, которые выводят результат, выполняют дополнительную проверку: они об- рабатывают объект события только в случае возникновения его в элементе и если элемент relatedTarget отличный от вложенного текстового узла центральной ячейки таблицы. ЛйОТИЫГ 2*11. МСПОЯЬМММ свойства reL-t#dTarS«t <html> <head> <title>relatedTarget Properties</title> <style type="text/css"> .direction {background-color:#OOFFFF; width:100; height:50; text-align:center) #main {background-color:#FF6666; text-align:center) </style> «script type="text/javascript"> function showArrival(evt) { if (evt.target.nodeType == 1) { if (evt.relatedTarget != evt.target.firstChild) { var direction = (evt.relatedTarget.firstChild) ? evt.relatedTarget.firstChild.nodevalue : "parts unknown"; window.status = "Arrived from: " + direction; function showDeparture(evt) { if (evt.target.nodeType == 1) { if (evt.relatedTarget != evt.target.firstChild) { var direction = (evt.relatedTarget.firstChild) ? evt.relatedTarget.firstChild.nodevalue : "parts unknown"; window.status = "Departed to: " + direction; </script> </head> Глава 25. Объекты событий 803
<body> <hl>relatedTarget Properties</hl> <hr /> <p>Roll. the mouse to the center box and look for arrival information in the status bar. Roll the mouse away from the center box and look for departure information in the status bar.</p> ctable cellspacing="O" cellpadding="5"> <tr> <td></td> <td class="direction">North</td> <tdx/td> </tr> <tr> <td class="direction">West</td> <td id="main" onmouseover="showArrival(event)" onmouseout="showDeparture(event)">Roll</td> <td class="direction">East</td> </tr> <tr> <tdx/td> <td class="direction">South</td> <tdx/td> </tr> </table> </body> </html> См. также: свойство target. target Значение: ссылка на объект элемента Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойство target — ссылка на объект элемента HTML, который является первоначальной целью события. Событие может передаваться вниз и всплывать вверх по иерархии объектов, об- рабатываясь в процессе продвижения на любом уровне структуры. При этом событие имеет свой- ство, указывающее на элемент, от которого происходит инициированное событие. При наличии ссылки на этот элемент можно получать и изменять его свойства или вызывать любые методы. Пример В качестве простейшего примера возможностей свойства target приведем лис- тинг 25.22. В нем в элементе body настроено два обработчика события, каждый из кото- рых вызывает отдельную функцию. Идея сценария очень проста: события onmousedown и onmouseup всплывают независимо от целевого элемента, а функции определяют послед- ние и изменяют их цвет стиля. В каждой функции проверяется свойство className целевого элемента. Если это свой- ство имеет значение bold (имя класса общее для всех трех элементов span абзаца), то пра- вило таблицы стилей для этого класса изменяется. В собственных сценариях вы можете за- дать более сложные операции форматирования документа. Обратите внимание, что сценарий может ничего и не “знать” об объектах страницы, что- бы правильно обратиться к ним — свойство srcElement предоставляет всю необходимую информацию о целевом элементе. 804 Часть III. Объекты документа
Листе* 25.# chtml> <head> <title>target Property«/title> <style type="text/css"> .bold {font-weight:bold} .ital {font-style:italic} </style> «script type="text/javascript"> function highlight(evt) { var elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target; if (elem.className == "bold") { document.stylesheets[0].cssRules[0].style.color = "red"; } else { elem.style.color = "#FFCC00"; function restore(evt) { var elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target; if (elem.className == "bold") { document.styleSheets[0].cssRules[0].style.color = "black"; } else { elem.style.color = "black"; </script> </head> «body onmousedown="highlight(event)" onmouseup="restore(event)"> <hl>target Property«/hl> «hr /> <p>One event handler...</p> <ul> <li>Can«/li> <li>Cover«/li> <li>Many«/li> <li>Objects«/li> </ul> <p>Lorem ipsum dolor sit amet, consectetaur adipisicing elit, «span class="bold">sed do«/span> eiusmod temper incididunt «span class="ital">ut labore et«/span> dolore magna aliqua. Ut enim adminim veniam, «span class="bold">quis nostrud exercitation«/span> ullamco laboris nisi ut aliquip ex ea «span class="bold">commodo consequat«/span>.</p> </body> </html> См. также: свойство relatedTarget. timestamp Значение: целочисленное Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Каждое событие имеет временную отметку, заданную в миллисекундах относительно да- ты начала отсчета в JavaScript, — 1 января 1970 года. Также, как с объектом Date, точность по- лученного времени полностью зависит от точности системных часов компьютера пользователя. Глава 25. Объекты событий 805
Точное время возникновения события может быть ценно только в некоторых ситуациях, а время между определенными событиями часто используется в приложениях решения задач на время или в играх в жанре экшн. Время возникновения последнего события можно сохра- нить в глобальной переменной; сравните его с текущей временной меткой последующих со- бытий, чтобы определить разницу между ними. Пример В листинге 25.23 приведен пример использования свойства timestamp. С его помо- щью вычисляется скорость ввода текста в области textarea. Вычисления существенно уп- рощены, поэтому они не учитывают длительных задержек и пауз, которые часто случаются при вводе больших текстовых фрагментов. Более того, полученное значение округляется к ближайшему целому. Листинг 25.23. СВОЙСТВО ti»eSt««p <html> <head> <title>timeStamp Property«/title> «script type="text/javascript"> var stamp; function calcSpeed(evt) { if (stamp) { var gross = evt.timestamp - stamp; var wpm = Math.round(6000/gross); document.getElementByld("wpm").firstChild.nodeValue = wpm + " wpm."; } stamp = evt.timestamp; } </script> </head> <body> <hl>timeStamp Property</hl> chr /> <p>Start typing, and watch your instantaneous typing speed below:</p> «pxtextarea cols="60" rows="10" wrap="hard" onkeypress="calcSpeed(event)"></textarea>«/p> . <p>Typing Speed: «span id="wpm">&#160;«/spanx/p> </body> </html> См. также: объект Datve. type Значение: строка Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Выяснить, какой тип события был инициирован для создания определенного объекта события, можно, используя свойство type. Его значение — строковая версия имени собы- тия — только имя события не имеет префикса on, который обычно связывают с именами приемника события в NN6. Это свойство может быть полезно, когда для обработки раз- личных видов событий используют всего одну функцию. Например, обработчики событий 806 Часть III. Объекты документа
onmousedown и onclick объекта могут вызывать одну функцию. Внутри функции ветвление задается в зависимости от типа события— mousedown или click— с соответствующей обработкой каждого типа. Вам не обязательно задавать совместное управление событиями, но знание о возможности организации подобной конструкции в сценариях весьма полезно. Это свойство и его значения полностью совместимы с моделями событий в NN4 и IE4+. События клавиатуры в Safari 1.0 распознаются как khtml_keydown, khtml_keypress и khtml keyup. Префикс в названиях типов представляет программное ядро, на основе которого создавался этот браузер. Подобное именование полностью со- ответствует стандартам еще незавершенной спецификации W3C DOM 3. См. также: все обработчики события (глава 15). view Значение: ссылка на объект window Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ Чем ближе объектная модель W3C DOM 2 к объектным моделям браузеров, тем сильнее ощущается необходимость в специальном объекте, называемом объектом абстрактного вида (класс Abstractview). Единственное свойство этого объекта (ссылка на содержащийся в нем документ) корневой узел уже знакомого документа. Пользовательские события всегда происхо- дят в пределах этого объекта, что отражено в свойстве view объекта event. В NN6 оно воз- вращает ссылку на объект window (может иметь многоуровневую структуру), в котором проис- ходит событие. Эта ссылка позволяет объекту события быть переданной сценариям других структур, а эти сценарии могут получить доступ к объекту document окна целевого элемента. См. также: объект window. Методы initEvent(eventType, bubbleFlag, cancelableFlag) initKeyEvent(eventType, bubbleFlag, cancelableFlag, view, ctrlKeyFlag, altKeyFlag, shiftKeyFlag, metaKeyFlag, keyCode, charCode) initMouseEvent(eventType, bubbleFlag, cancelableFlag, view, detailVal, screenX, screenY, clientx, clientY, ctrlKeyFlag, altKeyFlag, shiftKeyFlag, metaKeyFlag, buttonCode, re1atedTargetNodeRef) initMutationEvent(eventType, bubbleFlag, cancelableFlag, relatedNoderef, prevValue, newValue, attrName, attrChangeCode) initUIEvent(eventType, bubbleFlag, cancelableFlag, view, detailVal) Возвращаемое значение: отсутствует. Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Глава 25. Объекты событий 807
Методы инициализации объектов в W3C DOM предполагают назначение только что соз- данному событию всего набора свойств, характерных для него. Аргументы каждого метода инициализации зависят от типа создаваемого события. Тем не менее, все методы инициализа- ции имеют три основных аргумента: eventType, bubbleFlag, cancelableFlag. Пер- вый параметр имеет строковое значение и определяет тип события, например "mousedown" или "keypress ". Атрибут bubbleFlag является булевым значением, которое указывает на реализацию всплывания события (true) или отказ от всплывания (false). Третий аргумент также представляет собой булево значение, которое указывает на предотвращение или реали- зацию действия события по умолчанию. Отдельные методы содержат аргументы view и detaiIval. Первый соответствует окну или фрейму, в котором событие происходит, второй аргумент принимает целочисленный код, связанный с данными конкретного события. Вам совсем не обязательно использовать сложные методы, если вы настраиваете простое событие. Например, если требуется настроить событие mouseup, то можете инициализиро- вать его с помощью общего метода initEvent (), а затем связать это событие с конкрет- ным элементом, не указывая сведения о координатах, кнопках и других характеристиках со- бытия в методе initMouseEvent (). var evt = document.createEvent("MouseEvents"); evt.initEvent("mouseup", true, true); document.getElementByld("myButton").dispatchEvent(evt); См. также: метод document. createEvent (). preventDefault() Возвращаемое значение: отсутствует. Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ NN6+ продолжает следовать первоначальному способу предотвращения поведения по умолчанию обработчика события (т.е. задавать в качестве последнего оператора обработчика события return false). В то же время модель событий NN6+ предоставляет метод, кото- рый позволяет аннулировать действия по умолчанию, полностью происходящие в пределах вызванной обработчиком события функции. Например, рассмотрим текстовое поле, которое, как предполагается, в своих пределах позволяет вводить только числа. Обработчик события onkeypress может вызывать функцию, которая рассматривает каждый введенный символ. Если символ не цифра, то он не отображается в текстовом поле, просто не достигая его. Сле- дующая функция проверки правильности вызывается в обработчике события onkeypress описанного ниже текстового поля. function checklt (evt) { var charCode = evt.charCode; if (charCode <48 | charCode >57) { alert("Please make sure entries are numbers only"); evt.preventDefault(); } } Таким образом, ошибочный символ не будет добавлен в текстовое поле. Вызов метода preventDef ault () в NN6+/Moz/Safari эквивалентен присвоению свой- ству event. returnvalue значения true в IE5+.' См. также: свойство cancelable. 808 Часть III. Объекты документа
stopPropagation() Возвращаемое значение: отсутствует. Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Используйте метод stopPropagation (), чтобы не допустить продвижения события вниз или всплывания вверх по иерархии элементов. В функции приемника события метод вы- зывается следующим образом. evt.stopPropagation(); Альтернативным методом является задание отмены всплывания непосредственно в атри- буте обработчика события элемента. onclick="doButtonClick(this); event.stopPropagation()"; При написании межбраузерных сценариев также используются значения свойства cancelBubble, совместимого с IE4+. См. также: свойства bubbles, cancelBubble. Глава 25. Объекты событий 809
Таблица стилей и объекты стилей Полную поддержку таблицы стилей получили только с появлением браузеров версии 4 (браузеры IE3 час- тично поддерживали таблицы стилей). В настоящее время страницы Всемирной сети содержат большой объем инфор- мации и при этом подлежат постоянному изменению, поэто- му таблицы стилей применяются очень часто. С помощью таблиц стилей Web-разработчик получает возможность раз- граничить содержимое страницы и элементы, подлежащие изменению. Текстовая информация может поступать из раз- личных электронных источников. Разместить ее зачастую необходимо в разном контексте. Например: блок последних новостей поступает на многочисленные Web-узлы портала, при этом каждый узел имеет свой унифицированный вид. За- дача Web-дизайнера— определить, каким образом инфор- мация будет отображаться на Web-странице. Таблицы стилей помогают решать различные задачи. На- пример, крупному корпоративному Web-узлу необходимо придать унифицированный вид с помощью характерного сти- ля. Семейство таблиц стилей может определить тип шрифта и его размер, вид выделенного текста и ширину полей всего текста Web-узла. Применять эти стили к каждому элементу в отдельности довольно трудно и даже рискованно — если в коде одной из страниц дескрипторы стиля пропущены, унифицированный вид всего Web-узла будет нарушен. Более того, если требования корпоративного дизайна Web-узлов изменятся и вам придется изменять, например, тип шрифта, операция замены стилей в каждом дескрипторе даже при ис- пользовании функции “найти и заменить” станет очень не- простой задачей. Если же информация об используемых сти- лях будет содержаться во внешнем файле таблицы стилей, Web-дизайнер сможет внести все необходимые изменения только в этот файл. В результате вид всего Web-узла будет изменен быстро и просто. В этой книге мы не рассматриваем способы создания и применения таблиц стилей. Данная глава рассчитана на тех читателей, которые уже знакомы с терминами, используе-
мыми при работе с таблицами стилей (например, правило и селектор таблицы стилей). Если эти термины вам пока не знакомы, всю необходимую информацию вы сможете найти в учеб- ных пособиях и на специализированных Web-страницах. Браузеры Internet Explorer и Netscape Navigator достаточно строго придерживаются стандартов W3C для таблиц стилей (называемых Cascading Style Sheets — каскадные таблицы стилей — CSS). Всю дополнительную информа- цию рекомендуется искать в независимых источниках. В частности, Microsoft дополняет сло- варь несколькими терминами, которые употребляются лишь при использовании браузеров IE4+ для Windows. Поэтому, если вы создаете приложение, рассчитанное не только на эту модель браузеров и операционную систему, то вам следует привести целый ряд характери- стик каскадных таблиц к общему знаменателю. В этой главе рассматриваются все версии. Особое внимание следует уделить листингам совместимости для каждого элемента. И последнее замечание, касающееся совместимости: несмотря на то, что NN4 предостав- ляет возможность использования многих средств CSS, таблицы стилей и правила стилей в NN4 не представлены в качестве объектов. Некоторые стили непосредственно связаны со статической природой страницы NN4. Поскольку браузер не может переформатировать стра- ницу в ответ на изменения, стили уже загруженного содержимого Web-страницы просто не могут быть изменены. В NN6+/Mozl+ страница может быть свободно переформатирована, а все, что задается стилями, представлено в виде модели объекта. Имена объектов Сначала необходимо разобраться в терминах, относящихся к объектам таблиц стилей, с которыми вам предстоит работать. Иногда значения этих терминов частично совпадают. Некоторые объекты абстрактны по сравнению с другими, но они, тем не менее, важны. Мы рассмотрим следующие из них. Объект элемента стиля (style). Объект stylesheet (элемент массива styleSheets). Правило или объект cssRule (элемент массивов rules или cssRules). Объект style. Объект элемента style соответствует дескриптору <style> документа. Многие свойст- ва этот объект унаследовал от объектов обычных элементов HTML, рассмотренных в гла- ве 15. Пока объект элемента style имеет свойство disabled (отключенный), вы не сможе- те получить доступ к таблицам стилей с помощью объекта style. Таблица стилей вкладывается в документ с помощью дескриптора <style> или связыва- ется с документом посредством дескриптора <link>. Объект document обладает свойством styleSheets, которое позволяет активизировать массив (совокупность) всех задействован- ных в текущем документе объектов stylesheet, независимо от того, были они подключены или нет. Несмотря на то, что дескриптор <style> содержит строки кода, составляющие правила таблиц стилей, объект элемента style не используется для получения доступа к ин- дивидуальным правилам. Для этой цели задается объект stylesheet. С помощью этого объекта можно подключать или отключать всю таблицу, получать доступ к отдельным пра- вилам (используя массив свойств rules или cssRules), а также добавлять или удалять пра- вила для данной таблицы стилей. В основе каждой таблицы стилей — правила, определяющие, как элементы должны отобра- жаться. На уровне объектов термины, применяемые для IE4+ и NN6, отличаются. В модели объ- екта IE4+ каждое правило таблицы стилей называется объектом правила. NN6+/Moz, следуя стандарту W3C DOM 2, называет каждое правило объектом правила каскадных таблиц стилей. Глава 26. Таблица стилей и объекты стилей 811
IE5 для Macintosh и Safari принимает оба варианта обозначения одного и того же объекта. Не- смотря на разные имена, объекты имеют общие основные имена свойств. Чтобы обратиться к правилу, необходимо задать целый массив ссылок. Например, ссылка на первое правило первого объекта stylesheet документа для двух типов браузеров будет выглядеть следующим образом. var oneRule = document. stylesheets [0] . rules [0] IE4+, MaclE5, Safari var oneRule = document, stylesheets [0] . cssRules [0] MaclE5, NN6+/M0Z, Safari Последний объект из группы объектов, относящихся к стилям, — это объект style. Дан- ный объект — основа, в которой определены все стили. В предыдущих главах были приведены примеры того, как можно изменить одно или несколько свойств style-элемента. Чаще всего изменения осуществляются с помощью свойства style элемента HTML. Например, вы можете задать цвет шрифта элемента span, идентификатор которого равен hot, следующим образом. document.all.hot.style.color = "red" IE4+ document.getElementByld("hot").style.color = "red" IE5+,W3C Объект style также является свойством объекта rule/cssRule. Таким образом, если вы хотите изменить стиль элементов, находящихся под влиянием существующего правила таблиц стилей, получить доступ к объекту style можно разными способами, однако рабо- тать с этим объектом следует так же, как и с любыми другими элементами. document. stylesheets [0] . rules [0] . style. color = "red" IE4+, MaclE5, Safari document. stylesheets [0] . cssRules [0] . style, color = "red" MaclE5, NN6+/ Moz, Safari Многие Web-дизайнеры работают только с объектом style, поэтому он обычно ассоцииру- ется с объектом определенного элемента. Управлять объектами style Sheet приходится ред- ко, кроме тех случаев, когда их нужно активизировать или отключить в сценарии. Поэтому, если вы до сих пор знакомы не со всеми этими объектами, особое внимание уделите объекту style. Импортированные таблицы стилей Таблицы стилей, вложенные в документ посредством элемента style, могут импортиро- вать дополнительные таблицы с помощью селектора ©import. <style type="text/css"> ©import url(externalstyle.css); p {font-size:16pt} </style> В этом сценарии документ “видит” только один объект styleSheet. В такой объект вло- жена таблица стилей, содержащаяся во внешнем файле. ГЕ4+ называет одну из этих импортиро- ванных таблиц стилей объектом import. Объект import обладает всеми характеристиками объекта stylesheet, но его свойство parentstyle является ссылкой на styleSheet, ко- торый “владеет” правилом ©import. Оператор ©import отсутствует в совокупности правил объекта styleSheet в Е. Следовательно, для получения доступа к первому правилу импор- тированной таблицы стилей следует задать такую ссылку. document.styleSheets[0].imports[0].rules[0] W3C DOM и NN6+/Moz трактуют объекты правила import иначе, чем Е. В соответст- вии со стандартами W3C DOM даже импортированное правило считается элементом сово- купности cssRules объекта styleSheet. Одним из свойств объекта cssRules является type. Это свойство служит для выражения целого значения кода. С его помощью можно оп- ределить, относится ли текущее правило к CSS или принадлежит к другому типу правил, 812 Часть III. Объекты документа
включая правило import. Разумеется, импортированный объект правила в качестве одного из свойств имеет объект styleSheet, который, в свою очередь, содержит правила, опреде- ленны во внешнем файле таблицы стилей. Здесь также имеют место родительско-дочерние отношения, в то время, как к свойству parentstyle импортированного объекта обращают- ся с помощью ссылки на свойство parentstyle объекта styleSheet (как и в IE4+). Получение свойств стиля Объектные модели ГЕ4+ и NN6 (W3C) обладают одной и той же характерной особенностью поведения, которая может поначалу сбить вас с толку. С одной стороны, стандарты W3C и практика работы в HTML предлагают определять стили удаленно (т.е. подключать их с помо- щью дескрипторов <style> и <link>), а не задать значения атрибута style дескриптору ка- ждого элемента документа. Это соответствует тенденции отделения стилей от содержимого. С другой стороны, объектные модели могут быть очень коварны. Если объект элемента представляет свойство, отражающее атрибут дескриптора этого элемента в тот момент, когда программа впервые пытается прочесть это свойство, значение будет соотноситься с этим свойством только в том случае, если атрибут явно задан в коде HTML. Если же вы подклю- чаете удаленную таблицу стилей, то значения не будут представлены в дескрипторе в явном виде. Следовательно, свойство style такого элемента оказывается пустым, даже несмотря на то, что стиль данного элемента находится под контролем удаленной таблицы стилей. Про- блем не возникнет, если вы должны лишь задать новое значение свойства style, поскольку определенное вами значение свойства style объекта элемента аннулирует любой стиль, на- значенный этому свойству в удаленной таблице стилей (это новое значение содержится в свойстве style). Но если вы решили получить текущие настройки, то исходное значение не будет пред- ставлено в объекте style данного элемента. К счастью, в Е5+ появилось дополнительное свойство, доступное только для чтения, — currentstyle. Оно позволяет увидеть значения таблицы стилей, которые в данный момент применеф! к элементу, независимо от того, где расположены определения таблицы стилей. Свойство currentstyle выдает объект, который обладает тем же форматом и свойст- вами, что и обычное свойство style. Если ваша Web-страница рассчитана на аудиторию, использующую браузеры IE5 и более современные, вам следует ознакомиться со стилями элемента с помощью свойства currentstyle. Чтобы изменить свойство стиля объекта только для одного элемента, используйте свойство style. Но если изменения касаются всех элементов, стиль которых контролируется одним удаленным правилом таблиц стилей, эти изменения следует внести в свойство style объекта правила. В W3C DOM решение представлено в виде метода getComputedStyle (). Чтобы получить значение определенного свойства стиля, примененного к элементу, сначала следует получить зна- чение вычисляемого стиля (computed style) для указанного элемента, а затем определить необ- ходимое свойство CSS-стиля. Например, для получения значения свойства стиля font-family, примененного к элементу с идентификатором туР, выполните следующие операторы. var elem = document.getElementByld("myP"); var computedStyle = window.getComputedStyle(elem, ""); var fontFam = computedStyle.getPropertyValue("font-family"); Учтите, что вы должны использовать имя свойства CSS-стиля (например, font-family), а не его сценарный эквивалент (например, fontFamily). К сожалению, Safari 1.0 не под- держивает метод getComputedStyle (), а потому не позволяет получить значения свойств стилей, заданных вне атрибутов элементов. Глава 26. Таблица стилей и объекты стилей 813
Объект элемента style Свойства, методы и обработчики этого объекта описаны в главе 15. Свойства Методы Обработчики событий media type Синтаксис Доступ к объекту и методам элемента style. (IE4+) document.all.идентификатор.свойство Iметод([параметры]) (IE5+/W3C) document. getElementByld (идентификатор) . свойство Iметод ([параметры]) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Описание объекта Элемент style является одним из объектов указания (см. главу 36). Этот элемент распо- лагается в разделе head документа, а его содержимое не отображается на Web-странице. Со- держимое элемента style существенно влияет на то, каким образом будут отображаться ос- тальные элементы страницы. Большинство свойств, методов и обработчиков событий, которые унаследованы элементом style от элементов HTML, существенной роли в управле- нии документом не играют. Однако есть одно исключение — булево (логическое) свойство disabled. Существует не- сколько способов деакгивизации таблицы стилей (свойство disabled объекта stylesheet), однако для подключения и отключения таблицы стилей удобнее всего использовать объект элемента STYLE. Этому элементу вы можете назначить идентификатор и явно ссылаться на него. Следовательно, вам будет проще использовать его свойства, чем пытаться определить, какой именно объект stylesheet из массива styleSheets документа необходимо ис- пользовать в каждой конкретной ситуации. Свойства media Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство media представляет атрибут media элемента style. Этот атрибут определяет тип устройства вывода, соответствующего назначению текущей таблицы стилей. В специфи- кации к HTML 4.0 этому атрибуту приписывается целый ряд значений. Однако браузеры в большинстве случаев используют следующие значения: screen, print и all. Таким об- разом вы можете создать один набор стилей для отображения страницы на экране, а вто- рой — для печати документа. 814 Часть ///. Объекты документа
type Значение: строка Чтение/Запись Совместимость: WinIE4+, MacLE4+, NN6+, Mozl+, Safari 1+ Свойство type представляет атрибут type элемента style. Для таблиц стилей CSS это свойство всегда имеет значение text /css. Но если в сценарии данному свойству присвоить другое значение, то браузер не будет поддерживать этот тип таблиц стилей, таблица стилей перестанет восприниматься как CSS, а все стили, задаваемые этой таблицей, будут заменены на исходные стили по умолчанию. Объект stylesheet Свойства Методы Обработчики событий cssRules addimport() cssText addRule() disabled deleteRule() href insertRule() id imports media ownerNode ownerRule owningElement pages parent StyleSheet readonly rules title type removeRule() Синтаксис Доступ к свойствам и методам объекта stylesheet. (IE4+/W3C) document. stylesheets [индекс] . свойство /метод ( [параметры] ) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Описание объекта Если объект элемента style — это точное воплощение таблицы стилей, то объект styleSheet — это ее абстрактный эквивалент. Объект styleSheet существует на ос- нове определения таблицы стилей, вложенного в текущий документ с помощью дескрипто- ра <style> или присоединенного из внешнего файла с помощью дескриптора dink>. Каждый Глава 26. Таблица стилей и объекты стилей 815
элемент, который вводит таблицу стилей в текущий документ, создает свой собственный объект stylesheet. Доступ к объекту stylesheet осуществляется с помощью массива document. styleSheets. Если определение таблицы стилей в документе отсутствует, мас- сив имеет нулевую длину. Стили, которые были применены к документу с помощью атрибута элемента STYLE, не являются объектами styleSheet. Объекты styleSheet присутствуют как в IE4+, так и в W3C DOM. Более того, в браузе- рах обоих типов значение этого объекта одинаково. Однако во многих случаях свойства и ме- тоды значительно отличаются. Зачастую объекты несут одну и ту же информацию, но эта ин- формация передается с помощью свойств, имена которых отличаются в этих двух различных типах браузеров. Интересным является тот факт, что для некоторых особо важных свойств (например, тех, которые возвращают массив правил стилей и обращаются к элементу HTML, ответственному за таблицы стилей текущего документа) Мас1Е5+ и Safari поддерживает тер- минологию Microsoft и W3C. Методы этого объекта направлены, в основном, на добавление и удаление правил из таблицы стилей. Таким образом, объект styleSheet используется в качестве шлюза к отдельным правилам (заданным массивом rules или cssRules). Свойства cssRules Значение: массив объектов правил Только для чтения Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Свойство cssRules возвращает массив объектов правил таблицы стилей. В терминоло- гии W3C DOM это объекты cssRule. Данное свойство присутствует в IE5+ для Мас, но его нет в версии для Windows, например в IE6. Список объектов правил приведен в порядке представления их в исходном коде. Соответствующее свойство WinIE4+ — rules. Пример Используйте приложение The Evaluator (глава 13) для изучения свойства cssRule в брау- зерах W3C DOM и Мас1Е5. Сначала узнайте, сколько правил определено в первом объекте styleSheet страницы, введя в верхнее текстовое поле следующее выражение. document.styleSheets[0].cssRules.length Далее используйте массив, чтобы получить доступ к отдельным объектам правил и их свойствам. Введите в нижнее текстовое поле такое выражение. document.styleSheets[0].cssRules[1] Используйте этот синтаксис для изменения правил стилей, заданных в объекте styleSheet. См. также: свойство rules; объекты cssRule и rule. cssText Значение: строка Чтение/Запись Совместимость: WinIE5+, MacIE5, NN-, Moz-, Safari- Свойство cssText содержит строку правил таблицы стилей, заключенных в объекте styleSheet. Анализировать этот текст, чтобы найти определенные строки, не имеет смыс- ла, поскольку в тексте, возвращенном с помощью этого свойства, могут присутствовать сим- волы возврата каретки и другие элементы форматирования, которые не имеют места в тексте, заданном в правилах таблицы стилей в явном виде. Вы, конечно, можете использовать данное свойство, чтобы полностью переписать правила таблицы стилей прямым методом: скомпоновать 816 Часть III. Объекты документа
строку, состоящую из новых правил, и назначить эту строку свойству cssText. Формальный способ изменения правил (добавление и удаление) предпочтителен, но вы можете использо- вать свойство cssText, если рассчитываете только на пользователей IE5+. Пример Приложение The Evaluator также можно использовать для замены всех правил стиля с по- мощью свойства cssText. Начните с изучения значения, возвращаемого свойством cssText исходно отключенной таблицы стилей. Для этого введите в верхнее текстовое поле следую- щее выражение. document.stylesheets[0].cssText Далее подключите таблицу стилей, чтобы применить ее правила в документе. document.stylesheets[0].disabled = false Наконец, введите приведенное ниже выражение в верхнее текстовое поле приложения, чтобы заменить существующие правила таблицы стилей абсолютно новыми. document.stylesheets[0].cssText = "р {color:red}" Перезагрузите страницу, если хотите вернуться к исходным правилам таблицы стилей. См. также: методы addRule (), deleteRule (), insertRule () и removeRule. disabled Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойство disabled объекта элемента style характерно только для элемента, однако свойство disabled объекта styleSheet применимо также и к объекту styleSheet, ко- торый присоединен к документу с помощью элемента link. Активизация и отключение таблиц стилей— это один из способов изменения стилей Web-страницы, позволяющий пользователю указать необходимое форматирование. Web- страница может иметь большое количество таблиц стилей, контролирующих одни и те же элементы, однако сценарий имеет возможность подключить одну из таблиц и отключить дру- гую, чтобы изменить стиль страницы в целом. Указанная операция выполняется с помощью обработчика событий onload. Например, у вас есть отдельные таблицы стилей для браузе- ров Windows и Мас. Вы можете добавить эти таблицы в документ в отключенном исходном состоянии. Обработчик событий onload определяет операционную систему и активизирует таблицу стилей, предназначенную исключительно для нее. Если ваши таблицы стилей имеют не очень большой объем, их вставка для разных операционных систем не окажет значитель- ного влияния на время загрузки документа. Пример Приложение The Evaluator может подключать и отключать первый объект styleSheet страницы. Введите в верхнее текстовое поле следующее выражение. document.styleSheets[0].disabled = ('document.styleSheets[0].disabled) Включение в это выражение оператора отрицания (!), приведет к изменению текущего состояния на противоположное. Таким образом, при щелчке на кнопке Evaluate значение true свойства disabled будет заменено на значение false; и наоборот, значение false изменится на значение true. См. также: свойство disabled объекта элемента style. Глава 26. Таблица стилей и объекты стилей 817
href Значение: строка Чтение/Запись (см. текст) Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ ЕСли таблица стилей присоединяется к документу с помощью элемента link, свойство href объекта styleSheet содержит строку с URL соответствующего файла. Таким обра- зом, свойство href элемента link передается в объект styleSheet, который определяет результат присоединения стилей. В IE4+ для Windows это свойство доступно для чтения и за- писи, что позволяет динамично присоединять внешний файл таблицы стилей после того, как Web-страница уже загружена. В MacIE и NN6+/Moz это свойство доступно Только для чтения. См. также: объект элемента link. id Значение: строка Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство id объекта styleSheet наследует свойство id содержащегося в объекте его элемента-контейнера (style или link). Такое обстоятельство вызывает некоторые трудно- сти, поскольку кажется, что два объекта имеют одинаковый идентификатор. Однако это не так: id может служить индексом массива document. styleSheets в IE4+ (например, document. styleSheets [ "winLINK" ]); в NN6 подобного идентификатора, который был бы связан с объектом styleSheet, нет. См. также: свойство id объектов всех элементов. imports Значение: массив объектов styleSheet Только для чтения Совместимость: WinIE4+, MacDE4+, NN-, Moz-, Safari- Таблица стилей может содержать одно или более правил ©import для импортирования внешнего файла таблицы стилей в документ. Каждый импортированный объект styleSheet считается объектом import. Свойство imports представляет собой массив всех импор- тированных объектов styleSheet, принадлежащих текущему объекту styleSheet. Импортированные таблицы стилей не добавляются в массив document. styleSheets, поэтому ссылки на импортированные объекты должны задаваться с помощью массива document.styleSheets[i].imports[i]. Объект import является объектом styleSheet. Поэтому все свойства и методы, при- мененные к объекту styleSheet, могут применятся и к объекту import. Следовательно, если вы хотите загрузить на Web-страницу другую таблицу стилей, новый URL вы сможете задать в свойстве href импортированного объекта styleSheet. document.styleSheets[0].imports[0].href = "alternate.css"; Такие операции могут быть проведены в WinlE, но не в MacIE. См. также: объект styleSheet. media Значение: см. текст z Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Таблицы стилей CSS могут применяться для работы с такими видами устройств вывода, как экран монитора, принтер, а в будущем — со специальными устройствами обработки человеческой 818 Часть III. Объекты документа
речи и генераторами Брайля. Такую возможность предоставляет атрибут media элементов style или link. Его значение представлено в свойстве media объекта stylesheet. В IE4+ значение свойства media представляет собой строку с одним из трех возможных значений: screen, printer или all. W3C DOM и NN6+ позволяет определить атрибуту media множественные значения. Значение в NN6+/Moz/Safari представляет собой массив строк с названиями определенных устройств вывода. ownerNode Значение: ссылка на узел Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойство ownerNode представляет собой ссылку на узел документа, в котором опреде- лен объект styleSheet. Для тех объектов styleSheet, которые определены в элементах style и link, свойство ownerNode служит для ссылки на этот элемент. Соответствующее свойство в IE4+ называется owningElement. Отметим также, что в системе Мас1Е5 сущест- вует дополнительное свойство owningNode, имя которого несколько отличается, а значение совпадает со значением свойства owningElement. Пример Приложение The Evaluator можно запустить в NN6+/Mozl+/Safari для изучения свойства ownerNode первого объекта styleSheet документа. Введите в верхнее текстовое поле сле- дующее выражение. document.styleSheets[0].ownerNode.tagName См. также: свойства ownerRule и owningElement. ownerRule Значение: объект cssRule Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойство ownerRule применяется по отношению к объекту styleSheet, который был импортирован в документ с помощью правила ©import. Это свойство возвращает ссылку на правило ©import, отвечающее за загрузку внешней таблицы стилей. Между свойствами ownerRule и ownerNode существует взаимосвязь, которая заключается в том, что импор- тированное правило имеет свойство ownerRule, а значение его свойства ownerNode равно null; и наоборот, обычный styleSheet имеет значение ownerNode, а значение его свой- ства ownerRule равно null. Следует отметить, что в NN6 импортированные таблицы сти- лей не считаются объектами, поэтому данное свойство в NN пока не поддерживается. См. также: свойство ownerNode. owningElement Значение: ссылка на элемент Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство owningElement представляет собой ссылку на объект элемента, в котором определен объект styleSheet. Для тех объектов styleSheet, которые определены в эле- ментах style и link, свойство owningElement служит для ссылки на последние. Соот- ветствующее свойство в NN6+ называется ownerNode. В системе Мас1Е5 существует дополнительное свойство owningNode, имя которого несколько отличается, а значение сов- падает со значением свойства owningElement. Глава 26. Таблица стилей и объекты стилей 819
Пример В приложении The Evaluator, запущенном в IE4+, можно быстро ознакомиться с возмож- ностями свойства owningElement первого объекта styleSheet. Введите в верхнее тек- стовое поле следующее выражение. document.styleSheets[0].owningElement.tagName Этот оператор возвращает имя style дескриптора элемента. См. также: свойство ownerNode. pages Значение: массив правил ©page Только для чтения Совместимость: WinE5.5+, МасЕ-, NN-, Moz-, Safari- Правило стиля ©page определяет размеры и ширину полей напечатанной версии Web- страницы. Свойство pages возвращает массив правил ©page, содержащихся в текущем объек- те styleSheet. Если в таблице стилей не определено ни одно правило ©page, длина масси- ва будет равна нулю. Кроме свойств, характерных для всех объектов правил, правило ©page имеет одно до- полнительное свойство, доступное Только для чтения. Это свойство — pseudoClass, кото- рое возвращает все определения псевдоклассов в этом правиле. Например, приведенные ниже правила определяют разные конфигурации левого и правого полей страниц при печати. ©page :left {margin-left:4cm; margin-right:3cm;} ©page :right {margin-left:3cm; margin-right:4cm;} Значения свойства pseudoClass правил для каждой из двух страниц — : left и : right соответственно. Согласно стандартам W3C DOM, правило ©page — это всего лишь один из объектов правил, свойство type которого возвращает раде. Более подробную информацию об этом свойстве вы найдете по адресу. http://www.w3.org/TR/REC-CSS2/page.html. parentStyleSheet Значение: объект styleSheet Только для чтения Совместимость: WinE4+, МасЕ4+, NN6+, Mozl+, Safaril+ Импортированная таблица стилей отображается благодаря главному объекту styleSheet, заданному с помощью элементов style или link. Ссылка на этот объект styleSheet осуществляется с помощью свойства parentstylesheet. Значение свойства parent- StyleSheet для большинства объектов styleSheet (тех, которые не были импортированы с помощью правила ©import) равно null. Следует различать свойство parentStyleSheet, указывающее на объект stylesheet, и другие свойства, ссылающиеся на элемент HTML, которому “принадлежит” объект stylesheet. readonly Значение: булево Только для чтения Совместимость: WinE4+, МасЕ4+, NN-, Moz-, Safari- Имя readonly не совсем точно соответствует назначению этого свойства. Булево значе- ние позволяет сценарию определить, была ли текущая таблица стилей подключена к документу с помощью элемента style или импортирована из внешнего файла с помощью элемента 820 Часть III. Объекты документа
link (либо правила ©import). В том случае, если таблица стилей была вложена с помощью элемента style, свойство readonly будет иметь значение false. Если же таблица стилей была импортирована, свойство имеет значение true. Значение true не свидетельствует о том, что свойства стилей не могут быть изменены сценарием. Свойства стилей можно из- менять в процессе работы, однако эти изменения не будут отображаться во внешнем файле. См. также: свойство owningElement. rules Значение: массив объектов rule Только для чтения Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari 14- Свойство rules возвращает массив всех объектов правил (кроме правил @), определенных в текущей таблице стилей. Порядок следования объектов правил в массиве соответствует порядку расположения правил, определенных в элементе style внешнего файла исходного кода. Массив rules следует использовать в качестве основного метода ссылки на индивидуаль- ное правило, определенное в данной таблице стилей. Если вы используете цикл for для того, чтобы найти нужное правило в массиве, вероятнее всего, для этого следует применять свойство selectorText объекта правила. Этот метод основывается на том, что каждый селектор таб- лицы стилей уникален. Использование уникальных селекторов предпочтительно, однако вы можете при необходимости повторно использовать имя того или иного селектора для полу- чения дополнительной информации о стилях, примененных к тем же элементам селектора. Соответствующее свойство в NN64-/Moz имеет имя cssRules. В Мас1Е5 и Safari воспри- нимаются оба имени данного свойства. Пример Запустите приложение The Evaluator в IE44- для изучения свойства rules первого объек- та styleSheet страницы. Сначала определите количество правил в этом объекте, введя в верхнее текстовое поле следующее выражение. document.styleSheets[0].rules.length Далее изучите свойства одного из правил, введя в нижнее текстовое поле такое выражение. document.styleSheets[0].rules[1] Вы должны увидеть в поле результатов все свойства выбранного правила в IE44-. См. также: объект rule; свойство cssRules. title Значение: строка Чтение/Запись Совместимость: WinIE44-, MacIE4+, NN64-, Mozl4-, Safari It- Если вы зададите значение атрибуту title элемента style или link, который загружает таблицу стилей, это строковое значение преобразуется в свойство title объекта styleSheet. Строковое значение может служить своеобразным идентификатором, но оно не может быть использовано в качестве индекса массива styleSheets. В результате применения к ото- бражаемым элементам HTML атрибут title преобразует текст во всплывающую подсказку для элементов. Для скрытых элементов style и link атрибут не оказывает никакого влия- ния на вид страницы на экране. Следовательно, этот атрибут и соответствующее свойство вы можете использовать для задания любого строкового значения. См. также: свойство title всех элементов HTML. Глава 26. Таблица стилей и объекты стилей 821
type Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойство type объекта styleSheet имеет непосредственное отношение к атрибуту type элементов style или link, с помощью которых таблица стилей вложена в текущий документ. Если вы не экспериментируете с новым языком написания таблиц стилей (предположим, его даже поддерживает браузер), то это свойство будет иметь значение text/css. Методы addimport(" URL"[, индекс]) Возвращаемое значение: целочисленное Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Метод addlmport() позволяет добавить правило ©import к объекту styleSheet. Первый параметр, который для этого необходим, это URL внешнего файла .css, содержа- щего одно или более правил таблицы стилей. Если вы пропустите второй параметр, правило ©import будет присоединено в конце массива правил объекта styleSheet. Вы также мо- жете назначить целое число в качестве индекса места расположения этого правила в массиве. Порядок следования правил в объекте styleSheet влияет на порядок каскадного включе- ния перекрывающих друг друга правил таблиц стилей (т.е. множественные правила, приме- ненные к одним и тем же элементам). Значение, которое возвращается в результате применения этого метода, представляет со- бой целое число, которое служит индексом места расположения нового правила в массиве правил объекта styleSheet. Если вы впоследствии собираетесь обращаться к этому прави- лу, то можете сохранить значение, возвращенное методом addlmport (), и использовать его в качестве индекса массива rules. См. также: метод addRule. addRule("селектор", "спецСтиля"[, индекс]) removeRule(индекс) Возвращаемое значение: целочисленное (для addRule) Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Метод addRule () присоединяет или вставляет правило таблицы стилей в текущий объект styleSheet. Первые два параметра представляют собой строки двух компонентов каждого правила: селектор и спецификацию стиля. Допускается использовать любой действительный селектор, включая множественные селекторы, селекторы с разделителями. Строка специфика- ции стиля содержит список пар атрибут: значение, разделенных точками с запятой (без фи- гурных скобок, определяющих спецификацию обычного правила таблицы стилей). Если вы пропустите последний параметр, правило будет присоединено в конце массива правил rules объекта. Вы также можете назначить целое число в качестве индекса место расположения этого правила в массиве правил rules. Порядок правил в объекте styleSheet влияет на порядок каскадного включения перекрывающих друг друга правил таблиц стилей (т.е. множественные правила, примененные к одним и тем же элементам). Значение, которое при этом возвращается, не несет значащей информации. Для того чтобы удалить правило из массива rules объекта styleSheet, следует ис- пользовать метод removeRule (). Будьте внимательны, задавая значение индекса правила, 822 Часть III. Объекты документа
которое вы хотите удалить. В сценарии можно использовать цикл for, чтобы в массиве пра- вил найти соответствие свойству selectorText (при условии использования уникальных селекторов). Индекс соответствующего правила в дальнейшем может использоваться в каче- стве параметра метода removeRule (). Этот метод не возвращает значения. Соответствующие методы в NN6+ называются insertRule () и deleteRule (). Пример Приложение The Evaluator в IE4+ используется также для добавления правила таблицы стилей в первый объект styleSheet страницы. Сначала убедитесь в доступности таблицы стилей, введя в верхнее текстовое поле следующее выражение. document.styleSheets[0].disabled = false Далее добавьте стиль, который задает цвет элемента text Аге а. document.styleSheets[0].addRule("textarea" , "color:red") Введите в нижнее текстовое поле корректную ссылку на любой объект (например, document. body), чтобы узнать, как добавленный стиль применяется к элементу textArea. Теперь можете удалить добавленный ранее стиль, обратившись к последнему элементу коллекции rules. document.styleSheets[0].removeRule(document.styleSheets[0]. rules.length - 1) См. также: методы deleteRule () и insertRule () deleteRule(индекс) InsertRule("правило", индекс) Возвращаемое значение: целочисленное (для insertRule ()) Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari 14- Метод insertRule () присоединяет или вставляет правило таблицы стилей в текущий объект styleSheet. Первый параметр представляет собой строку, содержащую правило стиля в том виде, в котором оно обычно представлено в таблице стилей, включая селектор и фигурные скобки, в которые заключен список пар атрибут: значение, разделенных точками с запятой. Место вставки нового правила в массиве cssRules задается с помощью индекса. Если вы хотите присоединить правило в конце списка, используйте в качестве параметра свойство length массива cssRules. Порядок расположения правил в объекте styleSheet может повлиять на порядок каскадного включения перекрывающих друг друга правил таблиц стилей (т.е. множественные правила, примененные к одним и тем же элементам). Значение, которое возвращается, представляет собой индекс места расположения встав- ленного правила. / В Safari 1.0 этот метод выполняется без вывода сообщения об ошибке, хотя /наммвтцг вставленное правило никак не влияет на вид элементов страницы. Для того чтобы удалить правило из массива cssRules объекта styleSheet, следует использовать метод deleteRule (). Будьте внимательны, задавая значение индекса прави- ла, которое вы хотите удалить. В сценарии можно использовать цикл for, чтобы в массиве правил cssRules найти соответствие свойству selectorText (при условии использования уникальных селекторов). Индекс соответствующего правила в дальнейшем может использо- ваться в качестве параметра метода deleteRule (). Этот метод не возвращает значения. Соответствующие методы в IE4+ называются addRule () и removeRule (). Глава 26. Таблица стилей и объекты стилей 823
Пример Приложение The Evaluator в NN6+/Moz также используется для добавления правила таб- лицы стилей в первый объект styleSheet страницы. Сначала убедитесь в доступности табли- цы стилей, введя в верхнее текстовое поле следующее выражение. document.styleSheets[0].disabled = false Далее добавьте стиль, который задает цвет элемента text Area. document.styleSheets[0].insertRule("textarea {color:red}", document.styleSheets[0].cssRules.length) Введите в нижнее текстовое поле корректную ссылку на любой объект (например, document. body), чтобы узнать как добавленный стиль применяется к элементу textArea. Теперь можете удалить добавленный ранее стиль, обратившись к последнему элементу коллекции правил. document.styleSheets[0].deleteRule(document.styleSheets[0]. cssRules.length - 1) См. также: методы addRule () и removeRule (). Объекты cssrule и rale Свойства Методы Обработчики событий cssText parentstylesheet readonly selectorText style type Синтаксис Доступ к свойствам объектов rule и cssrule. (IE4+) document. styleSheets [индекс] . rules [индекс] . свойство (MaclE5/W3C) document.styleSheets [индекс] .cssRules [индекс] .свойство Описание объектов Объекты rule и cssRule — различные варианты одних и тех же объектов. В IE4+ объект называется rule (а массив этих объектов — rules). В NN6 (и Мас1Е5), в соответст- вии с рекомендациями W3C DOM, объект имеет имя cssRule (а массив этих объектов — cssRules). В этом разделе мы назовем их объектами правил. Объект правила состоит из двух основных компонентов. Первый —это текст селектора, которыр определяет, к какому элементу (элементам) следует применить правило стиля. Второй компонент — определение стиля с набором пар атрибут: значение, разделенных точками с запятой. В обеих моделях объектов, IE4+ и NN6+/W3C, определение стиля считается объек- том style, который имеет целый ряд свойств, представляющих поддерживаемые браузером 824 Часть III. Объекты документа
атрибуты стиля. Объект style, входящий в состав объекта правила, — это тот же объект style, связанный с одним из объектов элементов HTML. Для того чтобы получить доступ к свойст- вам style правила таблицы стилей, следует задать длинную ссылку. document.styleSheets[0].rules[0].style.color = "red"; Формат ссылки полностью соответствует правилам точечного синтаксиса JavaScript. Свойства cssText Значение: строка Чтение/Запись Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Свойство cssText полностью возвращает текст текущего объекта cssRule. Поскольку текст, возвращенный этим свойством, может быть разделен на отдельные строки, к свойствам ин- дивидуальных стилей рекомендуется обращаться с помощью свойства style объекта cssRule. Safari 1.0 возвращает пустую строку. См. также: свойство style. parentStyleSheet Значение: объект styleSheet Только для чтения Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari 1+ Свойство parentStyleSheet представляет собой ссылку на объект styleSheet, со- держащий текущий объект cssRule. Возвращаемое значение является ссылкой на объект styleSheet, у которого сценарий может запрашивать и изменять свойства, характеризую- щие всю таблицу стилей. См. также: свойство parentRule. readonly Значение: булево Только для чтения Совместимость: WinIE5+, MacIE5, NN-, Moz-, Safari- Имя readonly не совсем соответствует сущности этого свойства. Булево значение позво- ляет сценарию определить следующее: был ли текущий объект styleSheet правила вложен в документ с помощью элемента style, импортировался из внешнего файла посредством эле- мента link или использовалось правило ©import. Если таблица стилей была вложена с помо- щью элемента style, свойство readonly будет иметь значение false. Если таблица стилей была импортирована, свойство имеет значение true. Значение true не свидетельствует о том, что свойства стилей не могут быть изменены сценарием. Свойства стилей могут быть изменены в процессе работы, однако эти изменения не будут отображены во внешнем файле. См. также: свойство styleSheet. readonly. selectorText Значение: строка Только для чтения Совместимость: WinIE5+, MacIE5, NN6+, Mozl+, Safaril+ Свойство selectorText возвращает только селекторную часть правила таблицы сти- лей. Значение представляет собой строку. Если селектор содержит множественные, разде- ленные пробелами элементы, значение selectorText возвращается в форме строки с про- Глава 26. Таблица стилей и объекты стилей 825
белами. В том случае, если селектор применен к классам, которым предшествует точка, или идентификаторам, которым предшествует символ решетки, эти специальные символы также возвращаются в виде части строки. Если вы решили заменить селектор правила, рекомендуется удалить исходное правило и вста- вить на его место новое. При этом вы сохраните свойство style исходного правила и зада- дите стиль новому правилу. Пример Используйте приложение The Evaluator для изучения свойства selectorText правила первого объекта styleSheet страницы. Введите каждое из приведенных ниже выражений в верхнем текстовом поле. document.styleSheets[0].rules[0].selectorText document.styleSheets[0].rules[1].selectorText Сравните полученные результаты с результатами для элемента style страницы. См. также: свойство style. style Значение: объект style Чтение/Запись Совместимость: WinIE5+, MacIE5, NN6+, Mozl+, Safaril+ Свойство style объекта rule (или cssRule) само по себе является объектом, свойства которого состоят из атрибутов стилей CSS, поддерживаемых браузером. Для изменения свой- ства объекта style следует задать достаточно длинную ссылку. document.styleSheets[0].rules[0].style.color = "red"; Любые изменения свойств style правила влияют на стиль элементов, обозначенных в селекторе правил. Если вы хотите изменить стиль отдельного элемента, обратитесь к свой- тву style именно этого элемента. Значения стилей, примененные непосредственно к эле- менту, доминируют и отменяют значения, назначенные этому элементу в таблице стилей. Пример Приложение The Evaluator можно смело применять для изменения свойства style пра- вила styleSheet объекта страницы. Ниже приведены выражения, выполняемые в IE4+. Вы всегда можете заменить ссылку на объект cssRule ссылкой на объект rule, используемый в NN6+, Мас1Е5 и W3C DOM. Сначала перезагрузите страницу приложения и убедитесь, что таблица стилей активна. Для этого введите в верхнем текстовом поле следующее выражение. document.styleSheets[0].disabled = false Первое правило задается для элемента туР страницы. Изменим стиль font-size этого правила. document.styleSheets[0].rules[0].style.fontsize = "20pt" Изучите свойства объекта style: ознакомьтесь с описанием объекта style далее в этой главе и поэкспериментируйте с этими свойствами, произвольным образом изменив каждое из них. Чтобы восстановить значения стилей, достаточно перезагрузить страницу. См. также: объект style. type Значение: целое число Только для чтения Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safarl+ 826 Часть III. Объекты документа
W3C DOM выделяет несколько классов правил таблиц стилей. Для того чтобы сценарий мог определить, с каким типом cssRule он имеет дело, свойство type возвращает целое число, значение которого указывает на один из типов cssRule. Не все доступные типы пра- вил могут быть применены в NN6. Полный список типов, который соответствует стандартам W3C DOM, выглядит следующим образом. Тип Описание 0 1 Unknown type (Неизвестный тип) Regular style rule (Правило обычного стиля) 2 3 4 5 6 ©charset rule (Правило набора символов) ©import rule (Правило импортирования) ©media rule (Правило носителя) ©font-space rule (Правило шрифта) ©page rule (Правило страницы) Большинство правил таблиц стилей, с которыми вам предстоит работать, относится к ти- пу 1. Чтобы получить более подробную информацию о типах правил, обратитесь к специфи- кации W3C для CSS по адресу: http://www.w3 .org/TR/REC-CSS2. Объекты currentstyle, runtimestyle и style Свойства Методы Обработчики событий (См. ниже) Синтаксис Доступ к свойствам объектов currentstyle, runtimestyle и style. (IE4+/W3C) ссылкаНаЭлемент. style. свойство (IE4+/W3C) document. styleSheets [индекс] . style. свойство (IE5+) ссылкаНаЭлемент.currentstyle.свойство (IE5.5) ссылкаНаЭлемент. runtimestyle. свойство Описание объектов Объекты currentstyle, runtimestyle и style возвращают объект, содержащий целый ряд свойств, относящихся к спецификациям таблицы стилей, которая, в свою очередь, связана либо с объектом stylesheet (только для объекта style), либо с объектом любого отображаемого элемента HTML. Благодаря возможности переформатирования страницы в современных браузерах изменение свойств объектов style и runtimestyle, характер- ное для IE, мгновенно отражается на содержимом Web-страницы. Доступ к базовому объекту style осуществляется так же, как и к свойству объекта styleSheet или объекта элемента HTML. Необходимо помнить, что свойства стиля эле- мента HTML отображаются в объекте style только в том случае, если спецификация задана 827 Глава 26. Таблица стилей и объекты стилей
с помощью атрибута style внутри дескриптора элемента. Если необходимо таблицы стилей применить с помощью дескрипторов style или link (и если сценарий должен восприни- мать те значения свойства style, которые были заданы таблицами стилей), вы должны по- лучить свойства с помощью объекта currentstyle, доступного Только для чтения (это свойство поддерживается в IE5+). Объект currentstyle возвращает присоединенную таб- лицу стилей, примененную к объекту элемента HTML. Свойства объекта currentstyle в IE несколько отличаются от свойств объекта style. В объекте currents tyle отсутствуют свойства, содержащие комбинированные значения — border или borderBottom. С другой стороны, этот объект имеет такие специальные свой- ства, как расположение сторон прямоугольника обрезки (clipTop, clipRight, clipBottom и clipLef t), которые не поддерживаются свойством clip. Компания Microsoft разработала еще один объект стиля— runtimestyle— в IE5.5. Этот объект позволяет сценарию отменить любое свойство стиля, заданное в таблице стилей с помощью атрибута style. Иными словами, объект runtimestyle является версией currentstyle, доступной для чтения и записи. Отличие состоит в том, что, задав новое значение одному из свойств этого объекта, вы не сможете изменить определение значения в атрибуте style таблицы стилей. В основном, сценарий будет модифицировать свойство style элемента для того, чтобы внести необходимые изменения, если только вы не изменяе- те стили, подключая и отключая таблицы стилей (или не изменяете свойство className элемента таким образом, чтобы его контролировал другой селектор). Свойства стиля Если вы перечислите все свойства объекта style, поддерживаемые браузерами, начиная с IE4 и NN6, то у вас получится список, состоящий примерно из 180 элементов. Примерно такой же список получится при перечислении свойств для всех версий браузеров; подобный список атрибутов таблиц стилей существует и в W3C CSS. Имена атрибутов CSS зачастую неудобны для использования в сценарии, поскольку содержат дефис (например, font-size). Идентификаторы же JavaScript не могут иметь дефис в имени. Поэтому атрибуты, состоящие из нескольких слов, преобразуются в стандарт interCap (например, fontsize). Не все свойства поддерживаются в браузерах, воспринимающих такую модель объекта, как style. В частности, компания Microsoft разработала целый ряд свойств, уникальных для IE, а иногда — только для IE для Windows. Компания Netscape, в свою очередь, предлагает свойства, которые будто поддерживаются объектом style, однако в действительности брау- зеры их не поддерживают. Например, в спецификации CSS определено несколько атрибутов, которые ускоряют процесс получения содержимого, вводящегося с помощью синтезатора ре- чи. NN6 и NN7+ этого не уточняет, однако программа браузера Gecko в ядре браузера может быть адаптирована для такого объекта. Поэтому, если вы видите в списке свойство, имя ко- торого ни о чем вам не говорит, проверьте его в совместимых браузерах, чтобы понять, как оно работает. Вы также обнаружите несколько свойств, характерных для Mozzilla-совмести- мых браузеров, — их имена начинаются с ключевого слова moz. Все они соответствуют еще полностью не отлаженной технологии CSS 3. Префикс moz гарантирует совместимость дан- ных свойств с будущими свойствами браузеров (нетрудно догадаться, что в последних этот префикс будет отсутствовать). Некоторые браузеры также предлагают дополнительные свойства объекта style, кото- рые в действительности браузерами не поддерживаются. Рассмотрим, например, свойство quote объекта style для 1Е5/Мас и NN6, соответствующее атрибуту стиля quotes в спе- цификации W3C CSS2. Оказывается, свойство quote стиля не может использоваться сцена- рием для этих версий браузеров. Если вы видите, что определенное свойство поддерживается 828 Часть III. Объекты документа
только браузерами Мас1Е5 и NN6+, то проверьте свойство style (и атрибут таблицы стилей) в приложении The Evaluator, прежде чем применить его в своем проекте. С объектом связано такое количество свойств, что применить одно из них для достижения желаемого эффекта не так уж и просто. Чтобы облегчить вашу задачу, приведенный ниже список свойств разделен на функциональные категории, расположенные в соответствии с частотой их применения. Категория Описание Text & Fonts (Текст и шрифты) Спецификация шрифта, отображение текста, выравнивание текста Inline Display & Layout (Вид и макет) Вид элементов, выравнивание и изображение Positioning (Расположение) Явное расположение “слоев" Background (Фон) Фоновые изображения и цвета Borders & Edges (Границы и отступы) Границы, отступы и поля вокруг элементов Lists Параметры элементов ul или ol (Списки) Scrollbars (Полосы прокрутки) Цвет полосы прокрутки (только для IE5.5/Windows) Tables Параметры элементов и компонентов table (Таблицы) Printing (Печать) Разрывы страниц и выравнивание страниц при печати Miscellaneous (Дополнительные) Вспомогательные атрибуты Aural (Акустика) Воспроизведение содержимого, полученного из синтезатора речи Значения свойств Свойства объекта style имеют строковые значения. Более того, значения многих групп свойств стилей имеют общий формат. Поэтому полезно знать формат часто используемых значе- ний. Задача этой главы заключается не в описании особенностей таблицы стилей, а в ознакомлении с процессом создание сценариев. Если вы встретите незнакомые вам термины, воспользуйтесь справочниками или найдите нужную информацию о таблицах стилей CSS во Всемирной сети. Длина Существует немало значений длины, каждое из которых определяет физический размер в документе. Содержимое документа может отображаться на мониторе или распечатываться на листе бумаги. Поэтому любое значение длины должно указываться в определенных единицах измерения. Некоторые единицы измерения (рх, em, ех) считаются относительными, поскольку соответствующие точные размеры зависят от ряда факторов, не зависящих от таблицы стилей Глава 26. Таблица стилей и объекты стилей 829
(например, плотность пикселей конкретного экрана). Существуют и такие единицы, которые за- даны элементами глобального масштаба (например, размеры поля элемента р, заданные в em, зависят от настроек размера шрифта элемента body). Абсолютные единицы измерения (in, cm, mm, pi, pt) предпочтительнее использовать для документов, подлежащих печати. В сценарии единицы измерения длины следует использовать согласно следующей таблице. Единица измерения В сценарии Пример Пиксель рх 14px Em етп 1.5em Ex ех 1.5ex Дюйм in 3.0in Сантиметр cm 4.0cm Миллиметр mm 40mm Цицеро Pi 72pi Точка Pt 14pt Строковое значение длины может быть также представлено в процентах. Например, сти- лю абзаца lineHeight может задаваться размер шрифта, составляющий 120% обычного размера шрифта абзаца. Для этого необходимо записать следующее выражение. document.getElementByld("rnyP").style.lineHeight = "120" ,- Наследование стиля — одна из основных характеристик CSS — зачастую существенно влияет на свойства стиля, значения которого выражают длину. Цвет Существует три типа значений цвета: значения RGB (в нескольких форматах); обычные названия цветов; имена элементов пользовательского интерфейса системы. Значения RGB могут быть шестнадцатеричными. Чаще всего такие значения содержат в начале символ решетки, за которым следует шесть цифр, например #f f OOf f (можно исполь- зовать буквы как верхнего, так и нижнего регистра). Существуют специальные сокращения: вы задаете три цифры (подразумевается, что заданное значение будет расширено — каждая из цифр будет продублирована). Например, запись #fOf всегда расширяется до #f fOOf f. RGB-значение также ккожет задаваться в виде префикса rgb () и трех цифр (от 0 до 255). Кроме того, цвет можно указать как процентное соотношение компонентов красного, зелено- го и синего цветов. Ниже приведено несколько примеров. document.styleSheets[0].rules[0].style.color = "rgb(0, 255, 0)"; document.styleSheets[0].rules[0]-style.color = "rgb(0%, 100%, 0%)"; Браузеры поддерживают и полный список обычных названий цветов, разработанных компанией Netscape. Список с примерами цветов вы найдете по адресу: http://developer.netscape.com/library/manuals/1998/htmlguid/colortab.htm. Однако не все эти цвета Web-безопасны. Безопасные цвета вы можете определить, посетив страницу http: / /www. lynda. com/hexh. html. 830 Часть III. Объекты документа
Последняя категория значений цвета относится к элементам пользовательского интерфейса. Многие из этих элементов определяются настройками, заданными в папке Панель управления для монитора в системе. Строковые значения соответствуют распознаваемым компонентам пользовательского интерфейса — системным цветам. activeborder highlight scrollbar activecaption highlighttext threeddarkshadow appworkspace inactiveborder threedface background inactivecaption threedhighlight buttonface inactivecaptiontext threedlight shadow buttonhighlight infobackground threedshadow buttonshadow infotext window buttontext menu windowframe captiontext menutext windowtext graytext Использование таких настроек цвета при создании общедоступных Web-страниц нежела- тельно, поскольку в этом случае все зависит только от выбранных пользователем настроек. Работая над созданием корпоративного Web-узла (при условии, что системные настройки подлежат строгому контролю) вы вполне можете задать цвета таким образом. Это поможет вам назначить безопасную цветовую схему Web-страниц. Стороны прямоугольника Многие свойства стиля управляют видом сторон прямоугольников (например, толщина границы вокруг блокового элемента). В большинстве случаев значения стилей могут быть применены к отдельным сторонам или к комбинациям сторон прямоугольника, в зависимости от того, сколько значений может иметь то или иное свойство. Количество значений влияет на четыре стороны прямоугольника следующим образом. Количество значений Влияние 1 i Всем четырем сторонам назначено одно и то же значение 2 Верхней и нижней стороне назначено первое значение; левой и правой— второе значение 3 Верхней стороне назначено первое значение; левой и правой—второе значение; нижней стороне—третье значение 4 Верхней, правой, нижней и левой сторонам назначены индивидуальные значения в указанном порядке Например, вы можете задать цвет границы элемента так, чтобы все его стороны были ок- рашены в красный цвет, — для этого используют следующее выражение. ссылкаНаЭлемент.style.borderColor = "red"; Если же вы хотите, чтобы верхняя и нижняя стороны были красного цвета, а левая и пра- вая — зеленого, оператор должен выглядеть следующим образом. ссылкаНаЭлемент.style.borderColor = "red green"; Многие стили имеют свойства, в которых можно задавать множественные значения. Это могут быть цвета, длины или другие величины из списка допустимых значений. Гпава 26. Таблица стилей и объекты стилей 831
Комбинированные значения Существует иная категория значений стиля, в которую входят свойства, являющиеся со- кращениями для нескольких родственных свойств. Например, свойство border включает в себя свойства borderwidth, borderstyle и borderColor. Это возможно, поскольку три свойства-компонента представляют различные классы значений: borderwidth— ши- рина; borderstyle основано на списке возможных значений; borderColor— значение цвета. Следовательно, вы можете задать одно или более значений этого свойства (в произ- вольном порядке), и браузер поймет, как применить эти значения к назначенному подсвойст- ву. Каждому такому подсвойству можно назначить только одно значение. Это означает сле- дующее: если для четырех сторон прямоугольника задано одно свойство, значение этого свойства применяется ко всем четырем сторонам. Например, если задать свойству border одно значение следующим образом. ссылкаНаЭлемент.style.border = "blue"; то это будет равносильно такому оператору. ссылкаНаЭлемент.style.borderColor = "blue"; Однако если вы задаете множественные элементы. ссылкаНаЭлемент.style.border = "groove blue Зрх"; то это воспринимается, как эквивалент следующих трех операторов. ссылкаНаЭлемент.style.borderstyle = "groove"; ссылкаНаЭлемент.style.borderColor = "blue"; ссылкаНаЭлемент.style.borderwidth = "3px"; В описаниях свойств, которые приведены ниже, эти комбинированные значения отмечены своими названиями, употребляемыми в сценариях, с помощью оператора (| |) (оператор ИЛИ). border = "borderstyle || borderColor || borderwidth"; URL Формат свойства style отличается от формата остальных значений свойств, содержащих URL. Этот формат содержит приставку url (), где в скобках записан URL (относительный или абсолютный). Сам URL в кавычки не заключают, хотя остальные правила его задания со- блюдаются строго. ссылкаНаЭлемент.style.backgroundimage = "url(chainlink.jpg)"; URL не должен содержать пробелов. Если пробелы все же существуют, используйте URL- кодированную версию для задания адреса: преобразуйте пробелы в символы 20%. Этот формат помогает отличить значение URL от любого другого строкового значения в записях свойств. Свойства текста и шрифта color Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: цвет изображения элемента. Используется, в основном, для назначения цвета текста. При отображении в некоторых браузерах может влиять на цвет границы и вы- деленных участков других элементов. Значение: спецификация цвета. Пример: elementRef.style.color = "rgb(#22FFOO)"; 832 Часть III. Объекты документа
font Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: до шести свойств стиля, связанных со шрифтами. Значение: комбинированные fontstyle] |fontVariant | |fontweight| | fontsize| | lineHeight | | f ontFamily. См. индивидуальные свойства для форматов их значений. Пример:elementRef.style.font = "bold sans-serif 16px"; fontFamily Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: семейство шрифтов, которое должно применяться к элементу в указанном порядке очередности. Значение: разделенный запятыми список семейств шрифтов, которые должны при- меняться к элементу, начиная с имени наиболее предпочтительного для данного контек- ста варианта. Вы можете использовать одно из родовидных имен семейств. В этом слу- чае выбор оптимального шрифта, соответствующего классу, будет зависеть от браузера: serif | sans-serif | cursive | fantasy | monospace. He все браузеры поддерживают каждую из констант, однако serif, sans-serif и monospace поддерживают любой браузер. Пример:elementRef.style.fontFamily = "Bauhaus 93, Arial, monospace"; fontsize Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует размер символов текущего семейства шрифтов. Значение: длины (обычно значения выражаются в единицах рх и pt); константы относи- тельных размеров: larger | smaller; константы абсолютных размеров: xx-small | x-small | small|medium]large|х-large|хх-large. Пример: elementRef.style.fontsize = "16px" elementRef.style.fontsize = “small"; fontSizeAdjust Совместимость: WinlE-, MacIE5, NN6+, Moz1+, Safari- Контролирует: значение длины вторичного семейства шрифтов с тем, чтобы его символы имели ту же высоту, что и символы основного семейства шрифтов. Значение: число (включая значения с плавающей запятой) или попе. Пример: elementRef.style.fontSizeAdjust = "1.05"; fontStretch Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: ширину символов шрифта при отображении. Значение: константа ultra-condensed|extra-condensed|condensed|semi-condensed| semi-expanded| expanded] extra-expanded|ultra-expanded или wider |narrower | inherit|normal. Пример: elementRef.style.fontStretch = "expanded"; Глава 26. Таблица стилей и объекты стилей 833
fontstyle Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: курсивное начертание символов. Значение: константа normal | italic | oblique | inherit. Пример: elementRef.style.fontstyle = "italic"; fontvariant Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari- Контролирует: отображение букв в виде строковых символов. Значение: константа normal | small-caps | inherit. Пример: elementRef.style.fontvariant = "small-caps"; fontweight Совместимость: WinIE4+, MacfE4+, NN6+, Mozl+, Safaril+ Контролирует: отображение символов полужирным или слабым полужирным начертани- ем. Шрифты, поддерживающие нумерованную градацию, можно контролировать с помощью цифровых значений. Нормальный = 400; полужирный = 700. Значение: константа bold|bolder|lighter[normal|100|200|300|400|500|600| 700|800|inherit. Пример: elementRef.style.fontweight = "bold"; letterspacing Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: расстояние между символами. Используется для того, чтобы отменить собственные характеристики семейства шрифтов. Значение: длина (обычно в ет, относительно размера текущего шрифта); константа normal|inherit. Пример: elementRef.style.letterspacing = "1.2em"; lineBreak Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: правила разрыва строки для текстового содержимого на японском языке. Значение: константа normal | strict. Пример: elementRef.style.lineBreak = "strict"; lineHeight Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: высоту прямоугольного пространства, содержащего строку символов текста. Значение: длина (обычно в ет, относительно размера текущего шрифта); число (множитель унаследованной высоты строки); процентное отношение (относительно унаследованной вы- соты строки); константа normal | inherit. Пример:е1ement Ref.style.lineHe i ght = "1.1"; 834 Часть III. Объекты документа
quotes Совместимость: WinlE-, MacIE5, NN6+,.Mozl+, Safari- Контролирует: символы, используемые в качестве кавычек; Значение: разделенные пробелом символы открытых и закрытых кавычек; константа попе|inherit. Пример: elementRef.style.quotes = "« rubyAlign Совместимость: WinIE5+, MacIE5, NN-, Moz-, Safari- Контролирует: выравнивание “рубинового” текста в элементе ruby. Значение: константа auto| left | center) right | distribute-letter | distribute- space|line-edge. Пример: RUBYelementRef.style.rubyAlign = "distribute=letter"; rubyOverhang Совместимость: WinIE5+, MacIE5, NN-, Moz-, Safari- Контролирует: отступ “рубинового” текста в элементе ruby. Значение: константа auto | whitespace | попе. Пример: RUBYelementRef.style.rubyOverhang = "whitespace"; rubyPosition Совместимость: WinIE5+, MacIE5, NN-, Moz-, Safari- Контролирует: расположение “рубинового” текста относительно основного текста в эле- менте элемента ruby. Значение: константа above | inline. Пример: RUBYelementRef.style.rubyPosition = "inline"; textAlign Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: горизонтальное выравнивание текста относительно элемента, в котором содержится этот текст. Значение: константа center | justify | left | right. Пример: elementRef.style.textAlign = "center"; textAlignLast Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Контролирует: горизонтальное выравнивание последней строки каждого абзаца. Значение: константа auto | center | justify | left | right. Пример: elementRef.style.textAlignLast = "justify"; Глава 26. Таблица стилей и объекты стилей 835
textAutospace Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Коитролирует: дополнительные пробелы между идеографическими и неидеографиче- скими символами. Значение: константа none | ideograph-alpha | ideograph-numeric | ideograph- parenthesis |ideograph-space. Пример:elementRef.style.textAutospace = "ideograph-alpha"; textDecoration Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: отображение подчеркивания, линии над строкой текста и линии зачеркивания. Значение: константа none | blink | line-through | overline | underline. Пример: elementRef.style.textDecoration = "underline"; textDecorationBlink textDecorationLineThrough textDecorationNone textDecorationOverline textDecorationUnderline Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Контролирует: индивидуальные характеристики оформления текста, позволяющие при- менить различные методы форматирования к одному и тому же тексту. Значение: булево выражение true | false. Пример: elementRefstyle.textDecorationUnderline = true; textindent Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: величину отступа для первой строки блокового элемента текста (например, р). Значение: длина (отрицательные значения для втяжки); процентное соотношение (отно- сительно унаследованного значения). Пример:elementRef.style.textindent = "2.5em"; textJustify Совместимость: WinIE5+, MacIE5, NN-, Moz-, Safari- Контролирует: дополнительные отступы для элемента, свойство text Align которого имеет значение justify. Значение: константа auto|distribute|distribute-all-lines|distribute- center-last|inter-cluster|inter-ideograph|inter-word|kashida|newspaper. Пример: elementRef.style.textJustify = "distribute"; 836 Часть III. Объекты документа
textJustifyTrim Совместимость: WinIE5+, MacIE5, NN-, Moz-, Safari- Для использования в будущем. textKashidaSpace Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Контролирует: соотношение расширения протяжки и расширения пробелов для арабских систем письма. Значение: процентное соотношение. Пример: elementRef.style.textKashidaSpace = "90% "; textoverflow Совместимость: WinIE6+, MacIE-, NN-, Moz-, Safari- Контролирует: отображение троеточия в конце длинной строки текста, что указывает на доступность дополнительной информации. Значение: константа clip | ellipsis. textShadow Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: отображение тени вокруг элементов текста. Внимание: атрибут стиля для этого свойства не поддерживается в Мас1Е5 и NN6/7, однако данное свойство действительно для объекта style. Значение: каждая спецификация тени состоит из цвета по выбору и трех разделенных пробелами значений длины (горизонтальное смещение тени, вертикальное смещение тени, длина радиуса тени). Множественные значения отделены запятыми. textTrans f опп Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari)+ Контролирует: регистр отображения текста на экране (имеется в виду — без изменения регистра исходного текста). Значение: константа none | capitalize | lowercase | uppercase. Пример: elementRef.style.textTransform = "uppercase"; textUnder1inePos1tion Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Контролирует: расположение линии в подчеркнутом начертании — над текстом или под текстом. Кажется сходным по значению с textDecorationUnderline и textDecorat ionOver1ine. Значение: константа above | below. Пример: elementRef.style.textUnderlinePosition = "above"; Глава Таблица стилей и объекты стилей 837
unicodeBidi Совместимость: WinIE5+, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: в двунаправленном тексте (например, английском и арабском), насколько блок текста, направленный в противоположную сторону, вложен во внешний элемент. Значение: константа normal | embed | bidi-override. Пример: elementRef.style.unicodeBidi = "embed"; whiteSpace Совместимость: WinIE5.5+, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: интерпретацию символов пробела в коде источника элемента. Значение: константа normal | nowrap | pre. Пример: elementRef.style.whiteSpace = "nowrap"; wordBreak Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: характеристики разрыва слова (в основном, для текстов на азиатских язы- ках или содержащих как латинские, так и азиатские символы). Значение: константа normal | break-all | keep-all. Пример: elementRef.style.wordBreak = "break-all"; wordSpacing Совместимость: WinIE6+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: расстояние между словами. Значение: длина (обычно в единицах ет); константа normal. Пример: elementRef.style.whiteSpacing = "lem"; wordwrap Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Контролирует: характеристики перехода слова на новую строку в блоковом элементе текста, элементе с внутренне определенными размерами или позиционируемом элементе. Значение: константа normal | break-word. Пример: elementRef . style . wordwrap = "break-word" ; writingMode Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Контролирует: направление потока содержимого Web-страницы (слева направо/сверху вниз или сверху вниз/справа налево, как в некоторых азиатских языках). Значение: константа lr-tb | tb-rl. Пример: elementRef.style.writingMode = "tb-rl"; 838 Часть III. Объекты документа
Свойства вида и макета документа clear Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: расположение элемента относительно соседнего плавающего элемента. Значение: константа both | left | none | right. Пример: elementRef.style.clear = "right"; clip Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: прямоугольник обрезки элемента (т.е. прямоугольника, сквозь который пользователь видит содержимое элемента). Значение: rect(topLength, rightLength, bottomLength, leftLength)|auto. Пример: elementRef.style.clip = "rect(10px, ЗООрх, Opx)"; clipBottom clipLeft clipRight clipTop Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: отдельные границы прямоугольника обрезки элемента. Эти свойства объекта currentstyle доступны Только для чтения. Значение: длина | auto. Пример: var leftEdge = elementRef.currentstyle.clipLeft; content Совместимость: WinlE-, MacIE5+, NN6+, Mozl+, Safari- Контрблирует: содержимое, отображаемое элементом. Внимание: атрибут стиля для это- го свойства не поддерживается в 1Е5/Мас и NN6, однако данное свойство действительно для объекта style. Значение: см. http: //www. w3. org/TR/REC-CSS2/generate. html #propdef-content. counterIncrement Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: шаг изменения показаний счетчика, которые должны отображаться в свойстве content стиля. Внимание: атрибут стиля для этого свойства не поддерживается в Мас1Е5 и NN6/7, но данное свойство действительно для объекта style. Значение: одна и более пар идентификатора счетчика и целых чисел. Глава 26. Таблица стилей и объекты стилей 839
counterReset Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: восстанавливает именованный счетчик содержимого, которое должно отображаться в свойстве content стиля. Внимание: атрибут стиля для этого свойства не поддерживается в Мас1Е5 и NN6/7, но данное свойство действительно для объекта style. Значение: одна и более пар идентификаторов счетчика и целых чисел. cssFloat Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Коитролирует: горизонтальное выравнивание элемента, при котором элемент содержи- мого заключается в другой элемент (обычно изображение заключается в текст). Соответствует атрибуту float стиля CSS. См. также свойство floatstyle ниже. Плавающие (непозицио- нируемые) элементы следуют целому ряду правил. Подробности их использования вы найде- те по адресу: http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-float. Значение: константа lef 11 right | попе. Пример: elementRef . style. cssFloat = "right", ; cursor Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari- Контролирует: значок, который используется в качестве указателя мыши на экране. Вы- брать значок можно из библиотеки системы. В спецификации CSS2 присутствует синтаксис, предназначенный для загрузки дополнительных значков указателя, но IE5.5 и NN6/7 такой возможности не предоставляют. Значение: константа auto | crosshair | default | е-resize | help | move | n-resize | ne-resize|nw-resize(pointer|s-resize|se-resize|sw-resize|text|w-resize(wait. Пример: elementRef.style.cursor = "hand"; direction Совместимость: WinIE5+, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: направление расположения (слева направо или справа налево) внедренно- го текста (то же, что и атрибут dir элемента.). Значение: константа Itr | rtl. Пример: elementRef.style.direction = "rtl"; display Совместимость: WinIE4+, MaclE4+, NN6+, Mozl+, Safaril+ Контролирует: отображение элемента на экране. Содержимое Web-страницы, окружаю- щее неотображаемый элемент, располагается таким образом, чтобы занять место неотобра- жаемого элемента — так, будто этот элемент вовсе не должен отображаться на экране (еще один метод — см. свойство visibility). Обычно используется для того, чтобы скрыть или показать подразделы графической древовидной структуры. Может также указывать браузеру на необходимость отображения того или иного элемента как вложенного, так и блокового. Существуют специальные значения для особых типов элементов (например списков, таблиц, ячеек таблиц и т.д.). 840 Часть III. Объекты документа
Значение: константа block | compact | inline | inline-table | list-item j none | run-in|table|table-caption|table-cell|table-column-group|table-footer- group |table-header-group|table-row]table-row-group. Пример:elementRef.style.display = "none"; filter Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Контролирует: эффекты отображения статического содержимого Web-страницы и эффекты перехода от скрытого состояния к отображенному. Компания Microsoft пересмотрела синтаксис таблиц стилей filter для WinIE5.5 (используя элемент управления DXImage Transform ActiveX). Удобная утилита в режиме реального времени позволяет просмотреть результаты работы фильтра и предоставляет возможность копирования -и вставки кода. С помощью этой утилиты вы сможете добавлять фильтры и контролировать их с помощью сценария. Добавить в сценарий код эффекта скрытия и отображения можно в несколько этапов. Сначала этот эффект нужно за- грузить. Перед тем, как изображение будет показано, программа должна выполнить некоторые операции. Для получения и изменения спецификации фильтра используйте свойство style. filter. Для того чтобы использовать индивидуальные свойства фильтра, используйте объект elem. styles [i]. Подробнее объект f i Iter рассмотрен далее в этой главе. Значение: спецификация фильтра как строки. Пример: var filterSpec = elementRef.style.filter = "alpha(opacity=50) flipHO "; layoutGrid Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: свойства сетки страницы (в основном, для страниц на азиатских языках). Значение: комбинированные значения layoutGridMode | | layoutGridType | | layoutGridLine | | layoutGridChar. См. индивидуальные свойства форматов значений. Пример: elementRef.style.layoutGrid = "2em strict"; layoutGridChar Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: размер сетки символов (азиатские языки). Значение: длина; процентное соотношение; константа none | auto. Пример: elementRef.style.layoutGridChar = “Зет"; layoutGridLine Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: линейную высоту сетки (азиатские языки). Значение: длина; процентное соотношение; константа none | auto. Пример: elementRef.style.layoutGridLine = "110%"; layoutGridMode Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: одномерную или двухмерную сетку (азиатские языки). Значение: константа both | попе 11 ine | char. Пример: elementRef.style.layoutGridMode = "both"; Глава 26. Таблица стилей и объекты стилей 841
layoutGridType Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: тип сетки для текстового содержимого (азиатские языки). Значение: константа loose | strict | fixed. Пример: elementRef.style.layoutGridType = "strict"; markerOffset Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Контролирует: расстояние между границами прямоугольника с маркерами (выделение, которое отображается в виде прямоугольника с маркерами управления) и блоковым элементом текста. Внимание: атрибут стиля для этого свойства не поддерживается в Мас1Е5 и NN6/7, од- нако данное свойство действительно для объекта style. Значение: длина; константа auto. Пример: elementRef .style.markerOffset = "2em"; marks Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: отображение меток обрезки и других подобных элементов при печати страницы. Внимание: атрибут стиля для этого свойства не поддерживается в МасШ5 и NN6/7, однако данное свойство действительно для объекта style. Значение: константа crop | | cross | попе. Пример: elementRef.style.marks = "crop"; maxHeight maxWidth minHeight minWidth Совместимость: WinlE (см. текст), MacIE-, NN6+, Mozl+, Safari- Контролирует: максимальную и Минимальную высоту и ширину элемента. В IE6 поддер- живается только свойство minWidth. Значение: длина; процентное соотношение; константа (только для максимальных свойств) попе. Пример: elementRef.style.maxWidth = "ЗООрх"; overflow Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: отображение содержимого блокового элемента текста, когда размеры его исходного прямоугольника превышают размеры самого большого внешнего прямоугольного пространства. Если задано значение hidden, остаток содержимого блокового элемента отсека- ется; scroll означает, что во внешнем прямоугольнике появляется полоса прокрутки, позво- ляющая пользователю просмотреть содержимое элемента полностью; значение visible при- водит к тому, что содержимое блокового элементы выходит за пределы внешнего прямоугольника. Значение: константа auto | hidden | scroll | visible. Пример: elementRef.style.overflow = "scroll"; 842 Часть III. Объекты документа
overflowX overflowY Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Контролирует: отображение содержимого блокового элемента текста, когда ширина (overf lowX) или длина (overf lowY) его исходного прямоугольника превышают размеры самого большого внешнего прямоугольного пространства. Если задано значение hidden, ос- таток содержимого блокового элемента отсекается; scroll означает, что во внешнем пря- моугольнике появляется полоса прокрутки, позволяющая пользователю просмотреть содер- жимое элемента полностью; значение visible приводит к тому, что содержимое блокового элемента выходит за пределы внешнего прямоугольника. Значение: константа auto | hidden | scrol 11 visible. Пример: elementRef.style.overflow = "scroll"; styleFloat Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Контролирует: горизонтальное выравнивание элемента таким образом, чтобы его окру- жало содержимое Web-страницы (обычно изображение заключается в текст). Соответствует атрибуту float стиля CSS. См. также свойство cssFloat выше. Плавающие (непозицио- нируемые) элементы следуют целому ряду правил. Подробности вы найдете по адресу: http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-float. Значение: константа lef 11 right | none. Пример: elementRef.style.styleFloat = "right"; verticalAlign Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: вертикальное выравнивание внутреннего содержимого и содержимого ячеек таблиц относительно окружающего их содержимого. Не все константы поддерживают- ся браузерами всех версий. Значение: константа baseline | bottom|middle | sub | super | text-bottom| text- top | top; длина; процентное соотношение. Пример:elementRef.style.VerticalAlign = "baseline"; visibility Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: отображение элемента на Web-странице. Если элемент скрыт, его место на странице остается свободным. Если вы хотите, чтобы свободное место было занято ос- тальным содержимым, используйте свойство display. Это свойство часто применяют для скрытия и показа позиционируемых элементов, управляемых сценарием. Значение: константа collapse | hidden | visible. Пример: elementRef.style.visibility = "hidden"; Глава 26. Таблица стилей и объекты стилей 843
width Совместимость: WinIE4+, MacIE4+' NN6+, Mozl+, Safaril+ Контролирует: горизонтальные размеры блокового элемента текста. Браузеры более ран- них версий могут отображать содержимое самым неожиданным образом, включая вложение элементов с заданными свойствами стиля width. Значение: длина; процентное соотношение; константа auto. Пример: elementRef.style.width = "200pxn; zoom Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Контролирует: кратность увеличения отображаемого элемента. Значение: константа normal; процентное соотношение (где 100% соответствует норме); число с плавающей десятичной запятой (масштабный множитель, где 1.0 соответствует норме). Пример: elementRef.style.zoom = ".9"; Свойства позиционирования В главе 39 приведены примеры кодов позиционируемых элементов и их свойства style, bottom right Совместимость: WinIE5+, MacIE5, NN6+, Mozl+, Safaril+ Коитролирует: степень смещения позиционируемого элемента по отношению к нижней и правой границам прямоугольника, содержащего этот элемент. На практике размер пози- ционируемого элемента задается посредством свойств height и width. Значение: длина; процентное соотношение; константа auto. Пример: elementRef.style.bottom = "20рх"; left top Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: степень смещения позиционируемого элемента по отношению к верхней и левой границе прямоугольника, содержащего этот элемент. Используйте эти свойства для позиционирования элемента под управлением сценария. Для того чтобы расположить абсо- лютно позиционируемый элемент над внутренним элементом, задайте расположение внут- реннего элемента с помощью свойств offsetTop и offsetLeft, однако учтите при этом особенности различных браузеров (см. главу 39). Значение: длина; процентное соотношение; константа auto. / Пример: elementRef.style.top = "250рх"; 844 Часть III. Объекты документа
height width . Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: высоту и ширину блока элемента. Чаще всего используется для настройки размеров позиционируемого элемента (см. главу 39). Значение: длина; процентное соотношение; константа auto. Пример: elementRef.style.height = "ЗООрх"; pixelBottom pixelHeight pixelLeft pixelRight pixelTop pixelwidth Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safaril+ Контролирует: целые значения, заданные в пикселях, расположения (первоначально по- зиционируемых) элементов. Непиксельные значения этих свойств представляют строки, в ко- торых указаны единицы измерения (например ЗОет). Целочисленные значения свойства по- зволяют проводить числовую обработку размера позиционируемого элемента. Того же эффекта можно добиться межплатформенно, применив метод parselnt () для непиксель- ных значений этих свойств. Свойства pixelBottom и pixelRight отсутствуют в Мас1Е4. Значение: целое число. Пример: elementRef.style.pixelTop = elementRef.style.pixelTop + 20; posBottom posHeight posLeft posRight posTop posWidth Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Контролирует: числовые значения расположения (первоначально позиционируемых) элементов. Непиксельные версии этих свойств возвращают строки, которые также содержат единицы измерения (например 1.2ет). Эти свойства позволяют вам работать исключительно с числовыми значениями в тех же единицах измерения, в которых стиль определен изначаль- но. Того же эффекта можно добиться межплатформенно, используя метод parseFloat () в строковых версиях значений этих свойств. Значение: целое число. Пример: elementRef.style.posTop = elementRef.style.posTop + 0.5; Глава 26. Таблица стилей и объекты стилей 845
position Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: тип позиционируемого элемента. Элемент, который не позиционирован в яв- ном виде, называется статическим. Относительно позиционируемый элемент появляется на странице в своем обычном месте, но может быть позиционирован в явном виде относительно те- кущего места расположения. Абсолютно позиционируемый элемент должен иметь атрибуты стиля top и left, заданные в качестве координат расположения элемента. Мас1Е5 и NN6/Moz/Safari предоставляют возможность фиксировать место расположения элемента. При этом элемент не изменяет своего положения даже при прокрутке страницы (например, для создания эффекта во- дяных знаков). В главе 39 приведена подробная информация о позиционировании элементов. Значение: константа absolute | fixed | relative | static. Пример: elementRef.style.position = "absolute"; zIndex Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: уровень позиционируемых элементов относительно друг друга. Множест- венные элементы с одним и тем же значением z Index располагаются в порядке, заданном в исходном коде (первый элемент внизу). Значение: целое число; константа auto. Пример: elementRef . style. zlndex = " 3 " ; Свойства фона background Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: до пяти свойств фона элемента. Значение: комбинированные значения: backgroundAttachment | | background- color || backgroundimage|| backgroundposition|| backgroundRepeat. Пример: elementRef. style.background = "scroll url (bricks. jpg) repeat-x" ; backgroundAttachment Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: состояние фонового изображения: в фиксированном положении или про- кручивается вместе с содержимым. По умолчанию scroll. -Значение: константа fixed | scroll. Пример: elementRef.style.backgroundAttachment = "fixed"; backgroundcolor Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: чистый, непрозрачный или полностью прозрачный цвет фона. Если вы расположите на странице фоновое изображение, цвет фона будет виден через любые про- зрачные участки этого изображения. Значение: значение цвета; константа transparent. Пример: elementRef.style.backgroundcolor = "salmon"; 846 Часть III. Объекты документа
backgroundimage Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролнрует: URL (если есть) изображение, которое используется в качестве фона изо- бражения. Значение: значение URL; константа попе. Пример:elementRef.style.backgroundimage = "url(bricks.jpg)"; backgroundposition Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: расположение фонового изображения в левом верхнем углу. Любое сме- щение из левого верхнего угла (значение по умолчанию “0% 0%”) позволяет цвету изображе- ния просвечивать вдоль левой и верхней границы элемента. Значение: значения длины; процентные соотношения; константа left (center | right | | top | center | bottom. Можно задать единичные значения. Однако надежнее записать па- ры значений, разделив их пробелами. Пример: elementRef.style.backgroundposition = "left top"; backgroundPo s i t i onX backgroundPos i t ionY Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Контролирует: расположение левого (backgroundPos itionX) и верхнего (background- PositionY) углов фонового изображения. Любое смещение из левого верхнего угла изобра- жения (значение по умолчанию 0%) позволяет цвету изображения просвечивать вдоль левой и верхней границы элемента. Значение: значения длины; процентные соотношения; константа left | center | right (для backgroundPositionX); константа top | center | bottom (для backgroundPositionY). Пример:elementRef.style.backgroundPositionX = "5рх"; backgroundRepeat Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: параметр повторения фонового изображения. Изображение может повто- ряться вдоль одной оси. Значение: константа repeat | repeat-х| repeat-у | no-repeat. Пример:elementRef.style.backgroundRepeat = "repeat-у"; Свойства границ и полей border Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: до трех характеристик границ (цвет, стиль и ширина) всех четырех границ элемента. Значение: комбинированные значения borderColor| | borderstyle | |borderwidth. Пример: elementRef.style.border = "green groove 2px"; Глава 26. Таблица стилей и объекты стилей 847
borderBottom borderLeft borderRight borderTop Совместимость: WinIE4+, Мас1Е4+, NN6+, Mozl+, Safaril+ Контролирует:' до трех характеристик (цвет, стиль и ширина) одной из границ элемента. Значение: комбинированные значения: (для borderBottom) borderBottomColor||borderBottomStyle||borderBottomWidth (для borderLef t) borderLeftColor||borderLeftStyle||borderLeftwidth (для borderRight) borderRightColor||borderRightStyle||borderRightWidth (для borderTop) borderTopColor||borderTopStyle||borderTopWidth Пример: elementRef.style.borderLeft = "#3300ff solid 2px"; borderBottomColor borderLef tColor borderRightColor borderTopColor Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: цвет границы одной из сторон элемента. Значение: значение цвета; константа transparent. Пример: elementRef.style.borderTopColor = "rgb(30%, 50%, 0%)"; borderBottomStyle borderLeftStyle borderRightS ty1e borderTopStyle Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: стиль границы одной из сторон элемента при отображении. Значение: константа none | hidden | dotted| dashed| solid| double | groove | ridge | inset | outset. Версии IE для Windows более ранние, чем IE5.5, не поддерживают значения dotted и dashed. MacIE не поддерживает значение hidden. Пример:elementRef.style.borderRightStyle = "double"; 848 Часть III. Объекты документа
borderBottomwidth borderLeftWidth borderRightWidth borderTopWidth Совместимость: WinIE4+, MacE4+, NN6+, Mozl+, Safaril+ Контролирует: толщину границы элемента. Значение: значение длины; константа thin | medium) thick (точные размеры зависят от конкретного браузера). Пример: elementRef.style.borderBottomWidth = "5рх"; borderColor Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: цвет от одной до четырех сторон элемента при отображении. Значение: значения цвета от одной до четырех сторон прямоугольника. Пример:elementRef.style.borderColor = "green black"; borderstyle Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: стиль от одной до четырех сторон элемента при отображении. Значение: от одного до четырех постоянных значений для сторон прямоугольника: попе | hidden | dotted | dashed | sol id | double | groove | ridge | inset | outset. Версии Ш для Windows более ранние, чем Е5.5, не поддерживают значения dotted и dashed. МасЕ не поддерживает значение hidden. Пример: elementRef.style.borderstyle = "ridge"; borderWidth Совместимость: WinE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролируег толщину границы от одной до четырех сторон элемента. Значение: значение длины от одной до четырех сторон прямоугольника или константы thin | medium | thick (точные размеры зависят от конкретного браузера). Пример: elementRef.style.borderwidth = "5рх 4рх 5рх Зрх"; margin Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: толщину прозрачного поля за пределами границ от одной до четырех сто- рон элемента. Значение: значение длины от одной до четырех сторон прямоугольника. Пример: elementRef .style.margin = "Юрх 5px" ; Глава 26. Таблица стилей и объекты стилей 849
marginBottom marginLeft marginRight marginTop Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: толщину прозрачного поля за пределами границ одной стороны элемента. Значение: значение длины. Пример: elementRef.style.marginBottom = "50рх"; mozBorderRadius mozBorderRadiusBottomLeft mozBorderRadiusBottomRight mozBorderRadiusTopLeft mozBorderRadiusTopRight Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safari Контролирует: радиус границы вокруг элемента. Вы можете отдельно задать радиус скругления каждого угла, воспользовавшись единым стилем mozBorederRadius, или оп- ределить каждый параметр с помощью собственного свойства. Значение: значение радиуса. Пример:elementRef.style.mozBorderRadius = "20рх 10рх 20 рх Юрх"; mozOpacity Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safari Контролирует: степень прозрачности (непрозрачности) элемента, задаваемой в виде про- центного числового значения. Чем меньше значение этого свойства, тем прозрачнее элемент. Значение: процентное или числовое значение, задаваемое в диапазоне от 0.0 до 1.0. Пример: elementRef.style.mozopacity = "75%"; outline Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: до трех характеристик контура, окружающего элемент (таких, как для границы; контур не должен смещать окружающее его содержимое). Этот стиль не имеет пол- ной браузерной поддержки, хотя свойства отображены в объекте style. Значение: комбинированные значения outl ineColor | | outlinestyle | | outlinewidth. Пример: elementRef.style.outline = "red groove 2px"; outlinecolor Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: цвет всех четырех сторон контура. Этот стиль не имеет полной браузер- ной поддержки, хотя свойства отображены в объекте style. Значение: значения цвета; константа invert. Пример: elementRef.style.outlinecolor = "cornflowerblue"; 850 Часть III. Объекты документа
outlinestyle Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: стиль всех четырех сторон контура элемента при отображении. Этот стиль не имеет полной браузерной поддержки, хотя свойства отображены в объекте style. Значение: константа none | hidden | dotted | dashed | sol id | double | groove | ridge|inset|outset. Пример: elementRef.style.outlinestyle = "ridge"; outlinewidth Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: толщину всех четырех сторон контура элемента. Этот стиль не имеет полной браузерной поддержки, хотя свойства отображены в объекте style. Значение: значение длины от одной до четырех сторон прямоугольника или константы thin | medium | thick (точные размеры зависят от конкретного браузера). Пример: elementRef.style.outlinewidth = "4рх"; padding Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: ширину отступа между содержимым элемента и границами от одной до четырех сторон. Значение: значение длины от одной до четырех сторон прямоугольника. Пример: elementRef.style.padding = "5рх"; paddingBottom paddingLeft paddingRight paddingTop Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: ширину отступа между содержимым элемента и границей одной стороны. Значение: значение длины. Пример: elementRef.style.paddingBottom = ”2Орх"; Свойства списков liststyle Совместимость: WinIE4+, МасТЕ4+, NN6+, Mozl+, Safari 1+ Контролирует: до трех характеристик представления содержимого страницы в виде спи- ска (о1 или ul). То же относится к элементам dd, dt и li. Значение: комбинированные значения listStylelmage | | listStylePositi- оп||listStyleType. Пример: elementRef.style.liststyle = "none inside lower-alpha"; Глава 26. Таблица стилей и объекты стилей 851
1istStyleImage Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Контролирует: URL изображения, которое должно быть использовано в качестве марке- ра элемента списка. Значение: значение URL; константа попе. Пример: elementRef.style.listStylelmage = "url(custombullet.jpg)"; listStylePosition Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: форматирование маркера внутри текста, заключенного в список, или его расположение вне текста (по умолчанию). Значение: константа inside | outside. - Пример: elementRef.style.listStylePosition = "inside"; liststyleType Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Контролирует: стандартный наборов маркеров, который должен использоваться для эле- ментов списка. Изменение этого свойства для одного из элементов li списка приводит к из- менению стиля всех последующих элементов. Значение: для элементов ul константа circle | disc | square, для элементов ol кон- станта decimal|lower-alpha|lower-roman|upper-alpha|upper-roman. Пример: elementRef. style. listStyleType = "upper-roman"; Свойства полосы прокрутки scrollbar3dLightColor scrollbarArrowColor scrollbarBaseColor scrollbarDarkShadowColor scrollbarFaceColor scrollbarHighlightColor scrolIbarShadowColor scrollbarTrackColor Совместимость: WinIE5.5+, MacIE-, NN-, Moz-, Safari- Контролирует цвета отдельных компонентов полосы прокрутки для таких элементов, как applet, body, div, embed, obj ect или text area. Если вы хотите узнать, как различные цвета влияют на отдельные компоненты, посетите Web-страницу http://msdn.microsoft.com/ workshop/samples/author/dhtml/refs/scrollbarColor.htm. Значение: значения цвета; константа попе. Пример: elementRef.style.scrollbarTrackColor = "hotpink"; 852 Часть HI. Объекты документа
Свойства таблиц borderCollapse Совместимость: WinIE5+, MacIE5, NN6+, Mozl+, Safari- Контролирует: Соответствует ли элемент table модели раздельных границ CSS2 или модели совместных границ, В 1Е5/Мас этот стиль не имеет полной браузерной поддержки. Значение: константа collapse | separate. Пример: elementRef.style.borderCollapse = "separate"; borderSpacing Совместимость: WinIE5+, MacIE6, NN6+, Mozl+, Safaril+ Контролирует: расстояние между прямоугольными ячейками в таблице соответствующей модели раздельных границ (подобно атрибуту cellspacing элементов table). В Мас1Е5 этот стиль не имеет полной браузерной поддержки. Значение: одно значение длины (для расстояния по горизонтали и по вертикали) или спи- сок из двух значений длины, разделенных запятыми (первое значение — по горизонтали, вто- рое — по вертикали). Пример: elementRef. style .borderspacing = "Юрх"; captionSide Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: расположение элемента caption внутри элемента table. В IE5/Mac этот стиль не поддерживается, а в NN6 поддерживается только частично. Значение: константа top | right | bottom | left. Пример: elementRef.style.captionSide = "bottom"; emptyCells Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: отображение ячеек и их границ при отсутствии содержимого ячеек. По умол- чанию границы вокруг пустых ячеек не отображаются. В Мас1Е5 этот стиль не поддерживается. Значение: константа show | hide. Пример: elementRef.style.emptyCells = "show"; tableLayout Совместимость: WinIE5+, MacIE5, NN6+, Mozl+, Safaril+ Контролирует: расширяется ли таблица в соответствии с заданной шириной первой стро- ки ячеек или отображается только после задания ширины всех строк содержимого таблицы. Изменения, внесенные в это свойство после загрузки таблицы, на таблицу не влияют. Значение: константа auto | fixed. Пример: elementRef.style.tableLayout = "auto"; Глава 26. Таблица стилей и объекты стилей 853
Свойства страницы и печати orphans widows Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: минимальное количество строк абзаца, которые должны отображаться внизу (orphans) или вверху (widows) страницы, если происходит обрыв страницы. Значение: целое число. Пример: elementRef. style. orphans = "4 " ; page Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: страницу (определенную в правиле @page), к которой относится при пе- чати текущий элемент. Значение: идентификатор, назначенный существующему правилу ©page: Пример: elementRef.style.page = "landscape"; pageBreakAf ter pageBreakBefore Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari- Контролирует: должна ли страница обрываться перед или после текущего элемента, а также тип разрыва страницы. Значение: константа auto | always | avoid | left | right. Пример:elementRef.style.pageBreakBefore = "always"; pageBreaklnside Совместимость: WinlE-, MacIE5, NN6+, Mozl+, Safari- Контролирует: допустим ли обрыв страницы внутри элемента. Значение: константа auto | avoid. Пример: elementRef.style.pageBreaklnside = "avoid"; size Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Контролирует: размер или ориентацию страницы (заданную в правиле стиля с помощью свойства страницы). Используется для определения формата страниц. Значение: одно (одинаковое значение для ширины и высоты) или два значения длины, разделенные пробелом; константа auto | portrait | landscape. Пример: elementRef.style.size = "portrait"; 854 Часть III. Объекты документа
Дополнительные свойства accelerator Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: определена ли для данного элемента ускоряющая клавиша. Значение: булево выражение. Пример: elementRef.style.accelerator = "true"; behavior Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: внешнее поведение, которое должно применяться к текущему элементу. Значение: список URL-адресов, разделенных пробелами. URL-адреса могут указывать место расположения файла, идентификатор элемента object или одно из встроенных пове- дений (по умолчанию). Пример: elementRef.style.behavior - "url(#default#anchorClick)"; cssText Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari- Контролирует: текст правила CSS (Только для чтения). Это свойство существует благо- даря объектной модели браузера и не является частью спецификации CSS. Соответствующего атрибута CSS не существует. Значение: строка. Пример: var cssRuleText = elementRef.style.cssText; imeMode Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Контролирует: вводится ли текст в элемент input или элемент textarea с помощью Input Method Editor (для таких языков, как китайский, японский или корейский). Значение: константа auto | active | inactive | disabled. Пример: elementRef.style.imeMode = "active"; Акустические свойства Эти свойства определены в спецификации CSS2, а в NN6 для них существуют заполните- ли. Однако такие свойства в NN6 не поддерживаются. Эквивалентные свойства сценария пе- речислены только для полноты изложения материала. Глава 26. Таблица стилей и объекты стилей 855
azimuth cue cueAfter cueBefore elevation pause pauseAfter pauseBefore pitch pitchRange playDuring richness speak speakHeader speakNumeral speakPunc tua t i on speechRate stress voiceFamily volume Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Контролирует: различные свойства, которые прежде всего рассчитаны на браузеры, под- держивающие синтез человеческой речи. Значение: подробную информацию об акустических таблицах стилей вы найдете по адре- су: http://www.w3.org/TR/REC-CSS2/aural.html Объект фильтра Свойства Методы Обработчики событий См. текст Синтаксис Доступ к свойствам и методам объекта filter. (IE4+) document.all.obj ectID.stylefilters[индекс].свойствоIметод ([параметры]) (IE5.5+) document. all.objectID.stylefilters [имяФильтра] . свойство/метод ( [параметры] ) Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- 856 Часть III. Объекты документа
Описание объекта В этой главе речь уже шла о свойстве style. filter, позволяющем получать и изме- нять строковое значение, назначенное свойству style. filter элемента. Фильтры исполь- зуются только в системе IE для Windows. 1Е5/Мас это свойство не поддерживает, хотя и воз- вращает значение свойства style. filter. Задача данного раздела состоит в том, чтобы научить вас применять фильтры при написании сценария. Множественные фильтры — это только часть списка фильтров, элементы которого отде- ляются пробелами. Для некоторых типов фильтров существуют дополнительные специфика- ции. Например, фильтр glow () обладает тремя свойствами, которые позволяют более четко задавать; каким образом должен отображаться элемент с эффектом подсветки. Правило таб- лицы стилей для элемента с идентификатором glower выглядит следующим образом. #glower {filter:glow(color=yellow, strength=5, enabled=true)} Свойство currentstyle. filter для этого элемента имеет следующее строковое значение. glow(color=yellow, strength=5, enabled=true) Попытка изменить единичное подсвойство фильтра glow () путем синтаксического раз- деления строки не даст положительных результатов. Не стоит, например, пытаться добавить к свойству strength данного фильтра значение 5. Получение и изменение подсвойств Работать с индивидуальными свойствами фильтра удобнее всего, обращаясь к фильтру как к объекту элемента, на который этот фильтр оказывает влияние. Каждый тип объекта фильтра имеет свои индивидуальные подсвойства, которые вы задаете в таблице стилей. Приве- дя в качестве примера фильтр glow (), заметим, что обратиться только к свойству color мож- но следующим образом. var currColor = document.all.glower.currentstyle.filters["glow"].color; Для получения значения ссылка задается с помощью свойства currentstyle, поскольку в данном случае фильтр задан в определении таблицы стилей, и только свойство current Style может показать воздействующие на данный элемент свойства стиля. Для изменения цвета необ- ходимо задать новое значение свойству filter объекта с помощью свойства style элемента. document.all.glower.style.filters["glow"].color = "green"; Для того чтобы добавить к свойству strength фильтра glow () значение 5, используйте следующую синтаксическую конструкцию (какой бы громоздкой она вам ни казалась). document.all.glower.style.filters["glow"].strength = document.all.glower.currentstyle.filters["glow"].strength + 5; В табл. 26.1 перечислены имена объектов фильтра, которые поддерживаются браузерами версий IE4 и более современными, а также свойства, относящиеся к каждому типу фильтра. Кроме статических типов фильтров, которые применяются к содержимому и изменяют- ся в сценариях, объект filter IE4+ предоставляет ряд возможностей по преобразованию одного изображения в другое и изменению видимого элемента в скрытый. Задать преобра- зование изображения от видимого к скрытому можно в нескольких строках кода, используя при этом некоторые методы объекта filter. В табл. 26.2 представлен синтаксис фильт- ров преобразования. Глава 26. Таблица стилей и объекты стилей 857
Имя фильтра Описание и свойства alpha() Степень прозрачности Свойства: opacity (от 0 до 100) finishopacity (от 0 до 100) style (градиентная форма от 0 до 3) startx (координата, выраженная целым числом) startY (координата, выраженная целым числом) f inishx (координата, выраженная целым числом) f inishY (координата, выраженная целым числом) blur() Имитация размытого изображения Свойства: add (1 или 0) direction (0,45,90,135,180, 225, 270,315) strength (число пикселей) chroma() Прозрачность цвета Свойства: color (значение цвета) dropshadow() Эффект тени Свойства: color (значение цвета) of fx (горизонтально смещенные пиксели) of fy (вертикально смещенные пиксели) positive (1 или 0) flipHO Горизонтально отраженное изображение Свойства: отсутствуют flipv() Вертикально отраженное изображение Свойства: отсутствуют glow() Подсветка внешних граней Свойства: color (значение цвета) strength (интенсивность от 1 до 255) gray() Удалить цвет Свойства: отсутствуют invert() Контрастный цвет, насыщенность, уровень яркости Свойства: отсутствуют light () Добавить источник света (контролируется методами) Свойства: отсутствуют mask() Наложение прозрачной маски Свойства: color (значение цвета) 858 Часть III. Объекты документа
Окончание табл. 26.1 Имя фильтра Описание и свойства shadow() Отобразить в виде силуэта Свойства: color (значение цвета) direction (0,45,90,135,180, 225, 270,315) wave() Добавить синусоидальное искажение Свойства: add (1 или 0) freq (целое число волн) light (интенсивность от 0 до 100) phase (процент смещения от 0 до 100) strength (интенсивность от 1 до 255) xRay() Отображать только грани Свойства: отсутствуют Имя фильтра Описание и свойства Ы endTrans () Постепенно исчезает старый элемент и проявляется новый Свойства: duration (количество секунд, заданных с плавающей запятой) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет преобразование) stop () (останавливает процесс преобразования) revealTrans () Показывает новый вид элемента Свойства: duration (количество секунд, заданных с плавающей запятой) transition (номер кода, соответствующий тому или иному эффекту) о Box in 1 Расширяющийся прямоугольник 2 Сужающийся круг 3 Расширяющийся круг 4 Стирание вверх 5 Стирание вниз. 6 Стирание вправо 7 Стирание влево 8 Вертикальные жалюзи 9 Горизонтальные жалюзи ю Шахматная развертка по ширине 11 Шахматная развертка по высоте 12 Произвольное растворение Глава 26. Таблица стилей и объекты стилей 859
Окончание табл. 26.2 Имя фильтра Описание и свойства 13 Вертикальное внешнее растрескивание 14 Вертикальное внутреннее растрескивание 15 Горизонтальное внешнее растрескивание 16 Горизонтальное внутреннее растрескивание 17 Смывание слева вниз 18 Смывание слева вверх 19 Смывание справа вниз 20 Смывание справа вверх 21 Произвольное горизонтальное испещрение 22 Произвольное вертикальное испещрение 23 Произвольный эффект Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет преобразование) stop () (останавливает процесс преобразования) Для того чтобы преобразование от одного элемента к другому происходило под контро- лем сценария, фильтр должен быть применен к тому элементу, с которого начинается про- цесс. Сделать это можно, записав соответствующий код или назначив элементу стиль фильт- ра. Если вы решили добавить преобразование в сценарий, примените метод apply () соответствующего объекта filter. Затем запишите проводимые изменения— например, назначьте новый URL свойству scr элемента img. Пока вы выполняете'эту операцию, метод apply () фиксирует изображение, оставляя его неизменным. Листинг 26.1 представляет шахматную развертку одного изображения вместо другого после щелчка на нем. Л-сп«г 26.1. у. <html> <head> <title>!E4+ Transition</title> <style type="text/css"> img {filter:revealTrans(transition=10>} </style> <script type="text/javascript"> function doReveal() { document.all.mylMG.filters["revealTrans"].applyO; if (document.all.mylMG.src.indexOf("deskl") != -1) { document.all.mylMG.src = "desk3.gif"; } else { document.all.mylMG.src = "deskl.gif"; } document.all.mylMG.filters["revealTrans"].play(); } </script> </head> <body> <hl>IE4+ Transition</hl> 860 Часть III. Объекты документа
<hr /> <p>Click on the image to cause a reveal transition.</p> <img alt="image" id="myIMG" src="deskl.gif" height="90" width="120" onclick="doReveal()" /> </body> </html> Основываясь на примере, приведенном в листинге 26.1, в листинг 26.2 продемонстриру- ем, как сценарий может изменить свойство объекта filter, в том числе и фильтра преобра- зования. Перед применением метода apply () сценарий задает тип перехода на основе одно- го из элементов списка select, выбранного пользователем. i Ливгмг 26.2. Ыйршзд аЙ9го* «html> <head> <title>IE4+ Transition and Choices</title> <style type="text/css"> img {filter:revealTrans(transition=10)} </style> «script type="text/javascript"> function doReveal() { document.all.mylMG.filters("revealTrans"].transition = document.forms[0].transChoice.value; document.all.mylMG.filters("revealTrans"].applyO; if (document.all.mylMG.src.indexOf("deskl") != -1) { document.all.mylMG.src = "desk3.gif"; } else { document.all.mylMG.src = "deskl.gif"; } document.all.myiMG.filters("revealTrans"],play(); } </script> </head> <body> <hl>IE4+ Transition and Choices</hl> <hr /> <form> <p>Choose the desired transition type: «select name= "transChoice"> «option value="0">Box in«/option> «option value="l">Box out«/option> «option value="2">Circle in«/option> «option value="3">Circle out«/option> «option value="4">Wipe up«/option> «option value="5">Wipe down«/option> «option value="6">Wipe right«/option> «option value="7">Wipe left«/option> «option value="8">Vertical blinds«/option> «option value="9">Horizontal blinds«/option> «option value=" 10 "Checkerboard across«/option> «option value=" 11 "Checkerboard down«/option> «option value="12">Random dissolve«/option> «option value="13">Split vertical in«/option> «option value="14">Split vebical out«/option> «option value="15">Split horizontal in«/option> Глава 26. Таблица стилей и объекты стилей 861
«option value="16">Split horizontal out</option> «option value="17">Strips left down«/option> «option value="18">Strips left up«/option> «option value="19">Strips right down«/option> «option value="20">Strips right up«/option> «option value="21">Random bars horizontally«/option> «option value="22">Random bars vertically</option> «option value=,,23">Random effect«/option> </select>«/p> </form> <p>Click on the image to cause a reveal transition.</p> <img alt="image" id="myIMG" sr'c=“deskl .gif " height="90" width="120" onclick="doReveal()" /> </body> </html> Изменение синтаксиса фильтров в IE5.5 WinIE5.5 не только поддерживает способ управления фильтрами, принятый в IE4, но и предла- гает некоторые нововведения, которые Microsoft настоятельно рекомендует использовать (об этом свидетельствует тот факт, что на страницах Web-узла данной компании очень сложно найти документацию для синтаксиса IE4). В результате указанных нововведений имена мно- гих фильтров, как и их отдельных свойств, были изменены. Более того, изменился и метод применения компонентов фильтров в таблице стилей. Синтаксис таблицы стилей предполагает ссылку на новый компонент и имя фильтра. Вот как это выглядело для IE4. #glower {filter:glow(color=yellow, strength=5, enabled=true)} Запись для IE5.5 выглядит следующим образом. #glower {filter:progid:DXImageTransform.Microsoft.Glow(color=yellow, strength=5, enabled=true)} He пропустите дополнительный указатель progid:. Этот программный идентификатор становится частью имени фильтра, которое используется в сценарии для ссылки на этот фильтр. document.all.glower.style.filters["DXImageTransform.Microsoft.Glow"]. color = "green"; Некоторые имена фильтров остались неизменными (была добавлена только приставка), остальные — отнесены к категории новых фильтров, их свойства помогают получить специ- фические эффекты. Функции фильтра, ранее называемого revealTrans (), в новой версии распределены между несколькими новыми фильтрами, которые создают эффект перехода от одного изображения’к другому. В табл. 26.3 представлен синтаксис для IE5.5+. / Использование синтаксиса IE5.5+ может привести к проблемам отображения /н«з«метку вашей страницы браузерами (по крайней мере, браузерами более ранних версий). * Чаще асего трудности возникают при передаче эффекта преобразования одного изображения а другое. Если аы все же решили пользоваться синтаксисом IE6+, обязательно проверьте, как отображаются страницы разными версиями браузеров. 862 Часть III. Объекты документа
Имя фильтра Описание и свойства Alpha() Степень прозрачности Свойства: opacity (от 0 ДО 100) finishopacity (от 0 ДО 100) style (градиентная форма от 0 до 3) startx (координата, выраженная целым числом) startY (координата, выраженная целым числом) f inishx (координата, выраженная целым числом) f inishY (координата, выраженная целым числом) Bam () Эффект закрывающихся дверей Свойства: duration (количество секунд, заданное с плавающей запятой) движение (in или out) размещение (horisontal или vertical) percent (от 0 ДО 100) status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) Basiclmage О Вращение элемента, зеркальное отображение, цветовые эффекты и непрозрачность Свойства: grayscale (1 ИЛИ 0) invert (1 или 0) mask (1 или 0) maskcolor (значение цвета) mirror (1 или 0) opacity (от 0.0 ДО 1.0) rotation 0 (нет вращения), 1 (90°), 2 (180°), 3 (270°) xRay (1 или 0) Blinds() Эффект жалюзи Свойства: направление (up, down, right, left) squaresx (целое число столбцов) sguaresY (целое число строк) status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) Глава 26. Таблица стилей и объекты стилей 863
Продолжение табл. 26.3 Имя фильтра Описание и свойства Checkerboard () Эффект шахматной развертки - Свойства: bands (от 1 ДО 100) направление (up, down, right, left) duration (количество секунд с плавающей запятой) percent (от 0 ДО 100) slidestyle (HIDE, PUSH, SWAP) status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) Chroma() Прозрачность цвета Свойства: color (значение цвета) Dropshadow() Эффект тени Свойства: color (значение цвета) of fx (горизонтально смещенные пиксели) of fy (вертикально смещенные пиксели) positive (1 или 0) Fade() Плавный переход одного элемента в другой Свойства: duration (количество секунд с плавающей запятой) overlap (от 0.0 ДО 1.0) percent (от 0 ДО 100) status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) Glow() ' Подсветка внешних граней Свойства: color (значение цвета) strength (интенсивность от 1 до 255) Iris() Эффект изменения масштаба Свойства: duration (количество секунд с плавающей запятой) irisStyle (CIRCLE, CROSS, DIAMOND, PLUS, SQUARE, STAR) motion (in ИЛИ out) 864 Часть III. Объекты документа
Продолжение табл. 26.3 Имя фильтра Описание и свойства - percent (от 0 ДО 100) status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) Light() Добавление источника света (контролируется методами) Свойства: отсутствуют Методы: addAmbient (red, green, blue, strength) addCone (sourceLeft, sourceTop, sourceZAxis, targetLeft, targetTop, red, green, blue, strength, spreadAngle) addPoint (sourceLeft, sourceTop, sourceZAxis, red, green, blue, strength) changeColor (lightID, red, green, blue, absoluteColorFlag) changestrength (lightID, strength, absolutelntensityFlag) clear() moveLight (lightID, sourceLeft, sourceTop, sourceZAxis, absoluteMovementFlag) MaskFilter() Наложение прозрачной маски Свойства: color (значение цвета) MotionBlur() Имитация нечеткого изображения Свойства: add (1 или 0) direction (0,45,90,135,180,225,270,315) strength (число пикселей) RandomDissolve () Эффект растворения Свойства: duration (количество секунд с плавающей запятой) percent (от 0 ДО 100) status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) RandomBars() Эффект испещрения Свойства: duration (количество секунд с плавающей запятой) orientation(horisontalИЛИ vertical) percent (от 0 ДО 100) Глава 26. Таблица стилей и объекты стилей 865
Окончание табл. 26.3 Имя фильтра Описание и свойства status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) Shadow() Отобразить в виде силуэта Свойства: color (значение цвета) direction (0,45,90,135,180, 225, 270, 315) Stripes() Эффект нанесения полос Свойства: duration (количество секунд с плавающей запятой) motion (in или out) percent (ОТ 0 ДО 100) status 0 (приостановлен), 1 (применен), 2 (в процессе) Методы: apply () (фиксирует текущее состояние изображения на экране) play () (выполняет переход) stop () (останавливает процесс перехода) Wave() Синусоидальное искажение Свойства: add (1 или 0) freq (целое число волн) light (интенсивность от Одо 100) phase (процент смещения от 0 до 100) strength (интенсивность от 1 до 255) xRay() Отображение только границ Свойства: отсутствуют Более полную информацию об использовании фильтров в, IE для Windows вы найдете по адресу: http: //msdn.microsof t. com/workshop/author/fiIter/filters. asp. По- скольку большинство примеров требуют WinlE, рекомендуется просматривать указанные Web-страницы, используя браузер именно этой версии. 866 Часть III. Объекты документа
Объекты языка JavaScript
Объект string В главе 6 были представлены концепции значений и их типов, с которыми работает JavaScript: строки, числа и логические значения. В этой главе рассматривается стро- ковый тип данных, а также его взаимосвязь с числовым ти- пом. Кроме того, демонстрируются различные способы об- работки текстовых строк. 'На заметку Большинство синтаксических конструкций, с ко- торыми вы встретитесь в этой главе, идентич- ны представленным в языке программирования Java. Поскольку область применения JavaScript несравненно уже, чем у Java, создание сцена- риев на JavaScript требует меньшего опыта, чем программирование на Java. В то же время оп- ределенные саойства строковых объектов мож- но применять только в сценариях (но не в Java). Усовершенствование методов строкового объек- та в NN4 значительно упростило задачу по об- работке текста. Однако, если разрабатываемая страница предназначена и для ранних версий браузеров, вам потребуются определенные на- выки, присущие программистам на языке С. В этой главе приведено несколько функций об- щего назначения, которыми вы сможете пользо- ваться в своих сценариях. Типы данных string и number JavaScript не требует строгой типизации переменных, од- нако следует проявлять осторожность при работе с опреде- ленными типами данных. В этом разделе речь пойдет о стро- ковых и двухчисловых типах данных. Простые строки Строка состоит из одного или более стандартных тексто- вых символов, заключенных в кавычки. JavaScript позволяет использовать (с обеих сторон строки) и одинарные, и двойные
кавычки. Достоинство этого подхода проявляется, например, при включении одной строки в кавычках в другую. Пусть, например, HTML-код записывается в переменную, которая затем выводится в новом окне, полностью управляемом сценарием JavaScript. Строка текста имеет следующий вид. cinput type="checkbox" name="candy" />Chocolate Чтобы присвоить всю строку переменной, ее необходимо заключить в кавычки. По при- чине того, что кавычки присутствуют в самой строке, JavaScript (как и любой другой язык) не знает, где начинается или заканчивается строка. Присвоение будет проведено корректно, если воспользоваться другим типом кавычек. Представим два эквивалентных способа. result = '«input type="checkbox" name="candy" />Chocolate'; result = "«input type=’checkbox' name'=' candy' />Chocolate"; Обратите внимание, что строка заключена в кавычки одного типа. Внутри содержатся еще две строки, заключенные в кавычки. Рекомендуется выбрать одну из форм и использовать ее повсеместно в сценариях. Создание длинных строковых переменных Объединение строк — конкатенация — позволяет получить длинную строку на основе не- скольких подстрок. Это свойство является чрезвычайно важным при решении некоторых за- дач Web-программирования (например, если вся HTML-страница создается в одной перемен- ной, которая выводится на другой странице или фрейме методом document. write {)). Рекомендуется использовать как можно более короткие выражения, чтобы улучшить чи- таемость текста. В этом случае используется оператор сложения с присвоением (+=); он до- бавляет выражение из правой части к выражению в левой части. Ниже приведен простой пример, в котором переменная инициализируется пустой строкой. var newDocument = ""; newDocument += "<html>«head>«title>Life and Times«/title>«/head>"; newDocument += "<body>«hl>My Life and Welcome to It«/hl>"; newDocument += "by Sidney Finortny«hr />"; Начиная co второй строки, в каждом операторе переменной newDocument присваива- ется новый блок данных. ?Этот процесс можно продолжать до тех пор, пока в переменной newDocument не будет сохранена вся страница. / Избегайте использования оператора сложения с присвоением, который сущест- /назвмепсу венно увеличивает длину текстовой строки. Если при управлении текстоаыми стро- I ками наблюдается излишняя медлительность, то попробуйте разбить длинную строку на массив текстовых элементов (глава 30). Используйте метод join О массива для объединения массива текстовых элементов обратно в единую текстовую строку. Объединение строк и переменных В некоторых случаях возникает необходимость в создании строки на основе строк (символов, заключенных в кавычки) и строковых переменных. Методы конкатенации таких типов данных ничем не отличаются от конкатенации нескольких обычных строк. Операция обозначается символом “+”. В следующем примере в переменной содержится имя, которое затем используется как часть более сложной строки. yourName = prompt("Please enter your name:",""); var msg = "Good afternoon, " + yourName + "."; alert(msg); Глава 27. Объект string 869
В подобных операциях конкатенации возникают такие проблемы. Отсутствие (случайное) одной из кавычек, в которые должна быть заключена строка. Отсутствие пробелов в строках (в результате строка и переменная конкатенируются без разделителя). Отсутствие знака пунктуации в строке, следующей за значением переменной. Кроме того, помните, что переменная, приведенная в примере, может быть любым выра- жением, результатом которого является строка (в том числе ссылки на свойства и результаты выполнения некоторых методов). var msg = "The name of this document is " + document.title + alert(msg); Специальные символы При управлении строками в языке JavaScript иногда возникают трудности с использовани- ем определенных символов. В первую очередь, речь идет о кавычках, символе возврата ка- ретки, апострофах и символе табуляции. К счастью, JavaScript обеспечивает механизм при- менения в строках и таких вспомогательных символов. Для этого перед специальным символов вводят символ обратной косой черты. Символ косой черты определяет место в строке, в котором введен невидимый в обычном представлении для JavaScript символ. Наиболее распространены следующие пары (обратная косая черта-символ). \” Двойная кавычка \' Одинарная кавычка (апостроф) \\ Обратная косая черта \ь Символ <Backspace> \t Табуляция \п Новая строка \г Возврат каретки \f Символ подачи страницы Эти “внутренние символы” (известные еще как знаки перехода — данная терминология приобрела дополнительное значение для строк, используемых в Internet) задают внутри строк, заключенных в кавычки. При создании блока текста, в котором необходимо определить но- вый абзац, вставьте в соответствующем месте пару символов \п. msg = "You\'re doing fine."; msg = "This is the first line.\nThis is the second line."; msg = document.title + "\n" + document.links.length + " links present."; Технически операция возврата каретки (как известно со времен печатных машинок) со- стоит из двух действий: перевода строки (т.е. прокрутки на одну строку) и возврата каретки (перемещения каретки к левому краю). В строках JavaScript символ новой строки (\п) рас- сматривается как полный возврат каретки, однако его можно задать в комбинации \г\п. Ис- пользуемый формат зависит от средств обработки текста в CGI-программе. (О специальных требованиях к объекту textarea вы можете узнать в главе 20.) Не путайте строки, отображаемые в объектах textarea или диалоговых окнах, со стро- ками HTML-кода. В HTML-строках используйте стандартные дескрипторы (<Ьг> — для пе- ревода строки и <р> — в начале нового параграфа), а не внутреннее представление специ- альных символов. 870 Часть IV. Объекты языка JavaScript
Объект string Свойства Методы constructor anchor() length big О prototype* blink() bold» charAt() charCodeAt() concat() fixed() fontcolor() fontsize() fromCharCode()* indexOf() italics() lastlndexOf() link() localeCompare() match() replace() search() slice () small() split() strike() sub() substr() substring() sup() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toStringO toUpperCase() valueOf() ★Для статического объекта string Глава 27. Объект string 871
Синтаксис Создание строкового объекта. var myString = new String("characters"); Доступ к свойствам и методам статического объекта string. string, свойство|метод( [параметры] ) Доступ к свойствам и методам строкового объекта. строка, свойство] метод ( [параметры] ) Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Описание объекта JavaScript различает строковые значения и строковые объекты. И те, и другие используют одинаковые методы, поэтому обычно для присвоения переменной строкового значения нет необходимости создавать объект (конструктором String ()). Для этого требуется лишь обычная операция присвоения (var myString = " fred"), Различия проявляются там, где используется “объектность” строкового элемента. Под- робно об этом рассказано при изучении свойства string.prototype (далее в этой главе). Кроме того, использование полноценного строкового объекта может понадобиться при пере- даче данных Java-аплету. Если оказывается, что аплет не воспринимает строковое значение как тип данных String, следует создать новый объект (с помощью конструктора JavaScript) и передать его аплету. В сценариях часто возникает необходимость обработки строковых данных. Кроме конка- тенации строк, можно извлекать подстроки, удалять части строк или заменять их другим тек- стом. В отличие от многих языков написания сценариев, JavaScript практически не имеет встроенных средств обработки строк. Это значит, что методы обработки строки необходимо программировать самостоятельно (если только вы не воспользуетесь регулярными выражения- ми, поддерживаемыми в браузерах NN4+ и IE4+). Далее в этой главе приведен исходный код нескольких функций, которые полностью совместимы с более ранними версиями браузеров. При работе каждое строковое значение необходимо представить в качестве объекта, имею- щего свойства и методы (как и любой другой объект JavaScript). В последних версиях JavaScript определено несколько свойств и методов для работы со строковыми значениями (и одно допол- нительное свойство статического объекта String, которое всегда присутствует в окне браузе- ра). Синтаксис вызова строковых методов такой же, как и методов любого другого объекта. объектЗЬring.method() Частью ссылки на строковый объект может быть любое выражение, результатом выпол- нения которого является строка, содержащая обычные строки, переменные, методы или функции, возвращающие строки, или другие свойства объекта. Поэтому все приведенные ни- же примеры вызова метода toUpperCase () работают одинаково. "george bums" . toUpperCase () yourName.toUpperCase() // yourName — строковая переменная window.prompt("Enter your nametoUpperCase() document.forms[0].entry.value.toUpperCase() // entry — текстовое поле объекта Важно помнить следующее: вызов строкового метода не изменяет объект, который явля- ется частью ссылки. Вместо этого метод возвращает значение, используемое как параметр вызова другого метода (функции) или для присвоения переменной. 872 Часть IV. Объекты языка JavaScript
Поэтому для изменения содержимого строковой переменной (влияющей на результат вы- полнения метода) необходимо воспользоваться оператором присвоения. yourName = yourName.toUpperCase(); // значение переменной теперь // включает только прописные буквы Свойства constructor Значение: ссылка на функцию Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Свойство constructor является ссылкой на функцию, вызванную для создания текущей строки. Для естественного строкового объекта в JavaScript функцией-конструктором является String(). При создании новой строки конструктором new String () типом значения, возвращае- мым им, является object (т.е. оператор typeof возвращает значение object). Поэтому свойством constructor можно воспользоваться для проверки “строковости” объекта. if (typeof someValue == "object" ) { if (someValue.constructor == String) { // операторы обработки объекта string } } Несмотря на то, что это свойство предназначено для чтения и записи, а свойству String.prototype можно присвоить другое значение конструктора, естественное поведе- ние объекта string заключается в использовании старого конструктора. Пример Приложение The Evaluator (глава 13) можно использовать для изучения свойства constructor. Введите в верхнем текстовом поле следующее выражение. а = new String("abed") а.constructor == String a.constructor == Number См. также: свойство prototype. length Значение: целочисленное Только для чтения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Наиболее часто используемым свойством строкового объекта является length. Оно со- держит длину строки. Обращение к нему происходит так же, как к свойству length любого другого объекта. 1 string.length Это целочисленное значение равно количеству символов в строке. Символами также счи- таются пробелы и знаки пунктуации. Все специальные символы, начинающиеся с обратной- косой черты, считаются одиночными, включая символы новой строки и табуляции. Ниже приведено несколько примеров. "Lincoln".length // результат 7 "Four score". length // результат 10 Глава 27. Объект string 873
"One\ntwo".length // результат 7 "".length // результат О Свойство length часто используется, например, при обработке строк в циклах. prototype Значение: объект Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Строковые объекты, создаваемые конструктором new StringCстрока”), являются более значимыми объектами, чем обычные переменные, которым присвоены строковые зна- чения. Разумеется, создавать такие объекты для всех строк в сценарии нет необходимости. Однако в некоторых случаях они могут оказаться полезными. Например, значения в перемен- ных могут стать некорректными при попытке сохранения информации в других фреймах или окнах. Используя конструктор строкового объекта, можно быть уверенным в том, что стро- ковое значение будет доступно другим фреймам. Еще одним достоинством строковых объектов является возможность присвоения прото- типов свойств и методов всем строковым объектам документа. Прототип представляет со- бой свойство или метод, который становится частью каждого нового объекта при его созда- нии. Для строк, например, можно создать метод, предназначенный для преобразования строки в новый тип дескриптора шрифта, который не встроен в JavaScript по умолчанию. В листинге 27.1 представлен процесс создания и использования прототипа. <html> <head> <title>String Object Prototype«/title> «script type="text/javascript"> function makeltHotO { return "«font color='red'>" + this.toString() + "<\/font>"; } String.prototype.hot = makeltHot; </script> ' </head> <body> «script type="text/javascript"> document.write("<hl>This site is on " + "FIRE".hot() + "!!<\/hl>"); </script> </body> </html> Функция (makeltHot ()) накапливает строковые данные, которые возвращаются в объект, когда она вызывается как метод. Ключевое слово this указывает на объект, вызвавший функцию, который преобразуется в строку для последующей конкатенации. В разделе тела страницы прототип метода вызывается так же, как и существующие методы объекта string, превращающие строки в дескрипторы HTML (они рассмотрены далее). В следующих разделах методы строкового объекта разделены на две категории. В первой описываются методы синтаксической обработки, во второй— методы форматирования, ис- пользуемые для вывода текста в новые документы или другие фреймы. 874 Часть IV. Объекты языка JavaScript
Методы синтаксического анализа строка.charAt(индекс) Возвращаемое значение: односимвольная строка Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Метод строка. charAt () используется для чтения символа, находящегося в определен- ной позиции в строке. Аргументом метода является индекс. Индекс первого символа равен 0. Для получения последнего символа воспользуйтесь комбинацией строковых методов. myString.charAt(myString.length — 1) Используется метод строка. substring (), если сценарию требуется получить не- сколько символов, Попытка применения этого метода для извлечения одного символа является распространенной ошибкой — метод строка. charAt () работает гораздо эффективнее. Пример Введите каждое из приведенных далее выражений в верхнее текстовое поле приложения The Evaluator. а = "banana daiquiri" а.charAt(0) а.charAt(5) а.charAt(6) а.charAt(20) Эти методы возвращают Ь, а (третий символ а в слове banana), пробел и пустую строку, соответственно. См. также методы строка. last IndexOf (), строка. indexOf (), строка. substring (). строка.charCodeAt([индекс]) строка. fromChar Code (ном1 [, ном2 [, ... номп] ]) Возвращаемое значение: целочисленный код символа; строка, конкатенированная из символов, коды которых указаны как аргументы. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Преобразование символов в числовые эквиваленты представляет собой давнюю традицию в программировании. В течение долгого времени применялся стандарт ASCII, описывающий символы английского алфавита, буквенно-цифровые символы и символы пунктуации, — всего 128 значений (от 0 до 127). Расширенная версия этого стандарта включает 256 символов. Их точное значение зависит от операционной системы. Обычно это дополнительные символы других романских языков. Для того чтобы обеспечить поддержку нероманских и пиктографических язы- ков, был разработан стандарт Unicode, поддерживающий несколько тысяч различных символов. В JavaScript преобразование символов в коды достигается с помощью строковых методов. Допустимые значения зависят от конкретной версии браузера. NN4 работает только с 256 сим- волами стандарта ISO-Latin-I; NN6+ и IE4+ поддерживают систему Unicode. Два метода, выполняющих преобразование, синтаксически работают по-разному. Первый, строка. charCodeAt (), преобразует один символ строки в его числовой эквивалент. Кон- вертируемая строка указывается как объект перед именем метода — это может быть обычная строка в кавычках или любое выражение, результатом выполнения которого является строка. Если аргумент метода не указан, возвращается код первого символа строки. Для обработки другого символа следует указать его индекс (индекс первого символа равен 0). Глава 27. Объект string 875
"abc".charCodeAt() "abc".charCodeAt(0) "abc".charCodeAt(1) // результат 97 // результат 97 // результат 98 Если строка является пустой или значение индекса находится за пределами допустимого диапазона, результатом выполнения метода будет NaN. Для преобразования числовых значений в соответствующие им символы используется ме- тод строка. f romCharCode (). Обратите внимание, что объект, вызывающий метод, явля- ется статическим объектом string, а не строковым значением. В качестве аргументов мож- но указать одно или несколько целочисленных значений, разделенных запятыми. В процессе преобразования метод объединяет все символы в одну строку, как в следующем примере. String.fromCharCode(97, 98, 99) // результат "abc" Назаметку Метод строка. charCodeAt () работает некорректно в первой подверсии брау- зера MacNN4: он всегда возвращает значение NaN. Эта ошибка исправлена в последующих версиях. Пример Пример использования обоих методов приведен в листинге 27.2. Поскольку в этом при- мере выполняется захват выделенного на странице текста, то в сценарий включен код обра- ботки событий выделения в различных браузерах. Лист*г. 27-X символов _ _ <html> <head> <title>Character Codes</title> «script type="text/javascript"> function showCharCode() { var theText = ""; if (window.getSelection) { theText = window.getSelection().toStringO; } else if (document.getSelection) { theText = document.getSelection() ,- } else if (document.selection && document.selection.createRange) { theText = document.selection.createRange().text; if (theText) { document.forms[0].charCodeDisplay.value = theText.charCodeAt(); } else { document.forms[0].charCodeDisplay.value = " "; } } function showstring(form) { form.result.value = String.fromCharCode(form.entry1.value, form.entry2.value,form.entry3.value); }• document.onmouseup = showCharCode; </script> \ </head> <body> <b>Capturing Character Codes</b> <form> 876 Часть IV. Объекты языка JavaScript
Select any of this text, and see the character code of the first character. <p>Character Code: cinput type=’’text" name="charCodeDisplay" size="3" /xbr /></p> <hr /> <b>Converti'ng Codes to Charactersc/bxbr /> Enter a value 0-255:cinput type="text" name="entryl" size="6" />cbr /> Enter a value 0-255:cinput type="text" name="entry2" size="6" />cbr /> Enter a value 0-255:cinput type="text" name="entry3" size="6" />cbr /> cinput type="button" value="Show String" onclick="showstring(this.form)" /> Result:cinput type="text" name="result" size="5" /> c/form> c/body> с/html> После загрузки страницы выделите произвольный текстовый фрагмент. Если выделение начинается с символа а, то будет отображен код символа 97. Если же вы не выделите текст на странице, то будет возвращено значение NaN. Введите числовые значения в три текстовых поля в нижней части страницы. Значения меньше 32 представляют символы ASCII специального назначения, которые в большинстве шрифтов отображаются в виде пустотелых квадратиков. Но все же попробуйте ввести и эти числовые коды. Обратите внимание на то, что коды со всех трех значений подставляются в метод строка. f romCharCode как единое значение, поэтому в качестве результата воз- вращается комбинированная строка. На рис. 27.1 показан результат ввода во всех трех полях- кодов для прописных символов. строка.concat(с трока2) Возвращаемое значение: комбинация строк. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Оператор сложения с присвоением (+=) в JavaScript обеспечивает удобный способ конка- тенации строк. Современные браузеры поддерживают строковый метод, выполняющий ту же задачу. Строка, к которой добавляется текст, является объектом или значением, вызывающим метод. Добавляемая строка является аргументом метода. "abc".concat("def") // результат: "abcdef" Как и оператор сложения с присвоением, метод concat () ничего не знает об окончаниях слов. Поэтому, если требуется добавить пробел, его следует указывать явно. См. также: оператор сложения с присвоением (+=). 1 строка.indexOf(строкаПоиска [, начИндекс]) Возвращаемое значение: индекс первого символа подстроки строкаПоиска в строке. Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Метод JavaScript indexof (), как и строковые функции в других языках, возвращает ин- декс первого символа указанной подстроки в строке. Дополнительный аргумент метода ука- зывает позицию начала поиска. Возвращаемое значение всегда отсчитывается от начала строки — от 0, как и для других строковых методов. Если в строке нет данной подстроки, метод возвращает -1. Этот метод используется для поиска экземпляров подстроки в строке. Глава 27. Объект string 877
Рис. 27.1. Преобразование символов в ASCII-коды и наоборот В браузерах NN2 и NN3 присутствует ошибка, которая приводит к некорректной работе этого метода. Если выполняется поиск пустой строки, то метод indexOf () возвращает ее, а не ожидаемое значение -1. Поэтому до применения этого метода необходимо убедиться, что строка не является пустой (см. примеры на компакт-диске). Во всех примерах результат метода присваивается переменной offset. Пример Введите каждое из следующих выражений (без комментариев, начинающихся с символов //) в верхнее текстовое тюле приложения The Evaluator. Пример использования indexOf () приве- ден на прилагаемом к книге компакт-диске. Сравните все полученные результаты. а = "bananas" a.indexOf("b") // результат 0 (индекс первой буквы — ноль а.indexOf("а") a.indexOf("а",1) // результат 1 // результат 1 (начало со второй буквы) a.indexOf("а",2) // результат 3 (начало с третьей буквы) a.indexOf("а",4) // результат 5 (начало с пятой буквы) а.indexOf("nan") а.indexOf("nas") а.indexOf("s") a.indexOf("z") // результат 2 // результат 4 // результат 6 // результат -1 (в строке нет символов "z" См. также: методы строка. lastlndexOf (), строка. charAt (), строка. substring (). строка. lastlndexOf (строкаПомска [, начИндекс]) Возвращаемое Значение: индекс последнего символа подстроки searchstring в строке. Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ 878 Часть IV. Объекты языка JavaScript
Метод строка. lastlndexOf () тесно связан с методом строка. indexOf (). Разница заключается в том, что этот метод начинает поиск с конца строки (строка. length — 1), по- этому поиск проводится в обратном направлении. Все значения индексов отсчитываются от 0 — начала строки. Для сравнения результатов в приведенных примерах используются те же значения, что и в примерах метода строка. indexOf (). В строках, которые содержат только один эк- земпляр требуемой подстроки, методы возвращают одинаковые результаты; там же, где присут- ствует несколько необходимых экземпляров, результаты методов существенно различаются. Пример Введите каждое из приведенных далее выражений (без комментариев, начинающихся с символов / / ) в верхнее текстовое поле приложения The Evaluator. Пример использования lastlndexOf () приведен на прилагаемом к книге компакт-диске. Сравните все получен- ные результаты. а = "bananas" а.lastlndexOf("Ь") a.lastlndexOf("а") a.lastlndexOf("а" , 1) a.lastlndexOf("а" , 2) a.lastlndexOf("а" ,4) a.lastlndexOf("nan") a.lastlndexOf("nas") a.lastlndexOf("s") a.lastlndexOf("z") // результат 0 (индекс первой буквы - ноль) // результат 5 // результат 1 (со второй буквы в начало) // результат 1 (с третьей буквы в начало) // результат 3 (начало с пятой буквы) // результат 2 [в NN2.О результат -1 (ошибка)] // результат 4 // результат 6 // результат -1 (в строке нет символов "z") См. также: методы строка. indexOf (), строка. charAt (), строка. substring (). сорока.localeCompare(строка2) Возвращаемое Значение: целочисленное Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safaril+ Метод localeCompare () позволяет сценарию сравнить строки в кодировке Unicode, (с уче- том используемого браузером языка общения с пользователями). Необходимость в этом методе возникает лишь в определенных языковых системах (например турецкой). Если строки являются равными, метод возвращает нулевое значение. Если находящееся слева от точки строковое зна- чение, для которого вызван метод, меньше (подсчитывается сумма кодов символов), чем строка- аргумент, метод возвращает отрицательное целое число; в ином случае — положительное. Стандарт ЕСМА предполагает, что абсолютное значение отрицательного и положитель- ного результата зависит от разработчиков браузера. NN6+ подсчитывает сумму Uriicode- кодов символов исходной строки и строки аргумента, а затем вычисляет их разность. IE5.5+ возвращает просто -1 или 1. См. также: методы строка. toLocaleLowerCase (), строка. toLocaleUpperCase (). строка. match (регВыражение) Возвращаемое значение: массив строк, удовлетворяющих шаблону Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Метод строка .match () использует объект RegExp (регулярное выражение), появив- шийся в JavaScript в NN4 и IE4. Исследуемое строковое значение указывается слева от точки, а регулярное выражение — в аргументе метода. Параметр должен быть объектом, созданным одним из двух возможных способов. Если найдено хотя бы одно совпадение, метод возвращает массив строк. В ином случае он возвращает значение null. Каждый элемент массива является копией подстроки, удовлетво- Глава 27. Объект string 879
ряющей регулярному выражению. Этим методом можно воспользоваться для подсчета количе- ства экземпляров определенной подстроки или последовательности символов в данной строке. Поиск позиций подстрок в строке требует применения других методов синтаксического анализа. Пример Чтобы помочь вам изучить метод строка. match (), мы создали документ, представлен- ный листингом 27.3. Для ввода данных мы использовали два поля: первое принимает длин- ную строку, анализируемую методом, а второе — регулярное выражение. Если вы не знакомы с регулярными выражениями (глава 42), то во втором поле будет использоваться некое значе- ние по умолчанию. С помощью флажка укажите на необходимость поиска в режиме чувстви- тельности к регистру символов. После щелчка на кнопке Execute Match() сценарий создаст объект регулярного выражения, выполнит сам метод по отношению к длинной строке и вы- ведет два результата. Первый результат— это массив возвращаемых методов значений, а второй — количество найденных элементов. <html> «head» <title>Regular Expression Match</title> «script type="text/-javascript"> function doMatch(form) { var str = form.entry.value; var delim = (form.caseSens.checked) ? "/g" : "/gi"; var regexp = eval("/" + form.regexp.value + delim); var resultArray = str.match(regexp); if (resultArray) { form, result .value = resultArray.toString(); form.count.value = resultArray.length; } else { form.result.value = "<no matches»"; form.count.value = ""; } } «/script» «/head» «body» <b»String Match with Regular Expressions«/b> «hr /> «form» , Enter a main string:«input type="text" name="entry" size="60" value="Many a maN and womAN have meant to visit GerMAny." /xbr /> Enter a regular expression to match:«input type="text" name="regexp" size="25" value="\wa\w" /> «input type="checkbox" name="caseSens" />Case-sensitive «pxinput type="button" value="Execute match()" onclick="doMatch(this.form)" /> «input type="reset" /></p> <p»Result:«input type="text" name="result" size="40" /xbr /> Count:«input type="text" name="count" size="3" /xbr /></p> «/form» </body» </html> 880 Часть IV. Объекты языка JavaScript
По умолчанию в длинной строке прописные символы введены в произвольном порядке. Использование такой нестандартной строки в методе match () позволяет более глубоко изу- чить принципы работы последнего. В приведенной ниже таблице приведены примеры регу- лярных выражений, которые вы можете смело использовать при изучении этого метода. Регулярное выражение Описание man Как с учетом регистра, так и без учета регистра man\b man располагается в конце слова \bman man располагается в начале слова me* an Между тиа введено произвольное количество символов е (или ни одного) .a. Слева и справа от а введено по одному символу (пробел тоже рассматривается как символ) \as\s Слева и справа от а введены пробелы z Символ z (в строке по умолчанию не встречается) Если в сценарии листинга 27.3 метод match О возвращает значение null, то на экран выводится соответствующее сообщение, а счетчик обнуляется. См. также: объект RegExp (глава 42). строка. replace (регВыраженле, строкаЗамены) Возвращаемое значение: измененная строка. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Регулярные выражения широко используются в операциях поиска и замены. Метод строка. replace в JavaScript обеспечивает простой способ выполнения таких операций. Процесс поиска и замены требует наличия трех компонент. Первой является исходная строка, второй — регулярное выражение, с которым проводится сравнение, а третьей — под- строка, заменяющая исходный блок текста. В методе строка. replace () исходная строка указывается слева от точки. Она может быть и обычной строкой в кавычках. Регулярное вы- ражение задается в первом аргументе метода, а строка-заменитель — во втором. Определение регулярных выражений указывает, как проводить замену: только в одном совпадении или во всех. Если в конце регулярного выражения добавить параметр д, метод replace () проведет глобальный поиск и замену. Если вы знаете, как работать с регулярными выражениями, воспользуйтесь методом строка. replace (). Применение регулярных выражений делает операции поиска и замены более мощными. Рассмотрим монолог Гамлета. То be, or not to be: that is the question: Whether 'tis nobler in the mind to suffer Если нужно заменить оба экземпляра "be" на "exist", то выполним это с помощью оператора. var regexp = /Ье/g,- soliloquy.replace(regexp, "exist"); Однако такой подход не позволит узнать, является ли комбинация букв "Ь" и 11 е" от- дельным словом. А что, если исходная строка содержит слова "being" или "saber"? При- веденный выше пример заменяет буквы "be "ив этих словах. Глава 27. Объект string 881
Регулярные выражения поддерживают специальные символы, которые упрощают реше- ние этой задачи. В приведенном выше примере выполняется поиск слова "be". К искомому выражению необходимо добавить символы, ограничивающие слово (специальные символы \Ь). var regexp = /\bbe\b/g; soliloquy.replace(regexp, "exist"); В этом синтаксисе учитывается тот факт, что после первых двух символов "be" введены знаки пунктуации, а не только пробелы. Более подробно о синтаксисе регулярных выражений рассказано в главе 42. Пример Страница, представленная листингом 27.4, создана специально для демонстрации воз- можностей методов строка. replace () и строка. search (). В качестве исходного тек- ста используется пять строк из бессмертного “Гамлета”. В поля этого приложения можно вводить как регулярное выражение для поиска, так и заменяющее найденные элементы вы- ражение. Обратите внимание, что сценарий создает объект регулярного выражения автома- тически, поэтому вы можете смело вводить любые комбинации специальных символов. За- мена текста выполняется на глобальном уровне, поскольку во введенное выражение автоматически добавляется параметр д. Значения по умолчанию в полях приложения позволяют заменить синтаксическую конструк- цию 1 tis на it' s. Запуск сценария выполняется по щелчку на кнопке Execute replace() (рис. 27.2). Учтите, что символ обратной косой черты перед апострофом делает последний частью регулярно- го выражения, а не символом определения текстового типа данных веденного значения. Рис. 27.2. Использование регулярного выражения по умолчанию для замены тек- стового значения Вы можете самостоятельно изменить листинг сценария так, чтобы он заменял текст в HTML- документе, загруженном в браузере IE4+ или W3C. Для этого вам необходимо заключить абзац 882 Часть IV. Объекты языка JavaScript
в отдельный элемент (обычно span), а затем выполнить метод replace О по отношению к значению innerHTML элемента. Листинг ВТ А Иэммнмтмтвдм гв₽1ис«(> chtml> <head> <title>Regular Expression Replace and Search</title> <script type="text/javascript"> var mainString = "To be, or not to be: that is the question:\n"; mainString += "Whether \'tis nobler in the mind to suffer\n"; mainString += "The slings and arrows of outrageous fortune,\n"; mainString += "Or to take arms against a sea of troubles,\n"; mainString += "And by opposing end them."; function doReplace(form) { var replaceStr = form.replaceEntry.value; var delim = (form.caseSens.checked) ? "/g" : "/gi"; var regexp = eval("/" + form.regexp.value + delim); form.result.value = mainString.replace(regexp, replaceStr); function doSearch(form) { var replaceStr = form.replaceEntry.value; var delim = (form.caseSens.checked) ? "/g" : "/gi"; var regexp = eval("/” + form.regexp.value + delim); form.result.value = mainString.search(regexp); } </script> </head> <body> <b>String Replace and Search with Regular Expressions</b> <hr / > Text used for string.replace() and string.search() methods:<br /> <b>To be, or not to be: that is the question:<br /> Whether 1tis nobler in the mind to suffercbr /> The slings and arrows of outrageous fortune,<br /> Or to take arms against a sea of troubles,cbr /> And by opposing end them.c/b> <form> Enter a regular expression to match:<input type="text" name="regexp" size="25" value="\B't" /> cinput type="checkbox" name=11 caseSens" />Case-sensitive<br /> Enter a string to replace the matching strings:cinput type="text" name="replaceEntry" size="30" value="it " /> cp>cinput type="button" value= "Execute replaceO" onclick="doReplace(this.form)" /> cinput type="reset" /> cinput type="button" value="Execute search()" onclick="doSearch(this.form)" />c/p> cp>Result:cbr /> ctextarea name="result" cols="60" rows="5" wrap="virtual"> c/textarea>c/p> c/form> c/body> c/html> См. также: метод строка. match (); объект RegExp. Глава 27. Объект string 883
строка.search (регВыражение) Возвращаемое значение: целочисленное смещение. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Результаты метода строка. search () напоминают результаты метода строка. indexOf (). В обоих случаях возвращается индекс первого экземпляра подстроки в исходной строке или -1, если такового не обнаружено. Разница заключается в том, что метод строка. search () по- зволяет использовать в строке поиска регулярные выражения. Пример В листинге 27.4 приведен сценарий приложения, предназначенного для детального изуче- ния метода строка. search (). См. также: метод строка. match (); объект RegExp. строка.slice(начИндекс [, конИндекс]) Возвращаемое значение: строка. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Метод строка. slice () похож на метод строка. substring (): они оба позволяют из- влечь из строки подстроку (не изменяя исходную). Преимущество метода строка. slice () заключается в том, что в этом методе можно указать индекс, отсчитываемый не от начала, а от конца строки. Для извлечения подстроки, которая заканчивается за 2 символа до конца строки, методом строка. substring () требуется провести дополнительные вычисления. строка.substring(4, (string.length-2)) Метод строка. slice () позволяет указать отрицательное значение во втором аргумен- те, т.е. отсчитать индекс от конца строки. строка.slice(4, -2) Второй аргумент не является обязательным. Если он опущен, метод возвращает подстро- ку, началом которой служит заданная позиция, а концом — конец строки. Пример Листинг 27.5 содержит код приложения, предназначенного для всестороннего изучения метода строка.slice(). Окно приложения представлено на рис. 27.3. В верхней части страницы показана исходная строка, а в нижней части документа — элементы управления для ввода аргументов метода. <html> <head> <title>String Slicing and Dicing, Part I</title> <script type="text/javascript"> var mainString = "Electroencephalograph"; function showResults() { var form = document.forms[0]; var paraml = parselnt(form.paraml.options[form.paraml. selectedlndex].value); var param2 = parselnt(form.param2.options[form.param2. 884 Часть IV. Объекты языка JavaScript
selectedlndex].value); if (!param2) { form.resultl.value = mainString.slice(paraml); } else { form.resultl.value = mainString.slice(paraml, param2); «/script? </head> cbody onload="showResults()"> <t»String slice() Method«/b? «hr / > Text used for the methods:<br /> «font size="+l"?«tt?<b?Electroencephalograph<br /> ----5----5----5----5-</bx/ttx/font> <form> <table> <tr> <th>String Method</th> <th>Method Parameters</th> <th>Results«/th> </tr> <tr> <td>string.slice()</td? <td rowspan="3" valign=l,middle" ? (&nbsp;«select name="paraml" onchange="showResults()"> «option value="O,,?O</option? «option value="l"?l</option? «option value="2"?2</option? «option value="3">3«/option> «option value="5"?5</option? «/select?, «select name="param2" onchange="showResults()"> «option?(None)«/option? «option value=,,5">5«/option> «option value="10"?10«/option? «option value="-l">-l«/option> «option value="-5">-5</option> «option value="-10">-10</option> </select?&nbsp;) «/td> «tdxinput type="text" name="resultl" size="25" /?</td? </tr> «/table? «/form? «/body? «/html? См. также: методы строка. substr (), строка. substring (). строка. split ("разделитель" [, ограничитель^) Возвращаемое значение: массив элементов. Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Метод split по своей функциональности противоположен методу array, join () (см. главу 30). С точки зрения строкового объекта, JavaScript разбивает строку на элементы, Глава 27. Объект string 885
разделенные определенным символом, и создает из них массив. Инициализировать массив конструктором new Array () нет необходимости. Принимая во внимание наличие функцио- нальных методов объекта array, например array. sort (), часто возникает необходимость преобразовать набор строковых элементов в массив, чтобы воспользоваться ими. Если вашей целью является преобразование строки в массив отдельных символов, метод split () впол- не подойдет для выполнения этой задачи. В этом случае аргументом должна быть пустая строка. В NN3 и IE4 метод использует только первый аргумент. : Fite Edit Vtow FavorHw ТмЬ >Шр Рис. 27.3. Страница изучения метода slice () В браузерах NN4+ и IE4+ в качестве первого параметра можно применить объект регу- лярных выражений, что повышает возможности поиска символов-разделителей. Рассмотрим следующую строку. var nameList = "1.Fred,2.Jane,3.Steve"; Для преобразования этой строки в массив из трех элементов, содержащий лишь имена, без использования регулярных выражений потребуется провести определенный синтаксиче- ский анализ еще до начала метода string. split (). Применение регулярных выражений значительно упрощает задачу. var regexp = /,*\d.\b/; var newArray = nameList.split(regexp); // результат: массив "Fred", "Jane", "Steve"; Новый массив содержит только имена (без цифр или точек). Второй аргумент метода яв- ляется дополнительным. Он позволяет указать максимальное количество элементов, сохра- няемых в массиве. 886 Часть IV. Объекты языка JavaScript
Пример Используйте приложение The Evaluator для изучения метода строка. spl it (). Для начала сохраните текстовую строку со значениями, разделенными запятыми, в отдельной переменной. а = "Anderson,Smith,Johnson,Washington" Далее разделите эту строку по символам запятых, включив полученные элементы в массив. b = а.split(",") Чтобы доказать, что массив содержит четыре элемента, изучите значение его свойства length. b.length // результат 4 См. также: метод array. j oin (). строка. substr (начало [, длина]) Возвращаемое значение: строка. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Метод строка. substr () представляет собой вариант метода строка. substring (), который был частью языка JavaScript с момента его создания. Различие заключается в том, что аргументы метода строка, substr () указывают начальный индекс и количество сим- волов в подстроке, тогда как в методе сорока. substring () необходимо указывать на- чальный и конечный индексы. Как и для других методов, в строка. substr () первый аргумент, индекс, отсчитывается с нуля. Если второй аргумент не указан, то в подстроку включаются все символы от началь- ной позиции до конца строки. То же самое происходит и тогда, когда значение второго аргу- мента превосходит индекс последнего символа в строке. Пример Чтобы детально ознакомиться с методом строка. substr (), загрузите страницу, пред- ставленную листингом 27.6, и внимательно изучите ее возможности. <html> <head> <title>String Slicing and Dicing, Part II</title> «script type="text/javascript"> var mainString = "Electroencephalograph"; function showResults() { var form = document.forms[0]; var paraml = parselnt (form.paraml.options [form.paraml.selectedlndex] .value) ; var param2 = parselnt (form. param2. options [form.paranu. selectedlndex] .value) ; if (!param2) { form.resultl.value = mainString.substr(paraml); } else { form.resultl.value = mainString.substr(paraml, param2); } } </script> «/head> «body onload="showResults()"> <b>String substr() Methodc/b> «hr /> Глава 27. Объект string 887
Text used for the methods:<br /> <font size="+l”xttxb>Electroencephalograph<br /> ---5----5----5----5-</-bx/ttx/font> <form> <table> <tr> <th>String Method</th> <th>Method Parameters</th> <th>Results</th> </tr> <tr> <td>string.substr()</td> <td rowspan="3“ valign=,,middle"> (&nbsp;<select name=" paraml11 onchange="showResults () "> ' <option value="0">0</option> <option value="l">l</option> coption value="2">2</option> coption value="3">3</option> coption value=’'5">5</option> </select>, cselect name="param2" onchange="showResults()"> coption>(None)c/option> coption value="5">5c/option> coption value=”10">10c/option> coption value="20">20c/option> </select>&nbsp;) c/td> ctdxinput type="text" name="resultl" size="25" /x/td> c/tr> c/table> c/form> c/body> c/html> См. также: метод строка. substring (). строка.substring(индексА, индексВ) Возвращаемое значение: подстрока, заданная начальным (индекстА) и конечным (индексВ) индексами. Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Метод строка. substring () позволяет выделить подстроку (т.е. группу символов) из строки. Аргументами этого метода являются начальный и конечный индексы (первый символ строки имеет индекс 0) подстроки в исходной строке. Важно отметить, что символ, заданный конечным индексом, не включается в подстроку. В каком порядке заданы индексы — не имеет значения: метод начинает с меньшего и закан- чивает на большем (исключая последний символ). Если значения индексов совпадают, метод возвращает пустую строку, а если второй аргумент опущен, подстрока доходит до конца строки. Пример Чтобы детально ознакомиться с методом строка.substring(), загрузите страницу, представленную листингом 27.7, и внимательно изучите ее возможности. 888 Часть IV. Объекты языка JavaScript
<html> <head> «title>String Slicing and Dicing, Part III«/title> «script type="text/javascript"? var mainString = "Electroencephalograph"; function showResults() { var form = document. forms [0] ; var paraml = parselnt (form.paraml.options [form.paraml.selectedlndex] .value) ; var param2 = parselnt(form.param2. options[form.param2.selectedlndex].value); if (!param2) { form.resultl.vdlue = mainString.substring(paraml); } else { form.resultl.value = mainString.substring(paraml, param2); } } </script> «/head? <body onload="showResults()"> «b?String substr() Method</b> <hr / > Text used for the methods:«br /> <font size="+l"?«tt?<b?Electroencephalograph«br /> ----5----5----5----5-</bx/ttx/font> <form> <table> <tr> <th?String Method</th> <th?Method Parameters</th> <th?Results«/th? </tr> <tr> <td>string.substring()</td? <td>(&nbsp;<select name="paraml" onchange="showResults()"> «option value="0"?0</option? «option value="l"?l«/option? «option value="2"?2«/option? «option value="3">3«/option> «option value="5">5«/option> «/select?, «select name="param2" onchange="showResults()"> «option>(None)«/option> «option value=,,3">3</option> «option value="5"?5«/option? «option value="10">10«/option> </select >&nbsp,-) </td> «tdxinput type="text" name="resultl" size="25" /x/td> </tr? </table> «/form? «/body? </html> См. также: методы строка. substr (), строка. slice (). Глава 27. Объект string 889
строка.toLocaleLowerCase() строка.toLocaleUpperCase() Возвращаемое значение: строка. Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Два этих метода представляют собой варианты стандартных методов изменения регистра строки. Они учитывают определенные языковые системы, символы которых включают не только буквы латинского алфавита. См. также: методы строка. toLowerCase (), строка. toUpperCase (). строка.toLowerCase() строка.toUpperCase() Возвращаемое значение: строка в верхнем или нижнем регистре (в зависимости от метода). Совместимость: WinIE3+, МасЕЗ+, NN2+, Mozl+, Safaril+ В Internet (и в JavaScript) регистр имеет важное событие. URL на некоторых серверах (например, при обработке) требует учета регистра в именах файлов и папок. Два этих метода пред- ставляют собой простейшие строковые методы, цель которых — преобразование строки в верхний или нижний регистр. Строки со смешанным регистром преобразуются к единому типу. Если, например, текст, введенный пользователем в поле, необходимо сравнить с некоторой строкой без учета регистра, преобразуйте строки к одному регистру, а Затем проведите сравнение. Пример Вы можете смело использовать методы строка. toLowerCase (), строка. toUpperCase () в строковых выражениях. var newString = "HTTP://www.Netscape.COM" .toLowerCase () ; // результат "http://www.netscape.com" Эти методы также помогут сравнить строки, в которых регистр символов не имеет значения. if (guess.toUpperCase() == answer.toUpperCase()) {...} // сравнение строк без учета регистра символов См. также: методы строка.toLocaleLowerCase(), строка.toLocaleUpperCase(). строка.toString() строка.valueOf() Возвращаемое значение: строковое значение. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Оба метода возвращают строковые значения (в отличие от полноценных строковых объек- тов). Если строковый объект создан конструктором new String (), то его тип определяется как obj ect. Поэтому, если требуется определить тип сохраняемых в данном объекте значений, применяется метод valueOf () с последующим оператором typeof. Объект, в первую очередь, имеет метод toString (), так как он наследует этот метод от исходного объекта JavaScript Пример Используйте приложение The Evaluator для изучения метода valueOf (). Введите в верхнее текстовое поле приложения следующее выражение, а затем изучите полученные результаты в области Results. а = new String("hello") typeof a 890 Часть IV. Объекты языка JavaScript
b = a.valueOf() typeof b Поскольку все остальные объекты языка JavaScript поддерживают метод indexOf (), вы можете создать общую функцию, которая принимает в качестве аргументов тип объекта и разветвляет сценарий в зависимости от последнего. См. также: оператор typeof (глава 32). Функции обработки строковых данных Использовать строковые методы для достижения той или иной цели непросто, особенно, если требуется обеспечить совместимость с ранними версиями браузеров. Кроме того, трудно предугадать, какие способы обработки строк могут понадобиться в сценариях. Листинг 34.8 содержит библиотеку строковых функций, предназначенных для вставки, удаления и замены блоков текста в строке. Если браузеры, на которые ориентирована страница, поддерживают подключение внешних файлов JavaScript (. j s), функции будут всегда доступны сценариям. м -- й -------- Листинг27 0. Функции строками II извлечение начала строки до searchstring function getFront(mainStr,searchStr){ foundOffset = mainStr. indexOf (searchStr) ,- if (foundOffset == -1) { return null; } return mainStr. substring (0, foundOffset) ,- } // извлечение конца строки после searchstring function getEnd(mainStr,searchStr) { foundOffset = mainStr.indexOf(searchStr); if (foundOffset == -1) { return null; } return mainStr.substring(foundOffset+searchStr.length, mainStr.length); } // вставка insertstring перед searchstring function insertstring(mainStr,searchStr,insertstr) { var front = getFront(mainStr,searchStr); var end = getEnd(mainStr,searchStr); if (front != null && end != null) { return front + insertStr + searchStr + end; } return null; } // удаление deletestring function deleteString(mainStr,deleteStr) { return replacestring(mainStr,deleteStr, "") ,- } // замена searchstring на replacestring function replacestring(mainStr,searchStr,replaceStr) { var front = getFront(mainStr,searchStr); Глава 27. Объект string 891
var end = getEnd(mainStr,searchStr); if (front != null && end != null) { return front + replaceStr + end; } return null; } Две первые функции извлекают подстроку в начале или конце строки и являются проме- жуточными функциями набора, ядро которого составляют три последние функции. Обратите внимание, что одни функции зависят от других, поэтому только включение всей группы из пяти функций позволяет им работать так, как запланировано. В современных сценариях, подобных приведенному в листинге 27.8, для замены текстовых данных в одном операторе используется комбинация строковых методов и методов массива. function replaceString(mainStr, searchStr, replaceStr) { return mainStr.split(searchStr).join(replaceStr); } Для дальнейшего улучшения предложенной концепции вы можете создать пользователь- ский метод управления строковыми данными или строковыми объектами. После загрузки страницы укажите сценарию выполнить следующее выражение. String.prototype.replaceString = function(mainStr, searchStr, replaceStr) { return mainStr.split(searchStr).join(replaceStr); } Впоследствии вы можете вызвать этот метод из любого строкового значения даже в дру- гих сценариях страницы. myString = myString.replaceString(" CD ", " MP3 "); Методы форматирования Теперь мы подошли к рассмотрению следующей группы методов строкового объекта, ко- торые облегчают процесс создания различных характеристик строк, необходимых для созда- ния HTML-кода средствами JavaScript. Ниже приведен список этих методов. строка.anchor("anchorName") строка.blink() строка.bold() строка.fixed() строка.fontcolor(colorvalue) строка.fontsize(integerlto7) строка.italics() строка.link(locationOrURL) строка.big() строка.smal1() строка.strike() строка.sub() строка.sup() Вначале рассмотрим методы, не требующие никаких аргументов. Это, в первую очередь, методы, устанавливающие атрибуты шрифтов строки. В HTML-документе их изменение дос- тигается парой дескрипторов, например <Ь>. .. </Ь> для полужирного шрифта. Эти методы добавляют к строковому объекту необходимые дескрипторы и возвращают текст, готовый к добавлению в HTML-код. Например,,выражение "Good morning!".bold() превращается в <b>Good morning!</b> 892 Часть IV. Объекты языка JavaScript
HTML-код можно создать и без этих методов, вставив в него все необходимые дескрип- торы. Одним из достоинств строковых методов — это сохранение закрывающего дескрипто- ра пары. Листинг 27.9 демонстрирует пример использования простых строковых методов, ко- торые создают значение переменной, отображаемое затем на странице. Internet Explorer не поддерживает дескриптор <blink> и поэтому игнорирует метод строка. blink (). <html> <head> <title>HTML by JavaScript</title> </head> , <body> <script type="text/javascript"> var page = ""; page += "JavaScript can create HTML on the fly.<P>Numerous string object methods facilitate creating text that is " + "boldfaced".bold() + ", “ + "italicized".italics() + ", or even the terribly annoying " + "blinking text".blink () + ". " document.write(page); </script> </body> </html> Два следующих метода (строка. fontsize () и строка. fontcolor ()) также влия- ют на характеристики шрифта текста, отображаемого на HTML-странице. Аргументы доста- точно очевидны: целое число в диапазоне от 1 до 7, задающее относительный размер шриф- та, и цвет (в виде шестнадцатеричного триплета или константы-имени цвета) текста. В листинге 27.10 к строке из листинга 27.9 добавляется определенная строка текста. Эта строка не только изменяет размер шрифта определенных частей текста, но и применяет вло- женные атрибуты для задания цвета. Поскольку эти методы не изменяют содержимого стро- ки, их можно смело использовать как вложенные. <html> <head> <title>HTML by JavaScript</title> </head> <body> <script type="text/javascript"> var page = ""; page += "JavaScript can create HTML on the fly.<P>Numerous string object methods facilitate creating text that is " + "boldfaced".bold() + ", " + "italicized".italics() + ", or even the terribly annoying " + "blinking text".blink() + ".<br />"; page += "We can make " + "some words big".fontsize(5) + " and some words both'" + ("big and " + "colorful".fontcolor(1 coral1))-fontsize(5) + " at the same time."; document.write(page); </script> </body> </html> Глава 27. Объект string 893
Два заключительных строковых метода позволяют добавить для строки анкер и ссылку. Ар- гумент метода string. anchor () используется в качестве имени анкера. Поэтому выражение "Table of Contents".anchor("toe") преобразуется в <a name="toc">Table of Contents</a> Подобным образом метод string. link () принимает в качестве параметра URL. "Back to Home".1ink("index.html") Это выражение преобразуется в следующее. <а href="index.html">Back to Home</a> Этими методами пользоваться необязательно — ведь можно также установить дескрипто- ры HTML вручную. Методы применять удобнее, если аргументы являются переменными, значения которых зависят от введенных пользователем данных. Кодирование и декодирование строк URL При взаимодействии браузеров и серверов некоторые небуквенно-цифровые символы (например пробел) нельзя переслать в их естественной форме. Протоколы передачи данных позволяют отправить более узкий набор символов. Для представления всех остальных симво- лов используется специальный символ (%), за которым следует шестнадцатеричный код ASCH. Например, шестнадцатеричный код пробела равен 20 (десятичный — 32). Соответст- венно, он преобразуется к виду %20. Такие символы часто встречаются в списке URL посе- щенных браузером документов. JavaScript поддерживает две функции, escape () и unescape (), которые позволяют преобразовывать в код отдельные строки. Для преобразования строки в закодированный формат используется оператор. escape("Howdy Pardner") // результат "Howdy%20Pardner" Функция unescape () выполняет обратное преобразование. Об этих функциях, а также некоторых других речь пойдет в главе 34. 894 Часть IV. Объекты языка JavaScript
Объекты Math, Number и Boolean Типы данных JavaScript были представлены в главе 6. В настоящей главе мы подробно рассмотрим, как JavaScript работает с числовыми и логическими данными. Математические операции иногда вызывают трудности у программистов, однако, как вы сможете убедиться, их про- граммирование на JavaScript не представляет никаких слож- ностей. Если вы не очень хорошо помните основы математи- ки, внимательно изучите применяемую далее терминологию. Важно помнить, что (как и в случае со строками) числа и значения логического типа являются одновременно и объек- тами, и значениями. К счастью, различие проявляется лишь в очень тонком и сложном программировании. Для тех же, кто создает интерпретаторы JavaScript для браузеров, такое различие является жизненно важным. Для большинства авторов сценариев информация о чи- словых типах данных, преобразованиях, а также объекте Math является важной. Другие подробные сведения о число- вых и логических объектах будут представлены лишь с це- лью общего ознакомления, поскольку редко применяются в Web-программировании. Числа в JavaScript Более мощные языки программирования включают до- вольно много числовых типов, каждый из которых занимает определенный объем памяти компьютера. Но эффект от их ис- пользования при быстром создании несложных сценариев не- велик. Поэтому числа в JavaScript принадлежат лишь к одному из двух возможных типов: целому или с плавающей точкой. Целыми являются числа, не имеющие десятичной части (и, со- ответственно, не содержащие десятичной точки в своем пред- ставлении). Числа с плавающей точкой включают целую и дробную части. Если вы имеете опыт в программировании, обратитесь к описанию объекта Number далее в этой главе, где речь пойдет о том, как числовые типы данных в JavaScript соот- носятся с типами данных в других средах программирования.
Целые числа и числа с плавающей точкой Микропроцессор намного быстрее выполняет операции с целыми числами, чей с числами с плавающей точкой. Операции с последними требуют дополнительных действий. Разработ- чикам сценариев необходимо следить за тем, какие числа используются в расчетах. Большинство внутренних значений, которые применяются в JavaScript (например, индек- сы или длины объектов), являются целочисленными. Числа е плавающей точкой используют- ся, как правило, при выполнении операции деления, при работе со специальными константа- ми (например, число л) или при обработке введенных пользователями данных (например, денежных значений). К счастью, JavaScript позволяет проводить операции со смешанными типами данных. Обратите внимание, как получен результат в следующих примерах. 3+4=7 // целое число 3 + 4.1 = 7.1 // число с плавающей точкой 3 .9 + 4.1 = 8 // целое число В этих трех примерах, пожалуй, только последний результат оказался неожиданным. Если два числа с плавающей точкой дают результат с нулевой дробной частью, то такое число счи- тается целочисленным. При работе с числами с плавающей точкой необходимо помнить, что не все версии брау- зеров возвращают абсолютно точное значение до последней цифры после запятой. Например, в следующей таблице показан результат операции деления числа 8 на число 9, выполненной в различных браузерах (на платформе Windows) после преобразования в строковый тип. NN2 NN3 NN4 NN6+/Mozilla 1+/Safari 1+ IE3 IE4+ 0.88888888888888884 .8888888888888888 .8888888888888888 0.8888888888888888 0.888888888888889 0.8888888888888888 Очевидно, что браузеры с поддержкой JavaScript не подходят для расчета траекторий космических полетов. Применяя JavaScript для несложных ежедневных расчетов, необходимо не забывать об ошибках, характерных для операций с нецелочисленными данными. В NN язык JavaScript использует математику самой ОС. Системы, поддерживающие та- кую точность, которую обеспечивает JavaScript, встречаются нечасто. Как можно увидеть в таблице, современные браузеры (и Netscape, и Microsoft) отображают одинаковое количест- во чисел после запятой и подобным образом проводят округление. Это хорошо для расчетов, но не очень удобно, когда числа нужно выводить в определенном формате. В версиях, предшествующих IE5.5 и NN6, JavaScript не поддерживает методов формати- рования числовых результатов с плавающей точкой (см. методы форматирования объекта Number в современных браузерах далее в этой главе). В листинге 28.1 представлена универ- сальная процедура форматирования положительных значений, а также специальная процеду- ра для преобразования числа к денежному формату. <html> <head> <title>Number Formatting</title> «script type="text/javascript"> function format(expr, decplaces) { 896 Часть IV. Объекты языка JavaScript
var str = "" + Math.round(eval(expr) * Math.pow(10,decplaces)); while (str,length <= decplaces) { str = "0" + str; } var decpoint = str.length - decplaces; return str.substring(0,decpoint) + + str.substring(decpoint,str.length); function dollarize(expr) { return "$" + format(expr,2); } . </script? «/head? <body> <hl>How to Make Money</hl> <form> Enter a positive floating point value or arithmetic expression to be converted to a currency format: <pxinput type="text" name="entry" value="l/3" /> «input type="button" value="&gt;Dollars and Cents&gt;" onclick="this.form.result.value=dollarize(this.form. entry.value)" /? «input type="text" name="result" />«/p> «/form? «/body? «/html? Процедура может показаться сложной, но она чрезвычайно полезна, если Web-приложе- ние запрашивает значения с плавающей точкой и требует определенного форматирования во всех браузерах. Числа с плавающей точкой можно записать и в экспоненциальной форме. На это указыва- ет буква е (нижнего или верхнего регистра), за которой следует знак (+ или -) и значение. Приведем примеры некоторых значений, представленных в экспоненциальной форме. 1еб // 1,000,000 (знак "+" необязателен при положительном // показателе степени) 1е-4 // 0.0001 (плюс некоторая ошибка далее после запятой) -4е-3 // -0.004 Значения в диапазоне от 1е-5 до 1е15 JavaScript отображает в виде чисел неэкспоненци- альной формы (хотя в браузерах IE5.5, NN6 и W3C можно использовать и экспоненциальную форму). Значения вне этого диапазона отображаются в экспоненциальной форме во всех браузерах. Шестнадцатеричные и восьмеричные целые числа JavaScript позволяет работать со значениями в десятичном (основание 10), шестнадцате- ричном (основание 16) и восьмеричном (основание 8) форматах. При этом необходимо сле- довать нескольким правилам. Десятичные значения никогда не начинаются с 0. Поэтому, если пользователь введет де- сятичное число с начальным нулем, то до выполнения каких-либо операций сценарий должен устранить его из строки или воспользоваться глобальными функциями обработки чисел (они описаны в следующем разделе). Шестнадцатеричные значения начинаются с Ох или 0Х (нуль, а не буква "о"). Цифры от А до F могут быть представлены в любом регистре. Представим несколько чисел в шестна- дцатеричном формате. Глава 28. Объекты Math, Number и Boolean 897
0Х2В OXla Oxcc He пугайте шестнадцатеричные числа, используемые в арифметике, с теми значениями, которые применяются при указании цвета в Web-документах. Они записываются в специаль- ном шестнадцатеричном триплетном формате, на который указывает начальный символ решетки (например, #сОсОсО). Восьмеричные значения начинаются с 0. За ним следуют цифры от 0 до 7. Восьмеричные значения могут быть только целыми. В арифметических выражениях можно смешивать значения различных типов. JavaScript приводит результат к десятичной форме. Чтобы преобразовать числа к другой системе, необ- ходимо воспользоваться определенными функциями. В листинге 28.2 приведен пример функ- ции, преобразующей десятичное число в диапазоне от 0 до 255 в шестнадцатеричный формат. function toHex(dec) { hexChars = "0123456789ABCDEF" if (dec > 255) { return null } var i = dec % 16 var j = (dec - i) / 16 result = "OX” result += hexChars.charAt(j) result += hexChars.charAt(i) return result 2_________________________________________________________________________ Функция преобразования toHex () предполагает, что значение, передаваемое ей, являет- ся десятичным целым. Если требуется шестнадцатеричное представление числа в строковом формате, то используйте метод toString (), описанный в главе 34. Преобразование строк в числа В этой главе еще не обсуждался вопрос о том, как преобразования числа, представленного строкой, в формат, используемый для арифметических операций. Многие операторы и мате- матические методы JavaScript воспринимают строковое представление чисел и позволяют выполнять действия с ним. Несовместимость типов данных проявляется чаще всего при попыт- ке выполнить сложение оператором + (который для строк служит оператором конкатенации). Кроме того, при выполнении операций помните, что значения, поступающие из текстовых по- лей форм, являются строками. Таким образом, зачастую их следует преобразовывать в числа. Преобразование строк в числа выполняется с помощью одной из двух функций JavaScript. parselnt(строка [,сисИсчисления] ) parseFloat(строка [,сисИсчисления]) Эти функции заимствованы из языка Java. Термин синтаксический анализ имеет несколь- ко значений в программировании. Одно из них — извлечение. Функция parselnt () возвраща- ет целочисленное значение, извлеченное из строки. Функция parseFloat О выполняет эту же операцию для чисел с плавающей точкой. Ниже приведено несколько примеров. 898 Часть IV. Объекты языка JavaScript
parselnt("42") parselnt("42.33") parseFloat("42.33") parseFloat("42") parseFloat("fred") // результат 42 // результат 42 // результат 42.33 // результат 42 // результат NaN Поскольку функция parseFloat () работает и с целыми числами, в сценариях, где при- ходится обрабатывать разные типы данных, предпочтительнее использовать ее как универ- сальный способ обработки. Второй, дополнительный, аргумент каждой функции позволяет указать систему исчисле- ния. Это удобно, например, в случае, если в строке содержится десятичное число, начинаю- щееся с нуля, так как обычно такие значения трактуются как восьмеричные. Только при яв- ном указании системы исчисления функция преобразует число так, как ожидается. parselnt("010") parselnt("010" , 10) parselnt("F2") parselnt("F2", 16) // результат = 8 // результат = 10 // результат = NaN // результат = 242 Эти функции используются везде, где требуется применить целые числа или числа с пла- вающей точкой. var result = 3 + parselnt("3") // результат = 6 var ageVal = parselnt(document.forms[0].age.value) Последний приведенный метод позволяет удостовериться, что строковое значение свойства правильно преобразовано в число (хотя перед выполнением математических операций над введен- ными пользователем значениями следует провести более тщательную проверку— см. главу 43). Оба метода parselnt () и parseFloat () работают следующим образом: они обраба- тывают первый символ строки и продвигаются по значению далее до тех пор, пока не закон- чатся цифры или десятичные символы. Поэтому их можно использовать в таких строках, как воз- вращаемая свойством navigator. appVers ion (например 4.0 (compatible; MS IE 5.5; Windows95)), для извлечения только числовой части строки. Если строка не начинается с допустимого символа, методы возвращают значение NaN (not a number — не число). Преобразование чисел в строки Если одному из строковых методов, рассмотренных в главе 27, передать значение число- вого типа, JavaScript выдаст ошибку. Поэтому до того, как определить, например, сколько цифр содержит число, его необходимо преобразовать в строку. Для этого применяют несколько способов. Один из способов предполагает конкатенацию пустой строки и числа. Предположим, что переменная dollars содержит число 2500. Что- бы воспользоваться свойством length строкового объекта (см. далее) для подсчета количе- ства цифр, необходимо построить следующую конструкцию. ("" + dollars).length // результат = 4 . Скобки указывают JavaScript, что конкатенация выполняется до обращения к свойству length. Более элегантный способ заключается в использовании метода toString (). Формат его вызова такой же, как и для любого другого метода объекта. Например, для преобразования переменной dollars в строку используется выражение. dollars.toString() // результат = "2500" Этот метод обладает дополнительными возможностями в браузерах NN3+ и IE4+: Его вторым аргументом является система исчисления. Приведем пример преобразования шестна- дцатеричного числа в строку. var х = 3 0; var у = х.toString(16); // результат = "1е" Глава 28. Объекты Math, Number и Boolean 899
Аналогично, для двоичной системы используется аргумент 2, а для восьмеричной — 8. По умолчанию применяется десятичная система исчисления (10). Не путайте эти представле- ния с реальными числовыми преобразованиями. Результат метода toStringO нельзя ис- пользовать как числовой операнд в каких-либо выражениях. Браузеры IE5.5+, NN6 и W3C поддерживают три дополнительных метода объекта Number — toExponential (), toFixed () и toPrecision (). Эти методы возвращают строки с пред- ставлением чисел, определяемым принимаемыми параметрами. Когда число совсем не число В нескольких примерах предыдущего раздела результатом определенных операций было значение NaN. Оно не является строкой, а обозначает специальное значение — Not a Number (не число). Например, попытка преобразовать строку 11 joe" в целое число методом parseFloat 0 не приведет к успеху. Метод сообщит, что исходная строка не является числом. Когда приложение получает данные от пользователя или из базы данных, расположенных на сервере, не всегда то значение, которые должно быть числовым, действительно является таковым. Поэтому перед выполнением математических операций его необходимо проверить. JavaScript под- держивает специальную глобальную функцию isNaNf), позволяющую проверить строковое представление числа. Она возвращает true, если значение не является числом, и false в ином случае. Например, так выглядит проверка поля формы, которое должно содержать число. var ageEntry = parselnt(document.forms[0].age.value) if (isNaN(ageEntry)) { alert("Try entering your age again."); } Объект Math Если необходимо выполнить более сложные операции, чем простые арифметические дей- ствия, применяют методы объекта Math. Синтаксис Доступ к свойствам и методам объекта Math. Math, свойство Math.метод(значение[, значение]) Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1 + Описание объекта Кроме обычных арифметических операций (о которых подробно рассказано в главе 32), JavaScript включает в себя более широкие математические возможности, применение кото- рых может показаться странным для тех, кто не программировал в объектно-ориентирован- ной среде. Несмотря на то, что большая часть арифметических преобразований выполняется “на ходу” (например var result = 2 + 2), сложные операции требуют применения в JavaScript объекта Math (с прописной буквы М). Объект Math имеет несколько свойств (похожих на константы других языков программирования) и довольно много методов (похожих на математические функции других языков). 900 Часть IV. Объекты языка JavaScript
Объект Math используется в операторах так же, как и любой другой объект JavaScript: ссылка начинается с имени объекта Math, затем следует точка и имя требуемого свойства или метода. Math.свойство\метод([параметр]. . . [, параметр]) Свойства в качестве значений содержат константы (например число л). Методы, как пра- вило, требуют одного или нескольких аргументов. Каждый метод возвращает результат. Свойства Свойства объекта Math в JavaScript представляют собой набор математических констант. Они приведены в табл. 28.1 с точностью 16 знаков после запятой. Свойство Значение Описание Math.E 2.718281828459045091 Постоянная Эйлера (е) Math.LN2 0.6931471805599452862 Натуральный логарифм числа 2 Math.LNIO 2.302585092994045901 Натуральный логарифм числа 10 )Math.LOG2E 1.442695040888963387 Двойной логарифм числа е Math.LOGlOE 0.4342944819032518167 Десятичный логарифм числа е Math.PI 3.141592653589793116 Число л Math.SQRTl_2 0.7071067811865475727 Квадратный корень из 0,5 Math.SQRT2 1.414213562373095145 Квадратный корень из 2 Эти значения используются во многих арифметических операциях. Например, для вычис- ления периметра окружности диаметром d применяется формула. circumference = d * Math.PI,- Наиболее распространенной ошибкой разработчиков сценариев является то, что не учи- тывается регистр в имени объекта Math и в именах его свойств. Методы Методы — это основа возможностей объекта Math в JavaScript. За исключением метода Math. random (), все они имеют один или более аргументов. Тригонометрические методы, как правило, запускаются с одним параметром; другие методы определяют наибольшее или наи- меньшее из группы чисел. Метод Math. raridom () не имеет аргументов и возвращает случай- ное число в интервале от 0 до 1 (этот метод не поддерживается в версиях NN2 для Windows и Macintosh). Все методы объекта Math, их синтаксис и описание приведены в таблице 28.2. Таблица 28.2. Методы объекта Math Метод Возвращаемое значение Math.abs(val) Абсолютное значение val Math.acos(val) Арккосинус (в радианах) val Math.asin(val) Арксинус (в радианах) val Глава 28. Объекты Math, Number и Boolean 901
Окончание табл. 28.2 Метод Возвращаемое значение Math.atan(val) Math.atan2(vail, val2) Math.ceil(val) Math.cos(val) Math.exp(val) Math.floor(val) Math.log(val) Math.max(vail, val2) Math .'min (vail, val2) Math.pow(vail, val2) Math.random() Math.round(val) Math.sin(val) Math.sqrt(val) Math.tan(val) Арктангенс (в радианах) val Угол в полярных координатах меаду х и у Целое числр, большее или равное val Косинус val Постоянная Эйлера в степени val Целое число, меньшее или равное val Натуральный логарифм (с основанием е) val Большее из двух чисел vail и val2 Меньшее из двух чисел val 1 и val2 vail В степени val2 Случайное число в интервале от о до 1 N+1, когда val >= п. 5; иначеn Косинус (в радианах) val Квадратный корень val Тангенс (в радианах) val HTML не является средой для дизайнеров графических систем, поэтому в нем редко приме- няют тригонометрические функции для вычисления расположения объектов. Лишь после появле- ния позиционируемых элементов авторы сценариев получили возможность вычислять траекторию движущихся элементов. Для тех, кто не силен в программировании, математика является слож- ной наукой. Однако JavaScript позволяет ограничиться имеющимися знаниями в области ариф- метики и логики, оставляя сложные математические функции тем, кто любит ими пользоваться. Генерирование случайных чисел Метод Math. random () возвращает число с плавающей точкой в интервале от 0 до 1. Если сценарий, например, реализует карточную игру, то в ней требуются генерировать случайные значения в диапазоне от 1 до 52; для имитации игральной кости — от 1 до 6. Для генерирования случайного целого числа от нуля до заданного значения используется следующая формула. Math.floor(Math.random() * n) Максимальным значением является п. Для генерирования чисел из заданного диапазона применяется формула Math.floor(Math.random() * (n - m + 1)) + m где m — наименьшее возможное целое число, an — наибольшее. При игре в кости для каж- дой из них используется такая формула. newDieValue = Math.floor(Math.random() * 6) + 1; Сокращенный вариант использования объекта Math В главе 31 подробно описана конструкция JavaScript, позволяющая упростить обращение к различным свойствам и методам объекта Math. Для этого существует оператор with. 902 Часть IV. Объекты языка JavaScript
Оператор with указывает JavaScript, что следующая за ним группа операторов (в фигур- ных скобках) ссылается на определенный объект. Для объекта Math основная конструкция выглядит таким образом. with (Math) { //операторы } Во всех внутренних операторах можно опустить ссылку на объект Math. Сравните длин- ный способ подсчета площади круга (с радиусом шесть единиц) result = Math.pow(6,2) * Math.PI; с короткой ссылкой with (Math) { result = pow(6,2) * PI; } Последний пример' содержит больше строк кода, однако ссылки на объект короче, а чи- таемость кода лучше. Для длинной последовательности расчетов использование оператора with для обращения к свойствам и методам объекта Math позволяет сократить вводимый код, а также уменьшить вероятность ошибок в ссылках. Конструкцию with можно использо- вать и с другими полноценными объектами, при этом JavaScript присоединяет имя объекта лишь к тем ссылкам, где оно отсутствует. С другой стороны, такой подход не очень эффекти- вен, поскольку интерпретатору JavaScript приходится выполнять немало внутренних опера- ций для отслеживания всех ссылок. Объект Number Свойства Методы constructor t©Exponential() MAX_VALUE MIN_VALUE NaN’ toFixed() toLocaleString() toString() NEGATIVE-INFINITY POSITIVE_INFINITY toPrecision() valueOf() prototype Синтаксис Создание числового объекта. var val = new Number(number) Доступ к свойствам и методам объекта Number. число, свойство | метод( [параметры] ) Number.свойство|метод([параметры] ) Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Глава 28. Объекты Math, Number и Boolean 903
Описание объекта Объект Number используется редко, поскольку в большинстве случаев возможностей JavaScript вполне хватает для несложных расчетов. Однако объект Number содержит опреде- ленную информацию и обладает определенными преимуществами для опытных программистов. Первыми в списке идут свойства, определяющие числовые диапазоны в языке. Наиболь- шее число (и в NN, и в IE) равно 1.79Е+308, наименьшее — 2.22Е-308. Любое число, большее максимального, равно POSITIVE_INFINITY, а меньшее минимального— NEGATIVE_ INFINITY. Однако эти значения встречаются редко. Наиболее полезным свойством этого объекта JavaScript является prototype. В главе 27 было показано, как добавить метод к прототипу объекта String, чтобы его содержал каж- дый новый создаваемый объект. То же самое относится и к свойству Number .prototype. Если к каждому числовому объекту необходимо добавить определенную функциональность, это свойство оказывается полезным. Оно применяется к числовым объектам, но не к число- вым значениям. Для опытных программистов следует отметить, что числовые объекты и чи- словые значения в JavaScript внутренне определяются браузером как 64-битовые значения двойной точности IEEE. Свойства constructor См. string, constructor (глава27) MAX_VALUE MINVALUE NEGATIVEINFINITY POSITIVEINFINITY Значение: число Только для чтения Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safari 14- Свойства Number. MAX_VALUE и Number. MIN_VALUE принадлежат статическому объекту Number. Они равны наибольшему и наименьшему допустимому в JavaScript (и ECMAScript) значению: 1,7976931348623157 х 1О308 и 5 х 10’324 соответственно. Числа, находящиеся за пределами этого диапазона, равны Number.POSITIVE_INFINITY или Number.NEGATIVE_INFINITY. Пример Введите каждое из приведенных далее выражений в верхнее поле приложения The Evaluator, чтобы ознакомиться со значениями этих свойств. Number.MAX_VALUE Number.MIN_VALUE - Number.NEGATIVE_INFINITY Number.POSITIVE_INFINITY См. также: свойство NaN; глобальная функция isNaN (). 904 Часть IV. Объекты языка JavaScript
NaN Значение: NaN Только для чтения Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Свойство NaN представляет собой константу, посредством которой JavaScript сообщает, что аргумент, результат функции или метода, не является числом. Чаще всего значение NaN присутствует в сценарии как результат выполнения функции parselnt () или parseFloat (), когда преобразуемая строка начинается не с цифры. Для проверки, является ли значение NaN, используется глобальная функция IsNaN (). Пример См. описание функции isNaN () в главе 34. См. также: глобальная функция isNaN (). prototype См. строка.prototype (глава27). Методы число.toExponential(количество) число.toFixed(количество) число.toPrecislon(точность) Возвращаемое Значение: строка. Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safaril+ Последнее дополнение стандарта ЕСМА (а значит, и браузеров с поддержкой JavaScript) — три метода объекта Number, предназначенных для форматирования строковых представлений чисел. Каждый метод имеет свой тип аргумента, но все они возвращают строки. Все математи- ческие операции необходимо проводить над числовыми объектами, поскольку они имеют наи- большую точность. После того, как результат получен, одним из этих методов следует преобра- зовать число в строку для отображения в теле страницы или текстовом поле. Метод toExponential () отображает число в экспоненциальной форме, даже если оно принадлежит тому диапазону, в котором JavaScript применяет стандартную форму. Целочис- ленным параметром является количество знаков после запятой (отображаются даже нули). Например, если переменная содержит значение 345, метод toExponential (3) преобразу- ет его в строку 3.450е+2, т.е. представление числа 3,45x102 в JavaScript. Метод toFixed () используется для форматирования числа с определенным количест- вом цифр после запятой. Этот метод применяется, например, для отображения результатов финансовых расчетов в единицах и сотых долях (например, долларах и центах). Целочислен- ным аргументом является количество цифр после запятой. Если число имеет больше цифр, чем требуется отобразить, метод округляет его с учетом неокругленного значения соседней цифры. Например, значение 123.455 с учетом двух цифр после запятой выводится как 123.46, а 123.4549 — как 123.45. Метод toFixed () нельзя считать точным в округле- нии, однако его возможностей вполне достаточно в большинстве случаев. Метод toPrecision () позволяет определить общее количество цифр (до и после запя- той) в отображаемом числе. Другими словами, он определяет точность числа. Следующий список демонстрирует результаты, полученные при разных значениях аргумента. Глава 28. Объекты Math, Number и Boolean 905
var num = 123.45 num.toPrecision(1) num.toPrecision(2) num.toPrecision(3) num.toPrecision(4) num.toPrecision(5) num.toPrecision(6) // результат le+2 // результат 1.2e+2 // результат 123 // результат 123.5 // результат 123.45 // результат 123.450 Обратите внимание, что метод toPrecision () проводит такое же округление, как и toFixed(). Пример Вы можете использовать приложение The Evaluator для изучения методов чис- ло .toExponential(), чксло.toFixed(), число.toPrecision(precisionDigits), подставляя в них самые разные параметры. Перед вызовом этих методов назначьте числовое значения одной из встроенных глобальных переменных. а = 10/3 a.toFixed(4) " $" + a.toFixed(2) Ни один из этих методов не вызывается по отношению к текстовой строке (например, 123 . toExponencial (2) ). См. также: объект Math. число.toLocaleString() Возвращаемое значение: строка. Совместимость: WinIE5.5+, MacIE5+, NN6+, Mozl+, Safaril+ Согласно стандарту ЕСМА версии 3, браузеры обладают некоторой свободой действий в определении того, как метод toLocaleString () возвращает строковое значение, соот- ветствующее языковому стандарту клиентской системы или браузера. IE5.5 возвращает то же значение, что и метод toFixed (2). См. также: методы число. toFixed (), число. toString (). число. toString ([сисИсчисления]) Возвращаемое значение: строка. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Метод число. toString () возвращает строковое представление заданного числа. По умолчанию используется десятичная система исчисления (10), даже если аргумент задан в другой системе. Можно указать и другую систему исчисления (например, 2 для двоичной, 16 — для шестнадцатеричной), и число будет преобразовано в соответствующий формат. Пример Запустите приложение The Evaluator для изучения метода число. toString (). На- значьте значение 12 переменной а, чтобы увидеть, как число преобразуется в строку с разной основой числа. а = 12 a.toString() // base 10 a.toString(2) a.toString(16) См. также: метод toLocaleString (). 906 Часть IV. Объекты языка JavaScript .
число.valueOf() См. число. valueOf () (глава 27). Объект Boolean Свойства Методы constructor toStringO prototype valueOf() Синтаксис Создание объекта Boolean. var val = new Boolean(булевоЗначение) Доступ к свойствам объекта Boolean. булевОбъект.свойство | метод Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Описание объекта В JavaScript приходится часто работать со значениями логического типа, особенно в ус- ловных операторах. Так же, как строковые значения дополняются свойствами строковых объектов, значения логического типа обладают дополнительными свойствами благодаря объекту Boolean. Например, когда логическое значение выводится в текстовом поле, строки "true" и "false" представляют метод toStringO объекта Boolean. Объект Boolean может понадобиться лишь в случае, когда ко всем логическим объек- там, создаваемым конструктором new Boolean (), необходимо добавить свойство или ме- тод. Аргументами конструктора могут быть строковые версии значений, числа (0— false; любое целое— true), а также выражения, результатом которых является значение логиче- ского типа. Каждый новый объект Boolean будет обладать новыми свойствами или метода- ми, добавленными к свойству prototype этого объекта. Подробнее о свойствах и методах объекта Boolean можно узнать из листингов для соот- ветствующих свойств и методов объекта String (глава 27). Глава 28. Объекты Math, Number и Boolean 907
Объект Date о озможно, нечасто используемой, но чрезвычайно полез-, ной задачей JavaScript является обработка даты и BpeMeJ ни. Программисты избегали управления объектом Date в ранних версиях JavaScript, поскольку наличие многочислен- ных ошибок в браузерах на разных платформах сделали про- граммирование даты и времени опасным без общего тестиро- вания. Даже после уменьшения числа ошибок работа со значениями дат требует знания мировых временных зон и их взаимосвязей со стандартной точкой отсчета — GMT (Greenwich Mean Time — время по Гринвичу) или UTC (Coordinated Uni- versal Time — всеобщее скоординированное время). В последних версиях браузеров обработка даты и времени значительно улучшилась, поэтому есть надежда, что авторы будут чаще использовать подобные расчеты на своих страни- цах. В главе 54 приведен пример приложения, позволяющего выделить области Web-узла, обновленные с момента послед- него посещения. Такое приложение основано на арифметиче- ских операциях с датами и зональным распределением времени. Перед тем как рассмотреть методы управления датами в JavaScript, мы опишем основные принципы образования временных зон и их влияние на обработку даты и времени в браузере. Следующий раздел посвящен тем, кто мало зна- ком с такими понятиями, как GMT и UTC. Временные зоны и GMT По международному соглашению, Земной шар разделен на временные зоны. Например, если солнце находится в зе- ните, то это указывает на середину дня. Текущее время зоны мы устанавливаем на своих часах — это и есть локальное время. Замечательно, если вся активность происходит в преде- лах одной временной зоны. Однако быстрый информацион- ный обмен между различными частями Земного шара за- частую требует выхода за пределы локальной зоны. Живя в Нью-Йорке, например, вряд ли вам захочется разбудить ко- го-то в Лос-Анджелесе ранним телефонным звонком. Если рассмотреть временную зону, над которой солнце находится в данный момент, то во всех временных'зонах
к востоку от нее полдень уже пройдет, а время в каждой последующей зоне на один час больше (за исключением тех зон, где оно сдвинуто на определенные доли часа). Поэтому в телепрограммах в США, которые одновременно показывают в восточной и центральной зонах, анонсы выглядят примерно так: “10 по восточному времени, 9 по центральному”. ! В данном разделе мы будем говорить Солнце “движется” по отношению к Земле, /назаметеу поскольку это более привычно для нашего восприятия. Разумеется, исходя из » теории Коперника, все происходит наоборот. Многим международным компаниям приходится координировать расписания и график работы. Учесть разницу времени в различных зонах (не говоря уже о таких сезонных откло- нениях, как перевод времени) непросто. Чтобы спасти ситуацию, была определена стандарт- ная точка отсчета: временная зона, проходящая через обсерваторию в городе Гринвич в Анг- лии. Эту временную зону называют Средним временем по Гринвичу (Greenwich Mean Time или GMT). ‘‘Среднее” означает буквально следующее: точно с противоположной стороны Земного шара (в Тихом океане) находится меридиан, принятый за точку начала дня, — еще один международный стандарт. Таким образом, зона GMT расположена посередине полного цикла календарного дня. Недавно GMT получила еще одну аббревиатуру — UTC (произно- сится: ю-ти-си). Ее английская версия — Coordinated Universal Time (Всеобщее скоординиро- ванное время). Таким образом, UTC — это то же самое, что и GMT. Если системные часы компьютера установлены правильно, то отсчет проводится по вре- мени GMT. Но поскольку в папке Панель управления, как правило, выставлена локальная временная зона, все значения времени создания и изменения файлов отображаются в локаль- ном времени. Компьютер знает разницу между локальным временем и GMT. При переходе на летнее/зимнее время необходимо проверить корректность сделанных установок. В Windows операционная система автоматически осуществляет перевод часов и запрашивает подтвер- ждение этой операции. Если вы путешествуете с ноутбуком из одной зоны в другую, необхо- димо изменить установки временной зоны, а не часов компьютера. Обработка даты и времени в JavaScript выполняется, как и в системных часах (от которых зависит работа программ). Значения дат, генерируемых в сценарии, сохраняются во внутрен- нем формате GMT, однако для пользователя (не Web-серверу) все значения выводятся, как правило, в локальном представлении. Кроме того, помните, что значения дат генерируются сценариями в компьютере пользователя, а не пересылаются с сервера. Это довольно сложная для понимания концепция, которая используется при работе с датой и временем в JavaScript. При обработке даты и времени в JavaScript необходимо придерживаться общемирового взгляда: предполагается, что средства компьютера конечного пользователя правильно преоб- разуют локальное время в GMT. При тестировании иногда приходится изменять настройки системных часов, имитируя, таким образом, местонахождение в другой временной зоне. Объект Date Как и для других объектов в JavaScript, существует различие между единичным статиче- ским объектом Date, который присутствует в каждом окне (или фрейме) и объектом даты, содержащим определенную дату и время. Статический объект Date (с прописной буквы D) используется только в нескольких случаях: в первую очередь, для создания нового объекта даты или для вызова нескольких методов, поддерживаемых объектом Date. Большая часть процесса обработки даты и времени затрагивает копии объекта Date. Эти копии называют объектами даты. Каждый такой объект представляет собой “моментальный снимок” времени, выраженный в миллисекундах. Если вам требуется получить “идущие” часы, Глава 29. Объект Date 909
сценарий должен периодически создавать новые объекты даты — моментальные снимки теку- щего состояния системных часов. Для вывода времени на странице из объекта даты необхо- димо извлечь часы, минуты и секунды, а затем отобразить их (например, в виде электронных часов или гистограммы). Фактически, копия объекта даты, предназначенная для чтения или изменения компонент (например, месяца или часа), вызывает различные методы этого объекта. Несмотря на свое имя, объект даты содержит информацию не только о дате, но и о време- ни. Оба элемента присутствуют в каждом объекте. Создание объекта даты В операторе, создающем объект в JavaScript, используется ключевое слово new. Для этого применяется следующий синтаксис. var имяОбъектаДаты = new Date([параметры]); В описанном случае объект становится объектом даты, а не строкой или числовым значением. Когда переменная содержит ссылку на объект даты, доступ ко всем его методам осущест- вляется обычным образом. var result = имяОбъектаДаты.метод О; Переменные, подобные возвращаемому результату, сценарий использует для проведения расчетов или применяет их для отображения даты (некоторые методы позволяют извлечь компоненты даты или времени). Если же объекту даты нужно присвоить новое значение (например, добавить один год), для этого используется соответствующий метод. имяОбъектаДа ты.метод(новоеЗначение); Это выражение не похоже на стандартное присвоение в JavaScript с оператором =, однако именно так работают методы объекта даты. Программирование операций обработки дат в сценарии требует знания арифметики вре- менных зон. Несмотря на то, что JavaScript может выразить объект даты в локальном време- ни, внутренним форматом всегда является GMT. Для добавления одного года к текущей дате используются следующие методы. var oneDate = new DateO // • И var theYear = oneDate.getYear() // // theYear = theYear +1 // // oneDate.setYear(theYear) // // Создание объекта, содержащего текущую дату в GMT В переменной theYear теперь содержится значение 98 Переменная theYear становится равной 99 В объекте устанавливается новое значение года После окончания последовательности действий объект oneDate автоматически коррек- тирует другие компоненты даты, например, день недели, который, очевидно, через год будет другим. Теперь значение даты из объекта oneDate можно извлечь как строку и отобразить в поле страницы или отправить CGI-программе на сервере. Вопрос аргументов при создании нового объекта даты достаточно сложен (во многом из- за той гибкости, которую обеспечивает JavaScript). Вспомните, что оператор new Date () предназначен для создания области в памяти, в которой хранятся все компоненты даты. Но не ясно, какой датой и временем необходимо заполнить новый объект. В данном случае в силу вступают аргументы. Если оставить аргументы пустыми, JavaScript присвоит новому объекту текущую дату и время. Естественно, JavaScript воспользуется значением часов компьютера пользователя. Если эти значения не являются корректными, JavaScript не узнает об этом ничего. 910 Часть IV. Объекты языка JavaScript
I Помните, что новый объект даты содержит также и текущее время, например, 'На заметку 16:03:19 (в 24-часовом формате). Этот факт нужно учитывать при таких расче- тах, как количество дней между датами и т.д. Для создания нового объекта даты можно воспользоваться одним из пяти способов при- своения ему даты и времени. Речь идет об аргументах функции конструктора new Date (). new Date("Месяц дд, гггг чч:мм:сс") new Date("Месяц дд, гггг") new Date(гг,мм,дд,чч,мм,сс) new Date(гг,мм,дд) new Date(миллисекунды) Четыре первых способа можно разбить на две группы — с длинными строками и списком значений, разделенных запятой (причем параметры времени не являются обязательными). Если они опущены, метод устанавливает их значения равными 0 (полночь). Аргументы даты опустить нельзя — каждый объект даты при создании требует их указания. В строковых версиях необходимо указывать полное английское название месяца. Аббре- виатуры не поддерживаются. Далее следует число, год, часы, минуты и секунды (именно в такой последовательности). Для значений, меньших 10, используется одно- или двухсим- вольная версия (например, 4:05:00). Часы, минуты и секунды разделяются двоеточием. В коротких версиях параметров методов указывается список целочисленных аргументов в приведенном выше порядке. Аргументом последней версии параметров метода является значение даты и времени, вы- раженное в миллисекундах. Такой формат часто используется при арифметических расчетах дат (об этом рассказано далее). Для его преобразования в объект даты применяется конструк- тор new Date (). Впоследствии объект даты позволяет получить более удобные значения. Естественные свойства и методы объекта Как и объекты String и Array, объект Date поддерживает небольшой набор свойств и методов, характерных для всех объектов JavaScript. В браузерах NN3+ и IE3/J2+ объект Date имеет свойство prototype, позволяющее добавить к объекту новые свойства или методы. При- меры его использования описаны при рассмотрении свойства prototype объектов String и Array (в главах 27 и 30, соответственно). Кроме того, каждый объект даты в IE4+/W3C имеет свойство constructor, указывающее на функцию, с помощью которой был создан объект. Объект даты имеет несколько методов для преобразования значений своих компонент в строки. Они являются более специфическими, чем toString (). Метод valueof () возвращает значение в миллисекундах, которое совпадает с результатом метода getUTCMilliseconds () (см. следующий раздел). Методы объекта Date Набор методов объекта даты используется для чтения и изменения информации о дате и времени, сохраненной в объекте. Две категории этих методов легко различить, поскольку они начинаются со слов get и set, соответственно. Методы статического объекта Date, на- следуемые всеми его копиями, перечислены в табл. 29.1. Список впечатляет, однако в нем легко выделить общее. Большинство методов работает с одной компонентой даты или време- ни: годом, месяцем, числом и т.д. Каждый блок методов get и set подразделяется на два набора: для локального формата и для формата UTC. Если не указано другое, метод является частью объекта Date, начиная с первого поколения браузеров, поддерживающих сценарии. Глава 29. Объект Date 911
Таблица2&Л.Штади абыыга t>at- Метод Диапазон Описание dateObj.getFullYear() 1970- . . Год (NN4+, IE3+) dateObj.getYear() 70-... (См. текст) dateObj.getMonth() 0-11 Месяц (Январь = 0) dateObj.getDate() 1-31 Число dateObj.getDay() 0-6 День недели (Воскресенье = 0) dateObj.getHours() 0-23 Часы в 24-часовом формате dateObj.getMinutes() 0-59 Минуты dateObj.getSeconds() 0-59 Секунды dateObj.getTime() 0- . . . Миллисекунды с 1/1/70 00:00:00 GMT dateObj.getMiiliseconds() 0- . . . Миллисекунда с 1/1/70 00:00:00 GMT (NN4+, IE3+) dateObj.getUTCFullYear() 1970-.. • Год UTC (NN4+, IE3+) dateObj.getUTCMonth() 0-11 Месяц UTC (Январь = 0) (NN4+, IE3+) dateObj.getUTCDate() 1-31 Число UTC (NN4+, IE3+) dateObj .getUTCDayO 0-6 День недели UTC (Воскресенье = 0) (NN4+, 1ЕЗ+) dateObj.getUTCHours() 0-23 Часы UTC в 24-часовом формате (NN4+, IE3+) dateObj.getUTCMinutes() 0-59 Минуты UTC (NN4+, IE3+) dateObj.getUTCSeconds() 0-59 Секунды UTC (NN4+, IE3+) dateObj.getUTCMilliseconds() 0- . . . Миллисекунды UTC с 1/1/70 00:00:00 GMT (NN4+, IE3+) dateObj.setYear(val) 1970-.. • Установка года (четырехзначного) dateObj.setFullYear(val) 1970-.. • Установка года (NN4+, IE3+) dateObj.setMonth(val) 0-11 Установка месяца (Январь = 0) dateObj.setDate(val) 1-31 Установка числа dateObj.setDay(val) 0-6 Установка дня недели (Воскресенье = 0) dateObj.setHours(val) 0-23 Установка часов в 24-часовом формате dateObj.setMinutes(val) 0-59 Установка минут dateObj.setSeconds(val) 0-59 Установка секунд dateObj.setMilliseconds(val) 0- . . . Установка миллисекунде 1/1/70 00:00:00 GMT (NN4+, IE3/J2+) dateObj.setTime(val) 0- . . . Установка миллисекунд с 1/1/70 00:00:00 GMT dateObj.setUTCFullYear(val) 1970-.. • Установка года UTC (NN4+, IE3+) dateObj.setUTCMonth(val) 0-11 Установка месяца UTC (Январь = 0) (NN4+, IE3+) dateObj.setUTCDate(val) 1-31 Установка числа UTC (NN4+, IE3+) dateObj.setUTCDay(val) 0-6 Установка дня недели UTC (Воскресенье = 0) (NN4+, IE3+) dateObj.setUTCHours(val) 0-23 Установка часов UTC в 24-часовом формате (NN4+, 1ЕЗ+) 912 Часть IV. Объекты языка JavaScript
Окончание табл. 29.1 Метод Диапазон значений Описание dateObj.setUTCMinutes(val) 0-59 Установка минут UTC (NN4+, IE3+) dateObj.setUTCSeconds(val) 0-59 Установка секунд UTC (NN4+, IE3+) dateObj.setUTCMilliseconds(val) 0- . . . Установка миллисекунд UTC с 1/1/70 00:00:00 GMT (NN4+, IE3+) dateObj.getTimezoneOffset() 0- . . . Разница в минутах по отношению к GMT/UTC dateObj.toDateString() Строка с датой (без времени) в формате браузера (IE5.5+) dateObj.toGMTString() Строка с датой и временем в глобальном формате dateObj.toLocaleDateString() Строка с датой без времени в локализованном формате системы (NN6+, IE5.5+) dateObj.toLocaleString() Строка с датой и временем в локализованном формате системы dateObj.toLocaleTimeString() Строка со временем без даты и в локализованном формате системы (NN6+, IE5.5+) dateObj.toString() Строка с датой и временем в формате браузера dateObj.toTimeString() Строка со временем без даты в формате браузера (IE5.5+) dateObj.toUTCString() Строка с датой и временем в глобальном формате (NN4+, IE3+) Date.parse("dateString") Преобразование строки с датой в число миллисекунд Date.UTC(date values) Преобразование строки с датой GMT в число миллисекунд Выбор между UTC и локальными версиями методов зависит от нескольких факторов. Ес- ли страница предназначена для поддержки ранними версиями браузеров, в любом случае придется ограничиться локальными версиями. В новых браузерах операции, подобные вы- числению разницы между двумя датами или созданию счетчика времени, оставшегося до на- ступления события, выполняются с помощью любого набора методов (важно использовать во всех расчетах методы только одного типа). При смешанном применении различных методов по- лучится неправильный результат. UTC-версии методов оказываются полезными при расчетах, учитывающих временную зону пользователя и некоторое абсолютное значение другой зоны. JavaScript представляет информацию о дате в виде количества миллисекунд (тысячных долей секунд), прошедших с 1 января 1970 года GMT (UTC). Даты до этого момента хранятся как отри- цательные значения (см. раздел об ошибках далее в этой главе). Независимо от локализации фор- мата даты, миллисекунды являются универсальными единицами измерения времени в JavaScript. Для получения необходимой точности все действия по сложению или вычитанию даты следует проводить в формате миллисекунд. Несмотря на то, что значения в миллисекундах редко ото- бражаются пользователю, сценариям часто приходится проводить вычисления с ними. Для по- лучения даты и времени в формате миллисекунд используется метод dateObj . getTime (). var startDate = new Date(); var started = startDate.getTime(); Глава 29. Объект Date 913
В имени метода присутствует слово time (время), поскольку он возвращает общее число миллисекунд с 1 января 1970 года; в этом же значении содержится и дата. Другие методы get объекта даты возвращают определенные ее компоненты. При их об- работке следует проявлять осторожность, так как некоторые значения начинаются с о. На- пример, январь в JavaScript имеет номер 0, а декабрь— 11. Часы, минуты и секунды начи- наются с нуля (это вполне логично). В числах календаря используются реальные единицы — первый день имеет номер 1. Значение года, принадлежащего двадцатому веку, равно разно- сти между реальным годом и 1900. Например, год 1996 обозначается как 96. Годы до 1900 и после 1999 в JavaScript отображаются в полном четырехзначном формате. Таким образом, если значение меньше 100, к нему нужно добавить 1900. var today = new Date(); к var thisYear = today.getYear(); if (thisYear < 100) { thisYear += 1900; } В данном случае предполагается, что не используются даты до 100 года до нашей эры. Если страница предназначена для IE3+ и NN4+, воспользуйтесь методом getFullYear (), который возвращает четырехсимвольное значение года. Для изменения какой-либо компоненты даты применяется соответствующий метод set. Если изменение одного значения требует корректировки других, JavaScript выполняет все операции автоматически. Рассмотрим, как изменяются связанные значения в следующей по- следовательности. myBirthday = new Date("September 11, 2001"); result = myBirthday.getDay(); // результат 2, вторник myBirthday.setYear(2002); // переход к следующему году result = myBirthday.getDay(); // результат 3, среда То же число является другим днем недели — JavaScript сам отслеживает это изменение. Учет временных зон Понимание работы метода dateobj . getTimezoneOf f set {) требует знакомства с на- стройками операционной системы и международным форматом (по крайней мере, в компью- терном мире) представления даты и времени. Если в папке Панель управления значения для локальной временной зоны не установлены, соответствующие свойства будут пустыми для большинства дат. В восточной части Северной Америки, например, применяется стан- дартная восточная временная зона, которая на пять часов отстает от GMT. Результатом мето- да getTimezoneOf f set () является разница в минутах между временем, установленным в локальном компьютере и GMT, т.е. 300 минут в данном случае. На платформе Windows значение автоматически изменяется при переходе на летнее или зимнее время. Смещения к востоку от GMT (точки отсчета) представлены отрицательными значениями. Строковые даты После создания объекта даты при попытке ее отображения на странице JavaScript автома- тически применяет метод toString (). Формат строки зависит от браузера и операционной системы. Например, в IE6 для Windows ХР строка имеет следующий формат. Mon Jan 5 14:11:49 CDT 2004 В NN7 для Windows ХР эта строка принимает такой вид. Mon Jan 05 2004 14:11:49 GMT-0500 (Central Standard Time) 914 Часть IV. Объекты языка JavaScript
Internet Explorer возвращает свои собственные версии этой строки. Поэтому не стоит по- лагаться на определенный формат строки и расположение компонент даты в ней. Для их чте- ния следует пользоваться методами объекта даты. Тем не менее, JavaScript поддерживает два метода, результатом которых является стан- дартный строковый формат даты. Один из них, объектДаты. toGMTString (), преобразу- ет дату и время в эквивалент GMT. Формат выглядит так. Моп, 05 Jan 2004 19:11:49 GMT Если вы не слишком хорошо знакомы с форматом GMT, тщательно тестируйте работу своих сценариев. Восемь вечера зимой в пятницу в Калифорнии соответствуют четырем ча- сам утра в субботу по GMT. Если зональные преобразования времени проводить не требуется, то можно воспользо- ваться методом объектДаты. toLocaleString (). В NN7 для пользователей Windows в Северной Америке он возвратит значение. Monday, January 05, 2004 14:11:49 Начиная с версий IE5.5 и NN6, JavaScript позволяет преобразовать объект даты в отфор- матированные строковые значения даты или времени, что достигается благодаря методам toLocaleDateString () и toLocaleTimeString (). Они возвращают наиболее важные для пользователя значения, основываясь на настройках операционной системы и браузера. Удобные форматы даты в ранних версиях браузеров Если страница предназначена не только для IE5.5+/NN6+/W3C, то вам нужно создать соб- ственные методы, форматирующие дату, для различных версий браузеров. Один из способов создания строки из объекта даты (совместимый с IE4+ и NN4+) приведен в листинге 29.1. <html> <head> ч <title>Date String Maker</title> <script type="text/javascript"> monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", “December"]; dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; function customDateString(oneDate) { var theDay = dayNames [oneDate. getDay () ] ,- var theMonth = monthNames[oneDate.getMonth()]; var theYear = oneDate.getFullYear(); return theDay + ", " + theMonth + " " + oneDate.getDate() + ", " + theYear; } </script> </head> <body> <hl> Welcome! </hl> Глава 29. Объект Date 915
«script type="text/javascript"> document.write(customDateString(new Date())) </script> <hr /> </body> </html> Если часы в пользовательском компьютере установлены правильно, в заголовке страницы выводится текущая дата так, будто документ обновлен сегодня. Недостатком этого подхода (который отсутствует у более современного метода toLocaleDateStringO) является отображение даты в заданном формате, который может отличаться от локального, привычно- го для пользователей. Еще раз о преобразованиях Два последних метода, приведенных в листинге 29.1, принадлежат статическому объекту Date. Они преобразуют дату из строковой или числовой формы в количество миллисекунд. Это значение используется в качестве параметра метода dateObj . setTime О . Последний удобен для задания в объекте даты нового значения. Аргументом метода Date. parse () является строка, подобная той, которая была приведе- на в этом разделе (включая и международный формат). Date. UTC () использует список значе- ний, разделенных запятой (в формате: уу, mm, dd, hh, mm, ss) в зоне GMT. Метод Date.UTC () обеспечивает совместимость снизу вверх для преобразования времени в формате GMT (в брау- зерах NN4+ и IE4+ для этого применяются методы UTC). Ниже приведен пример создания объекта даты со значением 6 часов пополудни 4 марта 2004 года GMT в браузере WinIE6. var newObj = new Date(Date.UTC(2004,2,4,18,0,О)); result = newObj.toString(); // результат "Thu, Mar 04 10:00:00 PST 2004" Второй оператор возвращает время в локальной временной зоне, поскольку не все UTC- методы автоматически преобразуют время в формате GMT (Сохраняемое в объекте) в локальное. Арифметика даты и времени По ряду причин с датой и временем приходится выполнять различные вычисления. На- пример, подсчитать дату через определенное число дней или недель в будущем или количест- во дней между двумя датами. Для расчетов такого рода в JavaScript наиболее удобными еди- ницами исчисления являются миллисекунды. В сценариях, где проводятся вычисления, целесообразно ввести набор переменных, со- держащих количество миллисекунд в минуте, часе, дне и т.д., а затем использовать его в рас- четах. Ниже приведен пример присвоения нужных значений. var oneMinute = 60 * 1000; var oneHour = oneMinute *60; var oneDay = oneHour * 24; var oneWeek = oneDay * 7; С их помощью легко подсчитать, например, дату через одну неделю. var targetDate = new Date(); var datelnMs = targetDate.getTime(); datelnMs += oneWeek; targetDate.setTime(datelnMs); В другом примере компоненты объекта даты используются для вывода приветственного сообщения (по локальному времени). Листинг 29.2 дополняет листинг 29.1. 916 Часть IV. Объекты языка JavaScript
Листу Ж1. Аякжтлвс**» npmewwnweсообщение <html> cheacb <title>Date String Maker</title> <script type="text/javascript"> monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; function customDateString(oneDate) { var theDay = dayNames[oneDate.getDayO]; var theMonth = monthNames[oneDate.getMonth()]; var theYear = oneDate.getFullYear(); return theDay + ", " + theMonth + " " + oneDate.getDate() + ", " + theYear; } function dayPart(oneDate) { var theHour = oneDate.getHours(); if (theHour < 6 ) return "wee hours"; if (theHour < 12) return "morning"; if (theHour < 18) return "afternoon"; return "evening"; } </script> </head> <body> <hl>Welcome!</hl> <script type="text/javascript"> today = new Date(); var header = (customDateString(today)).italics(); header += "<BR>We hope you are enjoying the "; header += dayPart(today) + document.write(header); •«/script > <hr /> </body> </html> Сценарий делит день на четыре части и в зависимости от текущего момента времени вы- водит приветственное сообщение. Оно зависит от часа, содержащегося в объекте даты (значение последнего определяется временем загрузки страницы в браузер). После вывода на странице сообщение уже не изменяется, сколько времени она ни была бы загружена в браузере. Подсчет дней Арифметические операции с датой часто оказываются полезными. Например, для вывода числа рабочих дней, оставшихся до Рождества (во временной зоне пользователя), или тайме- ра обратного отсчета до 2100 года. Глава 29. Объект Date 917
Листинг 29.3 демонстрирует, как подсчитать разницу между текущей датой и заданной датой в будущем. Все вычисления относятся к локальной временной зоне. Пример выводит количество рабочих дней до Рождества (25 декабря). Сценарий следует такому алгоритму: те- кущая дата и ближайшее 25 декабря преобразуются в формат миллисекунд, затем вычисляет- ся их разность. В преобразованиях JavaScript автоматически учитывает високосные годы. Особенность заключается в правильной установке года следующего рождественского дня. Вы не сможете задать фиксированную дату этого года, так как программа, запущенная 26 де- кабря, будет считать ближайшим рождественским днем Рождество в следующем году. По- этому конструктор объекта даты Рождества использует специальные компоненты при ини- циализации объекта. <html> «head» <title>Christmas Countdown«/title> «script type="text/javascript"» function getDaysUntilXmas() { var oneMinute = 60 * 1000; var oneHour = oneMinute * 60; var oneDay = oneHour * 24; var today = new Date(); var nextXmas = new Date(); nextXmas.setMonth(11); nextXmas.setDate(25) ; if (today.getMonthO == 11 && today.getDate() > 25) { nextXmas.setFullYear(nextXmas.getFullYear() + 1); } var diff = nextXmas.getTime() - today.getTime(); diff = Math.floor(diff/oneDay); return diff; } </script» «/head» <body> <hl> «script type="text/javascript"» var header = "You have <i>" + getDaysUntilXmas() + "<\/i> "; header += "shopping days until Christmas."; document.write(header); «/script» </hl> «hr /» «/body» «/html» В другом варианте определения времени, оставшегося до некоторой даты, учитываются временные зоны. Страница выводит счетчик времени до точного начала Летних Олимпий- ских игр в Пекине в 2008 году. Это событие происходит в определенной временной зоне, по- этому необходимо правильно учесть разницу во времени с зоной пользователя. В листинге 29.4 приведена упрощенная версия, где таймер выводится в текстовом поле. Вывод, естественно, можно организовать различными способами на свой вкус. Точным вре- менем считается 11:00 GMT 8 августа 2008 года (дата, конечно же, точная, но время начала может измениться). ' 918 Часть IV. Объекты языка JavaScript
Сценарий устанавливает значения глобальных переменных, которые вычисляются только один раз, чтобы постоянно вызываемая для обновления таймера функция работала эффективно. Метод Date .UTC () возвращает дату и время начала Игр по GMT. Функция getTimeUntil (), аргу- мент которой задан в миллисекундах (переменная targetDate) подсчитывает разницу между датой начала и текущим внутренним значением миллисекунд часов персонального компьютера. Функция getCountDown () вычисляет количество дней, часов, минут и секунд в полу- ченном числе миллисекунд <html> <head> <title>Summer Games Countdown</title> <script type="text/javascript"> // глобально - вычисляется только один раз // целевая дата - 1100GMT on August 8, 2008 var targetDate = Date.UTC(2008, 7, 8, 11, 0, 0, 0); var oneMinute = 60 * 1000,- var oneHour = oneMinute * 60; var oneDay = oneHour * 24,- function getTimeUntil(targetMS) { var today = new Date(); var diff = targetMS - today.valueOf () ,- return Math.floor(diff); } function getCountDown() { var ms = getTimeUntil(targetDate); var output = ""; var days, hrs, mins, secs; if (ms >= 0) { days = Math.floor(ms/oneDay); ms -= oneDay * days; hrs = Math, floor (ms/oneHour) ,- ms -= oneHour * hrs; mins = Math.floor(ms/oneMinute); ms -= oneMinute * mins; secs = Math.floor(ms/1000) ,- output += days + 11 Days, " + hrs + " Hours, " + mins + " Minutes, " + secs + " Seconds"; } else { output += "The time has passed."; } return output; function. updateCountDown() { document.forms[0].timer.value = getCountDown(); setTimeout("updateCountDown()", 1000); } </script> </head> <body onload="updateCountDown()"> <hl>Beijing Games Torch Lighting Countdown»:/hl> <p> <script type="text/javascript"> document.write("(" + (new Date(targetDate)). Глава 29. Объект Date 919
toLocaleString О); document.write(" in your time zone.)"); </script> </p> ' <form> cinput type="text" name="timer" size="60" /> </form> chr I > c/body> c/html> Ошибки, связанные с управлением датой Каждое новое поколение браузеров повышает надежность обработки объектов даты в сце- нариях. К сожалению, NN2 имеет ряд ошибок, связанных с управлением датой, на многих платформах, что делает создание сложных цриложений просто невозможным. Это относится и к версии для Macintosh. Рекомендуется избегать программирования действий управления датой и временем в NN2 на всех платформах. Ситуация значительно улучшилась в NN3, однако некоторые ошибки остались. Одна из них проявляется на платформе Macintosh. При создании нового объекта, если учесть переход на летнее/зимнее время в аплете Дата и'Время панели управления, браузер автоматически добавит один час. Пример того, как следует обходить типичные ошибки, приведен в главе 54. Кроме того, NN3 для Macintosh неправильно вычисляет смещения временных зон к востоку от GMT. Вместо того чтобы генерировать отрицательные значения (уменьшающиеся для ка- ждой следующей зоны к востоку), положительная разница во времени просто нарастает при переходе от зоны к зоне к западу от Гринвича. Для Западного полушария это справедливо, однако после пересечения линии полудня значения продолжают расти, вместо того чтобы становиться отрицательными. Проблемы присутствуют и в IE3. Этот браузер не способен работать с датами до 1 января 1970 года (GMT). Попытки установить меньшие даты приводят к этому же значению. IE3 так- же неверно рассчитывает разницу во времени между зонами, следуя ошибочному алгоритму NN2. Браузеры NN3 и NN4 все еще испытывают трудности при обработке дат до 1 января 1 года до нашей эры. В IE4 проблем с такими датами не наблюдается. Необходимо помнить о различиях между версиями NN для Мас и Windows вплоть до вер- сии 4. В Windows при создании объекта, содержащего дату в другой (не текущей) части этого года, браузер устанавливает смещение временной зоны объекта для указанного времени года. На платформе Мас переход на летнее или зимнее время независимо от реальной даты в году настраивается в панели управления. Такая несогласованность присутствует в NN3 и NN4, в результате чего вычисления иногда оказываются смещенными на один час. Таким образом, программирование способов управления объектом Date требует тща- тельного планирования и активного тестирования на всех возможных комбинациях браузеров и платформ. Проверка дат, вводимых в формы При проверке дат, вводимых в формы, проблема заключается не столько в вычислениях, сколько в большом количестве допустимых форматов, применяющихся в мире. К сожалению, нет никаких возможностей установить, например, соответствует ли значение 03/04/2002 дате 4 марта 2002 года по североамериканскому стандарту или 3 апреля 2002 года по европейскому. 920 Часть IV. Объекты языка JavaScript
Рекомендую разделить поле даты на три компоненты: месяц, день и год. Пользователь введет значения, которые будут проверяться отдельно. Пример такого подхода приведен в листинге 29.5. Страница включает в себя форму, которая проверяется до отправки на сер- вер. Для каждой компоненты даты проводится своя проверка. Кроме того, дополнит,ельный тест осуществляется в обработчике события onsubmit формы. Если в каком-либо поле со- держатся неверные данные, отправка не происходит. <head> <title>Date Entry Validation</title> <script type="text/javascript"> // **Начало общих функций проверки данных** // проверка того, вводились ли входные данные function isEmpty(inputStr) { if (inputStr == "" || inputStr == null) { return true; } return false; } // проверка попадания данных в допустимый диапазон function inRange(inputStr, lo, hi) {. var num = parselnt(inputStr, 10); if (num < lo || num > hi) { return false; } return true; } // “Конец общих функций проверки данных** function validateMonth(field, bypassupdate) { var input = field.value; if (isEmpty(input)) { alert("Be sure to enter a month value."); select(field); return false; } else { input = parselnt(field.value, 10); if (isNaN(input)) { alert ("Entries must be numbers only."); select(field); return false; } else { if (!inRange(input,1,12)) { alert("Enter a number between 1 (January) and 12 (December)."); select(field); return false; } } } if (IbypassUpdate) { calcDate(); } Глава 29. Объект Date 921
return true; } function validateDate(field) { var input = field.value; if (isEmpty(input)) { alert("Be sure to enter a date value."); select(field); return false; } else { input = parselnt(field.value, 10); if (isNaN(input)) { alert("Entries must be numbers only."); select(field); return false; } else { var monthField = document.birthdate.month; if (IvalidateMonth(monthField, true)) return false; var monthVal = parselnt(monthField.value, 10); var monthMax = new Array(31,31,29,31,30,31,30,31,31, 30,31,30,31); var top = monthMax[monthVal]; if (!inRange(input,1,top)) { alert("Enter a number between 1 and " + top + "."); select(field); return false; } } } •calcDate () ,- return true; } function validateYear(field) { var input = field.value; if (isEmpty(input)) { alert("Be sure to enter a year value."); select(field); return false; } else { input = parselnt(field.value, 10); if (isNaN(input)) { alert("Entries must be numbers only."); select(field); return false; } else { if (!inRange(input,1900,2005)) { alert("Enter a number between 1900 and 2005."); select(field); return false; } } } calcDate () ,- return true; } 922 Часть IV. Объекты языка JavaScript
function select(field) { field.focus(); field.select(); } function calcDate() { var mm = parselnt(document.birthdate.month.value, 10); var dd = parselnt(document.birthdate.date.value, 10); var yy = parselnt(document.birthdate.year.value, 10); document.birthdate.fullDate.value = mm + "/" + dd + "/" + УУ; } function checkForm(form) { if (validateMonth(form.month)) { if (validateDate(form.date)) { if (validateYear(form.year)) { return true; return false; } </script> </head> <body> <form name="birthdate" action="mailto:fun@dannyg.com" method="POST" onsubmit="return checkForm(this)"> Please enter your birthdate,..<br /> Month:<input type="text" name="month" value="ln size="2" onchange="validateMonth(this)" /> Date:<input type="text" name="date" value="l“ size="2" onchange="validateDate(this)" /> Year:<input type="text“ name="year" value="1900" size="4" onchange="validateYear(this)" /> <p>Thank you for entering:cinput type="text" name="fullDate" size="10" /></p> <pxinput type="submit" /> cinput type="Reset" /></p> </form> </body> </html> На странице присутствуют три поля для ввода, а также одно скрытое поле формы. Данные , пересылаются CGI-программе на сервере, которая реагирует только на скрытое поле, содер- жащее полную дату в формате, пригодном для обработки, например, в базе данных Informix. Не все программы проверяют дату подобным образом. Некоторые приложения более тре- бовательны к дате, вводимой пользователем. Поэтому для введения даты может использо- ваться только одно поле, но в этом случае требуется другой вариант синтаксического анализа, а не тот, что приведен в листинге 29.5. Процедура проверки даты, введенной в одном поле, представлена в главе 43. Глава 29. Объект Date 923
Объект Array ассив представляет собой единую структуру в Java- Script, предназначенную для хранения упорядочен- ных наборов данных. В отличие от других языков програм- мирования, массивы JavaScript позволяют хранить данные самых разных типов. Такой подход позволяет, например, создать массив массивов — аналог многомерного массива. Если вы еще не знакомы с программированием, тема мас- сивов может показаться сложной. Важно понимать, что без свойств, которыми обладают массивы, решить некоторые за- дачи просто невозможно. Перед тем, как начать работу над новым сценарием, следует обдумать, прежде всего, как при- ложение будет управлять данными и как его можно усовер- шенствовать, применяя массивы. Прочтите эту главу, чтобы ознакомиться со свойствами и методами массивов JavaScript, изучить способы их приме- нения для решения свои задач. Структурированные данные В программировании массивом называют упорядоченный набор данных. Проще всего представить себе массив как таблицу, подобную создаваемым в процессорах электронных таблиц. В JavaScript возможны только массивы, подобные таблицам с одним столбцом данных и некоторым числом строк. Как отмечалось в части Ш, браузеры с поддержкой JavaScript создают несколько внутренних массивов для объ- ектов в документах HTML и свойств самого браузера. На- пример, если в документе содержится пять ссылок, браузер создает для них таблицу. Доступ к ссылкам осуществляется по индексу — так же, как и в массиве (начиная с 0): после имени массива в квадратных скобках указывается индекс, например, document .links [0]. Этот элемент соответст- вует первой ссылке в документе. Во многих приложениях JavaScript массив используется как хранилище данных, с которыми взаимодействуют пользователи страницы. Например, в приложении, приведенном в главе 50, показано, как применять массивы: страница позволяет пользо-
вателям проводить поиск в небольшой таблице по трем первым цифрам номера социального страхования и штату регистрации. Массивы JavaScript позволяют страницам частично воссоз- дать поведение более сложных CGI-программ, запускаемых на серверах. Если набор данных, используемый в сценарии, не больше по размеру, чем типичное изображение в формате .gif, пользователь задержек при загрузке страницы не заметит. При этом он сможет работать с не- большой базой данных, не обращаясь к серверу. Такие массивы, эмулирующие работу баз дан- ных, очень часто применяются в приложениях JavaScript. Назовем их бессерверными. При создании приложения поищите потенциальное применение массивам. Если среди ис- пользуемых данных есть несколько объектов или блоков данных, взаимодействующих со сценарием одинаковым образом, скорее всего, массив окажется подходящей структурой для их сохранения. Например, во всех браузерах текстовым полям формы можно присвоить оди- наковые имена. В этом случае объекты трактуются как элементы массива. Для управления этими данными в сценарии используется синтаксис доступа к массиву. Таким образом, реше- ние задачи сводится к написанию нескольких операторов JavaScript, а также исключается не- обходимость в создании специального кода для каждого отдельного поля. Пример такого приложения приведен в главе 51. Кроме того, можно создавать массивы, подобные кэшированным таблицам в языке Java, когда элементу данных поставлено в соответствие имя (ключ), а не числовой индекс. Если данные можно представить в формате таблицы, без сомнения, следует использовать массивы. Создание пустого массива Полноценный объект массива позволяет работать с ним так, как с любым встроенным массивом JavaScript. От вас не требуется определять функцию-конструктор, так как она не позволяет создавать объекты JavaScript. Достаточно создать новый объект массива, восполь- зовавшись следующей командой. var myArray = new Array () ; Объект массива имеет свойство length (для пустого массива оно равно 0). Важно, что оно не содержится в самом массиве, т.е. последний полностью предназначен для сохранения данных. Если требуется создать массив определенного размера (и заполнить его, например, значе- ниями null), в аргументе конструктора задается исходный размер. Например, именно так соз- дается новый массив из 500 элементов, содержащий информацию о коллекции компакт-дисков. var myCDCollection = new Array(500); Создание массива предварительного размера не дает никаких преимуществ, поскольку в любой момент всякому массиву можно добавить новое значение: значение свойства length корректируется автоматически. К примеру, если в массив myCDCollection [700] добавить новое значение, объект массива изменит свойство length (счетчик начинается с 0). myCDCollection [700] = "Gloria Estefan/Destiny"; collectionsize = myCDCollection.length; // результат 701 Объект массива имеет несколько методов, а также позволяет добавлять пользовательские свойства к прототипу (см. далее в этой главе). Заполнение массива данными Ввод данных в массив так же прост, как присвоение значений переменным. В листин- ге 30.1 (отсутствует на прилагаемом компакт-диске) предполагается, что с помощью объекта массива нового типа требуется создать список девяти планет Солнечной системы. Глава 30. Объект Array 925
solarSys = new Array(9); solarSys[0] = "Mercury"; solarSys[1] = "Venus"; solarSys[2] = "Earth"; solarSys[3] = "Mars"; solarSys[4] = "Jupiter"; solarSys[5] = "Saturn"; solarSys [6] = "Uranus"; solarSys[7] = "Neptune"; solarSys[8] = "Pluto"; Такой способ заполнения массива несколько утомителен при написании кода, однако по- следующий доступ к информации становится очень простым и унифицированным. onePlanet = solarSys[4]; // результат "Jupiter" Если известен желаемый порядок расположения данных (как в примере с массивом solarSys), можно воспользоваться более компактным способом создания массива. Вместо использования набора операторов присвоения (как в листинге 30.1) можно создать компакт- ный массив, указав все данные в аргументах конструктора Array (). solarSys = new Array("Mercury","Venus","Earth","Mars","Jupiter", "Saturn".Uranus","Neptune","Pluto"); Термин компактный массив означает, что данные размещаются в массиве подряд, начи- ная с позиции 0. В листинге 30.1 показан так называемый вертикальный набор данных. Каждый элемент содержит такой же тип данных, что и другие (название планеты), и их порядок следования совпадает с порядком расположения планет (по расстоянию от солнца). Расширенные возможности создания массивов в JavaScript JavaScript в браузерах NN4+ и IE4+ поддерживает еще один способ создания компактного массива. Кроме того, в них исправлена ошибка, связанная со старым вариантом. Новый, бо- лее простой способ создания компактного массива не требует применения конструктора объекта Array. Вместо этого JavaScript воспринимает так называемое буквенное обозначение. Чтобы понять разницу, рассмотрим стандартный оператор с применением конструктора в NN3. solarSys = new Array("Mercury","Venus","Earth","Mars","Jupiter", "Saturn","Uranus","Neptune","Pluto"); . JavaScript полностью поддерживает такой синтаксис, однако возможен вариант и с бук- венной записью. solarSys = ["Mercury","Venus","Earth","Mars","Jupiter", "Saturn","Uranus","Neptune","Pluto"]; Квадратные скобки эквивалентны вызову конструктора Array. Перед тем как использо- вать такой способ создания массива, нужно определить, для каких версий браузеров разраба- тывается страница. Исправление ошибки обусловлено тем, как должен работать конструктор компактного массива, если в его аргументе указано значение 1 — new Array (1). В NN3 и IE4 JavaScript 926 Часть IV. Объекты языка JavaScript
ошибочно создает массив длиной 1 с неопределенным элементом. В NN4 и во всех после- дующих браузерах (IE5+, NN6+, W3C) тот же оператор создает массив с одним элементом и размещает в нем некоторое значение. Удаление элементов массива Элементу массива всегда можно присвоить значение null или пустую строку, в результа- те чего произойдет очистка данных, занимающих этот элемент. Но полностью удалить элемент массива в NN4 и IE4 позволяет только оператор delete. Удаление элемента массива делает соответствующее ему значение недоступным, однако не уменьшает длины. Рассмотрим следующую последовательность операторов. туАггау.length // результат 5 delete туАггау[2] туАггау.length // результат 5 myArray[2] // результат неопределен Процесс удаления элемента массива не всегда освобождает память, в которой находились данные. Внутренний механизм интерпретатора JavaScript сам заботится об этом (подробнее см. оператор delete в главе 32). Современные браузеры поддерживают метод splice () массива, который позволяет уда- лить элемент (или набор элементов) массива. В результате выполнения длина массива авто- матически изменяется. Этот метод рассмотрен далее в этой главе. Параллельные массивы Использование массива для хранения данных часто предполагает проверку сценарием на- личия в нем определенного значения (например, можно убедиться, что информация, введен- ная пользователем в текстовое поле, доступна для обработки). Еще намного важнее оказыва- ется (при нахождении элемента) получение информации в другом массиве. Один из подходов заключается в использовании двух или более параллельных (реляционных) массивов: элемен- ты с одинаковыми индексами содержат связанную информацию. Рассмотрим три следующих массива. var regionalOffices = new Array("New York", "Chicago", "Houston", "Portland") ,- var regionalManagers = new Array("Shirley Smith", "Todd Gaston", "Leslie Jones", "Harold Zoot"); var regOfficeQuotas = new Array(300000, 250000, 350000, 225000); В данном случае предполагается, что Ширли Смит (Shirley Smith) является региональным менеджером офиса в Нью-Йорке; предельная норма выработки ее офиса составляет 300,000. В таком виде данные включены в документы. Возможно, они получены CGI-программой на сервере из базы данных SQL и вставлены в конструкторы массивов. Листинг 30.2 демонстри- рует, как эти данные отображаются на странице в элементе select для поиска менеджера и значений выработки его офиса. Порядок элементов в списке select является не случай- ным: для удобства поиска порядок следования элементов во всех массивах совпадает. Поиск в листинге 30.2 осуществляет функция getData (). Поскольку индексы опций в элементе select совпадают с индексами параллельных массивов, свойство selectedlndex элемента select обеспечивает удобный способ прямого обращения к нужным данным в разных массивах. ' Глава 30. Объект Array 927
<html> <head> «title>Parallel Array Lookup«/title> «script type="text/javascript"> // дата var regionalOffices = new Array("New York", "Chicago", "Houston", "Portland"); var regionalManagers = new Array("Shirley Smith", "Todd Gaston", "Leslie Jones", "Harold Zoot"); var regOfficeQuotas = new Array(300000, 250000, 350000, 225000); // просмотр в параллельных массивах function getData(form) { var i = form.offices.selectedlndex; form.manager.value = regionalManagers[in- form . quota . value = regOfficeQuotas[i]; } </script> </head> «body onload="getData(document.officeData)"> «hl>Parallel Array Lookup</hl> «hr /> «form name="officeData"> <p>Select a regional office: «select name="offices" onchange="getData(this.form)"> «option>New York«/option> <option>Chicago«/option> <option>Houston«/option> «opt ion>Portland«/opt ion> </select>«/p> <p>The manager is: «input type="text" name="manager" size="35" /><br /> The office quota is: «input 4 type="text" name="quota" size="8" /></p> </form> </body> </html> С другой стороны, если содержимое, которое нужно найти, введено пользователем в тек- стовое поле, в цикле необходимо провести поиск в одном из массивов и найти индекс совпа- дающего элемента. Листинг 30.3 представляет собой вариант листинга 30.2, но вместо эле- мента select для ввода названия региона используется текстовое поле. Предположив, что пользователи правильно указали регион (что не всегда правда), новая версия функции getData () в листинге 30.3 проводит действия, больше похожие на поиск: нахождение соответствия в одном массиве и отображение результатов из параллельных массивов. Цикл for итератив- но просматривает все элементы массива regionalOf f ices. Условный оператор if срав- нивает введенное значение и текущий элемент массива (преобразовав оба значения к верхне- му регистру). После нахождения соответствия цикл for прерывается (при этом переменная i будет содержать индекс нужного элемента). За пределами цикла for другой условный опера- тор i f проверяет, не достигло ли значение индекса длины массива (это значит, что совпаде- ния не найдено). Лишь в том случае, когда i указывает на какой-либо элемент массива, сце- нарий получает значения элементов (с тем же индексом) из двух других массивов. 928 Часть IV. Объекты языка JavaScript
<html> <head> «title>Paral'lel Array Lookup II</title> «script type="text/javascript"> // данные var regionalOffices = new Array("New York", "Chicago", "Houston", "Portland"); var regionalManagers = new Array("Shirley Smith", "Todd Gaston", "Leslie Jones", "Harold Zoot"); var regOfficeQuotas = new Array(300000, 250000, 350000, 225000); // просмотр в параллельных массивах function getData(form) { // копирование содержимого текстового поля var inputText = form.officelnp. value; // просмотр всех записей массива regionalOffices for (var i = 0; i < regionalOffices.length; i++) { // сравнение версий в верхнем регистре с записями //в массиве regionalOffices if (inputText.toUpperCase() == regionalOffices[i].toUpperCase()) { // если найдено совпадение, то выход из цикла break; } } // проверка не превышения счетчиком i максимального индекса if (i < regionalOffices.length) .{ // вывод соответствующих записей параллельных массивов form.manager.value = regionalManagers[i]; form.quota.value = regOfficeQuotas[i]; } else { // в цикле не найдено совпадений // очистка всех предыдущих значений form.manager.value = "°; form.quota.value = ""; // вывод совета пользователю , alert("No match found for " + inputText + "."); } } </script> </head> <body> <hl>Parallel Array Lookup IIc/hl> <hr /> «form name="officeData"> «p>Enter a regional office: «input type="text" name="officelnp" size="35" /> «input type="button" value="Search" onclick="getData(this.form)" /></p> <p>The manager is: «input type="text" name="manager" size="35" /xbr /> The office quota is: «input type="text" name="quota" size="8" />«/p> «/form> «/body> «/html> Глава 30. Объект Array 929
Многомерные массивы Альтернативой параллельным могут служить многомерные массивы. Несмотря на то, что массивы JavaScript являются одномерными, можно создать одномерный массив массивов или объектов. Логически правильнее создать массив определенных объектов, так как последние позволяют без особых проблем обращаться к своим свойствам, делая ссылки на данные из многомерных массивов более понятными при чтении кода (создание пользовательских объектов обсуждается в главе 33). Используя данные из предыдущего примера, представленная далее последовательность операторов создает конструктор объекта для каждой “записи данных”. Каждому элементу ос- новного массива присваивается новый объект. // Конструктор пользовательского объекта function officeRecord(city, manager, quota){ this.city = city; this.manager = manager; this.quota = quota; } // Создание основного массива var regionalOffices = new Array(); // Заполнение массива объектами regionalOffices [0] = new officeRecord("New York", "Shirley Smith", 300000); regionalOffices[1] = new officeRecord("Chicago", "Todd Gaston", 250000); regionalOffices[2] = new officeRecord("Houston", "Leslie Jones", 50000); regionalOffices[3] = new officeRecord("Portland", "Harold Zoot", 225000); Функция-конструктор объекта (officeRecord О) присваивает значения аргументов свойствам объекта. Поэтому для доступа к данным в массиве используется, во-первых, запись массива, указывающая на нужный элемент, и, во-вторых, обращение к имени свойства объекта. var eastOfficeManager = regionalOffices[0].manager; Индекс в таком массиве может быть не только числовым, но и строковым. regionalOffices["east"] = new officeRecord("New York", "Shirley Smith", 300000); Тогда доступ к элементу выглядит следующим образом. var eastOfficeManager = regionalOffices["east"].manager; Если вы привыкли работать с обычными многоуровневыми массивами (в других языках программирования), то можете воспользоваться массивом массивов. // Создание нового основного массива var regionalOffices = new Array(); // Заполнение его массивами regionalOffices [0] = new ArrayCNew York", "Shirley Smith", 300000); regionalOffices[1] = new Array("Chicago", "Todd Gaston", 250000); regionalOffices[2] = new Array("Houston", "Leslie Jones", 350000); regionalOffices[3] = new Array("Portland", "Harold Zoot", 225000); Для краткости можно применить сокращенную запись. // Создание нового основного массива var regionalOffices = [ ["New York", "Shirley Smith", 300000], ["Chicago", "Todd Gaston", 250000], 930 Часть IV. Объекты языка JavaScript
["Houston", "Leslie Jones", 350000], ["Portland", "Harold Zoot", 225000] ]; Обращение к элементу данных в массиве массивов требует применения двойной ссылки. Например, для получения имени менеджера из офиса в Хьюстоне используется следующий синтаксис. var HoustonMgr = regionalOffices[2][1]; Первый индекс в квадратных скобках соответствует внешнему массиву (regionalOf f ices), а второй — массиву, заданному ссылкой regionalOf f ices [2]. Свойства объекта Array constructor См. строка. constructor (глава 27). length Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Свойство length настоящего объекта массива содержит количество элементов в масси- ве. Элемент может содержать любой тип значений в JavaScript, включая null. Если в 10-м элементе массива содержимся значение, а остальные равны null, то длина равна 10. Обрати- те внимание на следующее: поскольку индекс массива начинается с нуля, индекс последней ячейки на единицу меньше длины массива. Поэтому таким свойством удобно пользоваться для добавления к массиву нового элемента. myArray[myArray.length] = значениеДобавляемогоЭлемента; Универсальной функции необязательно знать конкретное значение индекса, чтобы доба- вить новый элемент. prototype Значение: переменная или функция Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ В JavaScript объект массива содержит набор методов и свойство length— элементы, присущие всем объектам массивов. Свойство prototype позволяет сценарию добавить но- вые свойства или методы всем массивам, созданным в загруженном документе. Свойство prototype можно изменить в любом отдельно взятом объекте. Пример Чтобы продемонстрировать применение свойства prototype, в листинге 30.4 указыва- ется одно и то же свойство prototype для всех массивов объектов, созданных из статиче- ского объекта Array. Когда в сценарии создаются новые массивы (копии объекта Array так же, как и объекты даты, являются копиями объекта Date), это свойство становится их ча- стью автоматически. В одном из массивов, с, прототип свойства sponsor изменяется. Одна- ко это изменение не влияет на прототипы свойств других объектов Array. Поэтому создан- ный далее массив d включает исходное значение свойства sponsor. Глава 30. Объект Array 931
«html> <head> «title>Array prototypes«/title> «script type="text/javascript"> // добавление прототипа во все объекты Array Array.prototype.sponsor = "DG"; a = new Array(5); b = new Array(5); c = new Array(5); I/ замена свойства prototype для одного 1 экземпляра1 С.sponsor = "JS"; I/ выбор исходного свойства prototype d = new Array(5); «/script> </head> <body> <h2> «script type="text/javascript"> document.write("Array a a.sponsor + "<br />") is brought to you by: " + document.write("Array b is brought to you by: " + b.sponsor + "<br />") document.write("Array c is brought to you by: " + c.sponsor + "«br />") document.write("Array d is brought to you by: " + d. sponsor + " <br / > ") «/script> </h2> </body> </html> Прототипу можно присвоить свойства или функции. В последнем случае функция определя- ется обычным для JavaScript образом. После этого ее имя присваивается свойству prototype. function newFunc(paraml) { // операторы } Array.prototype.newMethod = newFunc; // здесь скобки не используются Для вызова функции (теперь она является новым временным методом объекта Array) ис- пользуется обычный синтаксис метода объекта. Например, вызов-прототипа метода show- Coverlmage () для десятого элемента массива CDCollection выглядит следующим образом. CDCollection.showCoverImage(9); Параметром функции является индекс (он используется, к примеру, для доступа к изобра- жению, URL которого содержится в свойстве объекта, хранимого в десятом элементе массива). Методы объекта Array Если информация сохранена в массиве, JavaScript позволяет воспользоваться несколькими методами, определенными для управления данными. Эти методы, принадлежащие создавае- мым объектам массивов, со временем изменяются, поэтому нужно следить, какие из них под- держиваются конкретной версией браузера. 932 Часть IV. Объекты языка JavaScript
массив, concat (массив2) Возвращаемое значение: объект массива. Совместимость: WinIE4+, MacIE4+, NN4+, Moz 1 +, Safari 1+ Метод массив. concat () позволяет объединить два объекта, создав третий объект мас- сива. Это действие никак не влияет на содержимое или поведение двух исходных массивов. Для конкатенации массивов первый указывается слева от точки, а второй — в аргументе метода. var arrayl = new Array(1,2,3); । var array2 = new Array ("a", "b", "c") ,- var аггауЗ = arrayl.concat(array2); // результат: массив co значениями 1,2,3,"a","b","с" Если элементом массива является строка или число (но не объект строки или числа), значе- ния из исходных массивов копируются в новый. После этого любая связь значений из нового массива с исходными прерывается. Если элементами исходного массива являются ссылки на объекты (любого типа), JavaScript копирует в новый массив только ссылки. Поэтому внесение изменений в одном из массивов влияет на объект, а значит, это отражается в обоих массивах. Пример Листинг 30.5 несколько сложнее предыдущих, однако в нем продемонстрировано сразу два принципа: использование метода массив. concat () для объединения массива и приня- тие решения об обработке или не обработке данных массива в зависимости от их типа. Стра- ница, отображаемая в окне браузера после загрузки кода листинга 30.5, показана на рис. 30.1. Рис. 30.1. Ссылка на объект сохраняется и в объединенном массиве После загрузки документа вы можете ознакомиться со всеми тремя массивами. Первый массив содержит только строковые значения, второй— два строковых значений и одну Глава 30. Объект Array 933
ссылку на объект формы (текстовое поле original). Сценарий этой страницы не только создает эти массивы, но и объединяет их с помощью метода массив. concat (); получен- ный результат отображается в третьем массиве. Чтобы отобразить содержимое массивов в виде столбцов данных, используется метод массив. j о in (), который преобразует элементы мас- сива в текстовую строку, разделенную символами возврата каретки. Две группы текстовых полей в нижней части страницы помогают разобраться с текущим содержимым массивов. Если в первом разделе вы введете значение элемента arrayThree [0], то оно заменит строковое значение в объединенном массиве. Поскольку это значение никак не связано с данными исходных двух массивов, то в них соответствующий элемент изменен не будет. Воспользовавшись методом showArray (), вы сможете удостовериться в том, что изменился только третий массив, но никак не первый или второй. Более сложной является взаимосвязь между объектами. Ссылка на первое текстовое поле второго раздела назначается третьему элементу второго массива (arrayTwo). После объеди- нения массивов эта же ссылка отображается последней в третьем массиве. Если ввести значе- ние для последнего элемента третьего массива в соответствующем поле страницы, то это при- ведет к обратным изменениям в исходных объектах, в том числе и в объекте arrayTwo [2]. При этом список элементов массива не изменится, поскольку в них по-прежнему указана ссылка на тот же объект. <html> <head> <title>Array Concatenation</title> «script type="text/javascript"> 11 глобальные переменные var arrayOne, arrayTwo, arrayThree, textObj; // инициализация после загрузки для доступа // к текстовым объектам формы function initialize() { var form = document.forms[0] ; textObj = form.original; arrayOne = new Array("Jerry", "Elaine","Kramer"); arrayTwo = new Array("Ross", "Rachel",textObj); arrayThree = arrayOne.concat(arrayTwo); updatel(form); update2(form); showArrays(); } 11 отображение текущих значений всех трех массивов function showArrays() { var form = document.forms[0] ; form.arrayl.value = arrayOne.join("\n"); form.array2.value = arrayTwo.join("\n"); form.аггауЗ.value = arrayThree.join("\n"); } // изменение значения первого элемента массива Array Three function updatel(form) { arrayThree[0] = form.source1.value; form.resultl.value = arrayOne[0]; form.result2.value = arrayThree[0]; showArrays(); } // изменение значения свойства объекта. 934 Часть IV. Объекты языка JavaScript
// указывающего на Array Three function update2(form) { arrayThree[5].value = form.source2.value; form.results.value = arrayTwo[2].value; form.result4.value = arrayThree[5].value; showArrays(); } c/script> c/head> cbody onload="initialize()"> <form> ctable> ctr> cth>arrayOnec/th> cth>arrayTwoc/th> cth>arrayThreec/th> <tr> «tdxtextarea name="arrayl" cols="25" rows="6"> c/textarea>c/td> ctdxtextarea name="array2" cols="25" rows="6"> c/textarea>c/td> ctdxtextarea name="array3" cols="25" rows="6"> </textareax/td> c/tr> c/table> cb>Enter new value for arrayThree[0]:c/b>cinput type="text" name="sourcel" value="Jerry" /> cinput type="button" value="Change arrayThree[0]" onclick="updatel(this.form)" /> <br /> Current array0ne[0] is:cinput type="text" name="resultl" /xbr /> Current arrayThree [0] is: cinput type="text" name="result2" /xbr /xhr /> textObj assigned to arrayTwo[2]:cinput type="text" name="original" onfocus="this.blur 0 " /xbr /> cb>Enter new value for arrayThree [5] :c/bxinput type=“text" name="source2" value="Phoebe" /> cinput type="button" value="Change arrayThree[5].value" onclick="update2 (this. form) " /xbr /> Current arrayTwo[2].value is:cinput type="text" name="results" /xbr /> Current arrayThree[5].value is:cinput type="text" name="result4" /> cpxinput type="button" value="Reset" onclick="location.reload()" />c/p> c/form> c/body> c/html> См. также: метод массив. join (). , array, join (разделитель) Возвращаемое значение: строка элементов массива, разделенных значением разделитель. Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Данные массива в их естественной форме нельзя просмотреть. Также нельзя и передать их CGI-программе на сервер. Чтобы перейти от дискретных элементов массива к строке, применяется Глава 30. Объект Array 935
метод массив. j oin (). Без него решение такой задачи требовало бы применения множест- венных операций над строками. Единственным аргументом метода является строка из одного или нескольких символов, действующих как разделители элементов. Например, чтобы перечислить элементы массива через запятую, используется следующий оператор. var arrayText = туАггау.join; Вызов метода не изменяет исходный массив. Поэтому результат метода необходимо при- своить переменной или, например, свойству элемента формы. Пример Сценарий листинга 30.6 преобразует массив названий планет в текстовую строку. На странице отображается поле, в котором можно ввести разделитель элементов массива в тек- стовой строке. <html> <head> <title>Array.join()</title> «script type="text/javascript"> solarSys = new Array(9); solarSys[0] = "Mercury"; solarSys[1] = "Venus"; solarSys[2] = "Earth"; solarSys[3] = "Mars"; solarSys[4] = "Jupiter"; solarSys[5] = "Saturn"; solarSys[6] = "Uranus"; solarSys[7] = "Neptune"; solarSys[8] = "Pluto"; 11 объединение элементов массива в строку function convert(form) { var delimiter = form.delim.value; form.output.value = unescape(solarSys.join(delimiter)); } </script> </head> <body> <h2>Converting arrays to strings«/h2> This document contains an array of planets in our solar system, «hr /> <form> Enter a string to act as a delimiter between entries: «input type="text" name="delim" value="," size="5" /> «pxinput type="button" value= "Display as String" onclick="convert(this.form)" /> <input type=“reset" /> «textarea name="output" rows="4" cols="40" wrap="virtual"></textarea>«/p> </form> </body> </html> См. также: метод строка. split (). 936 Часть /V. Объекты языка JavaScript
массив,pop() массив. push (значениеИлиОбъект) массив.shift() массив,unshift(значениеИлиОбъект) Возвращаемое значение: значение одного элемента массива. Совместимость: WinIE5.5+, MacIE-, NN4+, Mozl+, Safaril+ Понятйе стека хорошо знакомо опытным программистам, особенно тем, кто работал с языком ассемблера на уровне процессора. Даже если вы не программировали стек, то на- верняка встречали такой принцип в жизни. Классическую аналогию представляет собой стоп- ка подносов в кафетерии. Когда она создается, каждый поднос кладется поверх предыдущего. Посетитель забирает самый верхний поднос (т.е. последний, добавленный в стек). Таким об- разом, последний элемент, добавленный в стек, извлекается из него первым. JavaScript в браузерах NN4+ и IE5.5+ позволяет превратить массив в подобный стек. К тако- му стеку с любого конца (посредством одного из методов) можно добавить или извлечь данные. Часто используется следующая терминология: добавлять (push) и извлекать (pop). В ре- зультате добавления в массив методом push () значение размещается в последнем элементе массива. При вызове метода массив.рор.() последний элемент извлекается из массива и возвращается методом. При этом он удаляется, а длина массива уменьшается на единицу. Рассмотрим, что происходит с массивом, используемым как стек в приведенной ниже после- довательности операторов. var source = new Array("Homer","Marge","Bart","Lisa","Maggie"); var stack = new Array(); // стек = -<пустой> stack.push(source[0]); // стек = "Homer" stack.push(source[2]); // стек = "Homer","Bart" var Simpsonl = stack.pop(); // стек = "Homer" ; Simpsonl = "Bart" var Simpson2 = stack.pop(); // стек = <пустой> ; Simpson2 = "Homer" Кроме методов push () и pop (), обрабатывающих конечный элемент массива, существуют и два метода, которые управляют начальным элементом. Их имена не настолько описательны, как push () и pop (). Для вставки значения в начале массива применяется метод массив. unshi f t (), для его удаления— массив.shift (). Конечно же, эти методы не обязательно использовать в паре. Можно поместить один набор значений в конец массива методом push (), а другой — удалить из начала методом shift (). Выбор метода зависит от поставленной задачи. См. также: метод массив, concat (), массив, slice (). массив.reverse() Возвращаемое значение: массив элементов в обратном порядке. Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ В некоторых ситуациях можно изменить порядок следования элементов в массиве. Вы впра- ве создать цикл, обрабатывающий массив в порядке убывания индекса, однако CGI-программе на сервере может понадобиться массив, упорядоченный не так, как это выполняет сценарий. JavaScript позволяет изменить порядок элементов в массиве на противоположный: по- следний элемент становится первым (индекс 0). Помните, что такая операция изменяет ис- ходный массив, а не его копию, хотя сам метод и возвращает копию реверсивного массива. Только перезагрузка документа восстанавливает исходный порядок. Глава 30. Объект Array 937
Пример Листинг 30.7 представляет собой улучшенную версию листинга 30.6. Страница докумен- та, представленного этим листингом, содержит дополнительные кнопку и функцию, которые изменяют порядок следования элементов в массиве и отображают полученный результат в текстовой области. <html> «head> <title>Array.reverse()«/title> «script type="text/javascript"> solarSys = new Array(9); solarSys[0] = "Mercury"; solarSys[1] = "Venus"; solarSys[2] = "Earth"; solarSys[3] = "Mars"; solarSys[4] = "Jupiter"; solarSys[5] = "Saturn"; solarSys[6] = "Uranus"; solarSys[7] = "Neptune"; solarSys[8] = "Pluto"; // отображение массива, находящегося в памяти function showAsIs(form) { var delimiter = form.delim.value; form.output.value = unescape(solarSys.join(delimiter)); } // изменение направления массива и представление его строкой function reverselt(form) { var delimiter = form.delim.value; solarSys.reverse(); // изменение направления массива form.output.value = unescape(solarSys.join(delimiter)); } </script> </head> «body> <h2>Reversing array element order«/h2> This document contains an array of planets in our solar system. <hr /> <form> Enter a string to act as a delimiter between entries: «input type="text" name="delim" value="," size="5" /> «pxinput type="button" value="Array as-is" onclick="showAs!s(this.form)" /> cinput type="button" value="Reverse the array" onclick="reverselt(this.form)" /> «input type="reset" /> «input type="button" value="Reload" onclick="self.location.reload()" /> «textarea name="output" rows="4" cols="60"> «/textareax/p> </form> </body> </html> См. также: метод массив. sort (). 938 Часть IV. Объекты языка JavaScript
массив.slice(начИндекс [, конИндекс]) Возвращаемое значение: массив. Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Метод массив, slice () (подобный по своему действию одноименному строковому ме- тоду) позволяет извлекать из массива набор соседних элементов. Полученный сегмент стано- вится новым объектом массива. Значения и объекты из исходного массива ведут себя так же, как, например, массивы, созданные методом массив. concat (). Один аргумент является обязательным — индекс начального извлекаемого элемента. Если второй аргумент не указан, то метод обрабатывает массив до конца. В ином случае он извле- кает все элементы до указанного индекса, исключая последний. Например, для получения имен планет, соседних с Землей, используется следующий код. var solarSys = new Array("Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus", "Neptune","Pluto"); var nearby = solarSys.slice(1,4); // результат: новый массив "Venus", "Earth", "Mars" См. также: методы массив. splice (), строка. slice О . массив,sort([функцияСравнения]) Возвращаемое значение: массив значений, упорядоченных с помощью функции compareFunction. Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Сортировка массивов является мощным средством JavaScript, однако она сложна в ис- пользовании, если вы не знакомы с ее особенностями. Она становится возможной исключи- тельно благодаря использованию методу сортировки по любому критерию. Для записей, со- стоящих из строк, таким критерием может быть алфавитный порядок или их длина. Для числовых элементов, как правило, критерием является числовой порядок. Вначале рассмотрим, как сортирует элементы сам метод массив. sort () (без использо- вания функции, выполняющей сравнение). Если аргумент не указан, JavaScript преобразует элементы массива в строки, затем он выполнит сортировку строк. При этом используются ASCII-коды символов. Это значит, что числа, например, сортируются как строки, а не как чи- словые значения. Эго существенно влияет на конечный результат, содержащий числовые данные: значение 201 считается меньшим 88, поскольку в процессе сортировки при опреде- лении порядка сравниваются первые символы строк (“2” и “8”). Таким образом, в чистом ви- де метод массив. sort ()' подходит только для простой сортировки строк. К счастью, этот метод можно усовершенствовать, добавив функцию, которая выполнит сравнение элементов массива. Ей передается два элемента массива (метод массив. sort () не пересылает все значения массива этой функции для сортировки). Функция сортировки по- казывает методу sort (), какой из элементов предшествует другому. Для этого она возвра- щает значение определенного знака. Предположим, что функция сравнивает два значения, а и Ь. Типы возвращаемых методу sort () значений представлены в табл. 30.1. <0 Ь следует после а 0 Порядок а и ь не меняется >0 а следует после ь Глава 30. Объект Array 939
Рассмотрим следующий пример. myArray = new Array(12, 5, 200, 80); function compare(a,b) { return a — b; } myArray.sort(compare) Массив содержит четыре числовых значения. Для правильной их сортировки (в порядке возрастания) определена функция сравнения с именем compare (), которую вызывает метод sort (). Обратите внимание, что, в отличие от обычного вызова функций, аргументом мето- да sort () является указатель на нее (т.е. синтаксис исключает использование скобок). При вызове функции compare () JavaScript автоматически посылает ей два аргумента, проводя сравнение каждого элемента со всеми остальными. При каждом вызове compare () JavaScript передает переменным а и Ь два элемента массива. В предыдущем примере функция возвращает разность а и Ь. Если а больше Ь, метод sort () получает положительное значе- ние, т.е. а должно следовать после b (индекс элемента а должен быть больше индекса Ь). По- этому b в итоге может оказаться элементом myArray [0], а а — элементом с большим ин- дексом. Если же а меньше Ь, тогда возвращаемое значение отрицательно и метод sort () делает индекс элемента а меньшим, чем Ь. Сравнения с помощью внешней функции иногда оказываются довольно долгими (это за- висит от типов значений, сохраняемых в массивах). Например, вместо числовых сравнений, которые были только что показаны, можно выполнить и строковые сравнения. Следующая функция сортирует строки по последнему символу (в алфавитном порядке). fuhction compare(а,b) { // последний символ строки массива var aComp = a.charAt(a.length — 1); var bComp = b.charAt(b.length — 1); if (aComp < bComp) return -1; if (aComp > bComp) return 1; return 0 } Вначале функция извлекает последний символ из каждой строки, переданной ей. Затем их ASCII-коды сравниваются, и функция возвращает значение, которое указывает методу sort (), что необходимо делать со сравниваемыми элементами массива. Когда элементами массива являются объекты, их можно отсортировать даже по свойст- вам. Если аргументы а и b функции сортировки являются ссылками на элементы массива, то- гда их можно использовать для доступа к свойствам объектов. Например, пусть в массиве со- держатся объекты с информацией о служащих, и одним из свойств объекта является возраст, представленный в строковой форме. Тогда массив можно отсортировать, основываясь на чи- словом эквиваленте свойства аде, применяя следующую функцию сравнения. function compare(а,b) { return parselnt(a.age) — parselnt(b.age) } Сортировка массивов, в отличие от подобных процедур в других языках сценариев, не яв- ляется однозначной. “Неоднозначность” заключается в том, что последующие процедуры сортировки одного и того же массива некумулятивные. Кроме того, помните, что сортировка изменяет исходный массив. Если его требуется сохранить в исходном состоянии, создайте копию массива или перезагрузите страницу. Если элемент массива равен null, метод разме- щает его в конце массива. Сортировка массивов в JavaScript представляет собой очень удобное средство с большими возможностями. Поэтому часто при загрузке страницы, содержащей данные XML, создаются 940 Часть IV. Объекты языка JavaScript
копии этих данных в виде массивов объектов JavaScript (см. главу 57). Преобразование XML- данных в массивы JavaScript позволяет выполнить сортировку данных с помощью более про- стых и быстрых методов, чем собственные процедуры сортировки элементов XML. Пример В листинге 30.8 приведены примеры сортировки массива строковых значений (рис. 30.2). Четыре кнопки на этой странице выполняют разные процедуры сортировки. В трех из них применяются функции сравнения. Каждая из упомянутых функции использует собственный алгоритм сравнения данных. Рис. 30.2. Сортировка массива названий планет по последней букве <html> <head> <title>Array.sort()</title> «script type="text/javascript"> solarSys = new Array(9); solarSys[0] = "Mercury"; solarSys[1] = "Venus"; solarSys[2] = "Earth"; solarSys[3] = "Mars"; solarSys[4] = “JUpiter"; solarSys[5] = "Saturn"; solarSys[6] = "Uranus"; solarSys[7] = "Neptune"; solarSys[8] = "Pluto"; // функции сравнения * Глава 30. Объект Array 941
function comparel(a,b) { // обращение алфавитного порядка if (a > b) return -1; if (b > a) return 1; return 0; } function compareZ(a,b) { // последний символ в именах планет var aComp = a.charAt(a.length - 1) ; var bComp = b. charAt (b. length - 1) ,- if (aComp < bComp) return -1; if (aComp > bComp) return 1; return 0; } function compares(a,b) { // длина имен планет return a.length - b.length; // сортировка и отображение массивов function sortlt(form, compFunc) { var delimiter = " ; " ; if (compFunc == null) { solarSys.sort() ,- } else { solarSys.sort(compFunc); } // вывод результата в поле form.output.value = unescape(solarSys.join(delimiter)); </script> </head> «body onload="document.forms[0].output.value = unescape(solarSys.join(';'))"> <h2>Sorting array elements</h2> This document contains an array of planets in our solar system. <hr /> <form> Click on a button to sort the array: <pxinput type="button" value="Alphabetical A-Z" onclick="sortlt(this.form)" /> «input type="button" value="Alphabetical Z-A" onclick= "sortlt(this.form,comparel)" /> «input type="button" value="Last Character" onclick="sortlt(this.form,compare2)" /> «input type="button" value="Name Length" onclick="sortlt(this.form,compare!)" /> «input type="button" value="Reload Original" onclick="self.location.reload() ' /> «input type="text" name="output" size="62" /></p> «/form> </body> * </html> См. также: метод array. reverse (). 942 Часть IV. Объекты языка JavaScript
t Как отмечается в главе 42, массивы часто являются результатом выполнения /назвмту методов объектов регулярных выражений (например, массив строковых фраг- * ментов, совпадающих с указанным значением). Эти специальные массивы обла- дают нвбором собственных свойств, позволяющих сценврию анализировать найденную информацию. В остальном массивы, полученные в результвте обра- ботки регулярных выражений, ведут себя привычным образом. массив.splice(начИндекс , количество[, элем1 [, элем2 [,... элемИ] ] ]) Возвращаемое значение: массив. Совместимость: WinIE5.5+, MacIE-, NN4+, Mozl+, Safaril+ Если требуется удалить несколько элементов из середины массива, решение этой задачи облегчает метод массив.splice (). В ином случае потребовалось бы создать новый мас- сив из определенных частей исходного. Первым из двух обязательных параметров является индекс первого удаляемого элемента, вторым— общее число таких элементов. Удаление элементов влияет на длину всего массива. Метод splice () возвращает массив, содержащий все удаленные элементы. Метод splice () можно применять и для замены элементов массива. Дополнительные аргументы (начиная с третьего) позволяют указать данные, которые будут вставлены в массив вместо удаленных элементов. Каждый добавляемый элемент может принадлежать к любому типу данных JavaScript, а их количество не обязательно должно быть равным числу удален- ных элементов. Укажите второй параметр равным нулю и вы сможете воспользоваться мето- дом splice () для вставки одного или нескольких значений в любом месте массива. Пример Приложение The Evaluator позволяет изучить метод массив. splice (). Для начала соз- дайте массив, содержащий последовательность чисел. а = new Array(1,2,3,4,5) Далее удалите из него средние три элемента и замените их одной строкой. a.splice(1, 3, "two/three/four") В области результатов отображается строковая версия массива из трех элементов, воз- вращаемая этим методом. Чтобы ознакомиться с текущим содержимым массива, введите в верхнем текстовом поле приложения значение а. Чтобы вернуть в массив исходные числовые значения, воспользуйтесь следующим опе- ратором. a.spliced, 1, 2, 3, 4) Теперь массив а вновь обретает пять числовых значений. См. также: метод массив. slice (). массив.toLocaleString() Возвращаемое значение: строка. Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safaril+ Глава 30. Объект Array 943
массив.toString() Возвращаемое значение: строка. Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Метод массив. toLocaleString () и более ранний, поддерживаемый большим чис- лом браузеров — массив. toString (), позволяют вывести содержимое массива в строко- вой форме. Браузеры используют метод toString () по-своему при отображении массива в текстовом окне.»В этом случае элементы массива разделены запятой. Точный алгоритм преобразования, используемый методом toLocaleString (), зависит от версии браузера. Поэтому неудивительно, что IE и NN несколько отличаются в определен- ных деталях (это происходит даже для версии U.S. English браузеров и операционной системы). Например, если массив содержит целые числа, метод toLocaleString () в IE5.5+ возвра- щает список значений, разделенных запятой и пробелом и отформатированных с двумя зна- ками после запятой (как цены в долларах и центах). В NN6+ этот же метод возвращает обыч- ные целые числа, также разделенные запятой и пробелом. Если массив необходимо преобразовать в строку для других целей (например, данные в скры- том текстовом поле для передачи серверу или строка поиска, пересылаемая другой страни- цы), лучше воспользоваться методом массив, join (). Он предоставляет более надежный и гибкий способ управления символами-разделителями. Кроме того, результат будет одина- ковым независимо от локализации. См, также: метод массив. join (). 944 Часть IV. Объекты языка JavaScript
Управляющие структуры и обработка исключительных ситуаций Как правило, утром человек встает, собирается, идет на работу, вечером возвращается, а когда темнеет, включает свет. Аналогичная закономерность прослеживается и при работе программы с момента ее запуска до заверше- ния. Но в промежутке между утром и вечером — запуском и завершением, выполняется огромное количество крошечных шагов, однако не все действительно нужны. Время от времени, необходимо управлять происходящим, принимая решения или повторяя задачи до тех пор, пока работа не будет завер- шена. Управляющие структуры являются мощным средством осуществления подобных возможностей в JavaScript. Код управляющих структур подобен тому, что использу- ется во многих языках программирования, особенно после его расширения в NN4 и IE4. Принципы принятия решений и организации циклов практически одинаковы во всех зада- чах программирования. Существует и другой механизм программного управле- ния — это обработка ошибок (или исключительных ситуаций), формально данный механизм описывается в 3-м издании стан- дарта ЕСМА-262. Для версии JavaScript, используемой в IE5.5 и NN6, концепция обработки исключительных ситуаций яв- ляется новой, но во многих других средах данная методика стала довольно популярной. Применение такой технологии в сценарии может значительно улучшить процесс исправле- ния ошибок, вызванных неверно введенными пользователем данными либо сбоями в сети.
Конструкции if и if...else Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ B программах JavaScript часто возникают ситуации, в которых должно быть принято ре- шение, основанное на текущих значениях переменных или свойств объекта/ Одновременно можно получить только два результата в процессе принятия решения. Фактором, которым определяются дальнейшие операции программы, является некоторое выражение. Например, если человек входит ночью в дом, это выражение будет иметь следующий вид: “Слишком темно, без света ничего не видно”. Если данное выражение истинно, вошедщий в комнату включает свет; если ложно, возвращается к исходной задаче. Простые решения Фрагмент программы JavaScript для данного вида простого решения всегда начинается с оператора if, после которого следует проверяемое условие и выражения, выполняемые, если указанное условие соблюдается. В JavaScript не используется оператор then (как в некото- рых других языках); ключевое слово помещают в гфуглые скобки, а различные составляющие этой конструкции — в фигурные. Формальный синтаксис данной конструкции имеет такой вид. if (условие) { выражение, выполняемое при истинности условия } Это означает, что если условие истинно, далее в программе выполняются операторы, ука- занные в фигурных скобках. Если ложно, программа продолжает выполнять операторы, следующие после закрывающей фигурной скобки (}). Если передвижение по дому описать с помощью языка сценариев, код программы будет выглядеть следующим образом. if (tooDark == true){ найти выключатель включить свет } Если пользователь ранее не сталкивался с языками С или C++, использование двойного знака равенства может показаться странным. В следующей главе об этом операторе будет рассказываться более подробно, а пока необходимо знать, что он применяется для определе- ния равенства элементов, указанных по обе его стороны. Другими словами, выражению условие конструкции if всегда должно соответствовать булево значение (true или false). Так как некоторые свойства объекта имеют булево значение, ссылки на них можно указывать в выражении условие. Иначе выражение условие будет состоять из двух значений, разде- ленных оператором сравнения: == (равно) или ! = (не равно). Рассмотрим реальный пример — фрагмент программы на JavaScript. В данную функцию подставляется объект формы, в котором содержится текстовый объект entry. function notTooHigh(form) { if (parselnt(form.entry.value) >100) { alert("Sorry, the value you entered is too high. Try again."); return false; return true; } С помощью условия (в гфуглых скобках) содержимое поля проверяется на равенство строго определенному значению 100. Если введенное значение больше заданного, на эгфан выводится предупреждение, и в том месте сценария, где была вызвана данная функция, вы- ражению возвращается значение false. Но если это значение меньше 100, все указанные операторы пропускаются, и функция возвращает значение true. 946 Часть /V. Объекты языка JavaScript
Условные выражения Во многих условных управляющих выражениях числовые значения сравниваются со спе- циальными величинами — пустой строкой или null. При различных обстоятельствах ис- пользуются разные сокращенные именования. В табл. 31.1 приведено подробное описание значений, которые можно указывать в выражении условия управляющей структуры в качест- ве истины или лжи (или равенства). Истина Ложь Непустая строка Пустая строка Ненулевое число 0 Непустое значение null Объект существует Объект не существует Свойство определено Неопределенное свойство Вместо расшифровывания эквивалентного выражения в условии с помощью значений, при- веденных в таблице, можно просто указать проверяемое значение. Например, если переменная с именем myVal в конструкции if может принять значение null пустой строки или строково- го значения для дальнейшей обработки, код программы можно записать в следующей форме. if (myVal){ // Обработка myVal } Все нулевые или пустые строки условия расцениваются как false, поэтому операторы, указанные внутри конструкции if, в данном примере выполняются только в том случае, ко- гда значение myVal пригодно для обработки (т.е. существует). В этой книге данный меха- низм используется во всех ситуациях, когда необходимо определить поддержку объекта в ие- рархической структуре браузера. Например, следующий фрагмент программы выполняется только в том случае, если объект document имеет свойство массива images. if (document.images) { // Обработка объектов изображения } Составные решения Простую конструкцию if, описанную ранее, удобно использовать в случае, когда решение состоит в том, чтобы совершить небольшое отклонение в процедуре перед возвращением к главной задаче. Но не все решения, в программировании или в жизни, соответствуют данной си- туации. Для того чтобы задать два возможных варианта решений, в JavaScript в конструкцию if нужно добавить еще один компонент. Соответствующий синтаксис выглядит следующим образом. if (условие) { операторы, выполняемые при справедливости утверждения } else { операторы, выполняемые при ложности утверждения } Гпава 31. Управляющие структуры и обработка исключительных ситуаций 947
Добавляя в конструкцию if оператор else, пользователь определяет действия сценария в том случае, когда условие имеет ложное значение. Операторы, выполняемые при справед- ливости и ложности утверждения, не обязательно должны быть сбалансированы: один опера- тор может состоять из одной строки программы, другой — из сотни. Но когда завершается цикл любой из этих ветвей, выполнение программы продолжается с последней забывающей фигурной скобки. Для того чтобы продемонстрировать, насколько удобна данная конструк- ция, приведем пример. В этом фрагменте сценария вычисляется количество дней в феврале. Решение основывается на том, является ли этот год високосным (для этого он должен быть кратным четырем, т.е. его арифметический модуль должен быть равен нулю — см. главу 32). var howMany = 0 ; var theYear = 2002; if (theYear % 4 == 0) { howMany = 29; } else { howMany = 28; } В данном случае для задания количества дней переменной howMany выполняется только одна из двух возможных частей сценария, если не использовать оператор else, как в сле- дующем примере. var howMany = 0; var theYear = 2002; if (theYear % 4 == 0) { howMany = 29; } howMany = 28; Значение переменной всегда будет равным 28, иногда после гфатковременного приравни- вания 29. Для того чтобы избежать подобной ситуации, используют конструкцию else. Вложенные выражения if... else Разработка составного решения требует особого внимания к логической схеме решений. В сценарии необходимо предусмотреть любые возможные виды условий и соответствующие им ситуации развития действий. Потребность в сложных конструкциях исчезает с появлением оператора switch в NN4+ и NN4+ (этот оператор описывается далее в этой главе). Однако все еще могут возникать ситуации, когда необходимо будет использовать составное решение, состоящее из серии вложенных конструкций if. . .else. Если программист не пользуется текстовыми редакторами кода, где удобно форматировать код приложения и проверять его синтаксис (например, закрытие фигурных скобок), ему придется контролировать весь синтак- сис самому. Кроме того, в сообщениях об ошибках, выводимых средствами JavaScript, при возникновении таковых (см. главу 45) не указывается номер строки с ошибкой, а только оп- ределенная область сценария, вызвавшая неполадки. / Не забывайте еще одну важную особенность вложенных выражение if... else, /назмнтеу хотя это касается только ранних версий JavaScript, предшествующих 1.2. В этих ! версиях не существует возможности выхода из вложенной части конструкции. Поэтому при создании сложной структуры необходимо предусмотреть все воз- можные варианты. Только тогда вы будете уверенны, что для каждого набора условий выполняется соответствующий оператор. Конечно, после этого жела- тельно протестировать программу (см. главу 45). В листинге 31.1 демонстрируются многократно вложенные конструкции if.. . else; при выполнении программы на экране отображается простой интерфейс для решения сложной 948 Часть IV. Объекты языка JavaScript
проблемы. Пользователя просят ввести один из трех символов: А, В или С. Для каждого из следующих условий в сценарии обрабатывается соответствующее сообщение. Пользователь не вводит значение. Пользователь вводит А. Пользователь вводит В. Пользователь вводит С. Пользователь вводит собственное значение. <html> <head> <titlex/title> <script type="text/javascript"> function. testLetter(form){ inpVal = form.entry.value; // назначение сокращенного // имени переменной if (inpVal != "") { // продолжение, если запись не пустая if (inpVal == "А") { // alert("Thanks for the } else if (inpVal == "B") Это "А"? А. ") ; । { // Нет. Это "В"? alert("Thanks for the } else if (inpVal == "C") В. ") ; | { // Нет. Это "С"? alert("Thanks for the С. ") ; } else { // Нет. Ни одно из них alert("Sorry, wrong letter or case."); } } else { // значение пустое; пропуск всего выше alert("You did not enter anything."); } } </script> </head> <body> <form onsubmit="return false"> Please enter A, B, or C: <input type="text" name="entry" onchange="testLetter(this.form)" /> </form> </body> </html> В каждом случае выполняются только те операторы, которые соответствуют определен- ному условию, даже если для определения соответствия требуется обработать несколько от- дельных запросов. Совсем не обязательно выходить из вложенной конструкции, так как, при нахождении соблюдаемого условия соответствующий оператор выполняется, а остальные просто игнорируются. Даже если создание вложенной конструкции, например, подобной приведенной в листин- ге 31.1, не вызывает трудностей, необходимо следить за тем, чтобы каждой открывающей скоб- ке соответствовала закрывающая. Рекомендуется использовать следующий прием: после введе- ния открывающей скобки сразу же введите и закрывающую. Обычно после ввода открывающей скобки,-дважды нажимают <Entei> (первый раз — для создания строки, в которую в дальнейшем будет вводиться следующий оператор, а второй — для ввода закрывающей скобки). Используйте Гпава 31. Управляющие структуры и обработка исключительных ситуаций- 949
<Tab>, если необходимо в одной строке задать и открывающую, и закрывающую скобки. Чтобы вставить еще несколько строк, переместите вниз введенные ранее закрывающие скобки. Если придерживаться данной методики оформления кода программы, то после завершения процесса программирования все закрывающие скобки будут расположены с определенными отступам, даже если их пришлось передвинуть с начального места на несколько строк вниз. Для чего используется форматирование? Форматирование кода совершенно не сказывается на правильности работы сценария в JavaScript. Отступы в конструкциях If и дальнейшие отступы ее операторов выполняются для наглядности и удобного восприятия кода. Подобное форматирование является, своего рода договоренностью между большинством программистов. Поскольку код вводится в тек- стовом редакторе, используйте клавишу <ТаЬ> для визуального распределения строк по разным уровням. При загрузке документов HTML со сценариями символы табуляции браузе- ром не воспринимаются, а следовательно, не отображаются на странице. Условные выражения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Так как конструкции принятия решений в JavaScript уже были описаны в данной главе, теперь самое время рассказать об особенном выражении, которое можно использовать вме- сто управляющей структуры if... else для задания обычного типа решения. В этой конст- рукции переменной можно назначить одно из двух значений, в зависимости от поставленного условия. Структура данного условного выражения имеет следующий вид. переменная = (условие) ? значение! : значение2; Это выражение означает следующее: если булев результат оператора условие является истинным, переменной назначается значение!; в противном случае этой переменной на- значается значение2. Подобно другим конструкциям, условное выражение также необхо- димо помещать в круглые скобки. Вопросительный знак является ключевым, как и двоеточие, которым разделены два возможных значения. Данное условное выражение, хоть и не особо понятно, является очень компактным. Срав- ните следующий вариант конструкции if.. . else var collectorstatus; if (CDCount > 500) { collectorstatus = "fanatic"; } else { collectorstatus = "normal"; } с условным выражением, используемым для решения той же самой задачи var collectorstatus = (CDCount > 500) ? "fanatic" : "normal"; В последнем варианте для выполнения тех же операций используется гораздо меньше строк (хотя внутренняя обработка полностью идентична обработке конструкции if... else). Конеч- но, если в решении содержится более одного оператора задания значения переменной, предпоч- тительнее использовать конструкцию if.. .else или switch. Однако помните: если необхо- димо выполнить бинарное действие, например, установить в сценарии флажок истинности или ложности, в этой ситуации рекомендуется использовать именно условное выражение. 950 Часть IV. Объекты языка JavaScript
Циклы повторения операций (for) Совместимость: WinIE3+, МасГЕЗ+, NN2+, Mozl+, Safari 14- Как можно было убедиться, просмотрев примеры предыдущих глав, возможность цикличе- ского просмотра каждого элемента массива или опции элемента формы довольно часто исполь- зуются во многих сценариях JavaScript. Наверное, наиболее типичная операция для данной кон- струкции — это поиск в свойствах нескольких элементов определенных значений, например, определение выбранного переключателя. Для повторения выполнения одних и тех же действий в JavaScript используется специальный цикл for, названный так от ключевого слова, с которого и начинается данная структура. Два других цикла, while и do-while, описываются ниже. Как уже отмечалось, с помощью цикла for в JavaScript можно повторять набор операций любое количество раз, используя при этом счетчик цикла (хотя это и необязательно). Синтак- сис данной конструкции имеет следующей вид. for ([начальное выражение]; [условие] ; [выражение обновления] ) { операторы } Три выражения в круглых скобках (параметры оператора for) являются ключевыми при выполнении данного цикла. Начальное выражение выполняется только один раз при запуске цикла. Наиболее час- то в начальном выражении указывают имя и начальное значение переменной, используемой в цикле. Подобным образом, при указании в операторе var, объявляется и имя переменной, и ее начальное значение (как правило, о или 1). var i = 0; Имя переменной может быть любым, но наиболее часто используют символ i, сокращенно от index. Конечно, если пользователь предпочитает слово counter (счетчик) или другое, на- поминающее ему о значении этой переменной, можно использовать любые другие имена. Помните, что это выражение в цикле for выполняется только один раз. Второе выражение представляет собой условие, подобно соответствующему оператору в конструкции if (см. ранее в этой главе). Если переменная цикла уже установлена в началь- ном выражении, в операторе условие указывают конечное значение счетчика цикла. Поэто- му наиболее часто в этом выражении выполняется сравнение переменной-счетчика и некото- рого установленного значения (т.е. осуществляется проверка, является ли значение счетчика цикла меньше максимального разрешенного значения). Если это условие не соблюдается в самом начале, указанные в теле цикла операции не выполняются. Если же условие соблюда- ется, то выполнение каждый раз начинается с “вершины” цикла, и каждый раз проверяется условие для определения текущего результата выражения. Если значение счетчика увеличи- вается с каждой новой итерацией цикла, в конечном счете оно превысит значение, указанное в операторе условие, и данный оператор перестанет соответствовать условию. Когда это произойдет, выполнение цикла for полностью прекратится. Заключительный оператор— выражение обновления, выполняется в конце каждой итерации цикла, после запуска всех операторов, определенных в конструкции for. Причем в этом выражении можно снова использовать ту же переменную-счетчик. Если необходимо увели- чить ее значение на единицу при каждой итерации цикла (это называется приращением значе- ния), используйте специальный оператор JavaScript ++, который добавляется к имени перемен- ной. Именно так объясняются загадочные символы i++, используемые во всех циклах for. Но не думайте, что можно увеличить значение переменной только на единицу. Его можно увеличи- вать на любое число (и даже уменьшать с помощью соответствующего оператора). Глава 31. Управляющие структуры и обработка исключительных ситуаций 951
Используя всю изложенную выше информацию, рассмотрим синтаксис данного фрагмен- та программы, в котором показан обычный способ применения счетчика цикла i. // Приращение переменной цикла for (var i = минЗначение; i < = максЗначение; i++) { операторы } // Уменьшение переменной цикла for (var i = максЗначение; i > = минЗначение; i--) { операторы } Вначале переменная i инициализируется со значением, заданным в переменной mlnValue. Затем i сравнивается с MaxValue. Если значение i меньше или равно maxValue, обработка продолжается в теле цикла. В конце цикла выполняется выражение обновления. В предыду- щем примере значение 1 увеличивалось на 1. Если 1 инициализируется как 0, то при первом прохождении цикла для выполнения операторов используется переменная со значением 0. В следующий раз переменная уже имеет значение 1. Как, наверное, можно было заметить из приведенного синтаксиса, все параметры опера- тора for необязательны. Например, значением счетчика цикла, основанном на данных, кото- рые используются в обработке, можно управлять в выражениях, выполняемых внутри этого цикла. Поэтому выражение обновления может дублироваться с операцией, определенной в самом цикле. Однако рекомендуется использовать все три параметра (хотя бы до тех пор, пока у вас не появится абсолютная уверенность в своих силах и принципах работы этого типа цикла). Если, например, пропустить выражение условия и не указать в программе оператор выхода из цикла, этот цикл может стать бесконечным, что отрицательно скажется на приме- нении данного приложения. Использование счетчика цикла Счетчик i (имя может быть любое) является довольно мощным инструментом управления данными внутри повторяющегося цикла. Ниже приведен пример классической функции JavaScript, в которой создается массив, совместимый с NN2; при его инициализации каждому элементу присваивается значение 0. // Инициализация массива п элементов function MakeArray(n) { this.length = n; for (var i = 1; i <= n; i++) { this[i] = 0; } return this; } В данной функции счетчик цикла i инициализирован со значением 1. Так как необходимо создать массив пустых элементов (со значением 0), начинайте с элемента, индекс которого равен 1 (нулевой используется в свойстве length) в предыдущей строке. В условном выра- жении цикл продолжает выполняться до тех пор, пока значение счетчика меньше либо равно числу создаваемых элементов (п). После каждой итерации цикла значение счетчика увеличи- вается на 1. Во вложенном операторе, который выполняется в самом цикле, переменная i используется для установки значения индекса в выражении присвоения. this[i] = 0; В первой итерации цикла выражение имеет такой вид. this[l] =0; 952 Часть IV. Объекты языка JavaScript
В следующей итерации оно несколько изменяется, this[2] = 0; И так далее, пока все элементы не будут созданы и им не будет присвоено значение 0. Теперь просмотрите листинг 30.2 HTML-страницы, на которой пользователь выбирает ре- гиональный офис из списка select (с его помощью запускается сценарий поиска имени ме- неджера и нормы продаж, установленные в этом регионе.) Так как названия региональных офисов хранятся в массиве, можно изменить сценарий так, чтобы опции элемента select считывались из массива. В случае, когда изменится структура региональных офисов, вам по- требуется выполнить только одно исправление в массиве, а не переписывать всю страницу. Еще раз приведем этот массив, который создается во время загрузки страницы. var regionalOffices = new Array ("New-York", "Chicago", "Houston", "Portland"); Сценарий формы HTML может использоваться для динамического генерирования списка select следующим образом. «script type="text/javascript"> var elem = // начало назначения следующей части страницы и формы elem += "«p>Select a regional office: "; elem += "«select name='offices1 onchange='getData(this.form)'>"; // создание списка опций из массива названий офисов for (var i = 0; i « regionalOffices.length; i++) { elem += "«option"; // дескрипторы для опций if (i == 0) { // предварительный выбор первого элемента списка elem += " selected=1 selected'"; } elem += ">" + regionalOffices[i]; } elem += "«/select>«/p>"; // закрытие дескриптора выбранного элемента document.write(elem); // вывод элемента на страницу «/script> Обратите внимание на один важный момент, касающийся условного оператора цикла for: в JavaScript свойство length извлекается из массива и используется как конечное значение счетчика цикла. С точки зрения кода программы, а также стилистической структуры, этот ме- тод очень удобен для программного определения значений. Если компания добавляет новый региональный офис, то при внесении нового элемента в “базу данных” массива во всем коде программы автоматически выполняются соответствующие изменения, включая появление более длинного всплывающего меню. Также обратите внимание на то, что в условном выражении используется оператор “меньше” («) — это означает, что при изменении индексов массива, начинающихся с нуля, максимальное значение, которое можно использовать в данном цикле, на единицу больше индекса последнего элемента в массиве. Это нужно учитывать, так как переменная счетчика (i) используется как индекс элементов массива regionalOf fices, и при каждой итерации цикла считывается строка, содержащаяся в каждом из этих элементов. Счетчик также ис- пользуется для определения первой опции, после чего выполняется небольшое отклонение от основной программы (с помощью конструкции if), в результате которого в определение первой опции вставляется атрибут selected. Счетчик в цикле for часто влияет на проектируемую структуру данных, например двухмер- ные массивы (см. главу 30), которые используются как базы данных. Всегда помните о меха- низме изменения счетчика в цикле при написании сценариев JavaScript, благодаря которым со- вокупность данных, внедряемых в документы, объединяется в строго упорядоченные структуры. Глава 31. Управляющие структуры и обработка исключительных ситуаций 953
Выход из цикла Некоторые операторы цикла продолжают свою работу до тех пор, пока не будет выполнено некоторое условие. В этом условии указано значение счетчика, при достижении которого работа цикла прекращается. Общая картина действий такова: в цикле обрабатывается массив данных и при этом осуществляется поиск некоторого элемента, соответствующего установленному кри- терию. Проверка критерия проводится с помощью расположенной внутри цикла конструкции if. Если этот критерий выполняется, происходит выход из цикла; работа сценария будет про- должена с выполнения следующих операторов в основном блоке кода. Для выхода из цикла ис- пользуйте оператор break. Ниже показан способ применения оператора break в цикле for. for (var i = 0; i < array.length; i++) { if (array[i].property == magicvalue) { ' операции над элементом array[i] break } } Команда break для компилятора JavaScript означает выход из последнего обрабатывае- мого цикла for (в случае, если несколько циклов вложены друг в друга). Выполнение сцена- рия продолжается с оператора, следующего за закрывающей фигурной скобкой этого цикла. Переменное значение i остается тем же, что и в момент завершения цикла, т.е. в дальнейшем его можно использовать в спенарии для обращения, например, к тому же элементу массива. В главе 22 используется подобная конструкция. В листинге 22.8 представлен набор пере- ключателей, в атрибутах value которых содержатся четыре полных имени. В данной функ- ции с помощью цикла for определяется выбранная пользователем опция, а значение индекса соответствующего элемента после выхода из цикла используется для вывода на экран необ- ходимого сообщения. Описанная функция приведена в листинге 31.2. function fullName(form) { for (var i = 0; i < form.stooges.length; i++) { if (form.stooges[1] .phecked) { break; alert("You chose " + form.stooges[i].value + " } В этой ситуации выход из цикла for применялся не только для того, чтобы прервать ра- боту цикла, так как значение счетчика (оставшееся таким, каким оно было в момент останов- ки) затем используется при вызове различных свойств вне данного цикла. Оператор break имеет дополнительные преимущества при совместном использовании с новым свойством label элементов управления (См. далее в этой главе) Управление циклом с помощью оператора continue Еще одна возможность цикла for состоит возможности пропускать выполнение вложен- ных операторов для выполняемого условия. Другими словами, поскольку в цикле происходит постоянное повторение операторов и выполнение выражений с учетом текущего значения 954 Часть IV. Объекты языка JavaScript
счетчика, можно установить определенное значение счетчика, для которого операторы вы- полняться не будут. Для этого необходимо использовать вложенную конструкцию if, с по- мощью которой и будет осуществляться проверка этого значения. Если условие выполняется, в компилятор JavaScript передается указание немедленно пропустить остальную часть цикла, выполнить оператор обновления, а затем продолжать работу цикла сначала (пропуская ус- ловное выражение в параметрах цикла for). Для того чтобы разобраться в работе данной сложной конструкции, создайте специальный пример, в котором выполнение операций цикла будет пропускаться при достижении пере- менной “несчастливого” значения 13. for (var i = 0; i <= 20; i++) { if (i == 13) { continue; } операторы } В этом примере часть цикла опера торы выполняется для всех значений, кроме 13. С по- мощью оператора continue выполнение цикла “переносится” в область оператора i++, но при этом значение i увеличивается только при следующей итерации цикла. Если использует- ся несколько вложенных циклов for, оператор continue применяется к тому циклу for, в котором “сработала” конструкция if. Оператор continue усовершенствован в NN4+ и IE4+; в него добавлены новые возможности по взаимодействию со свойством 1аЫе эле- ментов управления. (См. далее в данной главе). Цикл while Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Цикл for — не единственный вид циклов в JavaScript. Кроме него, существует оператор while; он работает несколько иначе. В данном случае не проводится изменение значения счетчика, выполнение тела цикла while зависит от заданного в нем условия. Если это усло- вие изначально не выполняется, цикл не используется вообще. Базовый синтаксис цикла while приведен ниже. while (условие) { операторы } Выражение условие подобно тому, которое уже встречалось в конструкции if и в среднем параметре цикла for. При использовании цикла while вначале следует убедиться в том, что в программе выполняется некоторое условие (установленное в true). Тогда в цикле будут выпол- няться соответствующие операции, воздействующие на это условие, до тех пор, пока его значение не станет false. В этом случае произойдет выход из цикла; работа сценария продолжится с опе- раторов, следующих за закрывающей фигурной скобкой цикла. Если значения, проверяемые в опе- раторе условие, в цикле while никак не изменяются, то этот цикл становится бесконечным. В одном сценарии можно использовать циклы как for, так и while. Например, в листин- ге 31.3 (на компакт-диске) цикл for листинга 31.2 преобразован в цикл while. function full Name(form) { var i = 0; while (I form.stooges[i].checked) { Глава 31. Управляющие структуры и обработка исключительных ситуаций 955
} alert("You chose " + form.stooges[i].value + j Всегда помните о следующем: если условие цикла while зависит от значения счетчика этого цикла, то необходимо инициализировать счетчик заранее и управлять его значением в пределах цикла. При необходимости можно использовать управляющие операторы break и continue, ко- торые работают так же, как и в цикле for. По причине того, что в for и while счетчики и условия обрабатываются по-разному, будьте предельно осторожны (выполните неодно- кратное тестирование), применяя в этих циклах операторы break и continue. Не существует определенных правил для определения того, когда и какую конструкцию цикла следует использовать. Обычно циклы while применяют тогда, когда данные или объект, предназначенный для обработки, уже является частью сценария. Другими словами, значения, рассматриваемые в условии, или счетчики циклов (если они необходимы) в этом сценарии уже инициализированы. Если требуется несколько раз подряд вызвать свойства объекта или элементы массива для получения определенных данных и использования их позже в сцена- рии, выберите цикл for. Существует еще одна особенность использования цикла for, в котором программист дол- жен вначале объявить переменную i. Некоторые программисты объявляют (или инициализи- руют, если начальные значения известны) все переменные в начальных операторах сценария или функций. Именно поэтому в сценариях встречается много операторов var. Например, если в функции используется только один цикл for, не произойдет ничего страшного, если счетчик i будет объявлен или инициализирован в начальной части выражения этого цикла (см. предыдущие разделы). Но если в функции используется несколько циклов for, в кото- рых переменная i применяется многократно (т.е. циклы выполняются независимо друг от друга), то ее можно объявить один раз в начале функции и просто назначать новое начальное значение в каждой конструкции. Цикл do-while Совместимость: WinE4+, MacIE4+, NN2+, Mozl+, Safari 1+ В JavaScript существует еще одна конструкция цикла, так называемого do-while. Син- таксис цикла этой конструкции имеет следующий вид. do { операторы } while (условие) Циклы while и do-while существенно отличаются. В конструкции do-while опера- торы выполняются минимум один раз пд>ед тем, как условие будет проверено; а в цикле while, если условие проверено и не соблюдается (false), операторы не выполняются никогда. Используйте цикл do-while, если вы полностью уверены в том, что операторы будут выполнены хотя бы один раз. Если при первом же прохождении цикла условие может не со- блюдаться, используйте цикл while. Во многих случаях обе конструкции взаимозаменяемы, правда do-while совместима не со всеми браузерами, поддерживающими сценарии. 956 Часть IV. Объекты языка JavaScript
Просмотр свойств (цикл for-in) Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ В JavaScript существует некоторая разновидность цикла for — так называемый цикл for- in, с помощью которого можно получить имя и значение любого свойства объекта, расположен- ного в данный момент в памяти браузера. Синтаксис выглядит следующим образом. for (переменная in объект) { операторы } В параметре объект указывают ссылку на объект, а не его строковое имя. Компилятор JavaScript сам генерирует ссылку на объект, если имя объекта не заключено в кавычки, на- пример window или document. Используя переменную переменная, можно создать спе- циальный сценарий и с его помощью вывести на экран любые свойства любого объекта. В листинге 31.4 приведен пример страницы, в сценарии которой содержится вспомога- тельная функция. Данную функцию можно применять в своих документах HTML на стадии разработки и отладки документов в сценариях JavaScript. В этом примере исследуется теку- щий объект window, его свойства выводятся на страницу. <html> <head> <titlex/title> <script type="text/javascript"> function showProps(obj,objName) { var result = ""; for (var i in obj) { result += objName + "." + i + " = " + obj[i] + "<br />"; } return result; } </script> </head> <body> <b>Here are the properties of the current window:</b> <p> «script type="text/javascript"> document.write(showProps(window, "window")); </script> , </p> </body> </html> При отладке можно указать, чтобы результаты отображались в диалоговом окне преду- преждения. Для этого замените дескриптор HTML <br> символом возврата каретки \п, ото- бразив в диалоговом окне предупреждения правильно отформатированный текст. Данную функцию можно вызвать из любого места сценария, опустив и ссылку на объект, и строку для нее. Таким образом, можно идентифицировать объект после выведения результатов в диало- говом окне предупреждения. Функция showProps () может показаться знакомой, так как она очень похожа на приложение The Evaluator (см. главу 13). В главе 45 рассказано о том, как внедрить функциональные возможности The Evaluator в конструкцию страницы, чтобы можно было просмотреть значения свойств при отладке сценариев. Глава 31. Управляющие структуры и обработка исключительных ситуаций 957
Оператор with Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari 1+ С помощью оператора with можно объявить любое количество объектов, которые будут использоваться в сценарии. Таким образом, не стоит указывать полные формальные адреса, чтобы обратиться к свойствам или вызвать методы одного и того же объекта. Синтаксис вы- глядит следующим образом. with (объект) { операторы } Ссылка на объект представляет собой ссылку на любой допустимый объект, в настоящее время содержащийся в памяти браузера. В главе 28 описываются объекты Math и приводится соответствующий пример. Используя некоторые операторы Math в конструкции with, мож- но вызвать свойства и методы без указания объектной части ссылки на каждое свойство и метод. Преимущество структуры with состоит в том, что при ее использовании операторы управления объектами становятся более доступными для чтения и понимания. Обратите вни- мание на приведенную ниже функцию, в которой многократно вызывается один и тот же объект (различные его свойства). function seeColor(form) { newColor = (form.colorsList.options[form.colorsList. selectedlndex].text); return newColor; } Используя структуру with, можно значительно сократить это длинное выражение. function seeColor(form) { with (form.colorsList) { newColor = (options[selectedlndex].text) } return newColor; } Когда компилятор JavaScript сталкивается с неизвестным идентификатором внутри опера- тора with, то осуществляется попытка формирования ссылки вне объекта, а параметрами ссылки являются текущий объект и этот неизвестный идентификатор. Однако нельзя вклады- вать оператор with в другой оператор with (для другого объекта). Например, в предыдущем примере нельзя поместить оператор with (colorsList) внутри with (form) и при этом рассчитывать на то, что будет создана ссылка на основе этих двух имен объектов. Помните, что при использовании данного оператора могут возникать ошибки в формиро- вании самих операторов сценария (так как ссылки в JavaScript генерируются искусственно). Единичное использование данной конструкции существенно не отобразится на работе про- граммы, но если она используется в цикле и выполняется несколько раз, в большинстве слу- чаев скорость обработки данных снизится. Маркированные операторы Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ Использование многократно вложенных циклов может затруднять поиск конечного усло- вия, если оно выполняется глубоко внутри вложенных блоков. Проблема состоит в том, что с помощью операторов break или continue можно обратиться только к наиболее “близкому” уровню циклов. Поэтому даже при выходе из внутреннего цикла, внешний(е) 958 Часть IV. Объекты языка JavaScript
цикл(ы) продолжает(ют) выполняться. Если необходимо выйти из цикла после выполнения указанного условия, используйте оператор return, действие которого аналогично командам выхода в других языках. Если же после выполнения условия необходимо провести некоторую дальнейшую обработку данных в этой функции, в NN4+ и IE4+ предусмотрено средство, с помощью которого в JavaScript блокам операторов можно назначать соответствующие мар- керы. В этом случае операторы break и continue можно применять для маркированных блоков, а не для блоков, в которых содержится данный оператор. Маркер может быть любым идентификатором (именем, которое начинается с символа бу- квы; в нем не должно содержаться никаких пробелов или знаков препинания, кроме символа подчеркивания), сопровождаемым двоеточием. Также маркер должен предшествовать блоку логически выполняющихся операторов — if.. .else или конструкции цикла. Соответст- вующий синтаксис выглядит следующим образом. Маркер-. операторы Для того чтобы применить операторы break или continue к определенной группе опе- раций, к каждому оператору добавьте маркер (как некоторый параметр). break Маркер continue Маркер В листинге 31.5 описаны две версии одной и той же вложенной конструкции цикла, де- монстрирующие, насколько удобен данный метод при правильном использовании. В каждой версии в цикле используются различные переменные индекса, изменяемые до тех пор, пока их значения не будут соответствовать переменным, установленным вне цикла. Когда подоб- ное условие соблюдается (совпадение найдено), работа вложенной конструкции цикла пре- рывается, и обработка продолжается позже. Чтобы помочь вам разобраться в обработке дан- ных, которая происходит в цикле, на экране в текстовой области будут выведены ее промежуточные и конечные результаты. Если совпадение найдено, в варианте без маркеров, выполняется обычный оператор break. Следовательно происходит выход из вложенного цикла, но внешний цикл продолжа- ет работать со следующей итерации. К тому времени, когда будет выполнена вся циклическая конструкция (просмотрены все значения), произойдет немало лишних операций. Кроме того, значения переменных счетчика будут увеличены, так как циклы продолжают выполняться еще несколько раз после нахождения совпадения. В варианте с использованием маркеров выход из вложенного цикла осуществляется из маркированного внешнего цикла, если совпадение найдено. Таким образом обрабатывается гораздо меньшее количество строк программы, а переменные счетчика цикла соответствуют необходимым значениям. В листинге 31.5 проводится эксперимент — оператор break заме- няется оператором continue. Теперь проанализируйте два результата, отображенных в тек- стовой области, и найдите отличия этих двух версий программы. <html> <head> <title>Breaking Out of Nested Labeled Loops</title> «script type="text/javascript"> var targetA = 2; var targetB = 2; var range = 5; function runl() { var out = document.forms[0].output; Глава 31. Управляющие структуры и обработка исключительных ситуаций 959
out.value = "Running WITHOUT labeled break\n"; for (var i = 0; i <= range; i++) { out.value += "Outer loop #" + i + "\n"; for (var j =0; j <= range; j++) { out.value += " Inner loop #" + j + "\n"; if (i == targetA && j == targetB) { out.value += "**BREAKING OUT OF INNER LOOP**\n"; break; } } } out.value += "After looping, i="+i+", j="+j+ "\n"; function run2() { var out = document.forms[0].output; out.value = "Running WITH labeled break\n"; outerLoop: for (var i = 0; i <= range; i++) { out.value += "Outer loop #" + i + "\n"; innerLoop: for (var j =0; j <= range; j++) { out.value += " Inner loop #" + j + "\n"; if (i == targetA && j == targetB) { out.value += "**BREAKING OUT OF OUTER LOOP**\n"; break outerLoop; } } } out.value += "After looping, i = " + i + ", j = " + j + "\n"; } </script> </head> <body> <hl>Breaking Out of Nested Labeled Loops</hl> <hr /> <p>Look in the Results field for traces of these button scripts:</p> <form> <pxinput type="button" value="Execute WITHOUT Label" onclick="runl()" /></p> cpxinput type="button" value="Execute WITH Label" onclick="run2()" /></p> <p>Results:</p> <textarea name="output" rows="43" cols="60"></textarea> </form> </body> </html> Оператор switch Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ В некоторых случаях двоичных значений (истина или ложь) не достаточно для обработки всех операций в сценарии. Свойству object или значению variable может соответство- вать любое из нескольких значений, причем для выполнения каждого из них требуется 960 Часть IV. Объекты языка JavaScript
отдельный способ. Раньше для осуществления данной задачи необходимо было использовать несколько конструкций if ... else. Но чем больше условий необходимо проверить, тем ме- нее эффективной будет программа, так как каждое условие проверяется обязательно. Кроме того, блочная структура операторов и скобок может быть очень громоздкой и запутанной. Во многих языках программирования для решения этой задачи используется специальная управляющая структура, которую разработчики JavaScript добавили в NN4+ и IE4+. Работает этот оператор аналогично подобному оператору в Java и С, в нем используются ключевые слова вариантов выбора и переключателя. Основное преимущество данного оператора — это возможность создания любого количество вариантов ветвления, основанных на значении не- которого выражения. В начале структуры это выражение идентифицируют, а затем для каж- дого варианта выполнения задают маркер, соответствующий получаемому значению. Синтаксис оператора switch выглядит следующим образом. switch (выражение) { case вариант!: операторы [break] case вариант2: операторы [break] [default: операторы) } Параметр выражение оператора switch может принимать любое строковое или число- вое значение. Варианты значений не заключаются в кавычки, даже если они содержат стро- ковые выражения. Обратите внимание на то, что оператор break в данном случае использо- вать необязательно. При указании этого оператора проверка остальных вариантов не осуществляется. Еще одна опция — оператор default, который срабатывает в том случае, ко- гда значение выражения не соответствует ни одному из вариантов case. Если в конструкции всегда справедлив хотя бы один вариант, то последнюю часть конструкции не используют. В листинге 31.6 приведен пример программы, в которой используется оператор switch. На странице представлено два отдельных массива различных категорий изделия. Каждое изделие имеет название и цену, значения которых сохранены в соответствующем массиве. Названия изде- лий выводятся на экран с помощью списка select. Когда пользователь выбирает изделие, в соот- ветствующем массиве сценария выполняется поиск этого изделия, и его цена выводится на экран. Ценность данного приложения состоит в том, что для каждого изделия в списке заданы оп- ределенные значения. На экране пользователь видит название изделия, а в атрибуте value каж- дого дескриптора <option> определяется соответствующий этому изделию элемент массива. Также значение представляет собой выражение, которое используется для определения нужного варианта. Обратите внимание, что маркер назначается для всей конструкции switch. Таким обра- зом, многократно вложенные циклы каждого варианта будут полностью выходить из конструкции switch (с помощью маркированного оператора break) каждый раз, когда будет найдено выра- жение, соответствующее заданному в условии. Эту программу можно дополнить любыми эле- ментами массивов изделий, указав дополнительные операторы case для расширения структуры. <html> <head> <title>Switch Statement and Labeled Break</title> «script type="text/javascript"> Глава 31. Управляющие структуры и обработка исключительных ситуаций 961
// создание двух массивов товаров, // эмулирующих таблицы базы данных function product(name, price) { this.name = name; this.price = price; } var ICs = new Array(); ICs[0] = new product("Septium 900MHz","$149"); ICs[l] = new product("Septium Pro 1.0GHz","$249"); ICs[2] = new product("Octium BFD 750MHz","$329"); var snacks = new Array(); snacks[0] = new product("Rays Potato Chips","$1.79"); snackstl] = new product("Cheezey-ettes","$1.59"); snacks[2] = new product("Tortilla Flats","$2.29"); // просмотр 'таблицы', связанной с товаром function getPrice(selector) { var chipName = selector.options[selector.selectedlndex].text; var outField = document.forms[0].cost; master: switch(selector.options[selector.selectedlndex].value) { case "ICs": for (var i = 0; i < ICs.length; i++) { if (ICs[i].name == chipName) { outField.value = ICs [i] .price; break master; } } break; case "snacks": for (var i = 0; i < snacks.length; i++) { if (snacks[i].name == chipName) { outField.value = snacks[i].price; break master; } } break; default: outField.value = "Not Found"; } } </script> </head> <body> «bsBranching with the switch Statement«/bs <hr /> Select a chip for lookup in the chip price tables: «forms Chip:<select name="chips" onchange="getPrice(this)"s <optionx/option> «option value="ICs">Septium 900MHz</option> «option value="ICs">Septium Pro 1.0GHz«/options «option value="ICs"sOctium BFD 750MHz«/option> «option value="snacks">Rays Potato Chips«/options «option value="snacks">Cheezey-ettes«/option> «option value="snacks">Tortilla Flats«/option> «optionsPoker Chipset«/options «/selects&nbsp; Price:«input type="text" 962 Часть IV. Объекты языка JavaScript
name="cost" size="10" /> </form> </body> </html> Обработка исключительных ситуаций Тема обработки исключительных ситуаций является относительно новой в JavaScript, хотя она и описана в 3-м издании стандарта ЕСМА-262. Частично данный механизм осуществлен в IE5, а его более полная версия — в IE6 и NN6, а также Mozilla и Safari. Исключительные ситуации и ошибки Любой программист, создавая сценарии, помнит об ошибках в JavaScript — это могут быть как синтаксические ошибки в коде программы, так и ошибки при выполнении програм- мы, которые происходят во время обработки информации компилятором. Идеально, когда в программе определяется факт происхождения ошибки, и она обрабатывается настолько “аккуратно”, насколько это возможно. При таком “самоизлечении” можно предотвратить по- терю данных (это не так уж сложно в Web-приложениях), и уберечь пользователей от появле- ния на экране сообщений об ошибках. В главе 16 уже упоминалось об обработчике событий onerror (и свойстве window. onerror), с помощью которых в сценариях задается опреде- ленный уровень контроля над ошибками во время выполнения программы. Этот механизм управления событиями используется на глобальном уровне (т.е. в объекте window); в нем обрабатывается каждая ошибка, которая происходит на странице. Этот обработчик событий применялся прежде всего, как последняя защита от вывода пользователю любого сообщения об ошибках, и представлял действенный способ обработки исключительных ситуаций. Термин исключение, как правило, означает что-то необычное или аварийно происходящее. Это определение, казалось бы, имеет мало общего со словом “ошибка”. Но в языках про- граммирования эти два слова обладают близкими значениями. Разница между ними зависит прежде всего от принимаемой точки зрения. Рассмотрите простой сценарий, в котором вычисляется произведение чисел, вводимых пользователем в два текстовых поля на странице. Как и предполагается, результаты выводят- ся в третьем текстовом поле. Если в сценарии не предусматривается никакой проверки на правильность введенных данных, то будет проводиться попытка умножения любых значений, введенных в текстовые поля. Если пользователь вводит два числа, сценарий выполняется нормально, даже при том, что значения свойств value двух текстовых полей являются стро- ковыми; в строковых значениях содержатся числа' которые могут быть преобразованы в чи- словой тип данных, пригодный для умножения. В данной ситуации результат умножения двух чисел вычисляется и выводится на экран. Что же произойдет, если пользователь введет в одно из текстовых полей символ? Если в сценарии не осуществляется никакой проверки правильности введенных данных, на этот вопрос в JavaScript будет дан такой ответ: результат умножения — постоянная NaN (не явля- ется числом). Это загадочное NaN указывает на то, что произошла некоторая ошибка. Тут мож- но обвинять компьютер, а можно и самого себя. Сценарий был разработан в расчете на тех пользователей, которые никогда не делают ошибок при вводе (намеренно или нет). Однако пользователи допускают ошибки, поэтому предусмотреть вводимые пользователем данные, которые не подходят для выполнения опе- раций над ними (также исключения из правил, с которыми пытается работать написанная программа) — прямая обязанность программиста. Необходимо разработать дополнительный Глава 31. Управляющие структуры и обработка исключительных ситуаций 963
фрагмент программы, в котором будут обрабатываться исключительные ситуации, что пре- доставит пользователю возможность исправить введенные данные. В этом дополнительном фрагменте программы обрабатываются нежелательные и оши- бочные данные, введенные пользователем. Итак, в словарях JavaScript и объектной модели документа W3C термины исключения и ошибки взаимосвязаны; они используются при обработке исключительных ситуаций. Как вы вскоре убедитесь, в исключительной ситуации создается объект ошибки, в котором содержится информация об этой ситуации. Поэтому можете смело говорить об исключениях и ошибках как об одном и том же. Механизм обработки исключительных ситуаций Начинающим разработчикам JavaScript (или любой другой среды программирования) зачас- тую трудно сразу понять, как все описанное выше применяется в браузерах. Механизм за- грузки страницы, создания объектных моделей и вызов функций в сценарии с помощью об- работчиков событий (или получателей событий в терминологии W3C DOM) довольно прост. Но большинство действий происходит на втором плане. Например, объект события, который автоматически генерируется при каждом действии события (см. главу 25), кажется, находится “непонятно где”, в то время как функции обработчика вызываются со всеми данными, описы- вающими это событие. После завершения обработки, объект события исчезает, от него не ос- тается ничего, даже воспоминаний. В браузерах, предназначенных для обработки исключительных ситуаций, имеется большее количество необходимого для этого “материала”, который задействуется в сценарии при воз- никновении ошибки. Так как каждый программист наверняка хотя бы один раз сталкивался с ошибкой сценария, то механизм обработки исключительных ситуаций, встроенный в браузе- ры, ему в определенной степени знаком. При возникновении подобной ошибки браузер создает в выделенной ему памяти объект ошибки, в свойствах которого и содержится информация об этой ошибке. Конкретные данные (которые описываются ниже в этой главе) изменяются в зави- симости от версии браузера, но та информация, которая выводится в специальном окне, являет- ся результатом стандартной обработки браузером исключительных ситуаций или ошибок. По- скольку браузеры устаревают, их разработчики делают все возможное для предупреждения и исправления ошибок в сценариях. Например, в NN4+ ошибки выводятся на отдельной консо- ли JavaScript (которую можно вызвать, если ввести в поле адреса javascript: или щелк- нуть на значке ошибки в строке состояния, а также выбрав соответствующую команду в меню Tools (Сервис) NN6 или Mozilla). Пользователи в последнем случае увидят сообщение о воз- никновении ошибки только в строке состояния. В IE4+ для Windows строка состояния исполь- зуется снова, поскольку в ее левом нижнем углу появляется соответствующий значок ошибки: при двойном щелчке на нем на экран выводится подробная информация об этой ошибке. В МасЕ можно совсем отключить отображение сообщений об ошибках выполнения сценария. Safari же вообще не выводит сообщения об ошибках выполнения сценариев (см. главу 45). Истинная же обработка исключительных ситуаций — это нечто большее, чем просто вывод сообщения об ошибке. В результате обеспечивается единственный для сценариев способ приня- тия мер против получения неверных результатов. В идеале все ошибки выполнения программы должны пройти через этот механизм, что упрощает управление в нем исключительными ситуа- циями. Данный механизм также разработан для использования его в сценариях пользователя таким образом, что генерируемые ошибки прекрасно могут обрабатываться и в других частях программы. Другими словами, можно представить механизм обработки исключительных си- туаций как своего рода “обратный канал” взаимодействия одной части сценария с другой. Этот механизм построен на основе двух групп операторов приложений. Первая группа со- стоит из тройки try-catch-finally; вторая — из единственного оператора throw. 964 Часть IV. Объекты языка JavaScript
Использование конструкций try-catch-finally Назначение группы связанных между собой операторов try-catch-finally— это обеспечение управляющей среды, в которой могут запускаться операторы сценария, содер- жащие ошибки выполнения. Подобная задача осуществляется так’ чтобы при возникновении исключительной ситуации, ее обработка проводилась в сценарии, а остальные механизмы управления ошибками, характерные для браузера, не задействовались. Для каждого из трех операторов указывается блок кода, соответствующий следующему синтаксису. try { выполняемые операторы } catch (сведенияОбОшибке) { операторы, выполняемые при справедливости ситуации в блоке try } finally { операторы, выполняемые в любом случае [необязательно] } Каждый блок try должен располагаться на том же уровне вложенности, что и блоки catch и-или finally, т.е. на этом уровне не должно быть никаких других операторов. Например, в функции может использоваться одноуровневая конструкция try-catch, как показано в сле- дующем примере. function myFuncO { try { операторы } catch (е) { операторы } } Но если имеется еще один блок try, расположенный на один уровень ниже, соответст- вующие ему блоки catch и finally также следует располагать на этом более низком уровне. function myFuncO { try { операторы try { операторы } catch (е) { операторы } } catch (е) { опера торы } } Операторы, содержащиеся внутри блока try, включают инструкции, которые, на взгляд пользователя, могут послужить причиной возникновения ошибки выполнения программы из-за неверно введенных пользователем данных, неудачной загрузки какого-либо компонента страни- цы или подобных ошибок. Блок catch предназначен для предотвращения появления сообще- ния об ошибке в браузере (например, в NN6 и Mozilla это может быть консоль JavaScript). Гпава 31. Управляющие структуры и обработка исключительных ситуаций 965
Для получения информации об обработке исключительных ситуаций этого типа сущест- вует специальный термин переход. Когда с помощью какой-либо операции или метода про- водится запуск исключительной ситуации, говорят о “переходе к исключительной ситуации”. Например, если в операторе сценария вызывается метод строкового объекта, а этого метода для данного объекта не существует (возможно, его имя указано с ошибкой), то компилятор JavaScript “переходит к исключительной ситуации”. Некоторые исключительные ситуации имеют имена, в этих именах иногда (но не всегда) содержится важная информация об ошиб- ке. Имя описанной выше ситуации — ТуреЕггог (еще больше доказывает то, что “исключи- тельные ситуации” и “ошибки” невероятно похожи). Но не только в языке JavaScript (IE5+, NN6+ и W3C) существует переход к исключитель- ным ситуациям. В W3C DOM также определяются категории исключительных ситуаций для объектов DOM. Например, согласно W3C DOM 2, метод appendChild() (см. главу 15) может приводить к (или вызывать в терминологии W3C) одной из трех ситуаций. Имя исключительной ситуации Вызывается в случае НIERARCHY_REQUEST_ERR WRONG_DOCUMENT_ERR NO_MODIFICATION_ALLOWED_ERR Если типу текущего узла запрещается иметь дочерние узлы типа newchild, или если добавляемый узел является одним из родительских данного узла Если newChild и текущий узел были созданы из разных документов Если текущий узел предназначен только для чтения Так как исключительные ситуации можно вызвать с помощью метода appendChild(), в идеале оператор JavaScript, который используется для этого, должен располагаться внутри блока try. Работа блока немного необычна. Его формат внешне подобен функции, так как ключевое слово catch сопровождается парой круглых скобок и произвольной переменной, в которой задается ссылка на объект ошибки, а свойства этого объекта заполняются браузером при воз- никновении исключительной ситуации. В одном из таких свойств хранится имя ошибки. По- этому в блоке catch можно исследовать это имя и вызвать некоторую часть программы для обработки различных зарегистрированных ошибок. Для того чтобы понять, как использовать данную конструкцию в своей программе, приве- дем пример гипотетической универсальной функции, с помощью которой можно создать но- вый элемент и добавить его к некоторому узлу. Тип создаваемого элемента и ссылка на роди- тельский узел указываются как параметры. Чтобы предупредить потенциально неправильное использование значений параметра в этой функции, в ней проводится дополнительная обра- ботка ошибок. Таким образом обрабатываются все возможные исключительные ситуации для двух методов DOM: createElement О и appendChild(). Листинг для данной функции выглядит следующим образом. // Общий вариант function attachToEnd(theNode, newTag) { try { var newElem = document.createElement(newTag); theNode.appendChild(newElem); } catch (e) { switch (e.name) { case "INVALID_CHARACTER_ERR" : 966 Часть IV. Объекты языка JavaScript
операторы для обработки ошибки в методе createElement() break; case "RlERARCHY_REQUEST_ERR" операторы для обработки ошибки в методе appendChild( ) break; case "WRONG_DOCUMENT_ERR" : операторы для обработки ошибки в методе appendChild () break; case "NO_MODIFICATION_ALLOWED_ERR" : операторы для обработки ошибки в методе appendChild() break; default: операторы для обработки любой другой ошибки return false; } return true; Отдельный блок catch листинга 31.7 выполняется только тогда, когда исключительная си- туация возникает в одном из операторов в блоке try. Но исключение не обязательно должно быть одним из четырех указанных в блоке catch, это могут быть и ошибки синтаксиса, и лю- бые другие ошибки, которые присутствуют в блоке try. Именно поэтому пользователю предос- тавляется последняя возможность, чтобы обработать совершенно неожиданные ошибки. Работа программиста заключается не только в предупреждении ошибок, но также и в обеспечении правильных способов обработки исключительных ситуаций (независимо от того, будет все это проводиться в диалоговых окнах предупреждения или внутренними средствами). Напри- мер, в случае использования неверного символа в createElement () можно попробовать спасти данные, передаваемые функции attachToEnd (), и повторно вызвать метод, обраба- тывающий полученное значение theNode Восстановленное значение записывается в newTag. Если все эти операции были проведены успешно, блок try будет выполнен без ошибки, при- чем пользователь даже не узнает о том, что в сценарии есть проблема. В блоке finally содержится код, который всегда выполняется после блока try, незави- симо от того, происходит ли в этом блоке переход к ошибке. В отличие от блока catch, в блок finally объект ошибки не передается как параметр, поэтому то, что определяется в блоке try, остается неизвестным. Если блоки catch и finally следуют после блока try, их вы- полнение зависит от того, будет ли сгенерирована исключительная ситуация. Если ни одна исключительная ситуация не возникла, блок finally выполняется после запуска послед- него оператора блока try. Но если в блоке try исключение возникло, выполнение про- граммы начинается с блока catch. После завершения обработки блока catch выполняет- ся блок finally. В среде разработки, в которой программисты получают полный контроль над такими ресурсами, как память, блок finally может использоваться для удаления неко- торых временных элементов, сгенерированных в блоке try (независимо от того, возникает исключительная ситуация в этом блоке или нет). В настоящее время в JavaScript редко ис- пользуют данный вид технического обслуживания, но вам следует знать о программных воз- можностях блока finally в контексте конструкции try-catch-f inally. Исключительные ситуации на примерах Случай, рассмотренный в листинге 31.7, немного идеализирован. Получается, что браузер сообщает о каждой исключительной ситуации так, как это определено в формальной специ- фикации W3C DOM. К сожалению, браузеры вплоть до версий IE6 и NN7, так не делают Глава 31. Управляющие структуры и обработка исключительных ситуаций 967
(пока). В этих браузерах существуют дополнительные соглашения об именовании ошибок и синтаксисе, отличном от используемого в DOM, с помощью которых сообщение об ошибке отображается на экране во время возникновения исключительной ситуации. Совершенно прав тот, кто считает, что все эти несоответствия усложняют обработку исклю- чений, поддерживаемую несколькими браузерами. Даже сообщения о простых ошибках в этих двух версиях браузеров и спецификации W3C DOM могут быть разными. Пока в браузерах не наблюдается особого единодушия в отслеживании исключительных ситуаций, рекомендуется создавать сценарии только для одной из сред браузеров, таких как IE6 для Windows или NN7. Однако один аспект обработки исключительных ситуаций может все-таки применяться в IE5+, NN6 и W3C. Можно воспользоваться преимуществом конструкции try-catch для перехода к собственным исключительным ситуациям; на практике эту методику чаще всего используют в расширенных средах программирования. Переход к исключительным ситуациям Последнее, еще не рассмотренное ключевое слово обработки исключительных ситуаций throw, позволяет использовать специальные средства для управления таким процессом, как проверка правильности введенных данных. В любом месте блока try можно вручную преду- смотреть исключительные ситуации, которые тут же будут обрабатываться в соответствую- щем блоке catch. Более подробно исключительные ситуации описаны выше. Синтаксис для оператора throw имеет следующий вид. throw значение ; Указанное значение может быть любого типа, но рекомендуется применять значение объек- та ошибки (более подробно он описывается далее в этой главе). Любое указанное пользователем значение будет назначено параметру блока catch. Просмотрите следующие два примера. В первом случае это значение является строковым сообщением; во втором — объектом ошибки. В листинге 31.8 рассматривается одно входное текстовое поле для чисел от 1 до 5. После щелчка на кнопке проводится поиск соответствующего символа в массиве, и этот символ вы- водится во втором текстовом поле. Сценарий поиска состоит из двух простых подпрограмм проверки правильности данных, в которых проверяется, является ли введенный символ чис- лом и принадлежит ли это число нужному диапазону. Отслеживание ошибок осуществляется с помощью сценария. Если любое условие ошибки соблюдается, в операторе throw выпол- няется переход к блоку catch. В блоке catch переменной е назначается входной параметр string. Это означает, что указанное в операторе сообщение следует вывести в диалоговом окне предупреждения. Но одиночный блок catch используется не только для проверки двух условий возникновения ошибок (и, очевидно, любых других, добавленных программистом), он также выполняется подобно функциям (т.е. можно использовать ссылку на текстовое поле ввода данных, чтобы получить и выбрать введенный текст, в котором содержится ошибка). постинг 31.8. Вызов строковых , <html> <head> <title>Throwing a String Exception</title> «script type="text/javascript"> var letters = new Array("A","В","C","D”,"E"); function getLetter(fId) { try { var inp = parselnt(fid.value, 10); 968 Часть IV. Объекты языка JavaScript
if (isNaN(inp)) { throw "Entry was not a number."; } if (inp < 1 || inp > 5) { throw "Enter only 1 through 5."; } fid.form.output.value = letters[inp - 1]; } catch (e) { alert(e) ; fid.form.output.value = fid.focus(); fid.select(); } } </script> </head> <body> <hl>Throwing a String Exception»:/hl > <hr /> <form> Enter a number from 1 to 5: cinput type="text" name="inputJ' size="5" /> cinput type="button" value="Get Letter" onclick="getLetter(this.form.input)" /> Matching Letter is: cinput type="text" name="output" size="5" /> c/form> c/body> с/html> Упущение данной программы состоит в следующем: если бы внутри блока try возникла другая исключительная ситуация, значение, переданное блоку catch, было бы объектом ошибки, а не строкой. В таком случае, результат, выведенный в диалоговом окне предупреж- дения, совершенно бессмысленный. Поэтому в конструкциях throw-catch рекомендуется задать объект ошибки. Листинг 31.9 является усовершенствованной версией листинга 31.8, в которой демонстриру- ется возможность создания объекта ошибки, передаваемого в блок catch в операторе throw. <html> <head> <title>Throwing an Error Object Exception</title> <script type="text/javascript"> var letters =/new Array("A","В","C","D","E"); function getErrorObj(msg) { var err = new Error(msg); return err; } function getLetter(fId) { try { var inp = parselnt(fid.value, 10); if (isNaN(inp)) { throw getErrorObj("Entry was not a number."); } if (inp < 1 || inp >5) { throw getErrorObj("Enter only 1 through 5."); Глава 31. Управляющие структуры и обработка исключительных ситуаций 969
} fid.form.output.value = letters[inp - 1]; } catch (e) { alert(e.message); fid.form.output.value = fid.focus(); fid.select(); } } </script> </head> <body> • <hl>Throwing an Error Object Exception*:/hl> chr /> <form> Enter a number from 1 to 5: cinput type="text’' name="input" size="5" /> cinput type="button" value=,,Get Letter" onclick="getLetter(this.form.input)" /> Matching Letter is: cinput type="text" name="output" size="5" /> c/form> c/body> c/html> Единственное отличие блока catch в этой программе состоит в том, что в нем теперь воспринимается свойство message генерируемого объекта ошибки. Таким образом, если внут- ри блока try возникнет другая исключительная ситуация, сгенерированное браузером сооб- щение будет выводиться в диалоговом окне предупреждения. По правде говоря, на этом работа не заканчивается. Если сгенерированная браузером ис- ключительная ситуация и возникает, не всегда сообщение в диалоговом окне предупреждения будет понятно пользователю. В сообщении об ошибках будет, вероятно, указана ошибка син- таксиса либо ошибка введенных данных— наиболее бессмысленное сообщение, которое пользователь часто получает от своей любимой операционной системы. Рекомендуется вы- полнить переход из блока catch так, чтобы исключительные ситуации, “намеренно” созда- ваемые в сценарии, обрабатывались в диалоговых окнах предупреждения, которые определе- ны в этом блоке, но другие типы ситуаций будут обрабатываться иначе. Для этого можно “позаимствовать” одно из свойств объекта ошибки, например, name, чтобы пользовательские сообщения обрабатывались отдельно в блоке catch. В листинге 31.10 с помощью функции getErrorObj () свойству name назначается оп- ределенное пользователем значение последнего созданного объекта ошибки. Имя может быть любым, но лучше не использовать имена исключительных ситуаций, зарезервированных JavaScript или DOM. Но можно же не знать всех этих имен? Да, поэтому старайтесь дать уни- кальное имя своей ошибке. Ниже, в блоке, с помощью конструкции switch выполняется пе- реход для распознавания двух классов ошибок. По причине того, что в IE5 у объекта ошибки отсутствует свойство name, выражение (e.name), указанное в switch, принимает значение undefined, что влечет за собой выполнение случая default всякий раз, когда возникает “родная” исключительная ситуация (необходимо быть внимательным с тем, свойство какого объекта ошибки используется в операторах default). В этом упрощенном примере описы- вается единственная возможная проблема, отличная от тех, которые отслеживаются в блоке try (из-за нее могут возникнуть сложности при загрузке страницы). В данном примере в слу- чае возникновения других ошибок пользователю просто предлагается перезагрузить страницу и повторить свои действия. Суть состоит в том, что в одном блоке catch можно обрабаты- вать неограниченное количество классов пользовательских и системных ошибок. 970 Часть IV. Объекты языка JavaScript
Листинг 31.15, Иеспюмитммые («ггуацде гюлмймтмммшх объектов «html> <head> <title>Throwing a Custom Error Object Exception«/title> «script type="text/javascript"> var letters = new Array("A","В","C","D","E"); function getErrorObj(msg) { var err = new Error(msg); err.name = "MY_ERROR"; return err; function getLetter(fid) { try { var inp = parselnt(fid.value, 10); if (isNaN(inp)) { throw getErrorObj("Entry was not a number."); if (inp < 1 || inp >5) { throw getErrorObj("Enter only 1 through 5."); } fid.form.output.value = letters[inp - 1]; } catch (e) { switch (e.name) { case "MY_ERROR" : alert(e.message); fid.form.output.value = ""; fid.focus(); fid.select(); break; default : alert("Reload the page and try again."); } } ) «/scripts </head> <body> <hl>Throwing a Custom Error Object Exception«/hl> <hr /> «forms Enter a number from 1 to 5: «input type="text" name="input" size="5" /> «input type="button" value="Get Letter" onclick^"getLetter(this.form.input)" /s Matching Letter is: «input type="text" name="output" size="5" /> «/form> </body> </html> Если вам интересно посмотреть, как работает программа, альтернативная коду листинга 31.10, скопируйте файл листинга с компакт-диска себе на жесткий диск и измените последнюю строку блока try так, чтобы в имени массива отсутствовал один из символов. fid.form.output.value = letterfinp]; Это обеспечит неправильную загрузку страницы. Если вводится одно из допустимых значе- ний, скорее всего, на экране появится предупреждение о перезагрузке, а не фактическое сооб- щение объекта ошибки: символ не определен. Пользователи будут благодарны такому подходу. Ниже приведено подробное описание объекта ошибки. Глава 31. Управляющие структуры и обработка исключительных ситуаций 971
Объект ошибки Свойства Методы Error.prototype объектОшибки. toString() объектОшибки. constructor объектОшибки. description объ ектОшибки. f i 1 ename объектОшибки.lineNumber объектОшибки.message объектОшибки. name объектОшибки. number Синтаксис Создание объекта ошибки. var myError = new Error ("сообщение”) var myError = Error ("сообщение”) Доступ к статическому свойству объекта Error. Error.свойство Доступ к методам и свойствам объекта ошибки. Errorobject.свойство | метод ([свойство)] Совместимость: WinIE5+, MacIE-, NN6+, Mozl+, Safaril+ Описание объекта Образец объекта ошибки создается всякий раз, когда возникает исключительная ситуация или программист вызывает любой из типов конструкторов для создания этого объекта. В свойствах экземпляра объекта ошибки содержится информация о природе ошибки в таком виде, чтобы ее можно было просмотреть и соответственно обработать в блоке catch. В IE5 объект ошибки представлен в соответствии с формальным объектом ошибки ЕСМА-262, поэтому в версии IE5 не существует собственного набора свойств, которые не яв- ляются частью стандарта ЕСМА. Эти свойства все еще существуют в IE5.5+, разработка ко- торого также основывалась на указанном стандарте. С другой стороны, в NN6 используются как свойства ЕСМА, так и два собственных свойства. Эти дополнительные свойства нужны для вывода собственного сообщения об ошибке сценария в данном браузере. К сожалению, для разработчиков приложений во всех версиях браузеров не предусмотрено унифицирован- ного способа управления ошибками, поскольку ни одно свойство браузеров не поддерживает объект ошибки. Однако в IE5.5+ и NN6+ есть свойства name и message. Как отмечалось ранее в этой главе, программист может создать объект в любое время при использовании оператора throw, чтобы обеспечить собственную защиту от сбоев (см. описание листинга 31.9 обработки несуществующих в Internet Explorer свойств). 972 Часть IV. Объекты языка JavaScript
Свойства constructor См. строка, constructor (глава 27) description Возвращаемое значение: строка Чтение/Запись Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- B свойстве description содержится строка описания, с помощью которой обеспечива- ется определенный уровень детализации ошибки. Для ошибок, заданных браузером, описание представляет собой тот же текст, который выводится в диалоговом окне ошибки сценария в Internet Explorer. Несмотря на то, что это свойство и продолжает поддерживаться, все же предпочтительнее использовать свойство message. См. также: свойство message. filename lineNumber Возвращаемое значение: строка Чтение/Запись Совместимость: WinIE5+, MacIE-, NN6+, Moz-, Safari- B NN6 свойства filename и lineNumber объекта ошибки используются для обработки собственной внутренней ошибки сценария; эти значения являются частью сообщений об ошибках, которые выводятся на консоли JavaScript, filename представляет собой URL до- кумента, в котором содержится ошибка; lineNumber— номер строки исходного кода опе- ратора, с помощью которой генерируется исключительная ситуация. Эти свойства в JavaScript разработаны так, что при возникновении такой необходимости содержащуюся в них инфор- мацию можно будет использовать для собственной обработки ошибок. О том, как применять эту информацию для вывода сообщений об ошибках, определенных пользователем, речь шла при описании свойства window, error (глава 16). См. также: свойство window. error. message Возвращаемое значение: строка Чтение/Запись Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safaril+ B свойстве message содержится строка описания, которая обеспечивает необходимый уровень детализации ошибки. Для ошибок, заданных браузером, описание представляет со- бой тот же текст, который выводится в диалоговом окне ошибки сценария в Internet Explorer и на консоли NN6+. Эти сообщения более полезны для программистов, чем для пользовате- лей. К сожалению, не существует никаких стандартов для формулировки сообщения для дан- ной ошибки. Поэтому опасно использовать содержимое сообщения в блоке catch как сред- ство обработки определенных видов ошибок. Можно воспользоваться этой возможностью, если разрабатываемый сценарий предназначен для одной платформы браузера, но нет ника- ких гарантий, что текст сообщения для определенной исключительной ситуации не будет из- меняться в следующих версиях браузера. Пользовательские сообщения об ошибках, применяемые в приложении, могут быть напи- саны на доступном пользователю языке, если программист намеревается вывести сообщения на экран (см. листинги 31.8-31.10). См. также: свойство description. Глава 31. Управляющие структуры и обработка исключительных ситуаций 973
name Возвращаемое значение: строка Чтение/Запись Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safaril+ В свойстве name содержится слово, которым определяется тип произошедшей ошибки. Наиболее общий вид ошибки, определяемой в конструкторе new Error (), — Error. В JavaScript ошибки могут быть представлены другими именами: EvalError, RangeError, ReferenceError, SyntaxError, TypeError и URLError. Некоторые из этих типов ошибок не обязательно должны использоваться программистами (они применяются прежде всего при выполнении компилятором JavaScript возложенных на него задач), но некоторые браузеры также используют их в повседневной работе. К сожалению, имеются некоторые не- соответствия в имени, назначенном этому свойству для ошибок сценария. Если JavaScript используется в среде браузера, который поддерживает W3C DOM, неко- торые виды исключительных ситуаций DOM возвращаются с помощью свойства name. Часто браузеры назначают этому свойству собственные типы ошибок, но обычно в этом плане практически все версии браузеров поступают одинаково. Для пользовательских исключительных ситуаций, которые инициируются в сценарии, можно назначить любые имена. Как показано в листингах 31.9 и 31.10, эта информация мо- жет использоваться в блоке catch при обработке разных категорий ошибок. См. также: свойство message. number Возвращаемое значение: число Чтеиие/Запись Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- B IE5+ каждому описанию ошибки или сообщению назначается уникальный номер. Одна- ко использование свойства number влечет за собой некоторые проблемы. Несмотря на то, что разработчики Microsoft задокументировали средства синтаксиса, соответствующие ошибкам выполнения сценариев и их номеров, на практике браузеры Internet Explorer не выводят номера, описанные в документации Microsoft. Это неудобно, поскольку такой номер чаще всего не зави- сит от языка программирования (хотя в блоке catch легче указать номер ошибки, чем описание или сообщение). Свойство number появилось одновременно со свойством description (теперь замененное свойством message), поэтому пока неизвестно, насколько безопасно ис- пользовать значения номеров ошибок в сценариях. См. также: свойство description. Методы toString() Возвращаемое значение.* строка (см. текст) Совместимость: WinIE5+, MacIE-, NN6+, Mozl+, Safaril+ С помощью метода toString для объекта ошибки возвращается строковое описание ошибки. ВIE5 и IE5.5 посредством этого метода возвращается ссылка на этот же объект. В NN6 возвращается строка свойства message, которой предшествует строка Error: (с пробелом после двоеточия). Если необходимо получить удобочитаемое выражение объекта ошибки, ис- пользуют свойство message (а в 1Е5 — description). См. также: свойство сообщения. 974 Часть IV. Объекты языка JavaScript
Операторы JavaScript о о JavaScript существует огромное количество операто- ра^' ров. Это могут быть слова и символы, используемые в выражениях, с помощью которых выполняются операции над одним или двумя значениями для получения определенного результата. Любое значение, над которым оператор выполняет некоторое действие, называется операндом. В выражении мо- жет содержаться один операнд и один оператор (так называе- мый унарный оператор) или два операнда, разделенные одним оператором (бинарный оператор). Во многих операторах ис- пользуются одни и те же символы. Различие операторов за- ключается в их комбинировании и порядке расположения. / Большинство операторов JavaScript появилось ГН еще при разработке первой версии этого языка. « Но, как и следовало ожидать, со временем в словарь добавилось несколько новых опера- торов. В этой главе обратите внимание на ка- тегории операторов, которые указаны в табли- цах совместимости. Если для оператора в его категории существуют определенные ограни- чения, связанные с используемой версией, то они описываются полностью. Категории операторов Для того чтобы упростить восприятие большого количест- ва операторов JavaScript, они были поделены на семь катего- рий. (Автор дает неточное название второй категории, но, по его мнению, это название гораздо лучше передает назначение этой группы в данном языке программирования. — Примен. ред.) В табл. 32.1 приведены все существующие типы операторов. Любое выражение, в котором содержится оператор, в ко- нечном счете принимает некоторое значение. В одних случа- ях с помощью оператора изменяется значение одного из опе- рандов; в других— результатом является новое значение. Даже в простом выражении 5 + 5 используется два целочисленных операнда, объединенных оператором сложения. Данное выражение возвращает зна-
чение 10. Оператор применяется для указания компилятору JavaScript команды, которая должна быть выполнена для определения значения каждого выражения в сценарии. Таблица 32.1. Категории операторов JavaScript Тип Назначение Сравнения Используются для сравнения значений двух операндов, результатом является либо истина, либо ложь (наиболее часто используется в условных инструкциях if... else и конструкциях цикла for) Арифметические Объединяются два операнда для получения одного значения, которое является результатом арифметической или другой операции над ними Присвоения Значение выражения правого операнда присваивается переменной, указанной с левой стороны оператора, иногда с некоторым его изменением (в зависимости от символа, применяемого совместно с этим оператором) Булевы Используются для выполнения булевых операций над одним или двумя булевыми операндами Битовые Применяются для выполнения арифметических действий либо смещения двух операндов в двоичном представлении (основание = 2) Объектные Для определения средств наследования и возможностей определенного объекта перед вызовом его свойств или методов Комбинированные Группа операторов, используемых в особых ситуациях Сравнение двух операндов, которые на первый взгляд выглядят совершенно разными, не является чем-то необычным. В JavaScript важно не то, как выглядят эти операнды, важно их значение. Два совершенно непохожих операнда при сравнении могут оказаться идентичными. ’ Таким образом, выражение, в котором сравниваются два значения fred == 25 возвращает true, если значение, хранящееся в переменной fred после выполнения бо- лее ранней инструкции, равно 25. Операторы сравнения Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ При любом сравнении двух значений в JavaScript результат принимает булево значение true или false. Существует целый ряд операторов сравнения, которые можно выбрать в зависимости от действия, необходимого для выполнения над двумя операндами. В табл. 32.2 приведены все операторы сравнения. ГТЛиии 3U. Oneprofw Сравнен*» ы *пк U С . »-•-. . 1 Синтаксис Название Типы операндов Результаты == Равенство Все ! = Неравенство Все === Строгое равенство Все Булев Булев Булев (IE4+, NN4+, W3C) 976 Часть IV. Объекты языка JavaScript
Окончание табл. 32.2 Синтаксис Название Типы операндов Результаты i == Строгое неравенство Все Булев (IE4+, NN4+, W3C) > Больше чем Все Булев >= Больше .или равно Все Булев < Меньше чем Все Булев <= Меньше или равно Все Булев При использовании числовых значений результат операции будет аналогичен результа- там, получаемым с помощью обычных алгебраических преобразований. Ниже приведены не- которые примеры, результат которых может быть не достаточно очевидным. 10 == 10 10 == 10.0 // true // true 9! = 10 // true 9 > 10 // false 9.99 < = 9.98 // false Любым из этих способов можно сравнивать даже строковые значения. "Fred" == "Fred" // true "Fred" == "Fred" // false "Fred" > "Fred" // false "Fred" < "Fred" // true Для того чтобы сравнить два строковых значения, в JavaScript проводится преобразование каждого строкового символа в код ASCII. Каждый символ левого операнда сравнивается с соответствующим символом правого операнда. Для прописных букв код ASCII имеет мень- шее значение, чем для строчных, поэтому прописной букве присваивается меньшее значение, чем строчной. С полной уверенностью можно сказать, что операторы сравнения в JavaScript “чувст- вительны” к регистру. Для сравнения можно также использовать значения свойств объекта, возвращаемые функ- циями обработчиков событий или любыми другими функциями. Обычное сравнение строки, используемое при проверке правильности введенных данных, сводится к проверке наличия в этой строке определенных символов. form.entry.value != " " // true, если в поле задано значение Равенство несоизмеримых типов данных Во всех версиях JavaScript, предшествующих 1.2, при сравнении строкового значения, состоящего из цифр и строковых чисел (например, "123" == 123 или "123" != 123), предполагается, что сравниваться будут соизмеримые значения. В исключительных случаях проводится дополнительное преобразование данных, при этом тип данных оригинала не из- меняется (например, если значения содержатся в переменных). Но обычно ситуация гораздо сложнее, так как другие типы данных, например объекты, необходимо сравнивать в первона- чальном виде. Поэтому для всех версий JavaScript, предшествующих 1.2, используют правила сравнения, приведенные в табл. 32.3. Применение логической схемы, по которой выполняется сравнение (табл. 32.3), требует от программиста предусмотрительности, так как он должен описать все возможные и невоз- можные варианты преобразования типов данных для достижения равенства (даже при том, что исходные значения непосредственно не преобразуются). В этой ситуации рекомендуется Глава 32. Операторы JavaScript 977
провести требуемое преобразование непосредственно в операторе сравнения. Таким образом, лучше четко определить тип сравниваемых значений, например, строковые экземпляры двух значений или их числовые варианты, а не оставлять это компилятору JavaScript. Операнд А Операнд В Внутреннее осуществление сравнения Ссылка на объект Ссылка на объект Сравнение значений ссылок на объект Любой тип данных Пустое значение Проводится преобразование непустого значения в тип объекта и сравнивание с пустым значением Ссылка на объект Строковое значение Проводится преобразование объекта в строку и сравниваются строковые значения Строковое значение Числовое значение Проводится преобразование строкового значения в численное и сравниваются числовые значения Обратное преобразование числа в строку влечет за собой связывание пустой строки с этим числом. var а = "09"; var b = 9; а == " " + Ь; // результат false, так как "09" не равняется "9" Для преобразования строковых значений в числовые существует рад способов. Наиболее простой из них — это вычесть нуль из строки чисел. var а = "09"; var Ь = 9; а — 0 == Ь; // результат true, так как 9 равняется числу 9 Для преобразования строковых значений в числовые можно также использовать функции parselnt() иparseFloat (). var а = "09"; var b = 9,- Parselnt(a, 10) == b; // результат true, так как 9 равняется числу 9 Чтобы избежать двусмысленности внутренних преобразований в JavaScript 1.2, разработ- чики добавили еще два оператора равенства, конкретизирующих ситуацию при сравнении. С помощью операторов строгого равенства (===) и строгого неравенства (! ==) сравниваются и типы данных, и их значения. Единственный случай, при котором оператор === возвращает истинное значение, — это когда два операнда имеют один и тот же тип данных (например оба являются числами) и одно и то же значение. Поэтому автоматически число никогда не будет приравниваться к строковому варианту этого же числа. Перед сравнением значений ти- пов данных’и объектов сначала проверяется их соответствие. Также в JavaScript 1.2 предусмотрены некоторые глобальные функции для преобразова- ния строковых переменных в числовые и наоборот: String () и Number (). Для того чтобы продемонстрировать принцип работы данных методов, в следующих примерах используется опе- ратор typeof для определения типа данных выражений, в которых применены эти функции. typeof 9; // результат: числовое значение typeof String (9); // результат: строковое значение typeof "9"; // результат: строковое значение typeof Number ("9"); // результат: числовое значение Ни в одной из этих функций исходный тип данных преобразуемого значения не изменяет- ся. При сравнении используется значение функции. 978 Часть IV. Объекты языка JavaScript
var a = "09"; var b = 9; a = = String (b); typeof b; Number (a) == b; typeof a; // результат: false, так как "09" не равно "9" 11 результат: все еще число // результат: true, так как 9 равно 9 // результат: все еще строковое значение Этот пример является подтверждением того, насколько важно учитывать соответствие типов данных при проверке равенства двух значений. Арифметические операторы Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Арифметпические операторы — это те операторы, с помощью которых в результате пре- образования двух операндов получается результирующее значение. В табл. 32.4 приведены все вида арифметических операторов в JavaScript. Таблиц* 32А Арифметические операторш JwiScripr Синтаксис Название Типы операндов Результаты + Плюс Целочисленный, с плавающей запятой, строковый Целочисленный, с плавающей запятой, строковый - Минус Целочисленный, с плавающей запятой Целочисленный, с плавающей запятой ★ Умножение Целочисленный, с плавающей запятой Целочисленный, с плавающей запятой / Деление Целочисленный, с плавающей запятой Целочисленный, с плавающей запятой % Взятие по модулю Целочисленный, с плавающей запятой Целочисленный, с плавающей запятой ++ Приращение Целочисленный, с плавающей запятой Целочисленный, с плавающей запятой - Уменьшение Целочисленный, с плавающей запятой Целочисленный, с плавающей запятой +val Положительность Целочисленный, с плавающей запятой, строковый Целочисленный, с плавающей запятой -val Отрицательность Целочисленный, с плавающей запятой, строковый Целочисленный, с плавающей запятой Четыре основных арифметических оператора для чисел известны всем. Оператор “плюс” используется для сложения числовых и строковых значений. "Howdy " + "Doody" // результат "Howdy Doody" В объектно-ориентированном программировании оператор “+” является перегруженным. Это означает, что его действие зависит от контекста. Следует помнить, что при объединении строк никакие дополнительные операции, такие как, например, удаление пробелов между словами или их вставка, не выполняются. В предыдущем примере пробел между названиями является частью первой строки. Глава 32. Операторы JavaScript 979
Определение модуля проводится в случаях, когда необходимо узнать, делится ли одно число на другое без остатка. Этот оператор использовался в предыдущей главе при определе- нии високосности года. Существуют и другие способы определения високосного года, однако в примере просто проверяется, делится ли этот год на четыре нацело. Результатом данной операции является остаток от деления двух значений: если остаток — 0, год делится нацело. Отметим несколько лет, значения которых делят на четыре. 2002 % 4 // результат 2 2003 % 4 // результат 3 2004 % 4 // результат 0 (Ура! Високосный год!) Таким образом, этот оператор использовался в операторе условия if. . .else следую- щей структуры. var howMany = 0; today = new Date(); var theYear = today.getYear(); if (theYear % 4 == 0) { howMany = 29; } else { howMany = 28; } В некоторых других языках предлагается использовать операторы, при применении кото- рых результат представляет собой целую часть от деления: интегральное деление или div. В JavaScript не существует подобных операторов, однако можно осуществить выполняемые ими операции самим (при условии, что используемые операнды — положительные числа). Используйте методы Math, floor () или Math, ceil () и оператор деления. Math.floor (4/3); // результат 1 В этом примере можно указать только числа со значениями большими либо равными 0; в Math. ceil () же .используются только отрицательные значения. Оператор приращения (++) является унарным оператором (только один операнд). Его можно использовать в двух различных случаях, в зависимости от того, с какой стороны рас- положены символы операнда. Операторы приращения и уменьшения (--) могут использо- ваться вместе с операторами присвоения, которые будут описаны позже. Как следует из названия, с помощью оператора приращения проводится увеличение зна- чения операнда на единицу. Но в инструкции присвоения необходимо внимательно следить за тем, когда это увеличение будет осуществляться. При использовании одного знака = значение правого операнда записывается в переменную, указанную слева. Если оператор ++ расположен перед правым операндом (префикс), правый операнд увеличивается перед записью его значения в переменную; если оператор ++. расположен после правого операнда (постфикс), предыдущее значение операнда передается в переменную прежде, чем значение будет увеличено. Рас- смотрим следующий пример, чтобы лучше понять разницу между этими двумя ситуациями. var а = 10; //а инициализируется равным 10 var z = 0; // z инициализируется равным 0 z = а,- // а = 10, следовательно и z = 10 z = ++а; // а = 11 перед присвоением, // а = 11 и z становится равным 11 z = а++; // а = 11 перед присвоением, // таким образом z = 11; а = 12 z = а++; // а = 12 перед присвоением, // таким образом z = 12; а = 13 Оператор уменьшения работает аналогично, за исключением того, что значение операнда уменьшается на единицу. Операторы приращения и уменьшения наиболее часто используются 980 Часть IV. Объекты языка JavaScript
в счетчиках циклов for и while. Простая конструкция ++ или -- более компактна, чем пе- реназначение переменной с прибавлением к ней 1 (z = z + 1 или z *= 1). Так как эти операторы унарные, их можно использовать без инструкции присвоения при изменении зна- чения переменной счетчика цикла. function doNothingO { var i = 1; while (i < 20) { } alert(i); // отображение при i = 20 } Последние два арифметических оператора также являются унарными (работающими с од- ним операндом). И положительный, и отрицательный операторы могут использоваться в гло- бальной функции Number () для преобразования строкового операнда, состоящего из символов чисел, в числовой тип данных. Строковый операнд не изменяется, но после выполнения послед- ней операции возвращается значение числового типа, как показано в следующем фрагменте. var а = "123"; var Ь = +а; // Ь теперь = 123 typeof а; // результат: строковое значение typeof b; // результат: числовое значение У оператора отрицания (-val) существует дополнительная возможность. При помещении знака перед любым числом (без пробела между символом и значением) компилятор JavaScript преобразует указываемое положительное значение в отрицательное и наоборот. При этом значение операнда не изменяется, но выражение возвращает измененное значе- ние (см. следующий пример). var х = 2; var у = 8; var z = -х; // z равно -2, ax все еще 2 z = — (х + у); // z равно -10, ах—2иу—8 z = -х + у; // z равно 6, а х все еще 2 и у — 8 Для того чтобы сделать отрицательным булево значение, следуйте описанию булевых операторов, в частности, оператора Not (!). Операторы присвоения Совместимость: WinE3+, MacIE3+, NN2+, Mozl+, Safari 1+ Операторы присвоения — наиболее часто встречающиеся инструкции в сценариях JavaScript. Они применяются во всех случаях, когда проводится копирование значений или результатов выражения в переменную для использования этого значения в дальнейшем. Значения присваиваются переменным по многим причинам, даже тогда, когда можно ис- пользовать оригинальные значения или выражения в одном сценарии несколько раз. Далее приводится ряд причин, по которым переменным присваиваются различные значения. Имена переменных обычно короче. Имена переменных более наглядны. Может возникнуть необходимость сохранения оригинального значения для дальней- шего его использования в сценарии. Оригинальное значение является свойством, которое нельзя изменить. Многократный вызов в сценарии одного и того же метода неэффективен. Глава 32. Операторы JavaScript 981
Начинающие программисты часто игнорируют последнюю причину. Например, если с по- мощью сценария создается HTML-код нового документа, то более эффективно поместить стро- ку, состоящую из больших фрагментов страницы, в одну переменную перед вызовом метода document .write () для отображения на экране этого текста. Это гораздо удобнее, чем выво- дить HTML-документ по одной строке, при этом многократно вызывая операторы docu- ment . writein (). В табл. 32.5 приведены операторы присвоения, используемые в JavaScript. Синтаксис Название Пример Операция = Равенство X = У X = у += Добавление значения X += У X = X + У -= Вычитание значения X -= У X - X - у 1 * — Умножение на значение X *= У X = X * У /= Деление на значение X /= У X = X / У %= Взятие значения по модулю X %= у X = X % у << = Сдвиг влево на значение X «= у X = X « у >= Сдвиг вправо на значение X >= У X = X > У >>= Заполнение значения нулями X »= У X = X » У »>= Сдвиг вправо на значение X »>= у X = X »> у &= Побитовое И X &= у X = X и у 1= Побитовое ИЛИ X 1= У X = X 1 У Побитовое исключающее ИЛИ X л= У X = X У Как можно заметить в группе операторов, рассмотренных ранее (и в группе, которая опи- сывается далее в этой главе в разделе “Побитовые операторы”), используя операторы присвое- ния и простой знак “=”, в коде можно эффективно представить сложные операции, особенно, если обрабатывается несколько значений, которые необходимо объединить в последующих инструкциях. В предыдущих главах вам уже встречались примеры, в которых оператор при- ращения (+=) использовался при преобразовании строки в длинную строковую переменную, которая в конечном счете передавалась в метод document. write (). Ниже приведен фраг- мент листинга 37.3 с некоторыми изменениями. В данной программе можно использовать сценарии JavaScript для создания содержимого элемента select. var elem = " "; // вызов следующей части страницы и формы elem + = " <p>Select a regional office: elem + = " <select name = ’offices' onchange = ’getData(this.form)' >"; // формируется список опций из массива названий офисов for (var i = 0; i < regionalOffices.length; i ++) { elem + = " <option"; // дескрипторы OPTION if (i == 0) { // первый элемент в списке elem + = " selected"; } elem + = ">" + regionalOffices [i]; } elem + = "</select></p>"; // закрытие дескриптора элементов select document.write (elem); // отображение элементов на странице 982 Часть IV. Объекты языка JavaScript
Фрагмент сценария начинается с использования оператора присвоения, с помощью которого переменная elem инициализируется как пустая строка. Во многих строках используется опера- тор приращения для прибавления строкового значения к тому, которое содержится в перемен- ной elem в данный момент. Без оператора приращения пользователь вынужден применять про- стой оператор присвоения в каждой строке программы, (чтобы связать новые строковые данные с уже существующими). В этом случае начало программы будет выглядеть следующим образом. var elem = ""; // вызов следующей части страницы и формы elem = elem + " <p>Select a regional office: elem = elem + " <select name = 'offices' onchange = 'getData (this.form)'; В цикле for из-за многократного повторения elem+ код становится тяжелым для пони- мания, отладки и обновления. Такие усовершенствованные операторы присвоения являются более краткими, поэтому их спокойно можно использовать в циклах. Булевы операторы Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safari 1+ В программировании логическая арифметика играет довольно важную роль. Мы приво- дили примеры, в которых программы принимают решения, основываясь на том, возвращает ли оператор или выражение булево значение true либо false. Зато нечасто встречались примеры объединения нескольких булевых значений и выражений, так как подобные сцена- рии относятся к сценариям высокого уровня сложности. В различных условных выражениях, повсеместно используемых в JavaScript (подобных тем, которые применяются в конструкциях if), условие, которое должно проверяется в программе, может быть более сложным чем, скажем, сравнение значения переменной с некоторым установ- ленным значением или проверка на существование в поле пустого значения. Например, часто проверяют, содержит ли выражение, введенное в текстовое поле, все числа, необходимые для обработки в сценарии. Если бы в JavaScript не было специальной функции для вывода сообще- ния о содержимом введенной строки, программисту пришлось бы рассматривать каждый вве- денный символ по отдельности и исследовать, принадлежит ли он к диапазону 0-9. Данную операцию можно выполнить двумя способами: проверить все символы, значение ASCH которых меньше 0 или больше 9. Также можно проверить, является ли символ большим или равным О и меньшим или равным 9. В результате необходимо сравнить результаты обоих тестов. Булева математика Перейдем к особенностям булевой математики. Имея в наличии всего два значения true и false, можно обработать строку выражений, результаты которых являются булевыми, а затем с помощью булевой арифметики выяснить, является результат истиной или ложью. Однако булевы значения не прибавляют и не отнимают, как прибавляют и отнимают обыч- ные числа. Вместо этого используют один из трех булевых операторов JavaScript. В табл. 32.6 приведен синтаксис булевых операторов. Если пользователю не знакомы некоторые символы в таблице, отметим, что символы для оператора ИЛИ получены комбинацией <Shift+/>. Использование булевых операторов с булевыми операндами представляет некоторую сложность для тех, кто не сталкивался с ними ранее, поэтому начнем с наиболее простого оператора: Not (НЕТ). Для него необходим только один операнд. Оператор НЕТ располага- ется перед любым булевым значением, таким образом “переключая его” в значение, противо- положное по знаку (true в false или false в true). Глава 32. Операторы JavaScript 983
Таблица32.6.Булевыоператоры JavaSwipt Синтаксис Название Операнды Результаты && И Булевы Булевы II ИЛИ Булевы Булевы 1 НЕТ Один булев Булевы !true // результат: false !(10 > 5) // результат: false !(10 < 5) // результат: true !(document.title == "Flintstones") // результат: true Как видно из примера, заключение операнда выражения Not в круглые скобки никогда не бывает лишним, так как при наличии скобок компилятор JavaScript оценивает взятое в них выражение перед тем, как изменить его согласно оператору Not. С помощью оператора И (&&) два булевых значения складываются; результатом этого сло- жения может быть true или false, что зависит от значений обоих операндов. Существует так называемая таблица истинности, в которой расписаны результаты всех возможных комбина- ций значений операндов. Далее приведена таблица истинности для оператора И (табл. 32.7). Таблица 32.7. Левый операнд Оператор И Правый операнд Результат Истина && Истина Истина Истина && Ложь Ложь Ложь && Истина Ложь Ложь && Ложь Ложь Результат true можно получить только в одном случае — когда оба операнда имеют зна- чение true. Сторона, с которой расположен оператор true или false, не имеет никакого значения. Далее приведены примеры для каждого из рассмотренных случаев. 5 > 1 && 50 > 10 // результат: true 5 > 1 && 50 < 10 // результат: false 5 < 1 && 50 > 10 // результат: false 5 < 1 && 50 < 10 // результат: false . Совершенно обратное происходит с оператором ИЛИ (| |): результат true получить го- раздо легче, чем false, true возвращается в любом случае, когда хотя бы один из операн- дов (или оба) имеют истинное значение. Таблица истинности для оператора ИЛИ приведена далее (табл. 32.8). Левый операнд Оператор ИЛИ Правый операнд Результат Истина 1 1 Истина Истина 1 1 Ложь Ложь 1 1 Истина Истина Истина Истина Ложь 1 1 Ложь Ложь 984 Часть IV. Объекты языка JavaScript
Если с обеих сторон оператора указано выражение, значение которого true, результатом также будет истинное значение. Попробуйте изменить в предыдущих примерах операторы И на ИЛИ и посмотрите, как это скажется на результатах. 5 > 1 || 50 > 10 // результат: true 5 > 1 || 50 < 10 // результат: true 5 < 1 || 50 > 10 // результат: true 5 < 1 || 50 < 10 //.результат: false Оператор ИЛИ возвращает false только тогда, когда оба операнда имеют ложное значение. Применение булевых операторов Применение булевых операторов в JavaScript первый раз занимает некоторое время, тем более что приходится предварительно провести вычисления на бумаге (чтобы разобраться в логической схеме выражений). Ранее уже говорилось об использовании булевых операто- ров, когда необходимо выяснить, попадает ли символ в диапазон значений ASCII для провер- ки правильности ввода данных. В листинге 32.1 представлена функция, используемая далее в главе 43. С помощью этой функции проверяется значение ASCII каждого символа указан- ной строки. Если оно меньше 0 или больше 9, то во введенной строке не содержатся цифры. Листинг 3?. 1. Являет*,я rw аде денное значение цифрой? function isNumber (inputstr) { for (var i = 0; i < inputstr.length; i++) { var oneChar = inputstr.substring (i, i + 1); if (oneChar < "0" || oneChar > "9") { alert ("Please make sure entries are numerals only."); return false; } } return true; _}______________________________________________________________ Для того чтобы считать по одному символу (подстроке) из объекта string, используемо- го в цикле for, необходимо указать нужное условие в конструкции if. (oneChar < "0" || oneChar > "9") В этом выражении используется оператор ИЛИ для проверки обоих условий. Если приме- нить к данному выражению таблицу истинности ИЛИ (табл. 32.8), получим, что результат true будет возвращен (хотя бы одно условие должно быть истинным). После этого пользо- ватель получит сообщение о возникшей проблеме; вызывающий проверку оператор получит значение false. Функция возвратит значение true только в том случае, если оба условия, указанные в выражении, примут значение false для всех символов строки. От простого оператора ИЛИ перейдем к более сложным операциям. В функции (а точнее, в одном условии) проверяется отношение числа к нескольким числовым диапазонам. Сцена- рий, описанный в листинге 32.2, является фрагментом приложения поиска массивов (см. гла- ву 50), в котором пользователь вводит первые три символа номера социального страхования. Листинг 32.2. Проверка принадлежности номера одному из диапазонов // функция проверки принадлежности значения диапазону function inRange (inputstr) { num = parselnt (inputstr) if (num < 1 || (num > 586 && num < 596) || (num > 599 && num < Глава 32. Операторы JavaScript 985
700) || num > 728) { alert ("Sorry, the number you entered is not part of our database. ") ; return false; } return true; Во время вызова данной функции введенные пользователем данные одновременно проверя- ются в JavaScript на принадлежность к числовому типу данных. Теперь в функции необходимо проверить, относится это число к одному или нескольким диапазонам, которые отдельно представ- лены в приложении. Далее описаны условия, проверяемые в функции. Число не должно быть: меньше 1; больше 586 и меньше 596 (использование оператора И); больше 599 и меньше 700 (использование оператора И); больше 728. Каждое из этих условий объединено в одно с помощью оператора ИЛИ. Если какое-либо из этих условий принимает значение true, вся конструкция if принимает истинное значе- ние, и пользователь получает соответствующее сообщение. Вместо объединения такого количества булевых выражений в одном условии можно создать несколько вложенных конструкций if. Но недостатком подобной конструкции будет не только ее громоздкость, в случае “провала” одного из условий, для каждого из них в диалоговом окне будет выводиться собственное предупреждение. Объединенное булево условие намного эффективнее. Побитовые (или поразрядные) операторы Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Для программистов побитовые операции представляют собой довольно обширную тему. Если программист не работает с внешними процессами на CGI-сервере или подключенными аплетами Java, маловероятно, что он когда-либо будет использовать побитовые операторы. Опытные программисты, которые интересуются специфическими типами данных (например long integer), детально разбираются в этой области, поэтому остается только предоставить описание возможностей JavaScript. В табл. 32.9 приведены побитовые операторы JavaScript. Таблица 32.9.Побитовые ЛнвЗслИ » Оператор Название Левый операнд Правый операнд & Побитовое И Целочисленное значение Целочисленное значение 1 Побитовое ИЛИ Целочисленное значение Целочисленное значение Побитовое исключающее ИЛИ Целочисленное значение Целочисленное значение Побитовое НЕТ (Нет) Целочисленное значение « Смещение влево Целочисленное значение Количество разрядов, на которое проводится смещение >> Смещение вправо Целочисленное значение Количество разрядов, на которое проводится смещение >>> Заполнение нулями при смещении вправо Целочисленное значение Количество разрядов, на которое проводится смещение 986 Часть IV. Объекты языка JavaScript
Числовые значения операндов могут располагать любым из трех числовых литеральных базисов в JavaScript (десятичные числа, восьмеричные или шестнадцатеричные). Как только оператору указывается операнд, значение преобразуется в двоичное представление (длиной 32 бита). Для первых трех побитовых операций биты одного операнда сравниваются с соответ- ствующими битами другого операнда. Конечное значение каждого бита зависит от оператора. Побитовое И. 1, если оба символа — 1. Побитовое ИЛИ. 1, если хотя бы один из символов — 1. Побитовое исключающее ИЛИ. 1, если только один символ — 1. Побитовое НЕТ является унарным оператором, с помощью которого инвертируют значе- ние каждого бита в одиночном операнде. Побитовые операторы смещения управляют только одним операндом. Вторым операндом определяется число позиций, на которое смещаются двоичные значения разрядов в направлении стрелок оператора. Пример Применение оператора смещения влево (<<) влечет за собой следующий результат. 4 << 2 // результат 16 Это объясняется тем, что двоичное представление десятичного числа 4 имеет вид 00000100 (в любом случае, восемь разрядов). Использование оператора смещения влево для компилятора JavaScript означает, что необходимо сдвинуть все символы на два разряда влево. Результат данной операции будет 00010000 (в десятичном формате ему соответствует число 16). Если кого-нибудь заинтересовали эксперименты с этими операторами, используйте при- ложение The Evaluator (глава 13) для вычисления типовых выражений. Также вам будут инте- ресны книги по программированию на С и C++. Объектные операторы Для работы со следующей группой операторов используются объекты (включая пользова- тельские объекты, объекты JavaScript или DOM) и типы данных. Большинство из них осуще- ствлено уже после выхода первого браузера, поддерживающего JavaScript, таким образом, для каждого из них представлена собственная оценка совместимости. delete Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Для объектов массивов не существует метода, с помощью которого можно было бы уда- лить отдельный элемент, также для пользовательских объектов не представлено 'метода удаления свойств. Можно удалить данные в элементе массива или свойстве, указав пустую строку или пустую ссылку, но после этого элемент массива или свойство все равно останутся в объекте. С помощью оператора delete можно полностью удалить элементы и свойства. Помните о важном моменте, который имеет место при удалении элемента массива. Если в массиве используются числовые индексы, при удалении элемента массива удаляется и его индекс из полного массива, однако массив не “нарушается” (т.е. индексы элементов, распо- ложенных выше удаленного элемента, не изменяются). Пример Рассмотрим следующий простой массив. var oceans = new Array("Atlantic", "Pacific", "Indian","Arctic"); В этом массиве числовые индексы автоматически назначаются указанным элементам для дальнейшего обращения к ним в различных конструкциях (например, в цикле for). Глава 32. Операторы JavaScript 987
for (var i = 0; i < oceans.length; i++){ if (oceans[i] == form.destinatiop.value){ опера торы } } Если использовать выражение delete oceans[2]; в массиве произойдут существенные изменения. Сначала третий элемент массива будет уда- лен. Заметьте, что длина массива не изменится. После индекса (2) удаления из массива этот массив будет выглядеть следующим образом. oceans[0] = "Atlantic"; oceans[1] = "Pacific"; oceans[3] = "Arctic"; Если попробовать обратиться по ссылке oceans [2], результат будет undefined. Рекомендуется применять оператор delete в массивах с именными индексами. Таким образом будет легче контролировать остающиеся элементы и их значения, поскольку в дан- ном случае не имеет значения, отсутствует определенный числовой индекс или нет. Еще один аспект подобного удаления элементов — в JavaScript не обеспечивается абсо- лютный контроль за использованием памяти. Вся очистка ненужных данных из памяти про- водится с помощью ядра JavaScript, в результате чего принимается автоматическое решение, когда можно очистить память от расположенных в ней элементов, и когда неиспользованная прикладная память браузера должна восстанавливаться. Однако вы не сможете заставить браузер выполнить задачу очистки памяти вручную. in Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safaril+ C помощью оператора in можно проверить, имеет ли объект именованные свойства или методы. Операнд, указываемый слева от оператора, представляет собой строковую ссылку на свойство или метод (только имя метода без скобок); правый операнд — исследуемый объект. Если указанное свойство или метод присутствует в объекте, выражению возвращается значе- ние t rue. Таким образом можно применить оператор in в условных выражениях. Пример Поэкспериментируйте с этим оператором в приложении The Evaluator. Например, чтобы доказать, что метод write () доступен для объекта document, введите в верхнее текстовое поле следующее выражение. "write" in document Сравните работу метода document. createAttribute () в W3C DOM для IE5.5 и NN6. "createAttribute" in document В NN6 результатом будет true, а в IE5.5 — false. Используя этот оператор в условных выражениях, можно определить поддержку объекта в коде программы. Например, если программист намеревается использовать в своем сценарии метод document. createAttribute (), он предварительно должен удостовериться в том, что данный метод поддерживается (предполагается, что в браузерах всех пользователей опе- ратор in поддерживается). 988 Часть IV. Объекты языка JavaScript
instanceof Совместимость: WinIE5+, MacIE-, NN6+, Mozl+, Safaril+ C помощью оператора instanceof можно проверить, относится ли объект к модели JavaScript или DOM (NN6). Операнд, указываемый слева от оператора, представляет собой проверяемое значение; операнд, указываемый справа от оператора, — ссылку на корневой класс, в котором, возможно, содержится созданное значение. Для родных классов JavaScript в ссылках, указываемых справа от оператора, могут указы- ваться такие статические объекты, как Date, String, Number, Boolean, Object, Array и RegExp. Иногда необходимо помнить, что родные классы JavaScript могут быть дочерними для других родных классов, а это означает, что значение может быть экземпляром двух раз- личных статических объектов. Пример Рассмотрим следующий фрагмент программы (который можно исследовать в приложении The Evaluator). а = new Array(1,2,3); a instanceof Array; Второе выражение выдает результат true, так как конструктор Array использовался для генерирования объекта. Но Array в JavaScript сам является образцом корневого объекта Obj ect. Поэтому оба следующих выражения принимают значения true. instanceof Object; Array instanceof Object; new Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Многие объекты среды JavaScript имеют функции-конструкторы, встроенные в язык. Для обращения к этим функциям используют оператор new вместе с именем конструктора. В функ- ции возвращается ссылка на экземпляр объекта, который может быть использован в сценарии для получения, и установки свойств или вызова методов объекта. Например, при создании объекта даты today необходимо вызвать конструктор объекта Date следующим образом. var today = new Date(); В некоторых конструкторах создания объектов запрашиваются определенные параметры. В других, как в случае с объектом Date, можно использовать различные форматы парамет- ров, в зависимости от той информации, с помощью которой необходимо организовать исход- ный объект. Оператор new может использоваться со следующими объектами базового языка. JavaScript 1.0 JavaScript 1.1 JavaScript 1.2 JavaScript 1.5 Date Object (Пользовательский объект) Array Boolean Function RegExp Error Number String Глава 32. Операторы JavaScript 989
this Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ B JavaScript существует ключевое слово; с его помощью в операторе сценария можно об- ращаться к объекту, в котором эти инструкции расположены. Этот оператор, “обращающийся сам к себе”, — this. Наиболее часто он используется в обработчиках событий, в которых ссылки на себя пере- даются в функции для дальнейшей их обработки. cinput type="text" name= "entry" onchange= "process (this) "> В функции переданное значение назначается переменной, которая может использоваться для обращения к отправителю, свойству или методу. Пример Поскольку с помощью оператора this проводится обращение к объекту, к свойствам этого объекта также можно обращаться, используя его. Например, для того чтобы передать свойство value текстового объекта в функцию, оператор this задается в текущей ссылке на объект, и в ней же осуществляется обращение к свойству value. cinput type="text" name="entry" onchange="process(this.value)"> Оператор this можно также использовать внутри других объектов, например, пользова- тельских. Данная возможность часто практикуется при определении функции-конструктора пользовательского объекта, оператор this применяют для определения свойств этого объек- та и указания их значений. Рассмотрим следующий пример создания объекта. function bottledWater(brand, ozSize, flavor) { this.brand = brand; this.ozSize = ozSize; this.flavor = flavor; } var myWater = new bottledWater("Crystal Springs", 16, "original"); При создании нового объекта с помощью функции-конструктора операторы this опре- деляют каждое свойство объекта, после чего им назначаются соответствующие начальные значения. Довольно удобно использовать одинаковые имена для свойств и переменных пара- метров, это заметно облегчает работу с конструктором. Кроме того, если функция назначается как свойство объекта (и работает подобно методу объекта), с помощью оператора this внутри этой функции выполняется обращение к объекту, вызывающему функцию (таким образом открывается возможность доступа к свойствам объек- та). Например, если добавить следующее определение функции и выражение к только что созданному объекту myWater, функция может обратиться к свойству этого объекта brand. function adSlogan() { return "Drink " + this.brand + ", it's wet and wild!"; } myWater.getSlogan = adSlogan; При вызове метода myWater. getSlogan () в объекте вызывается функция adSlogan (), но в контексте объекта myWater. Таким образом, оператор this применяется в указанном объекте для обращения к свойству brand в форме (this. brand). Комплексные операторы Последняя группа операторов не вписывается ни в одну из предыдущих категорий, однако она является не менее важной. 990 Часть IV. Объекты языка JavaScript
Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Оператор “запятая” используется при определении нескольких выражений, которые необ- ходимо оценить, начиная с крайнего левого. Наиболее часто этот оператор используется при перечислении инициализируемых переменных. Например, объявление нескольких перемен- ных можно объединить в одном операторе следующим образом. var name, address, serialNumber; Еще один случай, в котором применяют данный оператор, — выражение конструкции цикла for. В следующем примере две различные числовые переменные инициализируются, а затем увеличиваются на различные числа. В начале работы цикла обе переменные были инициализи- рованы как нулевые (это совсем не обязательно, на данный пример так написан). При каждом последующем прохождении цикла одна переменная увеличивается на единицу, а вторая — на 10. for (var i=0, j = 0; i < someLength; i++, j+10) { } Только не пугайте оператор “запятая” с оператором “точка с запятой”, которую исполь- зуют для разделения выражений. ?: Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Оператор условия является сокращенной формой условного выражения конструкции if. . .else, которая уже описывалась в главе 31. Этот оператор обычно используется вме- сте с оператором присвоения для указания одного из двух значений переменной (в зависимо- сти от результата условного выражения). Формальный синтаксис для условного оператора выглядит следующим образом. условие ? выражениеЕслиПравда : выражениеЕслиЛожь Если используется оператор присвоения, обратитесь к такому синтаксису. var = условие ? выражениеЕслиПравда : выражениеЕслиЛожь; Не столь важно, в какой из двух форм будет использоваться этот оператор, лишь запомни- те, что выражение, в котором содержится этот оператор, принимает значение одного из двух выражений, указанных после вопросительного знака. В этом выражении можно выполнить любую операцию JavaScript, включая вызов других функций, а также вложение других услов- ных операторов одного из выражений для создания конструкции, эквивалентной вложенным структурам if. . .else. Чтобы полученное выражение соответствовало вложенным услов- ным выражениям, заключите внутренние выражения в круглые скобки (таким образом можно проверить, принимают ли они значения перед тем, как примет значение внешнее выражение). В следующем примере переменной назначается одно из трех строковых значений (в зависи- мости от значения переменной даты). var monthPart = (dateNum <= 10) ? "early" : ((dateNum <= 20) ? "middle" : "late"); Вначале внутреннему условному выражению, расположенному справа от первого двоеточия, будет присвоено значение либо middle, либо late; после чего внешнему условному выраже- нию передается либо значение early, либо результат внутреннего условного выражения. typeof Совместимость: WinIE3+, MacIE3+, NN3+, Mozl+, Safaril+ В отличие от большинства других операторов, преимущественно связанных с арифмети- кой и логикой, с помощью унарного оператора typeof определяется вид значения, которое Глава 32. Операторы JavaScript 991
получает переменная или выражение. Обычно этот оператор используется для определения того, относится ли переменное значение к одному из следующих типов: number, string, boolean, object, function или undefined. Пример Данная возможность в JavaScript очень полезна, так как в переменных данные не просто содержатся — они, как правило, изменяются в процессе выполнения программы, и, соответ- ственно, изменяются их типы. Может возникнуть ситуация, когда потребуется обработать значение другого типа. Наиболее часто свойство typeof используют как часть условия. if (typeof myVal == "number") { myVal = parselnt(myVal); } Значение операции typeof является строковым. void Совместимость: WinIE3+, MacIE3+, NN3+, Mozl+, Safaril+ Bo всех браузерах, поддерживающих сценарии, можно использовать запись javascript: псевдо-URL для определения параметра атрибутов href и src в дескрипторах HTML (например, ссылок). При работе с данным выражением необходимо быть внимательным, так как функция и операторы, вызываемые в URL, не возвращают и не принимают любое значение. Ес- ли значение такого выражения возвращено, то этим значением (а иногда каталогом папок жест- кого диска клиента) часто заменяется содержимое страницы. Чтобы такого не происходило, пе- ред функцией или выражением используют оператор void, вызываемый j avascript: URL. Пример Наиболее оптимальный способ использования данной конструкции состоит в размещении оператора перед выражением или функцией и разделение их пробелом, как показано ниже. j avascript: void doSomething(); Иногда вы будете брать выражение, следующее за оператором void, в круглые скобки. Использование скобок необходимо только в том случае, когда в выражении содержатся опера- торы с более низким приоритетом, чем оператор void (см. следующий раздел, “Приоритеты операторов”). Но не стоит автоматически брать в скобки все выражения, так как в некоторых браузерах это может вызвать проблемы. Атрибуту href ссылки а чаще всего назначают те- кущий URL для дальнейшего вызова ее обработчика событий onclick. href = "j avascript: void (0)"; С помощью оператора void можно убедиться в том, что функция или выражение не воз- вратит значение, которое может быть использовано атрибутом HTML. Даже обработчик со- бытий onclick ссылки не может работать так, как он бы работал при вызове этой ссылки (например, принимая значение return false). Приоритеты операторов При работе с выражениями, в которых используется несколько операторов (например листинг 32.10), важно помнить порядок, в котором компилятор JavaScript обрабатывает эти выражения. В JavaScript всем типам операторов назначены свои приоритеты (чтобы все вы- ражения обрабатывались в единственно возможной последовательности). В следующем выражении 10 + 4 * 5 // результат 30 992 Часть IV. Объекты языка JavaScript
компилятором JavaScript используется схема’приоритетности для выполнения умножения перед сложением несмотря на порядок, в котором расположены операторы. Другими словами, сначала перемножаются 4 и 5, а затем полученный результат добавляется к 10, таким образом получа- ется 30. Нельзя сделать так, чтобы результат этого выражения был другим. Если необходимо сначала прибавить 1 о к 4, а затем умножить эту сумму на 5, то отмените естественную приори- тетность операторов в JavaScript. Чтобы сделать это, следует взять оператор с более низким приоритетом в круглые скобки. Далее приведен пример с соответствующей коррекцией. (10 +4) * 5 // результат 70 Благодаря скобкам результат существенно изменился. Скобки в JavaScript имеют самый высокий приоритет; заключенное в них выражение будет обработано первым. С помощью табл. 32.10, в которой приведены приоритеты операторов JavaScript, изучите правило построения выражений с несколькими действиями. Совет: когда возникает сомнение относительно приоритетности операторов, используйте больше скобок, так как это более на- дежный способ указать правильную последовательность действий. Таблица32.10. Приоритетыоператоров JavaScript Уровень приоритета Оператор Замечания 1 О От внутренних к внешним [] Значение индекса массива function() Вызов любой удаленной функции 2 ! Булево НЕТ - Побитовое НЕТ - Отрицание ++ Приращение -- Декремент new - typeof void delete Удаление массива или объектного элемента 3 * Умножение / Деление % Деление по модулю- 4 + Сложение - Вычитание 5 << Поразрядные сдвиги >> 6 < Операторы сравнения Глава 32. Операторы JavaScript 993
Окончание табл. 32.10 Уровень приоритета Оператор Замечания 7 <= > >= Равенство 8 & Побитовое И 9 Побитовое исключающее ИЛИ 10 I ' Побитовое ИЛИ 11 && Булево И 12 II Булево ИЛИ 13 ? Условное выражение 14 = Операторы присвоения 15 += /= %= << = >= &= |= Запятая (разделитель параметров) Приведенная схема полезна в том случае, когда в одном выражении используются два оператора с одним уровнем приоритета. Если такое случается (например, со сложением и вы- читанием), обработка выражения проводится слева направо. Иногда в условном операторе указывается несколько булевых выражений (листинг 32.2). Компилятор JavaScript работает по принципу так называемой короткой обработки. Посколь- ку вложенные выражения рассматриваются слева направо, результат всего условия иногда может определяться раньше, чем все выражения будут обработаны. Если встречается опера- тор И, а левый операнд принимает значение false, результатом всего выражения будет false. В таком случае обработка правого операнда даже не проводится. Для оператора ИЛИ: если левый операнд— true, выражению автоматически присваивается истинный ре- зультат. Следующая особенность может немного запутать программиста, у которого не дос- 994 Часть IV. Объекты языка JavaScript
таточно опыта написания подобных сценариев: если в правом операнде существует синтак- сическая или какая-либо другая ошибка (и она не была обнаружена при обработке правого операнда выражения), о ее существовании узнать будет невозможно. Ее обнаружат уже поль- зователи страницы. Советуем проверять свои страницы на наличие подобных ошибок. / Обратите внимание, что все математические операции и операции объединения /назамвпдг строк выполняются раньше операторов сравнения. Это означает, что все выра- * жения, которые выступают в роли операндов, полностью обрабатываются перед их сравнением. Ключ к управлению выражениями, в которых выполняется несколько действий, — в изоляции отдельных выражений и анализе их работы (см. дополнительные советы по отладке главу 45). Глава 32. Операторы JavaScript 995
Функции и пользовательские объекты В сценариях, описанных в предыдущих главах этой кни- ги, уже использовались функции JavaScript, следова- тельно, даже у начинающего программиста должно сформи- роваться некоторое представление об их работе. В данной главе описывается объект function и возможность созда- ния программистом собственных объектов. (Для которых, как и для остальных объектов, будут существовать собственные свойства и методы.). Объект функции Свойства Методы Обработчики событий arguments apply() arity call() caller toString() constructor valueOf() length prototype Синтаксис Создание объекта функции. function имяФункции[[aprl, ...[, aprW] ] ) { опера торы (ы) } var имяФункции=пеи Function(("aprl",...[,"арг№'], "оператор!;... [; операторы]"]) object.eventHandlerNanie=function( [aprl, . . . [, аргЫ] ]) {оператор(ы)}
Доступ к свойствам и методам объекта функции. объектФункции.свойство|метод([параметры]) Совместимость: WinIE3+, MacIE3,+, NN2+, Mozl+, Safaril+ Описание объекта Такие общепринятые понятия, как процедуры, подпрограммы и функции, существующие в других языках, в JavaScript объединены в один тип: пользовательские функции, функция мо- жет возвращать значение (если в ней используется ключевое слово return), хотя это и не обя- зательно. Функции приспособлены для любой обработки данных, в них обрабатывается не только код JavaScript, который выполняется при загрузке документа. Существует возможность создать огромные функции, состоящие из сотни строк, но целе- сообразнее разбить такую функцию на отдельные процессы и поместить их в отдельные не- большие функции. Достоинства подобного метода состоят в следующем: меньшие фрагменты проще для написания и отладки; весь сценарий визуально выглядит проще, если он состоит из отдельных блоков; одни и те же функции можно сделать общими для нескольких сценари- ев и при этом использовать их многократно; функции также можно вызывать из различных частей сценария и открытых фреймов. Правда, для того чтобы научиться создавать функции, используемые многократно, потре- буется некоторое время и опыт. Поэтому советуем изучить как можно больше возможностей, а также ознакомиться с примерами других Web-программистов. Создание функций Стандартный способ определения функции заключается в использовании стандартного шаблона для дальнейшего заполнения его всем необходимым. Формальный синтаксис функ- ции имеет такой вид. function имяФункции ( [aprl] ... [, aprN] ) { оператор (ы) } Для имени функции, как правило, выбирают такое название, с помощью которого можно будет точно определить ее назначение и возможности. Если запланированную для функции задачу нельзя выразить именем из одного или максимум трех слов (которые сжаты в один не- прерывный набор символов имяФункции), то возможно, для одной функции предназначена слишком большая нагрузка. Скорее всего, лучше будет разделить поставленную задачу на две или более функций. Начинающему программисту рекомендуется использовать уже сущест- вующие функции, которые можно вызвать из функции, им написанной. Если складывается ситуация, когда необходимо скопировать строки программы из одной части функции и вста- вить их в другую (так как в них выполняются одни и те же операции), то лучше создать от- дельную функцию для этого фрагмента. Всегда можно создать так называемые анонимные функции, используя конструктор new Function (). Имя этой “анонимной” функции присваивается следующим образом. var имяФункции = new Function (["aprl", ... [,паргда"] , "оператор!.; . . . [; оператора} "] ) Такой способ создания функций особенно удобен в случае, когда такая функция в сцена- рии используется после загрузки документа. В этой структуре присутствуют все составляю- щие функции. Имя каждого параметра функции является строковым значением, все парамет- ры отделены друг от друга запятыми. Заключительная строка параметра состоит из операторов, Глава 33. Функции и пользовательские объекты 997
которые выполняются при вызове функции. Отделите каждый оператор JavaScript точкой с запятой и заключите всю последовательность в кавычки, как показано ниже. var willltFit = new Function("width","height","var sx = screen.availwidth; var sy = screen.availHeight; return (sx >= width && sy >= height)") В функции willltFit () — два параметра; в теле функции определяются две локальные переменные (sx и sy). Если значения входных параметров окажутся меньше, чем значения локальных переменных, возвращается булево значение true. Традиционно эта функция вы- глядит следующим образом. function willltFit(width, height) { var sx = screen.availwidth; var sy = screen.availHeight; return (sx >= width && sy >= height); } Если функция уже существует в памяти браузера, вызвать ее можно подобно любой дру- гой функции. if (willltFit(400,500)) { опера торы } В NN4+, IE4+ и W3C DOM для создания функций используется еще один формат. С помо- щью этой распространенной методики, получившей название выражение лямбда, создается ссылка на анонимную функцию (причем действительно анонимную, так как у данной функции нет никакого имени, по которому можно было бы обратиться к ней позже). Данный метод часто применяют для присвоения ссылок на функции в обработчиках событий, когда необходимо также передать объект события, используемый в Netscape Navigator. Далее приведен пример присвоения анонимной функции обработчику событий onchange для управления формой. document.forms[0].age.onchange = function(event) {isNumber(document.forms[0].age)} Вложенные функции В NN4+, NN4+ и W3C также предусмотрено вложение функций друг в друга. Раньше при написании сценария функции определялись на глобальном уровне, в результате чего каждая функция была доступна и во всех других сценариях. В данной ситуации можно формировать функции внутри друг друга, таким образом, вложенная функция не будет доступна из других частей сценария. Конечно, не рекомендуется многократно использовать одни и те же назва- ния, но можно создать функции с одинаковыми именами, вложенные в другие функции гло- бального уровня. Ниже приведен пример подобной структуры. function outerA(){ опера торы function innerAO { операторы } операторы function outerB(){ операторы function innerAO { операторы function innerB(){ операторы 998 Часть IV. Объекты языка JavaScript
} операторы } Вложенные функции удобно применять, когда один набор операторов необходимо вы- звать в нескольких местах большой функции, и такие операторы имеют значение только в кон- тексте этой большой функции. Другими словами, можно было бы выделить повторяющуюся последовательность в отдельную глобальную функцию, но целесообразнее оставить данные в пределах области, в которой они используются. К вложенной функции можно обращаться только из операторов функции, в которой она содержится (в любом порядке). Кроме того, все переменные, определенные во внешней функции (включая переменные параметров) доступны и во внутренней функции; хотя пере- менные, определенные во внутренней функции, не доступны для внешней функции. В разделе “Переменные: глобальные и локальные” речь пойдет об использовании переменных в различ- ных фрагментах сценария. Параметры функции В определении функции после имяФункции обязательно указывается набор круглых ско- бок. Если функции не передается определенная информация, поступающая при ее вызове, скоб- ки могут быть пусты. Но если с вызовом функции поступают некоторые данные, каждому из па- раметров необходимо дать имя. Параметром может быть любое значение: строковое, числовое, булево, это могут быть даже ссылки на объекты — формы или элементы форм. Выберите такие имена для переменных, по которым можно будет легко вспомнить их содержимое; избегайте многократного использования уже существующих названий объектов в качестве имен перемен- ных, поскольку объекты и переменные с одинаковыми именами в одном выражении легко пере- путать. Не рекомендуется использовать ключевые слова JavaScript (в том числе зарезервирован- ные слова, перечисленные в приложении Б) и имена глобальных переменных, определенных в другом месте сценария. (О глобальных переменных будет рассказано в следующих разделах.) В JavaScript можно не поддерживать соответствие между числом параметров в определе- нии функции и числом параметров, используемых в вызывающих их операторах. Если в функции определяется три параметра, а в вызывающем его операторе только два, третьему параметру присваивается значение null. function oneFunctionfa, b, с) { операторы } oneFunction ("George" , "Grade") В этом примере параметрам а и b в функции соответствуют значения George и Grade; параметру с — пустое значение (null). В JavaScript допускается передавать большее количество параметров из вызывающих операторов, чем число переменных параметров, указанных при определении этой функции. В данном языке существует специальный механизм — свойство arguments, с помощью ко- торого к функции можно “подключать” любые посторонние параметры. Свойства arguments Возвращаемое значение: массив аргументов Только чтение Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Глава 33. Функции и пользовательские объекты 999
Когда значения параметров передаются в функцию с помощью операторов, которые и вы- зывают эту функцию, такие значения параметров присваиваются свойству объекта функции arguments. Это свойство представляет собой массив значений, в котором содержатся зна- чения параметров, хранящихся в элементах этого массива. Индексация элементов начинается с нуля, независимо от того, определены параметры для этих элементов или нет. Используя оператор имяФункции. arguments. length, можно выяснить количество параметров, пе- реданных в данную функцию. Например, если в функцию передается четыре параметра, то имяФункции. arguments. length возвращает 4. Из этого следует, что можно использо- вать систему индексации массива (имяФункции. arguments [1]) для получения значения любого параметра (или параметров). Теоретически, программист не должен определять переменные параметров для функций и вызывать для этого соответствующий элемент массива. Но если используется свойство arguments, то рекомендуется обращаться к переменным параметров по именам, которые являются намного более удобными для восприятия, если они правильно подобраны. Однако могут возникнуть ситуации, в которых для одной определенной функции должно обрабаты- ваться несколько вызовов, при этом в каждом вызове задано различное количество парамет- ров. В функции могут обрабатываться любые параметры, даже те, которым не присвоены имена переменных. Пример См. листинги 33.1 и 33.2, в которых демонстрируется работа свойств arguments и caller. arity Возвращаемое значение: целочисленное Совместимость: WinlE-, MacIE-, NN4+, Moz-, Safari- См. свойство lenght далее в этой главе. caller Возвращаемое значение: ссылка на объект функции Совместимость: WinTE4+, MacIE4+, NN3+, Mozl+, Safaril+ При вызове одной функции из другой между ними устанавливается специальная связь для правильного обмена значениями. Поэтому в вызванной функции организуется ссылка на функцию, вызывающую ее. Подобная информация автоматически сохраняется в объекте функции как свойство caller. Эта зависимость подобна свойству opener, в котором ука- зывается окно или фрейм, используемый для создания подокна. Свойству присваивается зна- чение только в том случае, когда функция вызывается из другой функции; если это не так, свойству caller присваивается пустое значение null. Значение свойства caller представляет собой ссылку на объект функции; таким образом можно просматривать его свойства arguments иса11ег(в случае, когда он вызван из дру- гой функции). Следовательно, из функции можно обращаться к вызывающей ее функции для получения передаваемых ею значений. В свойстве имяФункции. caller хранится определение всей функции (включая обра- ботчик событий). Если вызов функции осуществляется из операторов JavaScript, не включен- ных ни в одну из функций, свойство имяФункции. caller имеет значение null. Только чтение Только чтение 1000 Часть IV. Объекты языка JavaScript
Пример Рассмотрите листинг 33.1, в котором используются оба свойства. Яистнн г Й.1. Свойства функции arguments и caller «html? <head> «tit1е?«/title? «script type="text/javascript"? function hansel(x,y) { var args = hansel.arguments; document.write("<p?hansel.caller is " + hansel.caller + "«br />"); document.write("hansel.arguments.length is " + hansel.arguments.length + "<br /?"); for (var i = 0; i < args.length; i++) { document.write("argument " + i + " is " + args[i] + "«br /?"); } document.write("<\/p>"); } function gretel(x,y,z) { today = new Date(); thisYear = today.getFullYear(); hansel(x,у,z,thisYear) ; } «/script? «/head? «body? «script type="text/javascript"? hansel(l, "two", 3) ; gretelt4, "five", 6, "seven"); «/script? «/body? «/html? После загрузки этой страницы в окне браузера будут отображены следующие результаты (в Safari в данном случае свойство caller примет значение undefined). hansel.caller is null hansel.arguments.length - 3 argument 0 is 1 argument 1 is two argument 2 is 3 hansel. caller is function gretel (x, y, z) { today = new DateO; thisYear = today.getFullYear(); hansel(x, у, z, thisYear); } hansel.arguments.length is 4 argument 0 is 4 argument 1 is five argument 2 is 6 argument 3 is 2001 (или другой текущий год) При загрузке документа функция hansel () вызывается непосредственно из тела сценария. Ей передаются три параметра, при том, что определяется только два. Несмотря на это, все три параметра записываются в свойство hansel .arguments. Далее из основной части сцена- рия вызывается функция gretel (), в которой, в свою очередь, снова вызывается hansel (). Глава 33. Функции и пользовательские объекты 1001
Но теперь при вызове передается уже четыре параметра. В функции gretel () обрабатываются только три из них, а при вызове hansel () добавляется еще один параметр, который является ре- зультатом выполненных в gretel () вычислений. В свойстве hansel. caller хранится полное содержимое функции gretel (). Примите во внимание то, что в hansel. arguments теперь содержатся все четыре параметра, включая значение года, полученное в функции gretel (). constructor См. string. constructor (глава 30). lenght Возвращаемое значение: целочисленное Только для чтения Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safaril+ На примере свойства arguments можно убедиться в том, что в JavaScript не очень стро- го контролируется соответствие количества параметров, передаваемых в функцию, и количе- ства переменных параметров, определенных для этой функции. Но из сценария можно обра- титься к свойству length для точного определения количества переменных параметров, определенных для конкретной функции. Ссылка на это свойство начинается с имени функ- ции, содержащейся в данном объекте. Например, рассмотрим следующее определение. function identify(name, rank, serialNum) { } Количество параметров можно определить в операторе сценария, расположенном за пре- делами функции, для чего используется ссылка следующего вида. identify.length Значение свойства в предыдущем примере— 3. Однако чаще всего вместо свойства length используется свойство arity, реализованное только в Netscape Navigator. prototype См. array .prototype (глава 30). Методы apply ([ текОбъект [, массивАргументов] ]) call([текОбъект[, aprl[, арг2[,... aprN] ]]]) Методы apply () и call () используются для вызова функции. На первый взгляд иногда кажется странным, зачем пользоваться такой сложной конструкцией, если можно просто указать сначала имя функции, а затем ее параметры и т.п. Отличие данных методов состоит в том, что с их помощью можно вызвать функцию, имея только ссылку на нее. Например, если функция определяется в конструкторе new Function () (или с помощью другого анонимного способа, под держиваемого в браузере), полученная ссылка на функцию является результатом выполне- ния конструктора. Дм вызова этой функции в дальнейшем с помощью только этой ссыпки (возможно, сохраняемой в глобальной переменной) подходят и apply (), и call (). Резуль- тат, полученный в обоих методах, одинаков, но определение используемого метода зависит от формы, в которой передаются параметры функции (подробнее об этом вы узнаете далее). Первый параметр, демонстрирующий работу обоих методов, — это ссылка на объект, ко- торый для данной функции является текущим. Для многоуровневых функций, определенных в сценарии, используйте ключевое слово this, которое означает, что контекстом функции 1002 Часть IV. Объекты языка JavaScript
становится текущий объект (как для обычной функции). Если нет таких параметров, которые необходимо передать в функцию, в обоих методах их можно опустить. Ссылка на объект используется, когда вызываемая функция принадлежит к функциям, ко- торые обычно определяются как методы пользовательского объекта. (Некоторые из показан- ных концепций рассматриваются позже в этой главе, поэтому после знакомства с пользова- тельскими объектами, возможно, придется возвратиться к этому разделу.) Пример В следующем примере генерируется пользовательский объект, после чего ему назначается метод для вывода сообщений о свойствах этого объекта. // Функции, вызываемые как метод объекта 'саг' function showCar() { alert(this.make + " : " + this.color),- } // Функция-конструктор объекта 'car' function car(make, color) { this.make = make; this.color = color; this, show = showCar,- } // Создание экземпляра объекта 'car' var myCar = new car("Ford", "blue"); Стандартный способ вывода сообщения из объекта myCar. myCar.show(); В этом случае при вызове функции showCar () текущий объект саг используется как кон- текст для ссылок this, указанных в функции. Другими словами, если функция showCar () вызывается как метод объекта, объект обрабатывается как “текущий”. Однако, используя методы apply() и call О, не обязательно связывать функцию showCar () с объектом myCar. В конструкторе саг () можно не указывать выражение опре- деления функции showCar в качестве метода объекта. Вместо этого вызовите метод showCar () и с его помощью обработайте myCar как текущий объект. showCar.call(myCar); В этом случае функция showCar () работает так же, как и прежде, и ссылка на объект в первом параметре метода call () обрабатывается как текущий объект функции showCar (). Что касается второго параметра метода apply (), то он представляет собой массив зна- чений, которые необходимо передать как параметры текущей функции. Порядок указания значений должен соответствовать порядку задания параметров, определенных для функции. С другой стороны, с помощью метода call () можно передать список индивидуальных па- раметров, отделенных друг от друга запятой. Все зависит от того, каким способом в данном сценарии передаются параметры. Если они уже представлены в форме массива, то использу- ют метод apply (); в остальных же случаях используют метод call ()'. ЕСМА рекомендует применять метод call (), когда при вызове функции параметры не передаются. toString() valueOf() Возвращаемое значение: строковое Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 14- Программисты довольно редко используют методы объекта функции toString () и value- Of О, которые необходимы для отладки сценария и вывода определения функции в строковом Глава 33. Функции и пользовательские объекты 1003
виде. Например, при вводе имени функции, определенной в приложении The Evaluator, в верх- нем текстовое поле компилятор JavaScript автоматически преобразует функцию в строку так, чтобы “значение” можно было вывести в области результатов. Использование этих методов и синтаксический анализ возвращаемого ими текста, имеет, хотя и редко, некоторое практи- ческое применение. Замечания по применению функций Понимание особенностей ввода и вывода функций JavaScript является основой успешного программирования, особенно в случае с несколькими приложениями. В данной главе описы- ваются все способы вызова функций, области рассмотрения переменных функции, рекурсия и разработка функций для многократного использования. Вызов функции В функции действия не выполняются до тех пор, пока она не вызвана с помощью имени иди ссылки. В сценарии функцию можно вызвать (т.е. “заставить ее выполнять определенные дейст- вия”) четырьмя способами: в обработчике событий объекта документа; в операторе JavaScript; в атрибуте HREF, в результате выполнения конструкции j avascript: URL; и более современ- ным способом — с помощью методов call () и apply (). Способ j avascript: URL (назы- ваемый также псевдо-URL) в этой книге подробно не описывается. Некоторые дескрипторы HTML имеют свои атрибуты HREF, предназначенные для хране- ния URL-адресов страниц, используемых при навигации в Internet или загрузки MIME-файлов, для воспроизведения которых требуются вспомогательные приложения или надстройки. По- добные HTML-элементы, как правило, задаются для дескрипторов объектов, выделяемых с помощью мыши (например, ссылок или областей карт изображений, обрабатываемых на сто- роне клиента). В браузерах, поддерживающих JavaScript, разработан специальный встроенный псевдо- протокол — j avascript: URL, с помощью которого к функциям или методам JavaScript мож- но обращаться в атрибуте HREF так же, как и к документу с помощью URL, определенному в сети. Например, довольно часто j avascript: URL используют для того, чтобы изменить со- держимое двух фреймов с помощью одной ссылки. Так как атрибут HREF разработан для обра- щения только к одному URL, то без этого метода осуществить одновременную загрузку разных документов в нескольких фреймах было бы невозможно. В противном случае вам необходимо создать функцию и задать в ней свойство location.href для двух фреймов, после чего эту функцию можно вызвать с помощью атрибута href. Ниже приведен соответствующий пример. function loadPages() { parent.frames[1].location.href = "page2.html"; parent.frames[2].location.href = "instrux2.html"; } <a href="javascript:loadPages()">Next</a> / При вызове функций вышеописанными способами могут использоваться пара- /на заметку метры, с помощью которых в функциях можно выполнять любые поставленные « задачи. Но существует ситуация, когда необходимо предотвратить потенциаль- ный побочный эффект: при возвращении функцией значения (возможно, функ- ция вызывается из других фрагментов сценария, в которых возвращаемые зна- чения должны использоваться в дальнейшем). С помощью атрибута href в окне target устанавливается любое значение, которое примет атрибут, поэтому воз- вращенное значение присваивается окну target, хотя это и не всегда оправдано. 1004 Часть IV. Объекты языка JavaScript
Чтобы предотвратить присвоение возвращенного значения атрибуту href при вызове функции используйте оператор void. <href = "javascript:void loadPages()"> Чтобы в атрибуте href не выполнялись никакие операции (т.е. чтобы сработал обработ- чик событий oncl ick), после оператора следует указать пустую функцию. <href = " j avascript:void(0)"> Для опытных программистов, владеющих несколькими языками, этот оператор знаком как способ объявления того, что функции или процедуры не возвращают значения. В JavaScript этот оператор имеет такие же функциональные возможности, как и в других языках; отличие заключается в его нетрадиционном применении. Переменные: глобальные и локальные В языке JavaScript переменная может быть двух типов. Как и следовало ожидать, любая пе- ременная, инициализированная в пределах основного потока сценария (не внутри функции), яв- ляется глобальной переменной', в любом операторе сценария этого же документа к ней можно обращаться, используя имя. Также иногда инициализируют переменные внутри функции (в ин- струкции var); таким образом, имя переменной можно будет использовать только в операторах этой функции. Ограничивая доступ к переменным одной функции, можно многократно использо- вать одни и те же имена переменных в нескольких функциях, а эти переменные могут иметь раз- личное применение в каждой функции. В листинге 33.2 демонстрируется данная возможность. Листинг 33.2. Страница с многократным использованием одних и тех же переменных <html> <head> <title>Variable Scope Trials</title> «script type="text/javasctipt"> var headGlobal = "Cumby"; function doNothingO { var headLocal = "Pokey"; return headLocal; } </script> </head> <body> «script type="text/javascript"> // две глобальные переменные var aBoy = "Charlie Brown"; var hisDog = "Snoopy"; function testvalues() { var hisDog = "Gromit"; // инициализация локальной ' // версии "hisDog" var page = ""; page += "headGlobal is: " + headGlobal + "<br />"; // page += "headLocal is: " + headLocal + "<br />" // не выполняется: не определена headLocal page += "headLocal value returned from head function is: " + doNothingO + "<br />"; page += " aBoy is: " + aBoy + "<br page += "local version of hisDog is: " + hisDog + "<br />“; document.write(page); } Глава 33. Функции и пользовательские объекты 1005
testvalues(); document.write("global version of hisDog is intact: " + hisDog); </script> </body> </html> На этой странице определяется несколько переменных, некоторые из них глобальные, не- которые локальные (они встречаются в таких разделах документа, как head и body). При за- грузке этой страницы вызывается функция testvalues (), в которой определяются теку- щие значения всех переменных. После этого извлекается еще одно значение переменной, которая использовалась в функции, но не была объявлена ранее. Таким образом, текст, выве- денный на страницу, будет выглядеть следующим образом. headGlobal : Gumby headLocal value, returned from head function is: Pokey aBoy is: Charlie Brown local version hisDog is: Gromit global version of hisDog is intact: Snoopy Исследуйте переменные, инициализированные в этом сценарии. Первая переменная объяв- ляется в разделе Head (headGlobal) и является глобальной, так как она не задается ни в одном определении функции. Для глобальных переменных необязательно указывать ключевое слово, но подобная практика весьма полезна— программисту гораздо легче отыскать переменные, инициализированные им специальным образом. Затем создается небольшая функция; в ней оп- ределяется переменная (headLocal), которая используется только в операторах этой функции. В разделе Body определяются еще две глобальные переменные: аВоу и hisDog. В функ- ции, расположенной в разделе Body (в качестве примера), снова используется переменная hisDog. Инициализация hisDog с ключевым словом var внутри функции для компилятора JavaScript означает, что необходимо создать отдельную переменную, которая будет использоваться только в этой функции. Подобная инициализация никак не соотносится с глобальной пере- менной с таким же именем. Это может запутать любого разработчика, даже автора сценария. В операторах описываемого сценария определяются значения объявленных в нем перемен- ных. В JavaScript не возникает никаких проблем при непосредственном обращении к глобаль- ным переменным, включая переменные, определенные в разделе Head. Но компилятор JavaS- cript не может получить локальную переменную, определенную в другой функции. Например, headLocal является локальной переменной своей функции. Попытка обратиться к этой перемен- ной приведет к сообщению об ошибке, в котором будет сказано, что имя переменной не определе- но. И это действительно так — для всех функций, кроме doNothing (), данная переменная не существует. Но если это значение необходимо использовать где-нибудь еще, можно создать функцию, которая будет возвращать его в нужный оператор (как в функции testvalues ()). Считывание глобального значения аВоу производится без возникновения проблем. Но поскольку в этой функции инициализирована собственная версия hisDog, то в ней можно обращаться только к данной версии переменной. Если внутри функции назначается перемен- ная, имя которой совпадает с именем уже существующей глобальной переменной, то в этой функции к последней обратиться будет невозможно. В доказательство того, что значение глобальной переменной, имя которой использовалось в функции testvalues (), не изменилось, это значение выводится в конце страницы. В ре- зультате выполнения программы Чарли Браун (Charlie Brown) и его собака опять будут вместе. Основная идея подобной схемы заключается в возможности многократного использования одного имени переменной во всех функциях, в которых это необходимо. Например, можно использо- вать переменную счетчика цикла i в каждой функции, в которой присутствуют циклы. (В принципе, один счетчик можно многократно использовать и в нескольких циклах for одной функции, 1005 Часть IV. Объекты языка JavaScript
поскольку в конструкции for значение заново инициализируется в начале цикла.) При передаче параметров в функцию их имена можно использовать для переменных этих параметров в качестве наглядности. Например, обычно полную форму ссылки на объект передают как параметр функции (используя параметр this. form в обработчиках событий). В каждой функции, в которой исполь- зуется один из этих объектов, можно применить form в переменной параметра. function doSomething(form) { операторы } «input type="button" value="Do Something” onclick="doSomething(this.form)"> Если при щелчке на кнопках, расположенных на странице, объекты форм этих кнопок пе- редаются как параметры различных функций, То в каждой из этих функций в качестве имени параметра можно использовать form (или любое другое имя). Использовать одни и те же имена рекомендуется только для “временных” переменных. В таком случае все переменные являются локальными для своих функций, а потому вы не пе- репутаете их с глобальными переменными. Многократное использование имени глобальной переменной в любой функции является рискованным. Часто методика глобализации и лока- лизации влечет за собой путаницу и ошибки. Некоторые программисты договариваются о тактике выбора имен (чтобы избежать ис- пользования глобальных переменных в качестве локальных). Иногда перед всеми именами глобальной переменной помещают строчную букву д. В примере, приведенном в листин- ге 33.2, глобальные переменные можно было бы назвать следующим образом. gHeadGlobal gABoy gHisDog Из этого следует, что при определении локальных переменных символ g лучше не использо- вать. В принципе, хороша любая схема, с помощью которой можно избежать многократного использования одной переменной (если, конечно, она эффективна в остальных отношениях). В случае с несколькими фреймами или несколькими окнами можно обращаться к гло- бальным переменным из любого другого документа, загруженного в браузер в данный мо- мент (см. главу 16). Правила “видимости” переменных остаются действительными и для вложенных функций в NN4+, IE4+ и W3C. Любые переменные, определенные во внешней функции (включая пе- ременные параметров), могут использоваться во всех функциях, вложенных в нее. Но если новая локальная переменная определяется внутри вложенной функции, эта переменная не бу- дет доступна для внешней функции. Вы можете возвратить значение из вложенной функции в оператор внешней функции, в котором она вызывается. Переменные параметров Когда в функцию поступают данные в виде параметров, помните, что их значения могут быть копиями данных (в случае с обычными значениями данных) или ссылками на реальные объекты (например, объекты форм). В последнем случае в функции можно изменить соответ- ствующие свойства объекта при передаче в эту функцию данного объекта как параметра (см. следующий пример). function validateCountry (form) { if (form.country.value == "") { form.country.value = "USA"; } } Глава 33. Функции и пользовательские объекты 1007
Поэтому всякий раз, передавая ссылку на объект как параметр функции, помните, что из- менения, проведенные в “переданной” функции версии этого объекта, будут отражены и на исходном объекте. Если в функции необходимо обратиться к свойствам или результатам выполнения мето- дов переданных данных (свойства объектов или строк), рекомендуется сделать это в начале функции. Как правило, программисты вначале инициализируют столько переменных, сколько необходимо для обработки всех групп данных, используемых далее в этой функции. Таким образом, можно дать логические (или смысловые) названия группам данных, а не полагаться на длинные ссылки для обращения к соответствующей области функции (например, лучше воспользоваться переменной inputStr вместо form. entry. value). Рекурсия в функциях Функцию можно вызвать саму в себе — эта операция известна под названием рекурсии. Классический пример запрограммированной рекурсии — вычисление факториала (факториал для значения 4 вычисляется как 4*3*2*1); также вычисления проведены в листинге 33.3 (листинг отсутствует на прилагаемом к книге компакт-диске). В третьей строке функции в выражении повторно вызывается текущая функция, парамет- ром которой является значение п-1. Поскольку эта функция вызывается сама в себе, во вто- рой строке производится проверка передаваемого в нее значения переменной — таким обра- зом определяется конечное значение вложенного выражения. Однако обратите внимание, что проверять рекурсивные функции нужно очень осторожно. В частности, удостоверьтесь в том, что рекурсия конечна, т.е. существует предел количества повторных вызовов этой функции. В листинге 33.3 этот предел соответствует начальному значению п. Если предел не указан, мо- жет произойти самопроизвольная очистка памяти браузера, а это приведет к сбоям в системе. Листинг 33.3. Использование рекурсии в JavaScript function factorial(п) { if (п > 0) { return п * (factorial(п-1)); } else { return 1; Преобразование функций в библиотеки Создавая функции для сценариев, следует также помнить о возможности создания универ- сальных функций (написанных так, чтобы их можно было многократно использовать в других приложениях, независимо от объектной структуры страницы). Наиболее подходящими для такого вида обработки являются функции, в которых осуществляется определенная проверка (см. примеры в главе 43), преобразование данных или математическая итерация. Чтобы функция стала универсальной (или общей), в ней не должно быть никаких ссылок на конкретные объекты, заданные с помощью их имен. Имена объектов всегда разные для каждого конкретного документа. Поэтому в подобную функцию определенный объект передают как параметр. Например, если создается функция, в которую в качестве параметра передается объект text, в этой функции можно использовать данные объекта или вызывать его методы, при этом ничего не зная о его структуре или имени. Рассмотрим данную возможность на примере функции (листинг 33.4), которая теперь является частью целого документа. 1008 Часть IV. Объекты языка JavaScript
Дмстмкг ЗЗ.Ф.Вызов универсальной функции <html> <head> <title>Variable Scope Trials</title> <script type="text/javascript"> function factorial(n) { if (n > 0) { return n * (factorial(n - 1)); } else { return 1; } } </script> </head> <body> <form> Enter an input value: <input type="text" name="input" value="0" /> <pxinput type="button" value="Calc Factorial" onclick="this.form.output.value = factorial(this.form.input.value)" /></p> <p>Results: <input type="text" name="output" /></p> </form> </body> </html> Данная функция является универсальной только благодаря возможности введения в нее значения (п) в качестве параметра. На форме с помощью обработчика событий onclick кноп- ки введенное только в одном поле значение передается в функцию factorial (). В возвра- щаемое значение присваивается полю вывода данных формы. Функция factorial () ниче- го “не знает” о том, будут ли в текущем документе использоваться формы, поля или кнопки. Если указанная функция понадобится вам в другом сценарии, ее можно скопировать и вста- вить в этот сценарий, так как она уже предварительно протестирована. Любая универсальная функция является частью персональной библиотеки сценариев программиста, которой он может пользоваться от случая к случаю, что экономит его время. Однако не все функции можно сделать универсальными. Все равно в сценарии придется соз- давать ссылки на объекты JavaScript или на пользовательские объекты. Если вам часто прихо- дится создавать функции, в которых выполняются одни и те же действия, то напишите одну универсальную функцию и поместить ее в библиотеку. Если посетители используют браузеры Netscape Navigator версии выше 3 (это же относится и к Internet Explorer), поместите эти функ- ции во внешнем файле библиотеки с расширением . j s (см. главу 13, в которой подробно описы- вается способ совместного использования вспомогательных функций в нескольких документах). Пользовательские объекты На примере предыдущих глав можно было убедиться в том, насколько удобно организовы- вать информацию об окнах браузера и содержащихся в них документах с помощью объектов. Но в примерах сценариев, которые были рассмотрены ранее, ни разу не использовалась возможность создания собственных объектов со своими свойствами и методами. Подобные объек- ты не являются элементами интерфейса пользователя на странице, они, скорее, принадлежат к объектам, в которых могут храниться данные и функции сценариев (выполняемые как методы), а результаты этих функций могут выводиться для обозрения пользователями в окне браузера. Глава 33. Функции и пользовательские объекты 1009
О данной технологии уже упоминалось в главе 30, когда речь шла о массивах. Массив представляет собой упорядоченный набор данных. Можно создать массив JavaScript, элемен- тами которого будут свойства — для обращения к ним используйте уже знакомый точечный синтаксис (имяМассива [индекс] . имяСвойства). Обычно в объекте содержатся различ- ные типы данных. Совсем не обязательно создавать упорядоченную совокупность данных, хотя в сценариях могут использоваться объекты с конструкций, похожих на массивы. Кроме того, к пользовательскому объекту можно прикрепить любое количество собственных функ- ций в качестве методов. Это означает, что программист имеет возможность полного управле- ния структурой объекта, его данными и поведением. Пример “объектов планет” Для формирования массива данных о планетах в этом разделе используется массив, соз- данный в главе 30. Однако в данной главе демонстрируется, насколько удобно использовать данные, когда они сохраняются в форме пользовательских объектов. В этом модифицирован- ном примере создается всплывающий список, содержащий названия девяти планет Солнеч- ной системы, и выводятся сведения о каждой выбранной планете. Согласно концепции поль- зовательского интерфейса (и многофреймовых структур), результат выводится в отдельном фрейме двухфреймового окна браузера. Это означает, что с помощью такого объекта создает- ся HTML-документ, который отображается в отдельном фрейме. Если это приложение разра- батывается строго для IE4+, NN6+ и W3C, можно использовать одни и те же данные для пре- образования вида таблицы в соответствии с выбором пользователя. Приведенный пример является полностью совместимым со всеми браузерами, поддерживающими сценарии. В этой главе не будет создаваться массив для хранения данных, мы создадим пользова- тельские объекты: для каждой планеты — отдельный объект. Объекты обладают пятью свой- ствами и одним методом. Каждая планета имеет следующие свойства: название, диаметр, расстояние от Солнца, продолжительность года и продолжительность дня. Для того чтобы указать дополнительные сведения об этих объектах, необходимо каждому из них определить возможность вывода “личных” сведений в специальном фрейме окна. Для этого лучше опре- делить одну функцию, в которой можно будет обрабатывать любой объект планеты, вместо того чтобы определять девять отдельных функций для каждого случая. В листинге 33.5 представлен исходный код документа, в котором создается набор фреймов для данных планетарных исследований; в листинге 33.6 приведена полная страница объектно-ориентированного'документа планет, который расположен в верхнем фрейме. «htmls «heads «titlesSolar System Viewer«/titles «script type="text/javascript"s function blank() { return "«htmls«bodys«\/bodys<\/htmls"; } «/scripts «/heads «frameset rows="50%,50%" onload="Framel.doDisplay(Framel.document.forms[0].planetsList)"s «frame name="Framel" src="lst33-06.htm" /s «frame name="Frame2" src="javascript:parent.blank()" /s «/framesets «/htmls 1010 Часть IV. Объекты языка JavaScript
В данной программе обратите внимание на одну особенность: нижний фрейм не загружается до тех пор, пока не загрузится документ верхнего фрейма, поэтому в атрибуте src второго фрейма необходимо указать определенный URL-адрес. Вместо того чтобы выполнять дополни- тельные действия и загружать файл с пустым документом HTML, здесь для вызова функции ис- пользуется конструкция javascript :URL. В данном примере возвращенное функцией значе- ние (пустая страница HTML) должно передаваться в указанный фрейм (при этом оператор void не используется). Это наиболее эффективный способ создания пустого фрейма в наборе фреймов. Листинг 33 л. <html> <head> <title>Our Solar System</title> <script type="text/javascript"> // определение метода function showPlanetO { var result = "<htmlxbodyxcenterxtable border= ' 2 ’ >" ; result += "ccaption align='top'>Planetary data for: <b>" + this.name + "</bx/caption>"; result += "<trxtd align= ' right' >Diameter: </tdxtd>" + this.diameter + "</tdx/tr>"; result += "ctrxtd align=' right' >Distance from Sun:</td> <td>" + this.distance + "</tdx/tr>" ; result += "<trxtd align=1 right'>One Orbit Around Sun:</td> <td>" + this.year + "</td></tr>"; result += "ctrxtd align='right' >One Revolution (Earth Time) :</tdxtd>" + this.day + "</tdx/tr>"; result += "</tablex/centerx/bodyx/html>"; // отображение результатов во втором фрейме окна parent.Frame2.document.write(result); parent.Frame2.document.close(); } // определение типа объектов планет;. // 'new' создает новый экземпляр и внедряет в объект данные function planet(name, diameter, distance, year, day) { this, name = name; this.diameter = diameter; this.distance = distance; this.year = year; this.day = day; this.showPlanet = showPlanet; // создание showPlanetO // как метода планеты } // создание объектов планет и сохранение их в переменных var Mercury = new planet("Mercury","3100 miles", "36 million miles", "88 days", "59 days"); var Venus = new planet("Venus", "7700 miles", "67 million miles", "225 days", "244 days"); var Earth = new planet("Earth", "7920 miles", "93 million miles", "365.25 days","24 hours"); var Mars = new planet("Mars", "4200 miles", "141 million miles", "687 days", "24 hours, 24 minutes"); var Jupiter = new planet("Jupiter","88,640 miles", "483 million miles", "11.9 years", "9 hpurs, 50 minutes"); var Saturn = new planet("Saturn", "74,500 miles", Глава 33. Функции и пользовательские объекты 1011
"886 million miles", "29.5 years", "10 hours, 39 minutes"); var Uranus = new planet("Uranus", "32,000 miles", "1.782 billion miles","84 years", "23 hours"); var Neptune = new planet("Neptune","31,000 miles", "2.793 billion miles","165 years", "15 hours, 48 minutes"); var Pluto = new planet("Pluto", "1500 miles", "3.67 billion miles", "248 years", "6 days, 7 hours"); 11 вызывается кнопкой и реализует метод объекта планеты function doDisplay(popup) { i = popup.selectedlndex; eval(popup.options[i].text + ".showPlanet()"); } </script> </head> <body> <hl>The Daily Planet</hl> chr /> <form> <p>Select a planet to view its planetary data: cselect name='planetsList’ onchange=’doDisplay(this)'> <option>Mercury</option> <option>Venus</option> <option selected="selected">Earthc/option> coption>Marsc/option> coption>Jupiterc/option> coption>Saturnc/option> coption>Uranusc/option> coption>Neptunec/option> coption>Plutoc/option> c/select>c/p> c/form> с/body> c/html> В разделе head основная задача состоит в определении функции, которая будет пред- ставлять метод для каждого из объектов. Подобную операцию следует выполнять при созда- нии каждого сценария, в котором функция выступает в роли метода. Если не определить функцию вначале, может возникнуть ошибка — имя функции не определено. Сравнивая этот метод извлечения данных с вариантом, в котором используется массив, обратите внимание, что в первом случае параметр для индекса не задается, а ссылка на каждое свойство начина- ется с ключевого слова this. Далее будет рассмотрен пользовательский метод; однако вна- чале мы разберемся с остальной частью кода раздела Head. Ниже описывается функция-конструктор объекта, в которой выполняется несколько важ- ных задач. Во-первых, в этой функции полностью устанавливается структура пользователь- ского объекта: свойства, предназначенные для хранения данных и их поиска, и всевозможные методы, которые можно вызвать из объекта. Имя функции— это название, которое позже используется для создания новых экземпляров объекта. Поэтому при выборе имени важно учитывать природу данного объекта. Вероятнее всего, вам понадобится занести некоторые данные в свойства. Чтобы иметь возможность обратиться к одному или нескольким экземп- лярам загруженного и готового к использованию объекта, в определении функции предусмот- рены параметры для каждого свойства, определенного в объекте. Для присвоения определенному свойству значений, передаваемых в качестве параметров функции, применяется ключевое слово this. В этом примере для передаваемых переменных параметров и свойств используются одинаковые имена. Прежде всего это сделано в целях удоб- ства (просто так принято). Вы можете назначать переменным и свойствам любые имена и обра- 7072 Часть IV. Объекты языка JavaScript
щаться к ним любыми известными способами. В функции-конструкторе planet () под экземп- ляры объекта зарезервировано пять разделов свойств, независимо от того, хранятся в свойствах какие-либо данные или нет (каждое неинициализированное свойство имеет значение null). Последний элемент в функции-конструкторе planet () — это ссылка на определенную ра- нее функцию showPlanet (). Обратите внимание, что в выражении присвоения при обраще- нии к функции не используются круглые скобки — только имя функции. Когда в сценарии встречается подобное выражение, компилятор просматривает все существующие определения (эти функции определены выше в сценарии) и ищет соответствующее указанному имени. Если соответствующая функция находится (как это и происходит в данном примере), функция при- сваивается идентификатору, расположенному слева от выражения присвоения. При этом дан- ный идентификатор автоматически служит именем метода указанного объекта. Как и для всех уже изученных методов JavaScript, при его вызове задается ссыпка на объект, потом точка, а за- тем имя метода, сопровождаемое пустыми скобками. Ниже приводится соответствующий пример. В следующем блоке операторов, согласно определению, установленному в конструкторе planet (), создаются индивидуальные объекты. Как и в случае с массивами, новый объект создается с помощью оператора присвоения и ключевого слова new. В данном случае имена объектов удобны не только тем, что они представляют собой реальные названия планет (объект Mercury соответствует планете Меркурий), но и тем, что их можно использовать позже, когда с помощью функции doDisplay О из “всплывающего” меню будет извлечено название и потребуется найти соответствующие его объекту данные. При создании нового объекта в памяти для него и его свойств резервируется специальная область (связанная с текущим документом). В этом сценарии резервируется девять областей для объектов, в каждой из которых содержится собственный набор свойств. Обратите внимание, что в функцию метода showPlanet () не передается ни один параметр (в функции он не ожидает- ся). Но в данном случае это очень удобно, так как при таком способе определения объектов ме- тод автоматически присоединяется к каждой версии (экземпляру) созданного объекта планеты. Последнее определение функции doDisplay () вызывается всякий раз, когда пользова- тель выбирает элемент из списка планет в верхнем фрейме. Данная функция также вызывает- ся с помощью обработчика событий onload набора фреймов, и начальная таблица отобра- жается для выбранного по умолчанию элемента (см. рис. 33.1). Однако при вызове функции из обработчика событий onload верхнего фрейма могут возникнуть проблемы (сбой в дру- гом фрейме), если документы фреймов полностью не загружены. В обработчике событий onchange для списка select в функцию doDisplay () переда- ются ссылки на элементы списка. В этой функции объект select присваивается переменной popup, позволяющей представить объект во всплывающем меню. В первом выражении опреде- ляется индекс выбранного элемента. С помощью этого индекса находится соответствующий ему текст. Однако возникает следующая трудность: эту текстовую строку нужно использовать как имя переменной — название планеты, а затем добавить ее в вызов метода showPlanet (). Для обработки несоизмеримых типов данных используют функцию eval (). Далее в круглых скоб- ках указывается строка для названия планеты, которая объединяется со ссыпкой на метод showPlanet (). В функции eval () обрабатывается та строка, которая преобразуется в пра- вильный вызов метода. Таким образом, если пользователь выбирает из всплывающего меню Jupiter, метод вызывается с помощью ссылки Jupiter. showPlanet (). Далее мы рассмотрим определение функции/метода showPlanet (), заданное в начале сцена- рия. При вызове этого метода в ответ на выбранную пользователем планету Jupiter единствен- ной областью рассмотрения метода становится объект Jupiter. Таким образом, с помощью ссылок на this .propertyName в showPlanet () можно обратиться только к Jupiter. Су- ществует один способ использовать this .name в этом объекте— присвойте свойству name значение Jupiter. Аналогично можно обратиться к остальным свойствам, определенным в данной функции/методе. Глава 33. Функции и пользовательские объекты 1013
Рис. 33.1. Вводимые и выводимые данные для описанного выше приложения Создание массива объектов В листинге 33.6 каждый объект планеты присваивается глобальной переменной, название которой соответствует “его” планете. При знакомстве с методиками пользовательских объек- тов этот принцип позволяет эффективно решить поставленные задачи, поскольку в данном случае представить переменную, соответствующую определенному объекту, предельно про- сто. Как можно убедиться на примере функции doDisplay (), при обращении к объекту по имени необходимо использовать фуйкцию eval (), чтобы преобразовать строковое представ- ление имени в допустимую ссылку на объект. Несмотря на то, что в данном простом примере это и не слишком важно, функция eval () не является сильной стороной JavaScript. Поэтому, вместо функции eval () рекомендуется найти способы обращения к объекту, в которых бы ис- пользовалось строковое значение. Одним из таких способов для данного приложения является помещение объектов в массив, индексы которого представляют названия планет. Для того чтобы присвоить пользовательские объекты массиву в листинге 33.6, сначала создают пустой массив, а затем каждому элементу массива присваивают результат вызова конструктора объекта. Измененный фрагмент программы выглядит следующим образом. // Создание массива var planets = new Array(); // "заполнение" массива новыми объектами планеты planets["Mercury"] = new planet("Mercury","3100 miles", "36 million miles", "88 days", "59 days"); planets["Venus"] = new planet("Venus", "7700 miles", "67 million miles", "225 days", "244 days"); planets["Earth"] = new planet("Earth", "7920 miles", "93 million miles", "365.25 days","24 hours"); planets["Mars"] = new planet("Mars", "4200 miles". 1014 Часть IV. Объекты языка JavaScript
"141 million miles", "687 days", "24 hours, 24 minutes"); planets["Jupiter"] = new planet("Jupiter ","88,640 miles", "483 million miles", "11.9 years", "9 hours, 50 minutes"); planets["Saturn"] = new planet("Saturn", "74,500 miles", "886 million miles", "29.5 years", "10 hours, 39 minutes"); planets["Uranus"] = new planet("Uranus ", "32,000 miles", "1.782 billion miles","84 years", "23 hours "); planets["Neptune"] = new planet("Neptune","31,000 miles", "2.793 billion miles","165 years", "15 hours, 48 minutes"); planets["Pluto"] = new planet(“Pluto", "1500 miles", "3.67 billion miles", "248 years", "6 days, 7 hours"); Наиболее существенное преимущество такого подхода демонстрируется в измененной функции doDisplay () , в которой строковое значение элемента select используется непо- средственно, без преобразования в ссылку на объект. // Вызов метода объектов планет при щелчке на кнопке function doDisplay(popup) { i = popup.selectedlndex; planets[popup.options[i].text].showPlanet(); } Сам факт использования такого количества подобных объектов должен наводить на мысль о хранении их в виде массива. По причине того, что в данном приложении названия напря- мую используются при выборе этих объектов, то подойдут имена элементов массива; в дру- гих случаях можно использовать числовые индексы, что упрощает выполнение операций цикла для массива. Добавление пользовательских методов В этом разделе описывается дополнительная возможность определения и применения пользовательских объектов. В пользовательском объекте в виде свойства может содержаться ссылка на другой пользовательский объект. Воспользуемся данной возможностью в рассмот- ренном выше примере. Допустим, необходимо добавить на страницу фотографии планет. Каждая фотография имеет свой URL, указывающий расположение файла фотографии; для каждой фотографии пред- ставлена дополнительная информация, в частности сведения об авторских правах и номер ссылки, который выводится для пользователя на странице. Один из способов обработки по- добной информации заключается в создании отдельного определения объекта для базы дан- ных фотографий. Такое определение может выглядеть следующим образом. function photo(name, URL, copyright, refNum) { this.name = name; this.URL = URL; this.copyright = copyright; this.refNum = refNum; } После этого для каждого изображения необходимо создать индивидуальный объект f oto. Ниже приведен пример одного из определений. mercuryPhoto = new photo("Planet Mercury", /images/merc44.gif", " (c)1990 NASA", 28372); Чтобы добавить объект f oto в объект planet необходимо описать в функции-конструк- торе planet еще одно свойство. Тогда обновленный конструктор planet будет выглядеть следующим образом. function planet(name, diameter, distance, year, day, photo) { this.name = name; this.diameter = diameter; Глава 33. Функции и пользовательские объекты 1015
this.distance = distance; this.year = year; this.day = day; this.showPlanet = showPlanet; this.photo = photo; // Добавленное свойство photo } После создания объектов foto объект planet можно создать, передав еще один пара- метр, — объект foto, который необходимо связать с этим объектом. // Создание нового объекта planet и хранение в нем переменных Mercury = new planet("mercury","3100 miles", "36 million miles", “88 days", "59 days", mercuryPhoto); Чтобы обратиться к свойству объекта foto, придется указать ссылку, которая необходи- ма для обращения к объекту planet. copyrightData = Mercury.photo.copyright; Пользовательские объекты этого типа имеют огромный потенциал. Например, можно внедрить все копии элементов и URL-адреса изображений сетевого каталога в один документ. Поскольку пользователь выбирает элементы для дальнейшего отображения на экране (про- сматривает их в определенной последовательности), на обновленной странице JavaScript ин- формация выводится моментально. Для этого нужно загрузить изображение, если оно не за- гружено предварительно, как описывается в главе 18. В последнем случае вся работа произ- водится мгновенно, без ожидания загрузки следующей страницы каталога. Если вы как начинающий программист замечаете сходство между конструкцией “объект в объекте” и реляционной базой данных, то у вас великое будущее. Для нескольких объектов можно задавать один и тот же подобъект, подобно свойству. Такая ситуация напоминает де- ловые контакты, представленные для одной компании. Несколько дополнительных способов создания объектов В листингах 33.5 и 33.6 используются способы создания объектов, совместимые со всеми браузерами, поддерживающими сценарии. Но существует несколько дополнительных спосо- бов, предназначенных для тех, кто пользуется более современными версиями браузеров. Начиная с NN3+ и IE4+, для генерирования пустого объекта можно использовать конст- руктор new Obj ect (). Просто присвойте имена свойствам и методам, как показано ниже. var Earth = new Obj ect(); Earth.diameter = "7920 miles"; Earth.distance = "93 million miles"; Earth.year = "365.25"; Earth.day = "24 hours"; Earth.showPlanet = showPlanet; // ссылка на функцию При создании похожих по структуре объектов, наиболее эффективно будет применяться пользовательский конструктор, приведенный в листинге 33.6. Но для отдельных объектов лучше подойдет конструктор new Obj ect (). Для создания нового объекта можно воспользоваться сокращенными буквенными назва- ниями. В таких случаях указывают пары имен свойств и их значений, заключенные в фигур- ные скобки. Таким образом можно присвоить целую конструкцию переменной, которая в дальнейшем будет выступать именем определенного объекта. Ниже приведен пример по- добного конструктора объекта. var Earth = {diameter:"7920 Milis", distance:"93 million miles", year:"365.25", day:"24 hours", showPlanet:showPlanet}; 1016 Часть IV. Объекты языка JavaScript
Для разделения пары имя-значение используется двоеточие, а для разделения самих пар между собой — запятые. Часть значения пары имя-значение может быть представлена масси- вом (для этого используют такую структуру конструктора, как [...]) или вложенными объек- тами (необходим еще один набор фигурных скобок). Для создания многократно вложенных объектов можно применить и вложенные массивы, и объекты. В целом, это очень компакт- ный способ внедрения данных в страницу для дальнейшего управления ими из сценария. Если знания CGI, XML и навыки в работе с базами данных не позволяют решить поставленную за- дачу, используйте серверные программы для преобразования данных XML в следующую компактную структуру JavaScript: каждая запись XML является собственным объектом JavaScript. Для большого количества записей присвойте определения объектов, заключенные в фигур- ные скобки, элементам массива. Тогда при выполнении сценариев на стороне клиента будет производиться итерация данных и генерироваться документ HTML для вывода данных в раз- личных форматах (согласно установленным критериям и порядку сортировки). Определение в объекте получателя и определителя свойства В следующей версии спецификации языков ЕСМА-262, вероятно, будут описаны так на- зываемые получатели и определители свойств. Но пока формальный синтаксис этих возмож- ностей окончательно не определен, данную методику можно начинать исследовать только в NN6, используя временный синтаксис, который наиболее приближен к вероятному формату (в данном методе будут использоваться различные ключевые слова, пока не утвердят стан- дарт). Как только стандарт будет принят, уже в следующей версии Netscape Navigator начнут использовать стандартные ключевые слова. В главе 14 уже шла речь о создании получателей и определителей объекта. В этой главе был описан расширенный синтаксис свойств NN6 некоторых объектов W3C DOM, в котором также использовалась определенная доля синтаксиса DOM, представленного разработчиками Microsoft (причем очень удобного). Получателя можно определить для любого контейнера, чтобы возвратить массив вложенных элементов аналогично document. all, используемому только в Internet Explorer. Цель получателя состоит в присвоении нового свойства прототипу объекта и определении способа оценки возвращаемого свойством значения. Определитель используется для того же, но при этом с его помощью задается способ применения к объекту значения, присвоенного свойст- ву. Оба определения написаны в форме анонимных функций таким образом, чтобы при чтении или записи значения свойства объекта можно было проводить обработку данных любой сложности. Получатели и определители присваиваются свойству prototype объекта, таким обра- зом, у программиста появляется возможность настраивать объекты DOM и исходные объекты JavaScript. В NN6 для получателей, определителей и методов прототипа объекта используется следующий синтаксис. объект.prototype.___defineGetter___("имя", function) объект.prototype.___defineSetter___("имя", function) Заметьте, что символы подчеркивания, расположенные до и после имени метода, состоят из двух символов (т.е. _, _, defineGetter, _, Это двойное подчеркивание определено в синтаксисе, который не будет использоваться в стандарте ЕСМА. В результате исчезнут конфликты с возможным будущим синтаксисом, используемым в этой технологии. Первым параметром метода является имя свойства, для которого определен получатель или определитель. Это может быть уже существующее имя свойства, в старом значении ко- торого больше нет необходимости. Вторым параметром может быть ссылка на функцию; но, скорее всего, это будет анонимная функция, определенная в текущем месте кода. Используя Глава 33. Функции и пользовательские объекты 1017
анонимную функцию, можно получить преимущества текущего состояния объекта, для кото- рого определено свойство. Для каждого свойства задайте и получателя, и определителя, даже если оно предназначается Только для чтения или только для записи. Для’ того чтобы лучше разобраться в работе данного механизма, рассмотрим получатель и определитель, используемые в главе 14 для добавления свойства innerText к элементам HTML в NN6+. Это свойство предназначено как для чтения, так и для записи, поэтому функции заданы и для получателя, и для определителя. Задание получателя выполняется следующим образом. HTMLElement.prototype.____defineGetter___("innerText", function () { var rng = document.createRange(); rng.selectNode(this); return rng.toString(); }) В данном примере изменяется основной объект HTMLElement — объект, который в NN6 используется для создания экземпляра каждого элемента HTML на странице. После выполне- ния вышеописанной инструкции каждый элемент HTML на странице наследует новое свойст- во innerText. При чтении свойства innerText для определенного элемента вызывается анонимная функция в соответствующем получателе. Таким образом, после создания объекта текстового диапазона диапазон определяется узлу, который является текущим элементом. Это превосходный пример того, как в контексте текущего объекта можно использовать ключевое слово this для обращения к этому же объекту. В результате возвращается строковая вер- сия выбранного диапазона. Необходимо, чтобы в функции получателя содержался оператор return и возвращенное значение имело требуемый тип данных. Обратите внимание на за- крытие фигурных скобок функции и круглых скобок метода получателя. При выполнении данной функции (при каждом чтении свойства) с помощью получателя всегда возвращается текущее состояние объекта. Если со времени загрузки страницы содер- жимое элемента изменилось, пользователь может быть уверен, что он получает текущий текст элемента. Эта операция намного сложнее простого выполнения операторов функции при загрузке страницы для определения статического представления текста элемента. Соответствующий определитель задается следующим образом. HTMLElement.prototype.____defineSetter___("innerText", function (txt) { var rng = document.createRange(); rng.selectNodeContents(this); rng. deleteContents () ; var newText = document.createTextNode(txt); this.appendChild(newText); return txt; }) Чтобы присвоить значение свойству объекта, нужное значение необходимо передать в пе- ременную параметра. Такая переменная указывается в определении функции. Для рассматри- ваемого определителя текущий объект (this) также управляет объектом текстового диапа- зона. Содержимое текущего элемента удаляется, и текстовый узел, состоящий из переданного в качестве параметра текста, вставляется в элемент. Чтобы полностью обеспечить соответст- вие процедуре установки свойства innerText в Internet Explorer, текст возвращается. Обыч- но определители не возвращают значения, однако в данном примере в выражении присвоения значения свойству innerText ему определяется новый текст. Если необходимо создать свойство, предназначенное Только для чтения, следует настроить определитель для свойства, но при этом присвоить ему пустую функцию, как показано ниже. node.prototype. defineSetter ("all", functionO {}) Это предотвращает появление ошибок в выражении присвоения значения свойству, пред- назначенному Только для чтения. Свойство, предназначенное для записи, должно иметь по- лучателя, который возвращает null или пустую строку. 1018 Часть IV. Объекты языка JavaScript
HTMLElement.prototype._defineGetter_("outerHTML", function() {return ""}) Так как показанный синтаксис для получателя и определителя используется только в NN6, вам необходимо в точности следовать выражениям определения объекта или выражениям определения, принятым для данной версии браузера. Не забывайте, что этот синтаксис изме- нится в будущих версиях браузеров, как только в ЕСМА будет принят формальный стандарт вышеописанного метода. Применение пользовательских объектов Не требуются особые знания для того, чтобы определить, когда вместо массива следует воспользоваться собственным объектом. Чем больший опыт работы с пользовательскими объектами, тем легче разобраться в принципе их действия. Следовательно, более опытные программисты проектируют свои сценарии уже с учетом данной возможности, особенно, ес- ли в объекте можно использовать один или несколько методов, с ним связанных. Это, конеч- но, не обязательно делать начинающим программистам, но если у вас уже есть определенный опыт работы с JavaScript, рекомендуется прочесть все, что относится к пользовательским объектам, причем не один раз. Концепция объектно-ориентированного программирования Как уже отмечалось, язык JavaScript, скорее, основан на объектах, чем является объектно- ориентированным. Вместо соблюдения схемы классов, подклассов и принципов наследования (как в объектно-ориентированных языках например, Java), в JavaScript используется то, что на- зывается наследованием прототипа. Подобная схема применима не только к исходным объек- там JavaScript или объектам DOM, ее также можно применять и для пользовательских объектов. Добавление прототипа Пользовательский объект часто определяется в функции-конструкторе, с помощью которой начальные Значения обычно распределяются по свойствам объекта (как в следующем примере). function car(plate, model, color) { this.plate = plate; this.model = model; this.color = color; } var carl = new car("AB 123", "Ford", "blue"); В NN4+, IE4+ и W3C можно по умолчанию присвоить значения свойствам, если ни одно из них значением не обеспечивается (null, 0 или пустая строка). С помощью оператора ИЛИ (| |) вы присвоите свойству переданное значение, если таковое существует, или значение, ус- тановленное в конструкторе по умолчанию. Таким образом, вы можете изменить предыду- щую функцию, чтобы присвоить свойствам значения по умолчанию. function cartplate, model, color) { this.plate = plate || "missing"; this.model = model || "unknown"; this.color = color || "unknown"; } var carl = new car("AB 123", "Ford", ""); Глава 33. Функции и пользовательские объекты 1019
После того, как будут выполнены предыдущие выражения, значения свойств объекта carl станут следующими. carl.plate // значение = "АВ 123" carl.model // значение = "Ford" carl.color // значение = "unknown" Если после этого прибавить к свойству prototype конструктора новое свойство car.prototype.companyOwned = true; любой объект автомобиля, как созданный, так и не созданный, автоматически наследует но- вое свойство companyOwned и соответствующее ему значение. При этом для любого опре- деленного объекта саг. значение свойства companyOwned можно отменить. Но если этого не сделать, объекты саг, свойство companyOwned которых не отменено, автоматически бу- дут наследовать любое изменение значения prototype. companyOwned. Таким образом в JavaScript определяются значения свойства prototype. Наследование прототипа Каждый раз при чтении или записи свойства объекта в JavaScript проводится проверка со- ответствий для данного имени свойства, причем осуществляется она в определенной после- довательности. Такая последовательность имеет следующий вид. 1. Если свойство имеет значение, присвоенное текущему (локальному) объекту, это зна- чение можно использовать. 2. Если не имеется никакого локального значения, проверьте значение прототипа свойст- ва конструктора объекта. 3. Структура прототипа просматривается до тех пор, пока не будет найдено соответствие свойству (со значением, ему присвоенным) либо найден “родной” объект Object. Поэтому при изменении значения свойства prototype конструктора не отменяйте зна- чение свойства в экземпляре этого конструктора — тогда будет возвращено текущее значение свойства prototype конструктора. Вложенные объекты и наследование прототипа Для тех, кто только начинает использовать вложенные объекты, следует научиться обра- щать внимание на специфические ситуации, подобные тем, когда в одном объекте вызыва- ется конструктор другого. Рассмотрим все тот же объект саг, определенный ранее. В этом сценарии считается, что объект саг является родственным корневому объекту, свойства которого общедоступны двум другим типам объектов. Один из них — транспортное средство флота компании, которое обладает свойствами корневого объекта car (plate, model, color), а также некоторыми собственными свойствами. Второй объект, в котором вновь ис- пользуется объект саг, представляет автомобиль, припаркованный в гараже компании. Этот объект имеет дополнительные свойства, описывающие параметры парковки транспортных средств. Этим объясняется тот факт, что объект саг определен сам в себе. Теперь рассмотрим функцию-конструктор для записи сведений о парковке и конструктор основного объекта саг. function car(plate, model, color) { this.plate = plate || "missing"; this.model = model || "unknown"; this.color = color || "unknown"; 1020 Часть IV. Объекты языка JavaScript
function carInLot(plate, model, color, timein, spaceNum) { this.timeln = timein; this.spaceNum = spaceNum; this.carinfo = car; this.carlnfо(plate, model, color); } В конструкторе carlnLot не только присваиваются значения соответствующим уникаль- ным свойствам (timein и spaceNum), в нем также содержится ссылка на конструктор саг, при- своенная свойству carinfo. Это присвоение ссылки свойству является простейшим спосо- бом, с помощью которого значения свойства, предназначенные для конструктора саг, можно передать в функцию-конструктор carlnLot. Для создания объекта carlnLot используйте следующее выражение. var carl = new carlnLot("AA 123", "Ford", "blue", "10:02AM", "31"); После выполнения этого выражения значения свойств объекта carl будут следующими. carl.timein carl.spaceNum carl.carinfo carl.plate carl.model carl.color // значение = "10:02AM" // значение = "31" // значение = ссылка на // значение = "АА 123" // значение = "Ford" // значение = "blue" конструктор объекта саг В данном случае можно сказать, что было создано пять объектов carlnLot (с carl по саг5). “Прототипность” проявляется, если, например, назначить новое свойство прототипу конструктора саг. car.prototype.companyOwned = true; Даже при том, что в объектах carlnLot используется конструктор саг, из экземпляров объектов carlnLot нельзя обратиться к объекту саг как к прототипу. Так как код остается прежним (даже при том, что в конструктор саг было добавлено свойство companyOwned), ни один объект carlnLot не наследует это свойство (даже если создать новый объект carlnLot после определения нового свойства prototype для саг). Чтобы экземпляры carlnLot могли наследовать свойство prototype. companyOwned, необходимо явно подключить прототип конструктора carlnLot к конструктору саг создания экземпляров объектов carlnLot. carlnLot.prototype = new car(); В конечном счете последовательность действий будет выглядеть следующим образом. function car(plate, model, color) { this.plate = plate || "missing"; this.model = model || "unknown"; this.color = color || "unknown"; } function carsInLot(plate, model, color, timein, spaceNum) { this.timeln = timein; this.spaceNum = spaceNum; this.carinfo = car; this.carlnfо(plate, model, color); } carsInLot.prototype = new car(); var carl = new carsInLot("123ABC", "Ford","blue","10:02AM", "32") car.prototype.companyOwned = true; После выполнения кода этого фрагмента значения свойств объекта carl будут следующими. carl.timeln // значение = "10:02АМ" carl.spaceNum // значение = "31" Глава 33. Функции и пользовательские объекты 1021
carl.carinfo carl.plate carl.model carl.color carl.companyOwned // значение = ссылке на конструктор саг // значение = "АА 123" и значение = "Ford" // значение = "blue" // значение = true Разработчики NN4+ добавили в этот браузер расширение синтаксиса прототипа. Это свойст- во __proto___(при его введении задается двойное подчеркивание до и после слова proto), в котором возвращается ссылка на следующий в последовательности прототипов объект. На- пример, если свойства carl._proto___вызываются после выполнения предыдущих опе- раторов, можно увидеть, что значения свойств следующего объекта прототипа такие. carl.____proto__.plate // значение = "АА 123" carl.____proto__.model // значение = "Ford" carl.____proto__.color // значение = "blue" carl.____proto__.companyOwned // значение = true Это свойство применяется при отладке пользовательских объектов и вызовов цепочки на- следования прототипов, но оно не является стандартом ЕСМА. Поэтому не рекомендуется использовать его в своих сценариях. Объект Object Свойства Методы constructor hasOwnProperty() prototype isPrototypeOf() propertylsEnumerable() toLocaleString() toString() valueOf() Синтаксис Создание объекта Object. function имяКонструктора([aprl, ... [,aprN]]) { оператор (ы) } var имяОбъекта = new имяКонструктора(["apr’l",... [,"aprN" ]); var имяОбъекта= new Obj ect(); var имяОбъекта = [свойство!:значение![, свойство2:значение2[,... N]}} Доступ к свойствам и методам объекта Obj ect. ссылкаНаОбъект. свойство | метод ( [параметры] ) Совместимость: WinIE4+, MacIE4+, NN3+, Mozl+, Safaril+ Описание объекта Такое имя объекта представляет собой некоторую тавтологию, но, несмотря на это, в сре- де JavaScript объект Obj ect является одним из наиболее важных. Это корневой объект, на ко- тором базируются все остальные объекты JavaScript — Date, Array, String и т.п. Object также используется для создания пользовательских объектов (см. ранее в данной главе). 1022 Часть IV. Объекты языка JavaScript
В принципе, никто не обращается к свойствам объекта Object. То же самое можно сказать и о многих его методах (toString () и valueOf ()), с помощью которых можно производить отладку в диалоговых окнах предупреждения (и в приложении The Evaluator). Такие окна пред- назначены для вывода нужной информации при обращении к объекту или его конструктору. Далее описываются наиболее популярные методы, которые используются для анализа среды прототипа экземпляра объекта. Прежде всего эти методы необходимы более опытным программистам, которые в своих сценариях используют мощную технологию моделирования объектно-ориентированных приложений. Методы hasOwnProperty("свойство") Возвращаемое значение: булево Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safari- Метод hasOwnProperty () возвращает true, если текущий экземпляр объекта облада- ет свойством, определенным в конструкторе или в соответствующей функции-конструкторе. Если это свойство определяется внешне (например, в результате присвоения ему свойства prototype объекта), метод возвращает false. Если использовать пример объектов саг и carlnLot, описанный ранее в этой главе, следующие выражения примут истинное значение. carl.hasOwnProperty("spaceNum"); carl.hasOwnProperty("model"); Даже при том, что свойство model определяется в конструкторе, который вызывается в другом конструкторе, оно соответствует объекту carl. Однако следующее выражение при- нимает значение false. carl.hasOwnProperty ("companyOwned"); Это свойство определяется для прототипа одной из функций-конструкторов и не является свойством, встроенным в экземпляр объекта. IsPrototypeOf (ссылкаНаОбъект) Возвращаемое значение: булево Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safari- Метод IsPrototypeOf () предназначен для определения того, является ли объект, пере- данный в качестве параметра, прототипом текущего объекта На практике версии этого метода в IE и NN/Moz не только по-разному функционируют — они вообще не используются ни в одном браузере для корректного определения зависимости между объектами. propertylsEnumerable ("свойство") Возвращаемое значение: булево Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safari- B терминологии спецификации ЕСМА-262 значение перечисляемо, если его можно кор- ректно использовать в таких конструкциях, как цикл проверки свойств for-in (глава 31). В перечисляемых свойствах могут храниться значения массивов, строк и, фактически, любые объекты. Если принять во внимание спецификацию ЕСМА, данный метод не должен рабо- тать по принципу прототипов. Глава 33. Функции и пользовательские объекты 1023
Глобальные функции и выражения дополнение ко всем объектам и позаимствованным из других языков конструкциям, которые были опи- саны в предыдущих главах этой книги, некоторые элементы языка необходимо рассмотреть более детально. Эти элементы не предназначены для определенных объектов (или объектов вообще), поэтому их можно использовать в любой части сце- нария. Большинство этих функций и выражений уже использо- вались в приведенных листингах программ. В данной главе перечислены все существенные элементы, о которых легко за- быть. В заключительной части главы приводится краткое опи- сание объектов, которые встроены в Internet Explorer и предна- значены только для использования в Windows. Более полную информацию вы найдете на информационном узле Microsoft. Прежде всего рассмотрим следующие глобальные функ- ции и выражения, которые используются в языке JavaScript. Функции decodeURI() decodeURIComponent О encodeURI() encodeURIComponent() escape() eval() isFinite() isNaNO Number() parseFloat() parselnt() toString() unescape() unwatch() watch() Выражения //и/*... */ (комментарии) const var
Глобальные функции не связаны с объектной моделью документа. Наоборот, обычно их используют для преобразования данных одного типа в другой. Существует незначительно количество глобальных выражений, однако некоторые из них используются практически в каждом сценарии. Функции decodeURI (11 кодировнныйиК!") decodeURIComponent (" элементКодированногоиН!") encodeURI (11 cwpoxaURI”) encodeURIComponent("элементик!") Возвращаемое Значение: строка Совместимость: WinIE5.5+, MacIE-, NN6+, Mozl+, Safari- B третьем издании стандарта ЕСМА-262, которому соответствуют IE5.5+, NN6+ и Mozilla, описываются вспомогательные функции, которые используют для более строгого преобразо- вания строк в допустимое строковое представление URI и наоборот. Раньше для этих опера- ций применяли функции escape () и unescape () (они описываются далее в этой главе). Функции кодировки предназначены для преобразования любой строки в форму, которую можно использовать как универсальный идентификатор ресурса (Uniform Resourse Identifier — URI), например, адрес Web-страницы или ссылка на CGI-сценарий сервера. В отличие от ла- тинских буквенно-цифровых символов, которые не изменяются при кодировке, в функции кодировки допустимо использовать как обычные символы, так и символы Unicode. Впослед- ствии они преобразуются в шестнадцатеричную форму (шестнадцатеричные числовые значе- ния символов), которая применяется для использования в Internet. Символ “пробел”, напри- мер, в шестнадцатеричном коде имеет значение %20. Возможно, наиболее существенная разница между функциями encodeURI () и escape () (и, соответственно, decodeURI () и unescape ()) состоит в том, что в последних версиях браузеров большинство символов не кодируется, хотя они и соответствуют синтаксису URI, рекомендованному в RFC2396 (http: // www. ietf .org/rfc/rfc2396. txt). Из это- го вытекает, что следующие символы нельзя кодировать с помощью функции encodeURI (). !-*' ( ) # Функции encodeURI () и decodeURI () используются только для уже полученных URL URI могут быть относительными и абсолютными, но эти две функции разработаны так, что символы, которые применяются при указании протокола (://), строки поиска (например, ? и =) или уровня каталога (/), не кодируются. Функция decodeURI () предназначена для обра- ботки URI, поступающих с серверов в виде ссылок на страницы. Однако помните, что CGI- программы некоторых серверов кодируют пробел как символ “плюс” (+), который нельзя де- кодировать в пробел с помощью функций JavaScript. Если в URI, который необходимо деко- дировать, вместо пробелов содержатся символы “плюс”, к этому декодированному URI сле- дует применить метод замены строк (в данном случае могут использоваться обычные строковые выражения). Для строк URI применяйте только те функции декодирования, кото- рые соответствуют функциям, используемым при их кодировании. Не пытайтесь декодиро- вать URI, созданный с помощью старой функции методом escape (), так как не все методы преобразования, используемые в нем, соответствуют современным правилам. Глава 34. Глобальные функции и выражения 1025
Разница между URI и элементом URI состоит в том, что элемент является отдельной ча- стью URI, в которой не содержатся символы-разделители. Например, при использовании функции encodeURIComponent () для полученного URI почти все символы (кроме точек) кодируются в шестнадцатеричный вид, включая разделители каталогов. Поэтому функции преобразования элементов следует использовать только для отдельных фрагментов URI. На- пример, при обработке строки поиска, в которой содержится пара имя-значение, функцию encodeURIComponent () можно использовать отдельно для имени и отдельно для значе- ния. Но если эту функцию применить к паре, которая уже имеет вид имя= значение, в ше- стнадцатеричном эквиваленте также будет преобразован символ равенства. Пример Попробуйте поэкспериментировать в приложении The Evaluator (глава 13) и найти разли- чия между кодированием полного URI и его элементов, а также кодированием и преобразо- ванием строки URI с помощью метода escape (). Например, сравним результаты следую- щих трех выражений. escape("http://www.giantco.com/index.html?code=42") encodeURI("ht tp://www.giantco.com/index.html?code=4 2") encodeURIComponent("http://www.giantco.com/index.html?code=42") Указанная строка URI является допустимой для обработки, поэтому после запуска функ- ции encodeURI () не происходит никаких изменений. Далее из строки поиска создайте строку, в которой содержится “пробел”, и посмотрите, как этот символ будет обрабатываться каждой из функций. escape("cvpoxaURI" [, 1]) unescape(" npeo6pCTpoxaURI”) Возвращаемое значение: строка Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safari- В поле адреса браузера часто можно увидеть URL, в котором содержится много символов % и чисел. Данный формат представляет собой кодированный URL (а точнее, кодированный URT). В этом формате можно отправлять большое количество слов и неалфавитно-цифровых сим- волов в виде одной непрерывной строки, состоящей из ограниченного набора общепринятых символов. При подобном кодировании в шестнадцатеричном представлении таких символов, как пробел, первым указывается символ процента. Например, шестнадцатеричное значение пробела — 20 (значение ASCH — 32), а в закодированном виде — %2 0. Следовательно, таким образом можно кодировать все символы, включая символы табуляции и перехода на другую строку, и передавать их как простую строку, которую легко декодировать и изменять на стороне приемника. Также этот способ можно использовать для предваритель- ной обработки большого количества строк текста, которые необходимо сохранить в виде од- ной строки символов в базах данных. Для кодирования строк обычного текста используйте метод escape (). Эта функция возвращает уже закодированный вариант введенного текста. var theCode = escape("Hello there"); // результат: "Hello%20there" He все (хотя многие) неалфавитно-цифровые символы конвертируются с помощью функ- ции escape (). Исключением составляет знак “плюс”, который используется в URL для раз- деления отдельных частей строки поиска. Если необходимо закодировать символ “плюс”, следует указать для функции второй необязательный параметр — тогда этот символ будет преобразован в шестнадцатеричный код (2В). 1026 Часть IV. Объекты языка JavaScript
var a = escape("Adding2+2"); // результат: "Adding%202+2 var a = escape("Adding2+2", 1); // результат: "Adding%202%2B2 Для декодирования полученной строки используют функцию unescape (). Она возвра- щает строку и преобразует все закодированные URL-строки, включая те, которые были зако- дированы с использованием необязательного параметра. В работе функция escape () напоминает сразу две более новые функции encodeURI () и encodeComponentURI (). Функцию escape () рекомендуется использовать для фраг- ментов URI (чаще всего это могут быть строки поиска). Если при выполнении сценария на этапе декодирования строк происходит сбой, проверьте, все ли функции, используемые для преобразования, одного типа; функцию unescape () применяйте только для строк URI, за- кодированных функцией escape (). / И наконец, вам следует знать о некоторых отличиях, которые имеют место при обработке символа @ в различных браузерах. Данный символ нельзя закодировать в IE, хотя в NN он преобразуется в значение %40. eval (" строка") Возвращаемое значение: строка Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Выполнение выражения, как может заметить любой программист, является довольно важ- ной операцией при написании сценария JavaScript (и программировании вообще). Выражение принимает некоторое значение. Однако иногда для получения определенных результатов с помощью выражения необходимо получить другое значение. Функция eval () преобразует строку таким образом, что в сценарии она расценивается, как выполняемое выражение. Пример С помощью функции eval () можно изменить значение любой инструкции или выражения JavaScript, сохраненных в виде строки. Это касается строковых эквивалентов арифметических выражений, присвоения значений объектам и обращения к методам объектов. Однако не реко- мендуется часто использовать данную функцию, так как она не всегда эффективна. К счастью, для перехода от строкового имени объекта к допустимой ссылке на объект функция eval () не требу- ется. .Например, если в циклах сценария обрабатывается некоторое количество объектов, в именах которых используются последовательные номера, вместо того, чтобы вызвать функцию eval () для получения ссылки на объект, применяются имена объектов в качестве индексов массива. Самый неэффективный способ управления полями с именами dataO, datal и т.д. приведен ниже. function fillFieldsO { var theObj; for (var i = 0; i < 10; i++) { theObj = eval("document.forms[0].data" + i); theObj.value = i; } } Более эффективный способ — это выполнение конкатенации в скобках индекса массива. function fillFieldsO { for (var i = 0; i < 10; i++) { document.forms[0].elements["data" + i].value = i; } } Глава 34. Глобальные функции и выражения 1027
Перед тем, как вызвать функцию eval О, попробуйте найти способ примене- Совет ния строкового значения индекса массива объектов. В стандарте W3C DOM обращение к объектам можно осуществить еще проще — с помощью метода document.getElementByld(), в котором строка передается как параметр, и в результате возвращается ссылка на нужный объект. IsFinite(число) Возвращаемое значение: булево Совместимость: WinIE4+> MacIE4+, NN4+, Mozl+, Safari 14- Функцию isFinite О практически никто и никогда не использует. Однако следует отме- тить, что ее предназначение состоит в определении того, находится ли некоторое число в диапа- зоне допустимых для обработки в JavaScript значений. Если число не принадлежит этому диапа- зону, функция возвращает false. Параметр функции должен иметь числовой тип данных. IsNaN(выражение) Возвращаемое значение: булево Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Для экземпляров, в которых выполняются арифметические операции с данными, посту- пающими из текстовых полей или других источников строковых значений, рекомендуется проверить, является ли полученное значение числом. Если значение числом не является, то при выполнении определенных вычислений может возникнуть ошибка. Пример Для предварительной проверки обрабатываемых значений используйте функцию isNaN (). Наиболее часто ее вызывают для проверки результата выполнения функций parselnt () и parseFloat (). В ситуации, когда строковые значения, предназначенные для обработки в этих функциях, не могут быть преобразованы в числовые, результатом будет значение NaN (специальный символ, обозначающий “не является числом”). Таким образом, если значение не является числом, функция isNaN () возвращает true. Следовательно, эту функцию используют для выявления несовместимости данных перед выполнением с ними необходимых операций. function calc(form) { var inputvalue = parselnt(form.entry.value); if (isNaN(inputvalue)) { alert("You must enter a number to continue."); } else { операторы вычисления } } Наиболее распространенная ошибка программистов при использовании данной функции состоит в том, что не все в точности соблюдают указанный регистр символов в ее имени. Часто пропускают верхний регистр в символе N. Number("строка") parseFloat("строка") parselnt (11 строка" [, основа] ) Возвращаемое значение: числовое Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ 1028 Часть IV. Объекты языка JavaScript
Все три функции предназначены для преобразования строкового значения в числовое. Функции parselnt () и parseFloat () совместимы с любыми версиями браузеров, в отличие от функции Number (), применяемой только в NN4 и IE4. Функцию Number () используют в случаях, когда не требуется особая точность, и значе- ние, полученное из текстового поля, обрабатывается независимо от того, принадлежит оно к типу чисел с плавающей запятой или к целым числам. В функцию передается единственный параметр — это строка, которую необходимо преобразовать в числовое значение. С помощью функции parseFloat () можно определить тип возвращенного значения: float или integer. Если в полученной строке содержится любое дробное ненулевое значе- ние, результатом является “число с плавающей запятой”. Но если строковое значение, к при- меру, имеет вид 3.00, возвращается “целочисленное значение”. Указав дополнительный параметр в parselnt (), можно определить основание системы исчисления преобразуемого числа. Если этот параметр не определен, компилятор JavaScript пытается определить его самостоятельно, при этом могут возникнуть некоторые проблемы. Основная проблема возникает, если строковое значение параметра parselnt () начинается с нуля, который мог быть получен из текстового поля или поля базы данных. В JavaScript числа, начинающиеся с нуля, обрабатываются как восьмеричные (основание 8). Поэтому ре- зультатом parselnt (" 010 ") будет десятичное значение 8. Используя функцию parselnt () при работе с десятичными числами, следует опреде- лять основание системы счисления как 10. Вы также вправе определить любое значение ос- нования системы исчисления в диапазоне от 2 до 36. Например, для того чтобы преобразо- вать строку двоичного значения в десятичное, укажите основание системы исчисления равным 2, как показано ниже. var n = parselnt ("011", 2); // результат: 3 Аналогично выполняется преобразование строки с шестнадцатеричным значением в деся- тичный эквивалент — для этого следует определить основание системы счисления 16. var n = parselnt ("4F", 16); // результат: 79 Пример И в parselnt (), и в parseFloat () существует одна очень важная особенность: если переданная в качестве параметра строка начинается хотя бы с одной цифры, за которой сле- дуют буквенные символы, в функции обрабатывается только та часть строки, в которой со- держатся цифры (остальные символы не принимаются во внимание). Поэтому можно исполь- зовать parseFloat () для строки navigator.appVersion, при обработке которой результатом будет только номер версии, а остальная часть строки анализироваться не будет. Например, в WinNN6 значение navigator. appVersion выглядит следующим образом. 5.0 (Windows; en-US) С помощью parseFloat () можно получить только числовую часть строки. var ver = parseFloat (navigator.appVersion) Поскольку рёзультатом является число, существует возможность выполнить сравнение, например, для проверки того, является ли версия данного браузера большей или равной 4. toString([основа]) Возвращаемое значение: строковое Совместимость: WinIE4+, MacIE4+, NN4+, Mozl+, Safari 1+ Глава 34. Глобальные функции и выражения 1029
Для каждого объекта языка JavaScript и каждого объекта document в DOM существует соответствующий метод toString (). Он используется для обработки (компиляции) содер- жимого объекта наиболее приемлемым способом. В табл. 34.1 приведены результаты приме- нения метода toString () для каждого из преобразуемых типов объекта language. Т0ИЧ» W. 1.праменениа WTOJH trios О *Ирияжжи Тип объекта Результат Строковый Численный Булев Массив Та же строка Строковый эквивалент (числовые символы не преобразуются) true или false Список элементов массива, разделенных между собой запятыми (после запятых пробел не используется) Функция Декомпилированное строковое определение функции Преобразовать в строку можно многие объекты DOM. Например, объект location воз- вращает собственный URL. Однако, если в объекте не содержится данных, которые можно преобразовать в строку, как правило, возвращается строка следующего вида. [obj ect типОбъекта] Пример Метод toStringO доступен во всех версиях браузеров. Для преобразования чисел с различными основаниями в их строковые эквиваленты устанавливайте значение параметра в пределах от 2 до 16. В листинге 34.1 вычисляется и выводится на экран таблица преобразо- вания для десятичных, шестнадцатеричных и двоичных значений, принадлежащих диапазону от 0 и 20. В этом случае исходным значением является индекс, получаемый из переменной- счетчнка при каждом выполнении операторов цикла. йнпвй'МКШмтаемтв tx>etxl*g() с тйкйммм еемвий 4гЛ Г ( Н ш Л t. <html> <head> <title>Number Conversion Table</title> </head> <body> <b>Using toStringO to convert to other number bases:</b> <hr / > «table border="1"> <tr> <th>Decimal</th> <th>Hexadecimal</th> <th>Binary</th> «script type="text/javascript"> var content = ""; for (var i = 0; i <= 20; i++) { content + = " < t r > " ; 1030 Часть IV. Объекты языка JavaScript
content += "<td>" + i.toString(10) + "<\/td>"; content += "<td>" + i.toString(16) + "<\/td>"; content += "<td>" + i.toString(2) + "<\/tdx\/tr>" ; } document.write(content); </script> </tr> </table> </body> </html> Метод toString () нельзя использовать для преобразования определенных пользовате- лем объектов в строку, имеющую смысл в обычном понимании, но программист может соз- дать свой собственный метод, предназначенный только для этой операции. Например, если необходимо, чтобы в методе toString () пользовательский объект обрабатывался подобно массиву, определите действие метода и присвойте эту функцию свойству объекта (как пока- зано в листинге 34.2). <html> <head> <title>Custom toString()</title> <script type="text/javascript"> function customToString() { var dataArray = new Array(); var count = 0; for (var i in this) { dataArray[count++] = thisfi]; if (count >2) { break; } } return dataArray.j oin(" , ") ; var book = {title:"The Aeneid", author:"Virgil", pageCount:543}; book.toString = customToString; </script> </head> <body> <b>A user-defined toString() result:</b> <hr /> «script type="text/javascript"> document.write(book.toString()); </script> </body> </html> При выполнении листинга 34.2 с помощью метода toString () объекта custom мож- но получить значения всех элементов объекта, кроме последнего, который является ссыл- кой на функцию обработчика. Программист вправе сам определять имена данных и/или их форматирование. Глава 34. Глобальные функции и выражения 1031
unwatch (свойство) watch(свойство, обработчик) Возвращаемое значение: нет Совместимость: WinlE-, МасЕ-, NN4+, Moz-, Safari- В NN4+ для передачи во внешние отладчики правильной информации в JavaScript пред- ставлено две глобальные функции, которые можно использовать для любого объекта (даже определяемого пользователем). Метод watch () используется для “слежения” за определен- ным свойством объекта. Если это свойство установлено в результате присвоения, функция вызывает другую определяемую пользователем функцию, в которую передается информация об имени свойства, а затем его старое и новое значение. С помощью функции unwatch мож- но “отключить” возможность наблюдения за определенным свойством. Выражения и /*...*/ Совместимость: WinE3+, МасШЗ+, NN2+, Mozl+, Safaril+ Выражения, которые не обрабатываются компилятором JavaScript (или компилятором сер- вера), называются комментариями. В этих операторах программист может делать пометки о рабо- те того или иного фрагмента сценария. С одной стороны, подробные комментарии полезны для разработчиков при создании сценария и его поддержке, но с другой стороны, при загрузке доку- мента загружаются и все содержащиеся в нем комментарии. Для загрузки каждого байта необ- рабатываемого содержимого страницы требуется немного больше времени. Несмотря на это, рекомендуется использовать как можно больше комментариев, особенно при создании сценариев. В JavaScript существует два вида комментариев. Один из них состоит из двух косых черт (между которыми не используется пробел). Все символы, расположенные справа от них в этой же строке, не обрабатываются, даже если они расположены в середине строки. Можно исполь- зовать любое количество подобных однострочных комментариев для того, чтобы точно пере- дать свою мысль. Для удобства восприятия текста между второй наклонной чертой и началом комментария ставят пробел. Далее приведен пример использования однострочных комментариев. // в этой строке описывается дальнейшее действие var = "Fred"; // комментарий этой строки // Если комментарий состоит из нескольких // предложений, начинайте каждое из них с // заглавной буквы И // Можно оставлять пустую строку, как показано выше. Для более длинных комментариев обычно используют другой синтаксис. В начале ком- ментария располагают косую черту и звездочку (/*), а в конце те же символы, только в об- ратном порядке (*/). Все операторы и строки между ними компилятором не обрабатывают- ся. Если необходимо быстро закомментировать большую часть программы для отладки сценария, выполните это с помощью многострочного комментария. Для того чтобы проще найти блоки комментариев в программе, для символов (/*) и (*/) отводят отдельные строки. /* некоторые закомментированные 1032 Часть IV. Объекты языка JavaScript
операторы V Если разрабатываемый документ имеет сложную структуру, использование комментариев является наиболее удобным способом организации фрагментов программы и их поиска. На- пример, перед каждой функцией можно разместить блок комментариев, в которых будет опи- сано ее назначение. /* ---------------------------------------------- calculated Выполняются вычисления, основанные на параметрах .... Вызывается с помощью blah blah blah. -------------------------------------------------*/ function calculate(form){ операторы } const Совместимость: WinlE-, MacE-, NN6+, Mozl+, Safari- Ключевое слово const, как правило, используют при инициализации константы. В отли- чие от переменной, содержимое которой изменяется в процессе загрузки страницы, установ- ленное значение константы не может быть изменено. Во многих языках программирования для идентификаторов постоянных используют прописные буквы; если в имени содержится несколько слов, их разделяют символами подчеркивания. Так программистам легче различать константы и переменные, используемые в программе. Пример Данная методика демонстрируется в листинге 34.3, код которого выполняется в NN6+/Mozl+. На приведенной странице выводятся данные о среднесуточной температуре в нескольких горо- дах. (Возможно, при запросе этой страницы пользователем данные изменяются на сервере и со- храняются в массиве данных.) Температура ниже нуля выделяется специальным стилем. Эта температура является постоянной контрольной точкой, поэтому она хранится в константе. <html> <head> <title>const(ant)</title> <style type="text/css"> .cold {font-weight:bold; color:blue} td {text-align:center} </style> <script type="text/javascript"> const FREEZING_F = 32; var cities = ["London", "Moscow", "New York", "Tokyo", "Sydney"]; var tempsF = [33, 12, 20, 40, 75]; function showDatad { var tableData = ""; for (var i = 0; i < cities.length; i++) { tableData += "<trxtd>" + cities [i] + "<\/tdxtd "; tableData += (tempsF[i] < FREEZING_F) ? "class='cold'" : "" tableData += ">" + tempsF[i] + "<\/tdx\/tr>"; } document.getElementByld("display").innerHTML = tableData; Глава 34. Глобальные функции и выражения 1033
} </script >,. </head> <body onload="showData()"> <hl>The const keyword</hl> <hr /> <table id="temps"> <tr> <th>City</th> <th>Temperature</th> </tr> <tbody id="display"></tbody> </table> </body> </html> Возможно, ключевое слово const будет включено в новую версию стандарта ЕСМА-262 и станет широко использоваться в сценариях JavaScript, разрабатываемых следующими вер- сиями браузеров. var Совместимость: WinIE3+, MacIE3+, NN2+, Mozl+, Safaril+ Перед использованием переменную необходимо объявить (и инициализировать, устано- вив некоторое значение) в выражении var. Если ключевое слово var пропущено, перемен- ная автоматически становится глобальной для текущего документа. Чтобы переменная оста- валась локальной для данной функции, ее следует объявить или инициализировать (при этом укажите ключевое слово var внутри фигурных скобок функции). Если никакое конкретное значение переменной не присваивается, в ней хранится значение null. Поскольку тип переменной в JavaScript может изменяться в процессе выполнения сценария, не стоить присваивать переменной пустую строку или нуль, если это не требуется для каких-либо операций. Например, если инициализировать переменную как пустую строку, впоследствии с по- мощью оператора приращения (+=) можно присоединить к этой строке новое значение. Также допускается объявлять и/или инициализировать несколько переменных, используя для них один оператор var (укажите его в каждой строке для содержащихся в ней перемен- ных). В таких случаях пары имяПеременной= значение отделяют друг от друга запятыми. var name, age, height; // простое объявление var color="green", temperature=85.6; // инициализация Имена переменных (или идентификаторы) должны представлять собой одну непрерывную строку символов, причем первый символ должен быть буквенным. Также запрещено исполь- зовать символы пунктуации, хотя символ подчеркивания допустим; он довольно часто ис- пользуется для разделения нескольких слов, из которых состоит имя переменной. В именах переменных (подобно большинству идентификаторов в JavaScript) имеет значение регистр, поэтому следует называть переменные в соответствии с их назначением. Объекты WinlE Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Одной из особенностей продукции компании Microsoft является оснащение операционной системы Windows функциональными возможностями Web-браузера. Объединение браузера и операционной среды наиболее четко просматривается в средствах Internet Explorer доступа к объектам ActiveX. В версиях WinlE разработано несколько подобных объектов. С помощью некоторых из них в JavaScript можно использовать возможности Visual Basic Script (VBScript). 1034 Часть IV. Объекты языка JavaScript
Поскольку данные объекты применяются только в Windows и программных средствах Ac- tiveX, в этом разделе специфика работы с ними в WinlE описывается не полностью. Для тех, кто совершенно не знаком с этими средствами, далее перечислены основные объекты WinlE. Более подробное описание данной технологии вы найдете на информационном узле в Micro- soft Developer Network (MSDN); ниже приведены соответствующие URL. В этом разделе рассматриваются следующие объекты: ActiveXObject, Dictionary, Enumerator, FileSystemObject и VBArray. В Microsoft эти объекты считаются частью языка JScript. Однако при работе с ними можно убедиться, что они являются собственными объектами Internet Explorer, причем только его версий для Windows. ActiveXObject ActiveXObject представляет собой универсальный объект, с помощью которого можно открывать и обращаться к тому, что в терминологии Microsoft иногда называется объектами автоматизации. Объект автоматизации— это программа, которая запускается на стороне клиента или обслуживается с сервера. В ней могут содержаться локальные приложения — программы Microsoft Office, исполняемые файлы DLL и т.д. Для получения ссылки на объект используйте следующий конструктор ActiveXOb j ect. var objRef = new ActiveXObject (appName.className [, remoteServerName]); Подобный синтаксис JScript используется в методе VBScript CreateObj ect (). Для того чтобы определить имя приложения и класса или типы, совместимые с этим приложением, не- обходимо иметь некоторые знания в области программирования Windows. Например, для по- лучения ссылки на рабочий лист Excel используется следующий конструктор. var mySheet = new ActiveXObject("Excel.Sheet"); При получении ссылки на объект следует также знать имена свойств и методов объекта, к которым нужно обратиться. Ко многим элементам можно обращаться с помощью специ- альных средств, разработанных компанией Microsoft, например, Visual InterDev, или инстру- ментов Visual Basic. Используя данные средства, вы вправе запросить объект для определе- ния его свойств и методов. К сожалению, свойства ActiveXObject нельзя перечислить в обычном контролере свойств JavaScript for- in. При доступе к ActiveXObject (особенно на стороне клиента) необходимо обеспечить определенную защиту. Установка обычной защиты, разработанной в Internet Explorer, пре- дотвращает доступ сценариев к приложениям клиента (во всяком случае, выводится запрос на подтверждение пользователем соответствующих полномочий). Говорить о том, что данные защищены надежно, нельзя. В общей среде, в которой достаточен гарантированный доступ ко всем клиентам, предлагается установка на принятие объектов ActiveX, исходящих из про- веренного источника. И наконец, если вы достаточно сведущи в вопросах программирования в Windows, не нужно ожидать, что с помощью ActiveXObj ect у вас появится возможность вторжения в область личных данных ничего не подозревающих пользователей. Dictionary Даже если объект Dictionary и является очень полезным при написании сценариев VBScript, в JavaScript уже разрабатывается эквивалентная возможность. Объект Dictionary работает подобно массиву JavaScript, который имеет строковые значения индекса (подобно хеш-таблице Java), хотя числовые индексные значения в Dictionary также приемлемы. В данном случае индексы называют ключами. Такое средство не является родным для масси- вов VBScript, следовательно, объект Dictionary используется в этом языке для обеспече- ния дополнительных возможностей. Однако, в отличие от массива JavaScript, в данном случае следует использовать различные свойства и методы объекта Dictionary для добавления, обращения или удаления его элементов. Глава 34. Глобальные функции и выражения 1035
При создании объекта Dictionary с помощью ActiveXObject применяется следую- щая структура. var diet = new ActiveXObject("Scripting.Dictionary"); Вам необходимо создать отдельный объект Dictionary для каждого массива. В табл. 34.2 приведены его свойства и методы. После создания пустого объекта Dictionary заполняйте его данными, применяя к каждому элементу метод Add (). Ниже приводится пример созда- ния объекта Dictionary для хранения названий столиц штатов США. var statecaps = new ActiveXObject("Scripting.Dictionary") statecaps.Add("Illinois", "Springfield"); Теперь можно обращаться к отдельным элементам, используя свойство Key (которое бла- годаря наследию VBScript выглядит, как метод JavaScript). Метод Key () является довольно удобным в объекте Dictionary; он возвращает массив всех ключей этого объекта в таком фор- мате, который затем можно использовать в индексированных строковых массивах JavaScript Таблиц 34.5. CasHfwe к метади сtionary Свойство Описание Count Определяется количество элементов в Dictionary (предназначено только для чтения) Item("ключ”) Используется для чтения или записи значений элементов с именем ключ Key("ключ”) .Используется для присвоения элементу нового ключевого имени Метод Описание Add("ключ", значение) Прибавляются значения, связанные с уникальным ключевым именем Exists("ключ") Если указанный ключ существует в словаре, возвращается булево true Items() Возвращаются значения VBArray, содержащиеся в словаре Keys() Возвращаются ключи VBArray, содержащиеся в словаре Remove("ключ” ) Используется для удаления ключ и его значения RemoveAll() Используется для удаления всех элементов Для получения более подробной информации посетите узел http: //msdn. microsof t. com/ scripting/jscript/do с/jsobjDictionary.htm. Enumerator Объект Enumerator используется в JavaScript для обеспечения доступа к множествам, прямой доступ к элементам которых (с помощью индекса или имени) невозможен. Этот объект не используется при работе с такими множествами DOM, как document .all (в этом случае для получения ссылки на любой из элементов всегда можно использовать метод item ()). Однако, если в сценарии используются объекты ActiveX, некоторые методы или свойства этих объектов могут возвращать множества, к которым нельзя обращаться данным способом или с помощью контролера свойств JavaScript for - in. Вместо этого необходимо поместить множество в объект Enumerator. Для выполнения данной операции вызовите конструктор объекта, передав множество в качестве параметра. var myEnum = new Enumerator(наборЭлементов); 1036 Часть IV. Объекты языка JavaScript
К экземплярам этого объекта можно обратиться, используя любой из четырех методов для установки “указателя” на определенный элемент и получения копии этого элемента. Другими словами, к элементу не обращаются непосредственно (т.е. не используется его порядковый номер в множестве). Вместо этого указатель перемещают на нужную позицию, а затем счи- тывается значение соответствующего элемента. Как видно из списка методов, приведенных в табл. 34.3, этот объект предназначен для обработки множества в цикле. Для управления указателем его устанавливают на позицию, соответствующую началу множества, затем зна- чение увеличивается — таким образом обеспечивается доступ ко всем элементам. myEnum.moveFirst() for (; !myEnum.atEnd(); myEnum.moveNextО) { val = myEnum.item(); // выражения обработки значений } Метод Описание atEnd() item() moveFirst() moveNext() Если указатель соответствует концу множества, возвращается true Возвращается значение текущей позиции указателя Указатель перемещается на первую позицию в множестве Указатель перемещается на следующую позицию в множестве VBArray С помощью объекта VBArray в JavaScript обращаются к безопасным массивам Visual Ba- sic. Это могут быть массивы, предназначенные Только для чтения, которые обычно возвра- щаются объектами ActiveX. Подобные массивы могут создаваться в разделах VBScript кли- ентских сценариев. Массивы Visual Basic по своей природе могут иметь любую размерность. В следующем примере создается VB-массив размерностью “3x2”. <script type="text/vbscript”> Dim myArray(2, 1) myArray(0, 0) = "A" myArray(0, 1) = "a" myArray(1, 0) = "B" myArray(1, 1) = "b" myArray(2, 1) = "C" myArray(2, 2) = "c" </script> После получения массива VB можно преобразовать его в объект, который не ограничива- ется интерпретатором JScript. < script type="text/javascript"> var theVBArray = new VBArray(myArray); </scripts К глобальным переменным одного блока языка сценариев можно обращаться из другого блока или даже на другом языке. Но в этом случае массив уже не является массивом JavaScript. Его можно преобразовать в таковой с помощью метода VBArray. toArray () или получить информацию об объекте VBArray, используя другие методы (кратко описанные в табл. 34.4). После преобразования VBArray в массив JavaScript можно использовать эти значения в лю- бом массиве JavaScript. Глава 34. Глобальные функции и выражения 1037
Метод Описание ч dimensions() getltem(diml [, dim2[,...dimN]]) Возвращается размерность оригинального массива Возвращается ссылка на массив, определенная адресами размерности ibound(dim) Возвращается низшее значение индекса для данной размерности toArray() Возвращается VBArray, преобразованный в массив JavaScript ubound(dim) Возвращается высшее значение индекса для данной размерности При использовании метода toArray () для массива с различной размерностью значения размерностей после первой “строки” просто прибавляются к массиву JavaScript (при этом вложенная структура не используется). 1038 Часть IV. Объекты языка JavaScript
Текстовые объекты тела страницы Определенное количество HTML-элементов относит- ся к категории средств, предназначенных для реше- ния более конкретных задач, чем управление контекстно- зависимыми объектами, рассмотренными в главе 15. В эту группу входят некоторые широко используемые элементы, например, элементы заголовка hl-hG, а также элементы, ко- торые в данный момент используются нечасто, поскольку для обеспечения их полной поддержки не хватает техниче- ских средств даже в самых современных браузерах. В этой главе рассмотрены все виды объектов, связанные с представ- лением текста на странице. К ним не относятся объекты, ко- торые представляют элементы управления формы (текстовые окна и другие элементы, рассмотренные в главе 23). Пре- имущественно эта глава посвящается объектам, рассматри- ваемым в главе 15: их свойствам, методам и обработчикам событий. В этой главе, в основном, рассмотрены средства, уникальные для каждого конкретного объекта (общие сред- ства объектов будут описаны в других главах книги). Кроме объектов HTML-элементов, в этой главе также речь пойдет об объекте TextRange (впервые представлен- ном в Ш4), а также о соответствующем ему объекте Range стандарта W3C DOM. Этот объект— достаточно мощное средство в сценариях, поскольку он позволяет на самом де- тальном уровне управлять содержимым тела страницы, от- личающимся от представляемых свойствами InnerText или nodeValue элементов. Чаще всего такой объект пред- ставляет текст, заданный в виде абзацев и списков, которые пользователь видит на экране. Объекты TextRange и Range предоставляют возможность управления курсором в сцена- рии при выполнении операций обработки содержимого стра- ницы (вырезания, копирования, вставки, а также утилит, производных от основных операций например, поиска и за- мены. Примите во внимание, что для использования средств, описание которых приведено в этой главе, вам потребуются браузеры не младше Ш4+ и NN6+/W3C; в некоторых случаях необходимо будет обратиться к браузеру ВЕ версии 5+. К со- жалению, в Мас1Е5+ объект TextRange не используется.
Объекты элементов blockuote и q Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойства, методы и обработчики событий объектов этих HTML-элементов описаны в главе 15. Свойства Методы Обработчики событий cite Синтаксис Доступ к свойствам и методам объектов этих элементов. (IE4+) [window. ] document .all. идентификатор. свойство | метод ( [параметры] ) (IE5+/W3C) [window.] document. getElementByld ("идентификатор") . свойство[ме- тод] [параметры] ) Описание объектов Элемент blockuote представляет собой специальный текстовый контейнер. Как прави- ло, браузеры начинают построение содержимого страницы с отдельной строки и делают от- ступ справа и слева от краев страницы приблизительно на 40 пикселей. Цитата вставляется в q-элемент, который не предусматривает перенос содержимого на следующую строку. С точки зрения объекта, единственным свойством, отличающим эти два объекта от подобно- го рода текстовых контейнеров, является cite (берет начало от атрибута cite в HTML 4.0). Данный атрибут обеспечивает URL-ссылку на цитату и не пересекается с атрибутами загруз- ки внешнего документа src и href. Свойство cite Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ 'Свойство cite может содержать URL (в виде строки), указывающий на источник ци- таты в элементе blockuote или элементе q. В будущем браузеры для управления доку- ментом будут содержать специальные пользовательские средства, однако ни один совре- менный браузер, поддерживающий свойство cite, пока не осуществляет никаких действий по обработке этой информации. Объект элемента br Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойсгва, методы и обработчики событий этого HTML-элемента описаны в главе 15. Свойства . Методы Обработчики событий clear 1040 Часть IV. Объекты языка JavaScript
Синтаксис Доступ к свойствам и методам объекта элемента Ьг. (IE4+) [window. ]document. all. идентификатор. свойство \ метод ([параметры] ) (IE5+/W3C) [window. ] document.getElementByld ("идентификатор”) . свойство]ме- тоде [параметры] ) Описание объекта Элемент Ьг осуществляет операции возврата каретки и перевода строки, часто применяе- мые при форматировании содержимого страницы. Он не обеспечивает такой междустрочный интервал, как между абзацами, что задается элементом р. Элемент Ьг отличается от стан- дартных элементов и объектов HTML наличием атрибута clear. Свойство clear Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойство clear определяет, как текст в элементе, следующем после элемента Ьг, обте- кает плавающий элемент (например изображение, плавающее вдоль правой границы). По- скольку браузеры последних версий не поддерживают это свойство, атрибут, на котором оно основано, в спецификации HTML 4.0 не представлен. Вместо него рекомендуется использо- вать атрибут clear таблицы стилей для Ьг-элемента. Свойство clear может принимать одно из следующих значений: all, left или right. См. также: свойство clear таблицы стилей. Объект элемента font Совместимость: WinIE44-, МасЕ44-, NN6-I-, Mozl-t, Safari 14- Свойства, методы и обработчики событий этого HTML-элемента описаны в главе 15. Свойства Методы Обработчики событий color face size Синтаксис Доступ к свойствам и методам объекта элемента FONT. (IE4+) [window.]document.all.идентификатор.свойство|метод([параметры]) (IE5+/W3C) [window. ] document. getElementByld ("идентификатор”) . свойство| ме- тод( [параметры]) Глава 35. Текстовые объекты тела страницы 1041
Описание объекта С точки зрения стандартного способа форматирования содержимого,,элемент font вна- чале отображался как объект только браузерами, поддерживающими каскадные таблицы сти- лей, в качестве наиболее предпочтительного метода управления гарнитурой шрифта, его цве- том и размером. Однако доминирующее положение таблиц стилей не означает, что вы не сможете использовать элемент font при разработке страниц с помощью средств современных браузеров — этот элемент удобнее использовать при построении небольшой страницы, которая должна быть совместимой сверху вниз (поддерживаться старыми версиями браузеров). Однако он вряд ли удовлетворит запросы программиста, желающего использовать сценарии для изме- нения параметров шрифтов содержимого тела страницы после загрузки страницы. Поэтому придерживайтесь эмпирического правила, согласно которому элемент font (свойства объекта элемента font) используют только в том случае, если необходимо, чтобы страница поддер- живалась всеми версиями браузеров. Таблицы стилей (и их свойства) применяются при раз- работке страниц, отображаемых исключительно с помощью браузеров IE4+ и NN6+/W3C. Свойства color Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Управление цветом объекта font можно осуществлять с помощью свойства Color. Зна- чение цвета представляется либо в виде шестнадцатеричных триплетов (например #FFCCFF), либо названия цвета, распознаваемого большинством браузеров. В любом случае, при зада- нии значения различие между прописными и строчными символами не отслеживается. Пример Листинг 35.1 содержит код страницы, в котором продемонстрированы три свойства объ- екта элемента font: color, face и size. В нем также показан самый эффективный способ изменения значений этих свойств с помощью метода setAttribute (). Код этого листинга корректно выполняется всеми браузерами, хотя списки select позволяют изменить текст только в IE4+ и NN6+/W3C. Элемент р имеет дочерний элемент font, содержащий три слова, форматирование кото- рых зависит от значений, выбранных в списках select. Каждый список задает одно из свойств объекта font, а их атрибуты name умышленно приравниваются к именам этих свойств; атрибуты value элементов option содержат строки, назначаемые в качестве значений опи- санных выше свойств. Каждый элемент select вызывает функцию setFontAttr (), переда- вая ей в качестве аргумента ссылку на себя. Первая задача функции setFontAttr () — это проверка поддержки браузером элемента font. Старые браузеры не поддерживают элементы document.all и myFont, а потому в них функция не выполняется. После успешного выполнения теста функция извлекает строку из значения value элемента select, передаваемую в качестве аргумента. Если в списке выбрано значение (отличное от пустой строки), то атрибут с названием, совпадающим с именем элемента select, получает значение. 1042 Часть IV. Объекты языка JavaScript
Досадная ошибка в MacIE не позволяет корректно установить цвет текста с по- мощью этого кода. Правильность кода не вызывает сомнений, поскольку осталь- ные два свойства поддаются изменению. «html» <head> <title»Font Object Properties«/title» <script type="text/javascript"» // общая функция, выполняющая все задачи function setFontAttr(select) { var choice = select.options[select.selectedlndex].value; if (choice) { document.getElementByld("rnyFONT").setAttribute(select.name, choice); } } </script> </head> <body> <hl>Font Object Properties«/hl» <br /» <p>This may look like a simple sentence, but <font id="rnyFONT"»THESE THREE WORDS</font> are contained by a FONT element.</p» <form> Select a text color: <select name="color" onchange="setFontAttr(this)"> <optionx/option> «option value="red">Red</option» «option value="green">Green«/option> «option value="blue">Blue«/option> «option value="#FA8072"»Some Hex Triplet Value</options «/selectxbr /» Select a font face: «select name="face" onchange="setFontAttr(this)"> «option>«/option> «option value="Helvetica">Helvetica«/option» «option value="Times"»Times«/option» «option value="Comic Sans MS, sans-serif">Comic Sans MS, sans-serif«/option> «option value="Courier, monospace">Courier, monospace«/option> «option value="Zapf Dingbats, serif">Zapf Dingbats, serif«/option> </select»«br /> Select a font size: «select name="size" onchange="setFontAttr(this)"> <option»«/option> «option value="3">3 (Default)«/option» «option value="+l"»lncrease Default by l«/option> «option value="-l"»Decrease Default by l«/option» «option value="l"»Smallest«/option» «option value="7"»Biggest</option» «/select» «/form» «/body» </html> См. также: атрибут color таблицы стилей. Глава 35. Текстовые объекты тела страницы 1043
face Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Типом шрифта объекта font можно управлять с помощью свойства face. Как и в случае с атрибутом face (и соответствующим ему атрибутом font-family таблицы стилей), в стро- ке с разделителем-запятой можно задать одно или несколько значений. Браузеры отображают текст с помощью шрифта, который указан самым первым в списке для текущего элемента. Пер- вый найденный в клиентской системе тип шрифта применяется к тексту, окруженному элемен- том font. Сначала необходимо задать список наиболее часто используемых шрифтов. Разре- шите отображать содержимое с помощью первичных гарнитур шрифта (sans-serif, serif и monospace); тем самым вы определите тип шрифта для тех систем, в которых не установле- ны шрифты, которые указаны в начале списка. Если вы уверены, что Windows отображает текст необходимым шрифтом, a Macintosh — другим, но похожим шрифтом с другим име- нем, то названия обоих шрифтов можно задать в одном и том же значении свойства. Браузер пропускает имена шрифтов, не установленных в данный момент на стороне клиента. Пример В листинге 35.1 приведен пример использования этого свойства элемента font. Вы не всегда будете видеть эффект изменения форматирования текста при выборе другого варианта шрифта в соответствующем списке, поскольку этот шрифт может быть не установлен в системе. См. также: атрибут font - family таблицы стилей. size Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Размером шрифта, указанным в элементе font, можно управлять с помощью свойства size. В отличие от рекомендуемого для использования атрибута font-size стиля, свойство size объекта элемента font (и соответствующего ему атрибута size) имеет ограничение на представляемое значение, обусловленное использованием в более ранних версиях HTML только относительного формата представления размера шрифта (1-7). Значения свойства size — это строки, иногда представленные в виде числовых значе- ний. Можно определить относительный размер заданного по умолчанию шрифта с помо- щью знака “плюс” или “минус”, вводимого перед значением. Например, если размер шрифта, заданный по умолчанию (в наборе установок пользователя), равен 3, то можно изменить раз- мер текстового фрагмента, вставив его внутрь элемента font и изменив впоследствии свой- ство size до значения +2. Чтобы более точно задать размер шрифта с помощью других единиц измерения (пикселей или точек), можно использовать атрибут font-size таблицы стилей. Пример В листинге 35.1 приведен пример использования этого свойства элемента font. См. также: атрибут font-size таблицы стилей. Объекты элементов h1-h6 Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойства, методы и обработчики событий HTML-элементов описаны в главе 15. 1044 Часть IV. Объекты языка JavaScript
Свойства Методы Обработчики событий align Синтаксис Доступ к свойствам и методам объектов элементов hl-h6. (IE4+) [window. ]document,all.идентификатор, свойство|метод([параметры] ) (IE5+/W3C) [window. ] document. getElementByld (" идентифика тор") . свойство | ме - тод( [параметры] ) Описание объектов Так называемые объекты заголовка (обозначаемые hl, h2, h3, h4, h5 и h6) предостав- ляют возможность эффективного форматирования документа, соответственно, шести различ- ным уровням и подуровням предоставления информации. Вы можете имитировать поведение заголовков не только p-элементами, но и таблицами стилей, однако первые очень часто со- держат важную контекстно-зависимую информацию о структуре документа. С помощью средств управления иерархической структурой документа браузеров IE4+ и NN6+ сценарий может генерировать собственное содержание или оглавление всех длинных документов, в процессе чего проводится поиск элементов свойства nodeName, которые принадлежат се- мейству hn. Поэтому для решения подобных задач следует использовать свойство элемента даже в том случае, если необходимо изменить внешний вид документа, задаваемый по умол- чанию стандартным шаблоном таблицы стилей. Рассматривая эти шесть объектов с точки зрения построения сценариев, можно прийти к вы- воду, что они в точности такие же, как и характерные текстовые объекты, которые обладают дополнительным свойством align. Поскольку каждый hn-элемент— блоковый, то можно ис- пользовать каскадные таблицы стилей для его выравнивания, причем этот способ более удоб- ный, чем использование соответствующих атрибутов или свойств. Таким образом, выбор за вами! Свойство align Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ С помощью строковых значений свойства align можно задать выравнивание элемента заголовка по левому краю (left), центру страницы (center) или же по правому краю (right). В языке HTML 4.0 вместо соответствующего атрибута align используется атрибут таблицы стилей text-align. См. также: атрибут таблицы стилей text-align. Объект элемента hr Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 1+ Свойства, методы и обработчики событий этих HTML-элементов описаны в главе 15. Глава 35. Текстовые объекты тела страницы 1045
Свойства Методы Обработчики событий align color noShade size width Синтаксис Доступ к свойствам и методам объектов элемента hr. (IE4+) [window. ] document. all. идентификатор. свойство | метод ([параметры]) (IE5+/W3C) [window.]document.getElementByld("идентификатор").свойство|ме- тод ( [параметры] ) Описание объектов Элемент hr предназначен для создания горизонтальных разделителей в соответствии с пара- метрами, задающими размер, форму и расположение текущего элемента (как правило, определяе- мых атрибутами). В таблицах стилей обычно указываются соответствующие настройки. Второй способ рекомендуется использовать только при создании страниц, которые должны загружаться исключительно в браузерах, поддерживающих CSS. В браузерах IE4+, NN6+-/W3C существует возможность изменить порядок отображения элемента hr либо напрямую (используя свойства объекта элемента), либо с помощью свойств таблицы стилей. Чтобы задать ссылку на специфи- ческий элемента hr необходимо определить элементу значение атрибута-идентификатора — этот способ вы, вероятнее всего, уже привыкли использовать для решения многих задач. Свойства align Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Управление горизонтальным выравниванием объекта элемента hr осуществляется с по- мощью свойства align. Задавая значения этого свойства, можно выровнять элементы на странице по левому краю (left), по центру страницы (center) или же по правому краю стра- ницы (right). По умолчанию элемент выравнивается по центру. Пример В листинге 35.2 приведен код страницы, в котором продемонстрированы способы изме- нения всех пяти свойств объекта элемента hr. Для выполнения этой задачи эффективно при- меняется метод setAttribute (). Эта страница загружается во всех браузерах, однако спи- ски select позволяют изменять текст только в браузерах Ш4+, NN6+/W3C. Элемент hr (с идентификатором myHR) отображается с настройками по умолчанию (ши- рина 100%, выровнен по центру и окрашен в стандартный цвет). Каждый список задает одно из свойств объекта hr, а атрибуты name списков умышленно приравниваются к именам этих 1046 Часть IV. Объекты языка JavaScript
свойств; атрибуты value элементов option содержат строки, назначаемые в качестве зна- чений описанных выше свойств. Каждый элемент select вызывает функцию setHRAttr (), передавая ей в качестве аргумента ссылку на себя. Первая задача функции setHRAttr () — это проверка поддержки браузером элемента font. Старые браузеры не поддерживают элементы document. all и myFont, а потому в них функция не выполняется. После успешного прохождения теста функция извлекает строку из значения value элемента select, передаваемую в качестве аргумента. Если в списке выбрано значение (отличное от пустой строки), то атрибут с названием, совпадающим с именем элемента select, получает значение. «html» <head> «title»hr Object Properties«/title» «script type="text/javascript"> // общая функция, выполняющая все задачи function setHRAttr(select) { var choice = select.options[select.selectedlndex].value; if (choice) { document.getElementByld("myHR").setAttribute(select.name, choice); } </script> </head> <body> <hl>hr Object Properties</hl> <br /> <p>Here is the hr element you will be controlling:«/p» <hr id="myHR" /> <form> Select an alignment: «select name="align" onchange="setHRAttr(this)"> <option>«/option> «option value="left">Left«/option> «option value="center">Center«/option> «option value="right"»Right</option» «/selectxbr /> Select a rule color (IE only): «select name="color" onchange="setHRAttr(this)"> <option>«/option> «option value=,,red">Red«/option> «option value="green"»Green«/option» «option value="blue">Blue«/option> «option value="#FA8072"»Some Hex Triplet Value«/option> «/selectxbr /> Select a rule shading: «select name="noShade" onchange="setHRAttr(this)"> <option>«/option> «option value="true,’»No Shading*/option» «option value="false"»Shading«/option> </select»«br /» Select a rule height: «select name="size" onchange="setHRAttr(thi s)"» <option»«/option» Глава 35. Текстовые объекты тела страницы 1047
«option value="2">2 (Default)</option> «option value="4">4 Pixels«/option> «option value="10">10 Pixels«/option> «/selectxbr /> Select a rule width: «select name="width" onchange="setHRAt'tr (this) "> <option>«/option> «option value="100%">100% (Default)</option> «option value="80%">80%«/option> «option value="300">300 Pixels«/option> </select> </form> </body> </html> См. также: атрибут text-align таблицы стилей. color Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Управление цветом объекта hr выполняется с помощью свойства color. Его значения могут быть представлены как в виде шестнадцатеричных триплетов (например #FFCCFF), так и с помощью названия цвета, распознаваемого большинством браузеров. В любом случае, при задании строки значения различия между прописными и строчными буквами не будет. При изменении заданного по умолчанию значения цвета исчезает “'тень” разделителя (трех- мерный эффект). Кроме того, существует универсальное значение, позволяющее вернуть ус- тановки цвета браузера по умолчанию после их изменения. Пример Пример изменения свойства color элемента hr приведен в листинге 35.2. См. также: атрибут color таблицы стилей. noShade Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Элемент hr, заданный с настройками по умолчанию, отображается с применением трех- мерного эффекта, называемого тенью. Этот режим отображения можно отключить в сцена- рии, изменив значение свойства noShade на true. Однако имейте в виду, что в браузере IE4+ операция изменения свойства noShade может проводиться только в одном направле- нии, т.е. нельзя восстановить эффект трехмерности после того, как он был снят. Более того, при определении цвета, отличного от заданного по умолчанию, эффект трехмерности разде- лителя, установленный по умолчанию, исчезает. Пример Пример изменения свойства noShade элемента hr приведен в листинге 35.2. Из-за весь- ма странной ошибки изменение этого свойства может привести к вполне непредвиденному результату. См. также: атрибут color элемента таблицы стилей. 1048 Часть IV. Объекты языка JavaScript
size Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Размер элемента hr представлен толщиной линии. Его можно изменить с помощью свой- ства size. Значениями этого свойства могут быть целочисленные величины, задающие ко- личество отображаемых пикселей. Пример Пример изменения свойства size элемента hr приведен в листинге 35.2. width Значение: целочисленное или строка Чтение/Запись Совместимость: WinIE4+, МасШ4+, NN6+, Mozl+, Safari 14- Значением параметра ширины разделителя можно управлять с помощью свойства width. Согласно установкам по умолчанию, элемент занимает всю ширину области родительского контейнера (как правило, body). Значение ширины может устанавливаться как в виде абсолютного количества пикселей (целочисленное значение), так и с помощью процентных единиц измерения относительно ширины родительского контейнера. Процентные значения задаются строковыми переменны- ми, заканчивающимися символом %. Пример Пример изменения свойства width элемента hr приведен в листинге 35.2. См. также: атрибут width таблицы стилей. Объект элемента label Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safaril+ Свойства, методы и обработчики событий этого HTML-элемента описаны в главе 15. Свойства Методы Обработчики событий accessKey form htmlFor Синтаксис Доступ к свойствам и методам объектов элементов label. (IE4+) [window. ] document. all. идентификатор. свойство | метод ( [параметры] ) (IE5+/W3C) [window. ] document.getElementByld ("идентификатор") . свойство| ме- тод ([параметры] ) Глава 35. Текстовые объекты тела страницы 1049
Описание объекта Элемент label позволяет установить контекстную связь между внешним элементом управления (текстовое поле, список, переключатель) и независимым текстом, используемым для обозначения элемента управления на странице. Элемент label не управляет отображе- нием и физическими свойствами элемента управления, поскольку эти задачи полностью воз- лагаются на средства HTML. Разместить надпись внутри элемента label, принадлежащего элементу управления формы, довольно важно в том случае, когда в сценарии выполняется управление иерархически упорядоченными элементами содержимого страницы. Кроме того, для получения достоверных результатов анализа данных поддержка однозначной связи меж- ду элементом управления формы и его надписью должна занимать одно из главных мест в списке первостепенных задач программиста. Свойства accessKey Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE5+, NN6+, Mozl+, Safari 14- Для большинства других HTML-объектов описание свойства accessKey представлено в главе 15, посвященной базовым элементам. При работе с объектом label это свойство ис- пользуется так же, как и в других объектах IE. Значение односимвольной строки представляет код символа, используемого совместно, с клавишей-модификатором, которая зависит от ОС или браузера (например, <Ctrl> в версии IE для Windows), для активизации элемента управ- ления формы с указанной надписью. Рекомендуется задавать исходное значение этого свой- ства с помощью атрибута accesskey элемента label. См. также: свойство accessKey базовых элементов. form Значение: ссылка на объект формы Чтение/Запись Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство f orm объекта элемента label возвращает ссылку на объект формы, содержащий элемент управления, с которым связана надпись элемента. Эго свойство используется при анализе узлов сложного документа, когда важно определить контейнер формы с точки зрения надписи, а не элемента управления формы. Ссылка На объект формы, возвращаемая объектом элемента label, аналогична той, которая представлена свойством form любого объекта управления. См. также: свойство accessKey элементов input. html For Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN6+, Mozl+, Safari 14- Свойство htmlFor представляет собой строку, содержащую ID элемента управления формы с указанной (текущей) надписью. Это значение, как правило, задается с помощью ат- рибута for в дескрипторе элемента label. Изменение этого значения не приводит к изме- нению расположения надписи, однако оно нарушает связь между надписью и элементом управления формы. 1050 Часть IV. Объекты языка JavaScript
Объект элемента marquee Совместимость: WinIE4+, MacDE4+, NN7+, Mozl+, Safari 1+ Свойства, методы и обработчики событий этого HTML-элемента описаны в главе 15. Свойства Методы Обработчики событий behaviour start() onbounce bgColor stop() onfinish direction height hspace loop scrollAmount scrollDelay trueSpeed vspace width onstart Синтаксис Доступ к свойствам и методам объекта элемента marquee. (IE4+) [window. ] document. all. идентификатор, свойство | метод ( [параметры] ) Описание объекта Элемент marquee — это частный элемент семейства Microsoft, обеспечивающий про- крутку текста в прямоугольнике с помощью атрибутов элемента width и height. Прокру- чиваемый в элементе текст размещается между открывающим и закрывающим дескриптора- ми элемента. Только объектная модель браузеров IE4+ позволяет в сценарии управлять этим элементом и многими свойствами его объекта. Свойства behavior Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойство behavior задает способ перемещения текста в области прокрутки. Это свойст- во принимает значение одной из этих трех строк: alternate, scroll и slide. При ис- пользовании alternate направление прокрутки текста принимает два значения: вверх и вниз (или вправо и влево, что зависит от значения свойства direction). Если задано зна- чение scroll, то это означает, что текст будет полностью прокручен внутри области перед его повторным отображением на экране. При задании значения slide прокрутка текста про- Глава 35. Текстовые объекты тела страницы 1051
исходит до тех пор, пока не отобразится последний элемент. Если в качестве значения свой- ства задать slide (вместо значения соответствующего атрибута дескриптора), то прокрутка текста приостановится после того, как текст достигнет границы прямоугольника. Свойство behavior имеет значение по умолчанию scroll. Пример В листинге 35.3 содержится код страницы, в котором продемонстрированы способы изменения нескольких свойств элементов marquee: behavior, bgColor, direction, scrollAmount и scrol iDelay. Браузеры NN7+/Moz позволяют изменять далеко не все эти свойства. <html> <head> <title>marquee Object Properties</title> «script type="text/javascript"> // общая функция, выполняющая все задачи function setMARQUEEAttr(select) { var choice = select.options[select.selectedlndex].value; if (choice) { document.getElementByld("myMARQUEE"). setAttribute(select.name, choice),- } } </script> </head> <body> <hl>marquee Object Properties</hl> <br I > <hr I > «marquee id="myMARQUEE" width="400" height="24">This is the marquee element object you will be controlling.«/marquee> «form> «input type="button" value="Start Marquee" onclick="document.getElementByld('myMARQUEE1).start()" /> «input type="button" value="Stop Marquee" onclick="document.getElementByld ('myMARQUEE') .stopO " /xbr /> Select a behavior: «select name="behavior" onchange="setMARQUEEAttr(this)"> <option>«/option> «option value="alternate">Alternate«/option> «option value="scroll">Scroll«/option> «option value="slide">Slide«/option> «/selectxbr /> Select a background color: «select name="bgColor" onchange="setMARQUEEAttr(this)"> «option>«/option> «option value="red">Red«/option> «option value="green">Green«/option> «option value="blue">Blue</option> «option value="#FA8072">Some Hex Triplet Value«/option> «/selectxbr /> Select a scrolling direction: «select name="direction" onchange="setMARQUEEAttr(this)"> 1052 Часть IV. Объекты языка JavaScript
<option></option> «option value="left">Left«/option> «option value="right">Right«/option> «option value="up">Up«/option> «option value="down">Down«/option> «/selectxbr /> Select a scroll amount: «select name="scrollAmount" onchange="setMARQUEEAttr(this)"> «option>«/option> «option value="4">4«/option> «option value="6">6 (Default)«/option> «option value="10">10«/option> «/selectxbr /> Select a scroll delay: «select name="scrollDelay" onchange="setMARQUEEAttr(this)"> <option>«/option> «option value="50">Short«/option> «option value="85">Normal«/option> «option value="125">Long«/option> «/select> «/form> «/body> </html> См. также: свойство direction объекта marquee. bgColor Значение: шестнадцатеричный триплет или имя цвета Чтение/Запись Совместимость: WinIE4+, MacDE4+, NN-, Moz-, Safari- Свойство bgColor определяет цвет фона прямоугольной области элемента marquee. Для задания цвета текста необходимо поместить объект marquee в область действия элемента font или же определить элементу marquee атрибут color таблицы стилей. Значения всех свойств цветов могут представлять либо обычные шестнадцатеричные триплеты HTML (например #00FF00), либо названия, используемые в браузерах NN (список цветов расположен на узле: http://www.developer.netscape.com/docs/manuals/htmlguid/colortab.htm). Пример Пример использования свойства bgColor приведен ранее в листинге 35.3. direction Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN7+, Mozl+, Safari- Значение свойства direction предоставляет возможность получить или задать направ- ление прокрутки текста (вертикальное или горизонтальное). Существует четыре возможных варианта значений этого свойства: left, right, down, up. По умолчанию устанавливается значение left. Пример Пример использования свойства direction приведен ранее в листинге 35.3. См. также: свойство behavior объекта marquee. Глава 35. Текстовые объекты тела страницы 1053
height width Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN7+, Mozl+, Safari- Свойства height и width представляют возможность получить или установить размер прямоугольника, в котором размещается элемент, в пикселях. Каждое свойство задается незави- симо от другого. Подобно необязательным атрибутом объектов IE, если width или height определены в дескрипторе, то вы не сможете использовать соответствующие свойства для получения размера элементов и изменения значений по умолчанию. hspace vspace Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Свойства hspace и vspace предоставляют возможность устанавливать или изменять от- ступы вокруг элемента marquee. При установке значения свойства hspace происходит из- менение как левой, так и правой границ элемента; свойство vspace управляет расположени- ем верхней и нижней границ. Толщина границы не зависит от высоты и ширины элемента. loop Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- С помощью свойства loop можно указать количество повторных “прокруток” элемента marquee, задаваемых в соответствии со значением атрибута loop. Несмотря на то, что это свойство имеет статус чтения-записи, его изменение с помощью сценария не приведет к си- туации, когда обработка текста в цикле выполняется большее количество раз перед останов- кой, чем это задано. Исходя из этого, такое свойство лучше рассматривать как используемое Только для чтения. scrol lAmount scrollDelay Значение: целочисленное Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN7+, Mozl+, Safari- Свойства scrollAmount и scrollDelay управляют скоростью и плавностью прокрут- ки текста элемента marquee. Количество пикселей между процессами обновления прокру- чиваемого текста контролируется свойством scrollAmount. Чем меньше это количество, тем меньше “скачков” будет при прокрутке (по умолчанию это значение равно 6). В то же время, можно управлять интервалом между каждым обновлением текста с помощью свойства scrollDelay (в миллисекундах). Чем меньше это число, тем чаще осуществляется обнов- ление (по умолчанию эти значения задаются в диапазоне от 85 и 90 миллисекунд в зависимо- сти от операционной системы). Таким образом, сочетание небольших значений свойств scrollAmount и scrollDelay приводит к наиболее плавной прокрутке содержимого. 1054 Часть IV. Объекты языка JavaScript
Пример Пример использования свойств scrollAmount и scrollDelay приведен ранее в лис- тинге 35.3. См. также: свойство trueSpeed объекта marquee. trueSpeed Значение: булево Чтение/Запись Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- В браузере ГЕ имеется встроенный программный регулятор, предотвращающий быструю прокрутку элемента marquee в том случае, когда атрибуту scrolldelay или свойству scrollDelay присваивается значение, меньшее 60. Но если вы все-таки решили использо- вать скорость прокрутки, большую 60 (подразумевается, что значение должно быть меньше 60), необходимо также установить значение свойства trueSpeed равным true. См. также: свойство scrollDelay объекта marquee. Методы start О stop () Возвращаемое Значение: отсутствует. Совместимость: WinIE4+, MacIE4+, NN7+, Mozl+, Safari- Сценарий может запускать или останавливать (приостанавливать) работу элемента marquee с помощью методов start () или stop (). Ни один из этих методов не имеет параметров, поэтому их можно определять так часто, как это необходимо после загрузки страницы. Пом- ните, что метод start () не запускает обработчик событий onstart для объекта. Пример Пример использования методов stop О и start О н scrollDelay приведен ранее в листинге 35.3. Эти методы вызываются в обработчиках событий отдельных кнопок страницы. Обработчики событий onbounce Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Обработчик событий onbounce запускается только тогда, когда свойство behavior элемента marquee принимает значение alternate. В этом возвратно-поступательном режиме каж- дый раз, когда прокручиваемый текст достигает границы области, перед выполнением обрат- ного движения, запускается событие onbounce. Если вы решили надоедать посетителям ва- шего узла, то установите звуковое оповещение при каждом запуске события onbounce (это шутка, не делайте этого). См. также: свойство behavior объекта marquee. Глава 35. Текстовые объекты тела страницы 1055
onfinish Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Обработчик событий onf inish запускается только тогда, когда значение циклической прокрутки элемента marquee равно числу 1 или больше. После выполнения последнего цикла обработки текста запускается событие onf inish. См. также: свойство loop объекта marquee. onstart Совместимость: WinIE4+, MacIE4+, NN-, Moz-, Safari- Обработчик событий onstart запускается при инициализации процесса прокрутки эле- ментом marquee, но только после загрузки страницы. Метод start () не приводит к запус- ку этого обработчика событий. См. также: метод start () объекта marquee. Объект Range Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойства Методы Обработчики событий collapsed commonAncestorContainer cloneContents() cloneRange() endContainer endoffset' collapse() compareBoundaryPoints() startcontainer compareNode() startoffset comparePoint() createContextualFragment() deleteContents() detach() extractcontents() insertNode() intersectNode() isPointlnRange() selectNode() selectNodeContents() setEnd() setEndAfter() setEndBefore() setstart() setStartAfter 0 setStartBefore() surroundContents() toString() 1056 Часть IV. Объекты языка JavaScript
Синтаксис , Создание объекта Range. var rangeRef = document.creatRange(); Доступ к свойствам и методам объекта Range. (NN6+/MOZ1+) ссылкаНаОбъект.свойство\метод([параметры]) Описание объекта Объект Range относится к W3C DOM, поддерживаемой компанией Microsoft при разра- ботке объекта TextRange. Существенные различия (немалая часть которых представляет собой почти разные словари свойств и методов) касаются режима работы и функциональных возможностей этих двух весьма подобных объектов. Несмотря на то, что Microsoft была включена в рабочую группу и принимала участие в подготовке документации W3C DOM вто- рого уровня, ни один из участников компании не получил преимуществ в используемой мо- дели DOM — причиной тому стало появление объекта Range. Поскольку DOM версии W3C не была представлена в IE5.5, то о поддержке объекта Range в нем не стоит даже говорить. Между тем, для сравнения свойств двух “равнозначных” объектов просмотрите раздел, по- священный объекту TextRange (далее в этой главе). Ни один Range версии W3C DOM ли- бо TextRange, предложенный Microsoft, не используется в браузерах МасЕ. Назначение объекта Range в W3C DOM — это предоставление сценарию возможности управления отдельными элементами содержимого (обычно это часть текстового содержимого документов), которые не всегда представлены в иерархической структуре документа отдель- ными узлами. Наряду с тем, что объект Range используется для получения доступа к узлам и элементам, он также расширяет границы возможностей сценария по управлению содержи- мым на самом детальном уровне. Содержимое объекта Range иногда называется выделени- ем, однако это совсем не означает, что текст выделятся на странице подобно тому, как это делается с помощью мыши. Термин “выделение” в данном случае применяется к части со- держимого документа, к которой нельзя обратиться как к отдельному объекту, расположен- ному вне дерева узлов документа. Когда в сценарии создается объект Range, разработчику предоставляется возможность, с помощью различных методов осуществить проверку, изме- нение, удаление, перемещение и вставку содержимого страницы. Объект Range (речь идет об экземпляре статического объекта Range) имеет начальную и конечную точку, которые совместно определяют границы диапазона. Граничные точки диапазона определяются в виде смещения относительно положения диапазона в контейнере. Смещение вычисляется в количестве символов от границы содержимого узла (при этом игно- рируются любые символы атрибутов или дескрипторов HTML). Когда обе границы оказыва- ются на краях одного и того же узла, смещение также подсчитывается в количестве узлов в контейнере, окружающем начальную и конечную точки. Приведенный пример поможет по- нять изложенные выше доводы. Рассмотрим следующий упрощенный HTML-документ. <html> <body> <p>This paragraph has an <em>emphasized</em> segment.</p> </body> </html> Можно создать объект Range, который представляет текст внутри элемента ет разными способами, в каждом из которых подсчет смещения содержимого выполняется по-разному. Глава 35. Текстовые объекты тела страницы 1057
1. От единственного дочернего узла элемента ет (текстовый узел). Смещение в на- чальной точке равно нулю, оно представляет собой расположение точки ввода перед первым символом (е в нижнем регистре); смещение в конечной точке равно 10, это расположение символа (отсчет начинается с нуля), следующего после d (в нижнем ре- гистре) символа. 2. От элемента ет В данной ситуации дочерний текстовый узел располагается внутри элемента em. Существует только один узел, поэтому смещение в начальной точке рав- но 0, в то время как в конечной точке — 1. 3. От дочерних узлов элемента р (два текстовых узла и один узел элемента). Сущест- вует возможность установить значения диапазона от начальной точки до самого конца (подсчитывая символы) первого дочернего текстового узла элемента р. Затем можно установить значение конечной точки, располагаемой перед первым символом последнего дочернего текстового узла элемента р. Результирующая область определя- ет текст элемента em. 4. От p-элемента. С точки зрения элемента р, диапазон можно определить смещением от узла 1 (конец второго узла, вложенного в элемент р) до узла 2 (начало третьего узла). Эти непохожие друг на друга способы предоставляют большую гибкость, однако вы не всегда будете знать, как их использовать. Не стоит отчаиваться, методы объектов Range сло- варя W3C помогут вам выбрать подход для подсчета смещения. Начальная точка объекта Range может находиться в одном элементе, а конечная точка — в другом. Например, рассмотрим следующий HTML-код. <р> And how to introduce our <em>very special</em> guest:</p> В тексте, выделенном полужирным шрифтом, отображается содержимое объекта Range. Видно, что выделенная область пересекает границы элемента таким образом, что при замене текста в этой области не всегда удобно использовать свойства объекта HTML или свойства узла объекта. В инструкции W3C есть правила, согласно которым создатели браузеров должны предусмотреть в своих программных продуктах средства перемещения и удаления HTML- содержимого, пересекающего границы узлов. Важной характеристикой объекта Range является его размер, который может быть нулевым или составлять несколько символов. Начальная и ко- нечная точки всегда располагаются между символами. Когда начальная и конечная точки нахо- дятся в одном и том же месте, объект Range выступает в роли указателя на место вставки текста. Управление выделениями Для создания объекта Range используйте метод document. createRange (). Прирав- няйте объект Range, возвращаемый этим методом, к переменной, которую впоследствии можно использовать для управления выделенной областью. var rng = document.createRange() Наряду с активным объектом Range, хранящимся в переменной, также можно использовать другие методы объекта для того, чтобы установить начальную и конечную точки области. Если область должна состоять из всего содержимого узла, то используйте два эффективных метода: selectNode () и selectContents (). Основной параметр для обоих методов — это ссылка на узел, содержимое которого необходимо включить в область. Различие между этйми двумя методами заключается в способе подсчета смещения для области (эти методы рассмотрены де- тально ниже в этой главе). Другой набор методов (setStartBefore (), setStartAfter О, setEndBefore (), setEndAf ter ()) предоставляет возможность установки значения каждой точки по отдельности относительно расположения границ узла. Чтобы более точно задать 1058 Часть IV. Объекты языка JavaScript
границы области, используйте методы setstart О и setEndO, позволяющие определить исходный узел (указывающий начало отсчета смещения) и целочисленное значение смещения. Если требуется указать точку вставки (например, необходимо вставить определенное со- держимое в существующий узел), расположите конечную точку в выбранном месте, а затем запустите метод collapse (). Параметр метода определяет, в каком месте (в конечной или начальной точке области) должен запуститься метод collapse. Набор других методов позволяет сценариям напрямую управлять содержимым области. Можно копировать (cloneContents ()), удалять (deleteContents (), extractcontents ()), вставлять узел (insertNode ()) и даже размещать содержимое области в новом родитель- ском узле (surroundContents ()). Некоторые свойства позволяют сценариям проверять информацию об области (например, значения смещения), содержащих их контейнерах, кроме того, просмотреть сведения о состоянии области и данные о внешнем наиболее близком узле, содержащем начальную и конечную точку. Браузер NN содержит дополнительный метод управления объектом Range (который фактически является методом объекта, включающего в себя Range) — он называется createContextualFragment О . Этот метод позволяет сценариям создать полноценный узел (Document Fragment) из произвольных строк содер- жимого HTML (данная особенность пока еще не предложена в W3C DOM). Описываемый метод изначально был разработан как дополнительный, который в конечном счете стал свой- ством innerHTML в браузере NN6+/Mozl+. Управления объектом Range используется специфический набор операторов, необходи- мых для выполнения самых простых задач. При использовании объекта Range обычно вы- полняют три основных действия. 1. Создание текстовой области. 2. Установка начальной и конечной точек. 3. Провести изменение или перемещение области. Как только вы почувствуете себя уверенно в управлении объектом Range, то сразу пой- мете, что он обеспечивает достаточно высокий уровень гибкости в сценарии, особенно при управлении содержимым тела страницы. Чтобы получить сведения об основных способах применения объекта Range в сценариях, просмотрите примеры, описывающие отдельные свойства и методы, представленные в следующих разделах. Свойства collapsed Значение: булево Чтение/Запись Совместимость: WinlE-, МасЕ-, NN6+, Mozl+, Safaril+ Свойство collapsed сообщает о том, установлены ли начальная и конечная точки об- ласти в одном и том же элементе документа. Если значение эквивалентно true, то началь- ный и конечный контейнеры области совпадают, совпадают также и значения смещений. Это свойство может использоваться для проверки того, представляет ли выделенная область ме- сто вставки содержимого перед новым узлом. if (rng.collapsed) { rng.insertNode(ссылкаНаНовыйУзел) } Глава 35. Текстовые объекты тела страницы 1059
Пример Используйте в приложении The Evaluator встроенный объект rng для изучения свойства collapsed. Перезагрузите страницу и включите в выделение следующий узел. rng.selectNode(document.body) Введите в верхнее текстовое поле a.collapsed. Это выражение возвратит результат false, поскольку конечная точка выделения другая. См. также: свойства endcontainer, endoffset, startcontainer, startoffset; метод Range.collapse(). commonAnces torContainer Значение: ссылка на объект узла Чтение/Запись Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойство commonAncestorContainer возвращает ссылку на узел в дереве документа, в котором расположены начальная и конечная точки диапазона. Нередко начальная точка об- ласти находится в одном узле, а конечная — в другом. В этом случае обобщенный узел со- стоит из обоих узлов (как правило, это узел document. body). В спецификации W3C DOM разделяемый обобщенный узел называется корневым узлом области (термин, который пре- доставляет больше информации). Пример Используйте в приложении The Evaluator встроенный объект rng для изучения свойства commonAncestorContainer. Перезагрузите страницу. Установите начальную точку непо- средственно перед началом содержимого элемента туЕМ, а конечную — в конце внешнего элемента туР. rng.setStartBefore(document.getElementByld("туЕМ").firstChild) rng.setEndAfter(document.getElementByld("myP").lastchild) Удостоверьтесь, что выделение включает узел туЕМ (слово all) и заканчивается элемен- том туР. rng.toString() Проверьте также, что контейнеры конечных точек представляют разные узлы. rng.startcontainer.tagName rng.endContainer.tagName Наконец, узнайте, какой узел содержит обе конечные точки. rng.commonAncestorContainer.id Вы получите результат туР, поскольку именно он содержит узлы туР и туЕМ. См. также: свойства endContainer, endoffset, startcontainer, startoffset; все методы set и select объекта Range. endContainer s tartContainer Значение: ссылка на объект узла Чтение/Запись Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойства endContainer и startcontainer возвращают ссылку на узел дерева ие- рархической структуры документа, содержащий начальную и конечную точки области, соот- ветственно. Имейте в виду, что объектная модель автоматически рассчитывает размер 1060 Часть IV. Объекты языка JavaScript
контейнера, сам же контейнер может и не соответствовать необходимой ссылке, используе- мой для установки начальной и конечной точек области. Например, при использовании мето- да selectNode () для установки начальной и конечной точек области, окружающей необ- ходимый узел, контейнеры конечных точек наиболее вероятно будут попадать в следующие по уровню узлы. Таким образом, если сначала необходимо расширить область для включения в нее узла, содержащего текущую начальную точку, используется значение, возвращаемое свойством startcontainer, в качестве параметра метода setstartBef ore (). rng.setStartBefore(rng.startcontainer) Пример Используйте в приложении The Evaluator встроенный объект rng для изучения свойств endContainer и startcontainer. Перезагрузите страницу и включите в выделение узел туЕМ. rng.selectNode(document.getElementByld("туЕМ") Изучите контейнеры начальной и конечной точек выделения. rng.startcontainer.id rng.endcontainer.id Поскольку в выделении содержится весь элемент туЕМ, то начальная и конечная точки выделения находятся за его пределами. Таким образом, контейнером последних выступает объект туР, который содержит элемент туЕМ. См. также: свойства commonAncestor, endoffset, startoffset, а также все мето- ды set и select объекта Range. endOffset startoffset Значение: целочисленное Чтение/Запись Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Свойства endoffset и startoffset возвращают целочисленное значение количества символов или узлов, которое определяет расположение начальной и конечной точек области, соответственно. Эти смещения указаны для узлов, выполняющих роль контейнеров для об- ласти (см. свойства Range. endContainer и Range. startContainter, описанные ра- нее в этой главе). Когда граница области находится на границе узла (или, лучше сказать, “между” узлами), возвращаемое целое число задает количество узлов (отсчет начинается с нуля от граничного контейнера). Если граница области находится посередине текстового узла, возвращаемое це- лое число представляет собой индекс символа внутри этого узла. Каждая граница имеют свою систему измерения (символы или узлы, в зависимости от используемых контейнеров), что нередко приводит к путанице (если не быть достаточно внимательным). При этом воз- вращаемое целое число для конечной точки может быть меньшим, чем значение для началь- ной точки. Рассмотрим следующие вложенные элементы. <р> This paragraph has an <em>emphasized</em> segment.</p> Следующий оператор устанавливает значение начальной точки области внутри первого узла, а также конечную точку области в закрывающем элементе ЕМ узла. var rng = document.createRange(); mg.setstart(document.getElementByld("myP").FirstChild,19); mg.setEndAfter(document.getElementByld("myEM")); Глава 35. Текстовые объекты тела страницы 1061
Используя полужирный шрифт для представления текста области и символ вертикальной черты (|) для определения границ в пределах узлов, можно представить, как выполняется опи- санный выше сценарий. <р id="myP">This program has |an <em id="myEM">emphasizecl</em> | segment.</p>; Поскольку начало области находится в текстовом узле (первый дочерний узел элемента р), значение startoffset равно 19; оно определяет расположение символа а относительно ап от- носительно начала узла, его содержащего. Однако конечная точка находится в конце элемента em. Сценарий распознает эту точку как границу узла и поэтому осуществляет подсчет значения endoffset внутри содержимого внешнего контейнера— элемента р. Значение endOffset равно 2 (текстовый узел элемента р имеет индекс 0; элемент em имеет индекс 1; конечная точка находится в начале последнего текстового узла элемента р, имеющего индекс 2). При создании сценариев значения endOffset и startoffset используются достаточ- но часто; также часто применяются свойства endContainer и startcontainer для по- лучения целочисленных значений смещения. Пример Используйте в приложении The Evaluator встроенный объект rng для изучения свойств endOffset и startoffset. Перезагрузите страницу и включите в выделение узел туЕМ, а затем сместите начальную точку за пределы символов текстового узла myP. rng.selectNode(document.getElementByld("myEM")) rng.setstart(document.getElementByld("myP").firstChild, 7) Изучите типы узлов контейнеров начальной и конечной точек выделения. rng.startcontainer.nodeType rng.endContainer.nodeType Тип контейнера начальной точки имеет индекс 3 (текстовый узел), а контейнер конечной точки равен 1 (элемент). Определите смещение начальной и конечной точек выделения. rng.startoffset rng.endoffset См. также: свойства endContainer, startcontainer, все методы set и select объекта Range. Методы cloneContents О сloneRange() Возвращаемое значение: ссылка на узел Document Fragment; ссылка на объект Range Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safari 14- Метод cloneContents () (не поддерживаемый в браузере NN6, однако совместимый с будущими его версиями) хранит копию содержимого объекта Range и возвращает ссылку на эту копию. Копия хранится в памяти браузера, но не является частью дерева узлов доку- мента. Метод cloneRange () (используется в NN64-) выполняет те же действия с областью и хранит копию области в памяти браузера. Область может содержать части соседних узлов; она не обязательно находится в одном элементе узла. Именно поэтому данные области отно- сятся к типу Document Fragment (один из типов узлов W3C DOM). Поскольку Document- Fragment — это реальный узел, его можно использовать в других методах узлов дерева 1062 Часть IV. Объекты языка JavaScript
документов, в которых узлы представлены в виде параметров. Вы можете смело клонировать текстовую область для того, чтобы вставить полученные копии в другом месте документа. Наоборот, метод cloneRange () предназначен для работы с объектами Range. Если вы будете управлять не только содержимым области, но и всем объектом Range, то этот метод возвратит ссылку на него (см. случай, когда область заключает в себя весь документ). Метод cloneRange О можно использовать для получения копии области, что позволяет сравнить конечные точки текущей и другой области (задача выполняется с помощью мето- да Range. compareBoundaryPoints ()). Пример Используйте в приложении The Evaluator встроенный объект rng для изучения метода clonecontents. Перезагрузите страницу и включите В выделение узел туР. rng.selectNode(document.getElementByld("myP") Скопируйте исходное выделение и сохраните его в переменной Ь. b = rng.cloneContents() Переместите исходное выделение так, чтобы точка его вставки располагалась в конце тела страницы. Для этого сначала расширьте его для включения элемента body, а затем сверните в конце выделения. rng.selectNode(document.body) rng.collapse(false) Далее вставьте копию выделения в конце элемента body. rng.insertNode(b) Если вы прокрутите страницу вниз, то увидите, что копия текста не помещается в границы выделения, что приводит к ошибке выполнении метода insertNode (). Но вы всегда може- те воспользоваться методом appendChild О или insertBef ore (), чтобы добавить ко- пию выделения в иерархическую структуру документа. См. также: методы Range. compareBoundaryPoints (), extractcontents (). collapse([начальноеБулевоЗначениё]) Возвращаемое значение: отсутствует. Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Метод collapse О используется для сжатия области от ее текущего размера до точки вставки символа. Сжатие области выполняется в том случае (хотя на первый взгляд это и ка- жется лишним), когда в функции сценария обрабатывается содержимое тела страницы или большая часть ее текста. Например, в типичном цикле сценария подсчета количества слов создается текстовая область, полностью содержащая тело страницы. Чтобы начать процедуру подсчета слов, нужно сжать область до точки вставки, расположенной в ее начале. Затем, ис- пользуя метод expand (), присвоить области первое слово текста (и увеличьте счетчик, если метод expand () возвращает значение true). С этого момента область расширится в на- правлении “от” первого слова. Может потребоваться сжать область в конце текущего выде- ления так, чтобы дальнейший поиск начинался со следующего текущего слова. Впоследствии метод collapse () будет выполняться с несколько измененными параметрами. Необязательный параметр метода collapse О — это булево значение, задающее распо- ложение точки вставки после сжатия области (в конце или в начале текущей области). Дейст- вия по умолчанию эквиваленты значению true. Это означает, что пока метод collapse () не перенастроен противоположным образом, он будет преобразовывать область в точку вставки, располагающуюся перед текущей областью. Данный метод удобно использовать Глава 35. Текстовые объекты тела страницы 1063
в начале сценария подсчета количества слов, поскольку сжатие текстовой области лучше проводить именно здесь. Для последующих преобразований текста потребуется сжать об- ласть таким образом, чтобы результирующая точка вставки находилась после текущей облас- ти. Таким образом, в методе collapse () рекомендуется задать параметр false. Пример Чтобы ознакомиться с примерами использования метода collapse О , обратитесь к лис- тингам 35.11 и 15.14. См. также: методы Range . setEnd (), Range . setStart (). compareBoundaryPoints(целоеЧисло, ссылкаНаИсходнуюОбласхъ) Возвращаемое значение: целочисленное (-1,0 или 1) Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 14- Создание нескольких объектов областей и присвоение их разным переменным не является проблемой. Вы можете использовать метод compareBoundaryPoints () для сравнения относительного расположения начальной и конечной точек областей. Одна область представ- ляет собой объект, который используется для вызова метода compareBoundaryPoints (), другая же область — это второй параметр метода. Порядок, в котором происходит обраще- ние к этим областям, влияет на результаты, полученные на основе значения первого параметра. Значением первого параметра может быть одна из четырех констант, являющихся свойст- вами статического объекта Range: Range. START_TO_START, Range. START_TO_END, Range. END_TO_START и Range . END_TO_END. Что именно определяют эти значения для текущей области, зависит от того, что указано в качестве второго параметра и точки, с кото- рой проводится сравнение. Например, рассмотрим следующее содержимое страницы, кото- рое включает две текстовые области, определенные внутри нее. It was the best of times. Первая текстовая область (в данном случае она присвоена переменной rngl) отобра- жается полужирным шрифтом, в то время как вторая текстовая область (rng 2) представ- лена полужирным курсивом. Другими словами, переменная rng2 вложена в rngl. Можно сравнить начальное место расположения переменной rngl относительно гпд2 с помощью значения Range. START_TO_START, заданного в качестве первого параметра метода compareBoundaryPoints О. var result = rngl.compareBoundaryPoints(Range.START_TO_START, rng2); Значение, возвращаемое методом compareBoundaryPoints О, является целочислен- ным. Если места расположения обеих анализируемых точек совпадают, то значение возвра- щаемой переменной равно 0. Если начальная точка так называемой исходной области распо- лагается после области, из которой запускается метод, возвращаемое значение равно -1; в противном случае возвращаемое значение равно 1. Таким образом, можно сделать вывод: поскольку начальная точка rngl находится после начальной точки rng2, то методом воз- вращается значение переменной, равное -1. При изменении оператора для запуска метода в точке rng2 результат будет эквивалентен 1. var result = rng2.compareBoundaryPoints(Range.START_TO_START, rngl); На практике этот метод применяется для получения информации о том, совпадают ли обе области, совпадает ли одна и та же точка границ обеих областей, и начинается ли одна об- ласть там, где заканчивается другая 1064 Часть IV. Объекты языка JavaScript
Пример Страница, представленная листингом 35.4, позволяет сравнивать текстовые диапазоны в NN6+/Moz. Нижний абзац содержит элемент span, в который включен объект Range, назна- чаемый фиксированному текстовому узлу в процессе загрузки страницы (в функции init ()). Этот фиксированный диапазон будет использоваться при сравнении с текстовым выделением. После создания выделения в сценарии используются все четыре варианта метода compareBoundaryPoints () для сравнения начальной и конечной точек выделения и фик- сированного диапазона. В первом столбце таблицы показано значение, возвращенное мето- дом, а в третьем столбце приведено описание полученных результатов. Чтобы ознакомиться с работой сценария этой страницы, сначала выделите первое слово фиксированного текстового диапазона (медленно перетащите указатель над красным тек- стом). Как видите, начальные точки обоих диапазонов пока одинаковые, поскольку возвра- щается значение 0. Метод compareBoundaryPoints () в любом случае применяется по отношению к фиксированному текстовому диапазону, поэтому сравнение выполняется с точ- ки зрения этого диапазона. Таким образом, в первой строке таблицы для параметра START_TO_END указано, что начальная точка фиксированного диапазона следует раньше ко- нечной точки выделения; в результате возвращается значение -1. Существуют и другие типы выделений: начало в тексте перед фиксированным диапазоном и конец— в фиксированном диапазоне; начало в тексте в фиксированном диапазоне и конец — за пределами фиксированного диапазона; начало и конец в тексте фиксированного диапазона; начало и конец в тексте перед фиксированным диапазоном; начало в тексте после фиксированного диапазона. Изучите возвращаемые результаты в каждом из случаев. <html> <head> <title>TextRange.compareBoundaryPoints() Method</title> <style type="text/css"> td {text-align:center} .propName {font-family:Courier, monospace} #fixedRangeElem {color:red; font-weight:bold} </style> «script type="text/javascript"> var fixedRange; function setAndShowRangeData() { try { var selectedRange = window.getSelectionO; selectedRange = selectedRange.getRangeAt(0); var resultl = fixedRange.compareBoundaryPoints( Range.START_TO_END, selectedRange); var result2 = fixedRange.compareBoundaryPoints( Range.START_TO_START, selectedRange); var result! = fixedRange.compareBoundaryPoints( Range.END_TO_START, selectedRange); Глава 35. Текстовые объекты тела страницы 1065
var result4 = fixedRange.compareBoundaryPoints( Range.END_TO_END, selectedRange); document.getElementByld("Bl").innerHTML = resultl; document.getElementByld("compare1").innerHTML = getDescription(resultl); document.getElementByld("B2").innerHTML = result2; document.getElementByld("compare2").innerHTML = getDescription(result2); document.getElementById("B3").innerHTML = result3; document.getElementByld("сотрагеЗ”).innerHTML = getDescription(result3); document.getElementByld("B4").innerHTML = result4; document.getElementByld("compare4").innerHTML = getDescription(result4); } catch(err) { alert("Vital Range or Selection object services are not yet implemented in this browser."); function getDescription(comparisonvalue) { switch (comparisonvalue) { case -1 : return "comes before"; break; case 0 : return "is the same as"; break; case 1 : return "comes after"; break; default : return "vs."; } } function init() { fixedRange = document.createRange(); fixedRange.selectNodeContents(document. getElementByld("fixedRangeElem").firstChild); fixedRange.setEnd(fixedRange.endContainer, f ixedRange.endContainer.nodeValue.length); } </script> </head> <body onload="init()"> <hl>TextRange.compareBoundaryPoints() Method</hl> <hr /> <p>Select text in the paragraph in various places relative to the fixed text range (shown in red). See the relations between the fixed and selected ranges with respect to their start and end points.</p> ^table id="results" border="l" cellspacing="2" cellpadding="2"> <tr> < th>Property</th> <th>Returned Value</th> 1066 Часть IV. Объекты языка JavaScript
<th>Fixed Range vs. Selection</th> </tr> <tr> <td class="propName">StartToEnd</td> <td class="count" id="Bl">&nbsp;</td> ctd class="count" id="Cl">Start of Fixed «span id="compare1">vs.</span> End of Selection</td> </tr> <tr> ctd class="propName">StartToStartc/td> ctd class="count" id="B2">&nbsp;</td> ctd class="count" id="C2">Start of Fixed cspan id="compare2">vs.</span> Start of Selectionc/td> </tr> ctr> ctd class="propName">EndToStartc/td> ctd class="count" id="B3">&nbsp;</td> • ctd class="count" id="C3">End of Fixed cspan id="compare3">vs.c/span> Start of Selectionc/td> c/tr> ctr> ctd class="propName">EndToEndc/td> ctd class="count" id="B4">&nbsp;</td> ctd class="count" id="C4">End of Fixed cspan id="compare4">vs,c/span> End of Selectionc/td> c/tr> c/table> chr /> cp onmouseup="setAndShowRangeData()">Lorem ipsum dolor sit, cspan id="fixedRangeElem">consectetaur adipisicing elit c/span>, sed do eiusmod temper incididunt ut labore et dolore aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> c/body> c/html> compareNode (ссылкаНаУзел) Возвращаемое значение: целочисленное (-1, 0 или 1) Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ Этот метод возвращает целочисленный код, который указывает расположение определен- ного узла относительно диапазона. Ссылка на узел представляет единственный аргумент ме- тода. Возвращаемые целочисленные коды могут быть представлены и встроенными констан- тами: Range.NODE_BEFORE, Range.NODE_AFTER, Range.NODE_BEFORE_AND_AFTER, Range .NODE_INSIDE. Первые два параметра вполне очевидны; третий параметр описывает случай, когда узел начинается перед диапазоном, а заканчивается после него. Четвертая кон- станта, наоборот, описывает случай полного включения узла в диапазон. См. также: метод compare Point (). comparePoint(ссылка НаУзел, смещение) Возвращаемое значение: целочисленное (0,1, 2 или 3) Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ f Глава 35. Текстовые объекты тела страницы 1067
Этот метод возвращает целочисленный код, который указывает расположение определен- ного узла относительно диапазона после смещения. Аргументы метода — это ссылка на узел и смещение (количество элементов или символов в текстовом узле). Возвращаемые целочис- ленные константы задают расположение узла относительно точки, а не диапазона. Значение -1 указывает расположение перед начальной точкой диапазона, 1 — после конечной точки диа- пазона, а 0 — в самом диапазоне. См. также: метод compareNode (). createContextualFragment("текст") Возвращаемое значение: узел Document Fragment в W3C DOM Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ Метод createContextualFragment () — это метод объекта Range браузера NN6 (расширение объекта Range в W3C DOM). Данный метод предоставляет способ, согласно которому с помощью средств W3C DOM второго уровня иерархической структуры узлов можно создать строку текста HTML (без или с помощью дескрипторов HTML) для вставки или добавления ее в существующее дерево узлов. В результате развития браузера NN6 этот метод заполнил “пробел” в функциональных средствах и в конечном счете был одобрен для использования в браузерах Netscape (что уравновесило свойство innerHTML в браузе- рах Microsoft). В данном методе устранена необходимость создания сложного элемента HTML в результате построения последовательностей методов document. createElement () и document. createTextNode () для каждого фрагмента. Кроме того, лишней оказалась и возможность перенастройки дерева узлов, предшествующая вставке в существующий доку- мент текстового фрагмента. Однако наличие свойства innerHTML во всех объектах элемен- тов уменьшает значение метода createContexualFragment (), позволяя использовать один и тот же код в различных браузерах. Параметром метода createContexualFragment () может быть любой текст, включая де- скрипторы HTML. Однако для активизации метода необходимо иметь готовый объект Range. По- следовательность операций по созданию узла для области документа должна быть следующей. var rng = document.createRange(); rng.selectNode(document.body) // подойдет любой узел var fragment = rng.createContextualFragment(l,<Hl>Howdy</Hl>"); Как и область документа, узел не является частью дерева узлов документа до тех пор, пока вы не используете ее в качестве параметра одного из методов — Node. insertBef ore О или Node. appendChild (). Пример Используйте встроенный объект rng приложения The Evaluator для замены части дерева узлов документа. Сначала создайте фрагмент на основе встроенного диапазона. b = rng.createContextualFragment("<span style=’font-size:22pt1> a bunch of</span>") Этот фрагмент содержит элемент span, в котором располагается текстовый узел. Теперь вы можете изучить свойства фрагмента, введя в нижнее поле приложения Ь. Чтобы заменить элемент туЕМ страницы новым фрагментом, используется метод createContextualFragment () внешнего элемента myP. document.getElementByld("myP").replaceChild(b, document.getElementByld("myEM")) 1068 Часть IV. Объекты языка JavaScript
Теперь фрагмент становится полноправным дочерним узлом элемента туР. Вы можете ввести в верхнем поле приложения следующее выражение для получения копии текстового узла элемента span. document.getElementByld("myP").childNodes[1].firstChild.nodeValue См. также: объект Node (глава 15). deleteContents() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Метод deleteContents () удаляет все содержимое текущей области дерева документа. После удаления область уменьшается до точки вставки, которая просто разделяет содержи- мое (если такое существует) соседних узлов. Расположение границ области содействует тому, браузер переопределяет расположение элемента, заключенного внутрь области, после удаления последней. Простое удаление — это такое удаление, прн котором границы области симметричны. В качестве примера рассмотрим следующий фрагмент HTML с выделенной полужирным шрифтом областью. <p>One paragraph with an <em>emphasis</em> inside.</p> После удаления содержимого этой области исчезнет текстовый узел внутри элемента ет, но сам элемент ет останется в дереве документа (без дочерних узлов). Наряду с этим область может определяться в качестве второго дочернего узла элемента р, как показано ниже. <p>One paragraph with an <em>emphasls</em> inside.</p> При удалении содержимого области также удаляются текстовый узел и узел элемента ет, при этом элемент р имеет единственный полноценный тестовый дочерний узел (хотя в этом случае между словами ап и inside будет находиться дополнительный пробел, поскольку при сжатии элемента ет пробел автоматически не удаляется). В случае несимметричности границ области браузер сделает все возможное, чтобы обес- печить целостность дерева узлов документа после удаления. Рассмотрим следующий фраг- мент HTML-кода и выделенную в нем область. <p>One paragraph with an <em>eniphasis</em> inside.</p> После удаления содержимого выделенной области дерево узлов документа для этого фрагмента кода будет выглядеть следующим образом. <p>One paragraph <em>emphasis</em> inside.</р> Область сжимается в точку вставки после дескриптора <ет>. Однако примите к сведе- нию, что элемент ет будет “заботиться” о тексте, который все еще остается под его управле- нием. Возможны также и другие комбинации расположения границ области и узлов. Поэтому всегда проверяйте, являются ли границы области асимметричными, перед выполнением уда- ления и применением новых параметров. Пример Используйте встроенный объект rng приложения The Evaluator для знакомства с метода- ми удаления текстовых узлов и элементов. Сначала назначьте текстовый диапазон текстовому узлу, содержащемуся в элементе туЕМ. rng.setstart(document.getElementByld("туЕМ").firstChild, 0) rng.setEnd(document.getElementByld("myEM").lastchild, document.getElementByld("myEM").lastchild.length) Проверьте существование диапазона, введя в нижнее поле а, чтобы ознакомиться с его свойствами. Оба контейнера представлены тестовыми узлами (на самом деле это один и тот же текстовый узел), поэтому смещение измеряется в символах. Глава 35. Текстовые объекты тела страницы 1069
Далее удалите содержимое диапазона. rng.deleteContents() Курсивное слово all удаляется из дерева узлов, а вот элемент туЕМ — нет. Чтобы дока- зать это, добавьте в элемент новый текст. document.getElementByld("туЕМ")-innerHTML = "a band of " Курсивное начертание элемента em применяется к новому тексту, как и должно быть. Измените границы диапазона, чтобы включить в него элемент туЕМ. rng.selectNode(document.getElementByld("myEM")) Опять изучите свойства объекта Range, введя rng в нижнее поле приложения. Контейнер представлен элементом р, который содержит элемент em. Смещение измеряется в узлах, а не символах. Удалите содержимое диапазона. rng.deleteContents() В результате пропадет не только курсивный текст, но и весь элемент туЕМ; элемент ту₽ получит два дочерних узла. Чтобы проверить это, введите в верхнее поле приложения сле- дующие два выражения. document.getElementByld("myP").childNodes.length document.getElementByld("myP").childNodes[0].nodeValue Объедините два сестринских узла, выполнив метод normalize () их контейнера. document.getElementByld("myP").normalize() Для проверки полученного результата подсчитайте количество дочерних узлов. См. также: метод Range. extraContents (). detach() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Метод detach () извещает браузер о необходимости извлечь текущий объект области из DOM. В процессе этой операции размер объекта области приравнивается нулю, что приводит к ошибке сценария при попытке получения доступа к нему. Если необходимо, то можете на- значить используемой переменной значение новой области. Не спешите удалять область по- сле завершения всех необходимых операций (в конечном счете, задействованные для области ресурсы браузера не столь велики). Практика “уборки за собой мусора” весьма поощрительна, особенно если сценарий повторно создает и управляет рядом новых выделенных областей. См. также: метод document. createRange (). extractcontents() Возвращаемое значение: ссылка на узел Document Fragment Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safaril+ Метод extractcontents () удаляет содержимое области и возвращает ссылку на узел фрагмента документа, хранящегося в памяти браузера, однако больше не являющегося ча- стью дерева узлов документа. Содержимое области может состоять из частей нескольких узлов и находиться за пределами одного узла элемента. Таким образом, ее данные относятся к типу Document Fragment (один из типов узлов W3C DOM). Поскольку DocumentFragment — это реально существующий узел, его можно использовать в других методах дерева докумен- та, в которых узлы выступают в качестве параметров. В любом случае можно извлечь тексто- вую область из одного места документа и вставить ее в другую часть. 1070 Часть IV. Объекты языка JavaScript
Пример В приложении The Evaluator используйте встроенный объект rng для изучения метода extractcontents (). Для начала включите в этот встроенный объект текст элемента туР. rng.selectNode(document.getElementByld("myP")) Далее извлеките содержимое диапазона и сохраните его в переменной Ь. Ь = a.extractcontents() Вставьте извлеченный фрагмент в конец тела страницы. document.body.appendChild(b) Если прокрутить страницу, то можно ознакомиться с добавленным текстом. См. также: методы clonecontents (), deleteContents (). insertNode (ссылкаНаУзел} Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN7+, Mozl+, Safaril+ Метод insertNode () вставляет узел в начальной точке текущей области. Вставляемый узел может быть фрагментом текстового узла, а его создателем может быть любое соответст- вующее средство, например, метод document. createNode () или любой метод извлече- ния узла из структуры документа. Пример Листинг 35.5 демонстрирует возможности метода insertNode О, а также элемента select. В данном примере вы также найдете упрощенный вариант функции отмены операций изменения текстовых данных. В странице, представленной этим кодом, пользователь может вы- делить произвольный текст абзаца, а сценарий автоматически преобразует его символы в про- писные. Эта задача требует выполнения нескольких операций, в частности, создания выделения с помощью метода window.getSelection(). После проверки существования в выделении текста (выделение не свернуто) оно будет представлено объектом Range (чтобы текст можно было сохранить в глобальной переменной). После этого выделение удаляется из дерева узлов документа и отображается как свернутая точка вставки. Копия выделения в форме объекта Range сохраняет- ся в объекте undoBuf fer, позволяющем вставить удаленный текст в исходное место. В сце- нарии создается новый текстовый узел, содержащий прописной вариант исходного текста. Метод insertNode () вставляет преобразованный текст в свернутую точку вставки. В процессе отмены операции действия выполняются в обратном порядке. Исходное располо- жение и текстовые строки извлекаются из объекта undoBuf fer. После создания объекта Range с исходными начальной и конечной точками исходный текст, преобразованный в текстовый узел, вставляется в свернутую точку вставки. Для полноты картины объект undoBuf fer воз- вращается в исходное состояние. <html> <head> <title>NN Selection Object Replacement</title> «script type="text/javascript"> var undoBuffer = {rng:{}, txt:" "}; function convertSelection() { Глава 35. Текстовые объекты тела страницы 1071
var sei, grossRng, netRng, newText; try { sei = window.getSelection() ,- if (1 sei.isCollapsed) { grossRng = sel.getRangeAt(O); undoBuffer.txt = grossRng.toString(); undoBuffer.mg.startcontainer = , grossRng.startContainer; undoBuffer.rng.startoffset = grossRng.startOffset; undoBuffer.rng.endContainer = grossRng.endContainer; undoBuffer.mg.endoffset = grossRng.endoffset; sei.deleteFromDocument(); netRng = sei.getRangeAt(0); newText = document.createTextNode(undoBuffer.txt. toUpperCase() ) ; netRng.insertNode(newText); netRng.commonAncestorContainer.parentNode.normalize(); } } catch(err) { alert("Vital Range or Selection object services are not yet implemented in this browser."); } } function undoConversion() { var rng, oldText; if (undoBuffer. mg) { rng = document.createRange(); rng.setstart(undoBuffer.rng.startcontainer, undoBuffer.mg.startoffset); mg.setEnd(undoBuffer.rng.endContainer, undoBuf f er. mg. endof f set) ; rng.extractcontents(); oldText = document.createTextNode(undoBuffer.txt); mg. insertNode (oldText) ,- undoBuffer.rng = {}; undoBu ffer.txt = ""; } } </script> </head> <body> «hl id="Hl_l">NN6+/Moz Selection Object Replacement</hl> <hr /> <p id="P_l" onmouseup="convertselection()">This paragraph contains text that you can select. Selections are deleted and replaced by all uppercase versions of the selected text.</p> «button onclick="undoConversion()">Undo Last«/button> «button onclick="location.reload(true)">Start Over«/button> </body> «/html> intersectsNode (ссылкаНаУзел) Возвращаемое значение: булево Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari 1+ 1072 Часть IV. Объекты языка JavaScript
Этот метод возвращает булево значение, указывающее на перекрывание (true) илй непе- рекрывание (false) диапазона, и такое значение указывается в виде аргумента узла. См. также: метод compareNode (). isPointInRange(ссылкаНаУзел, смещение) Возвращаемое значение: булево Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Этот метод возвращает булево значение, указывающее на включение (true) или непопада- ние (false) определенного в качестве аргумента узла и смещенного узла в текущий диапазон. selectNode (ссылкаНаУзел) selectNodeContents(ссмлкаНаУзел) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Методы selectNode () и selectNodeContents () — это наиболее удобные методы для задания начальной н конечной точек, между которыми размещается узел или его содержи- мое. Тип узла, который применятся в качестве параметра в обоих методах (текстовый узел или узел элемента), зависит от контейнера области н единиц измерения смещения точек (см. свойст- ва контейнера и измерение смещения точек в объекте Range, описанные выше в этой главе). Используйте метод selectNode (), если необходимо определить узел элемента как та- кой, что должен быть выделен в виде области. Начальный н конечный узлы новой области — это самые близкие соседние узлы элемента. Смещение точек определяется в родительском узле выделяемого узла. Если вы выделяете текстовый узел, то его узел-контейнер для обоих точек диапазона принадлежит родительскому элементу текстового узла. При использовании метода selectNodeContents () узлы начального и конечного кон- тейнеров представляют собой один и тот же элемент, определенный как параметр. Значения смещений определяются в виде количества узлов в этом элементе. Если выделить содержи- мое текстового узла, то последний будет выступать в роли родительского узла для начального и конечного элементов; прн этом область сжимается в начале выделенного текста. Обычно узлы элементов определяются как параметры в любом из методов, что позволяет включить в область отдельные элементы (с помощью метода selectNode ()) или только их содержимое (метод selectNodeContents ()). Пример Используйте встроенный объект rng приложения The Evaluator для изучения методов selectNode () н selectNodeContents (). Начните с изменения границ этого объекта таким образом, чтобы он включил в себя элемент myP. rng.selectNode(document.getElementByld("myP")) Введите в нижнее поле а, чтобы ознакомиться со свойствами объекта диапазона. По- скольку он полностью включает узел абзаца, то его контейнером будет выступать элемент body (родительский элемент для элемента myP). Теперь измените диапазон так, чтобы он включал только содержимое элемента myP. rng.selectNodeContents(document.getElementByld(”myP")) Щелкните на кнопке List Properties для повторного ознакомления со свойствами диапа- зона. Теперь контейнером диапазона является элемент р. См. также: методы setEndO, setEndAfter (), setEndBefore (), setstart (), setStratAfter(), setStartBefore(). Глава 35. Текстовые объекты тела страницы 1073
s e tEnd(ссылкаНаУзел, смещение) setstart(ссылкаНаУзел, смещение) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Вам предоставляется возможность независимого задания начальной и конечной точек текстовой области. Для этого используются методы setstart () и setEnd (). Возможно, эти методы не настолько удобны, как selectNode () или selectNodeContents (), одна- ко они позволяют получить окончательный наиболее точный результат относительного рас- положения границ области. Первый параметр обоих этих методов — это ссылка на узел. Такая ссылка может указы- вать на элемент или текстовый узел. Ваш выбор в данной ситуации также определяет систему исчисления, применяемую к целочисленному значению смещения, задаваемому в качестве второго параметра. В случае, если первый параметр является узлом элемента, смещение под- считывается как приращение дочерних узлов внутри определенного элемента узла. Если пер- вый параметр представляет собой текстовый узел, то смещение подсчитывается как прира- щение символов внутри текстового узла. При определении начальной и конечной точек области с помощью этих методов ограни- чения на симметричность границ области не накладываются. Одна из границ может быть опре- делена относительно текстового узла, а другая — относительно узла элемента (или наоборот). Для задания конечной точки области, равной последнему узлу или символу внутри тек- стового узла (в зависимости от единиц измерения параметра смещения), используйте свойст- во length. Например, для задания конечной точки в конце последнего узла элемента (предполагается, что во внешнем элементе существует несколько вложенных элементов и текстовых узлов) используется первый параметр. rng.setEnd(document.getElementByld("myP"), document.getElementByld("myP").childNodes.length); Эти выражения достаточно громоздкие, поэтому лучше использовать сокращенную ссыл- ку на значения параметров, как показано ниже. В данном случае конечная точка задается по- сле последнего символа последнего узла элемента р. var nodeRef = document.getElementByld("myP").lastChild; rng.setEnd(nodeRef.nodeValue.length); В двух предыдущих примерах (в которых использовалось свойство length), вы могли убедиться, что значения свойства всегда указывают на узел или позицию символа, находящиеся после последнего объекта области, так как процесс определения индекса объекта начинается с нуля. Обратите также внимание на то, что конец области и конечную точку узла можно оп- ределить с помощью четырех следующих методов: setEndAfter(), setEndBefore (), setStartAfter (), setStartBefore (). Если необходимо задать конечную точку не на границе узла, то используйте методы setEnd () и setstart (). Пример Используйте встроенный объект rng приложения The Evaluator для знакомства с метода- ми setEnd () и setstart (). В первом диапазоне назначьте начальную и конечную точки так, чтобы включить в него второй узел (элемент туЕМ) элемента туР. rng.setStart(document.getElementByld("туР"), 1) mg.setEnd(document.getElementById("myP"), 2) Текст, включенный в диапазон, состоит из слова all и пробела, который представлен элементом туЕМ. Чтобы доказать это, введите в верхнее текстовое поле следующее выраже- ние (Safari 1.0 возвращает некорректное значение). rng.toString() 1074 Часть IV. Объекты языка JavaScript
Если щелкнуть в области результатов справа от слова all, то можно доказать существо- вание пробела. Проверяя свойства диапазона (введите в нижнее поле а), вы замените, что диапазон начинается перед и заканчивается после элемента туЕМ. Далее измените начальную точку, разместив ее в первом текстовом узле элемента туР. rng.setstart(document.getElementByld("туР").firstChild, 11) Щелкните на кнопке List Properties, чтобы получить сведения о свойствах startcontainer (текстовый узел) и startoffset (расположение символа начальной точки) диапазона. Как и следовало ожидать, свойства, определяющие конечную точку диапазона, не изменились. Введите в верхнем поле приложения rng. toString (), чтобы убедиться во включении в диа- пазон текста обоих узлов элемента туР. См. также: методы selectNode (), selectNodeContents (), setEndAfter (), setEndBefore(), setStartAfter(), setStartBefore(). setEndAf ter (ссылкаНаУзел) setEndBefore(ссылкаНаУзел) setStartAfter(ссылкаНаУзел) setStartBefore(ссылкаНаУзел) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Начальную и конечную точки текстовой области можно задать в соответствии с сущест- вующими границами узла с помощью указанных четырех методов. Ключевые слова before и after в именах методов используются для того, чтобы определить, какую границу узла исполь- зовать в качестве границы области. Например, применение методов setStartBefore О и setEndAf ter () для одного и того же узла элемента в качестве параметра аналогично исполь- зованию метода selectNode () для того же элемента. В качестве параметра одного из этих мето- дов можно определить текстовый узел. Поскольку эти методы оперируют только границами узлов, значения смещения всегда определяются с учетом расположения узла, а не символа. Возьмите на заметку, что границы области необязательно должны быть симметричными (другими словами, одна граница может располагаться внутри одного узла, а другая — внутри другого). Пример Используйте встроенный объект rng приложения The Evaluator для изучения методов setEndAfter(), setEndBefore(), setStartAfter() и setStartBefore(). Начни- те с установки начальной и конечной точек так, чтобы в диапазон попал элемент туЕМ, со- держащийся в элементе туР. rng.setStartBefore(document.getElementByld("туЕМ")) rng.setEndAfter(document.getElementByld("myEM")) Текст, включенный в диапазон, состоит из слова all и пробела, который представлен элементом туЕМ. Чтобы доказать это, введите в верхнее текстовое поле следующее выраже- ние (Safari 1.0 возвращает некорректное значение). rng.toString() Далее измените начальную точку так, чтобы диапазон начинался с первого текстового уз- ла элемента туР. mg.setStartBefore(document.getElementByld("myP").firstChild) Глава 35. Текстовые объекты тела страницы 1075
Введите в нижнее поле приложения rng, чтобы ознакомиться со свойствами start- Container (должно приравниваться к элементу р) и endContainer (должно приравни- ваться к элементу em) диапазона. См. также: методы selectNode (), selectNodeContents (), setEnd (), setstart (). surroundcontents (ссылкаНаУзел) Возвращаемое значение: отсутствуют Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ Метод surroundContents О используется для заключения текущей области в новый родительский элемент. Новый родительский элемент указывается как параметр метода. В про- цессе выполнения метода ни один из элементов или узлов дерева документа не удаляется и не перемещается, однако текущая область становится дочерним узлом нового узла. Если теку- щая область совпадает с уже существующим узлом, то связь между областью и его родитель- ским узлом рассматривается как между “дедом и внуком”. Применив этот метод, можно помес- тить выделенный посетителем страницы текст в элемент span, позволяющий отобразить свое содержимое с помощью специальных шрифтов или других параметров таблицы стилей. Если узел элемента используется в качестве нового родительского узла, имеющего свои собственные дочерние узлы, то эти узлы удаляются перед тем, как элемент располагается в новом контейнере. Поэтому для получения наиболее прогнозируемых результатов исполь- зуйте в качестве параметра метода surroundContents () узлы без содержимого. Пример В листинге 35.6 показан пример использования метода surroundContents () для вставки диапазона в новый элемент. В процессе загрузки страницы глобальная переменная newSpan сохраняет элемент span, использующийся как прототип элементов, которые будут представлять новые родительские узлы. После выделения текста в одном из двух абзацев вы- деление преобразуется в диапазон. Далее метод surroundContents () вставляет этот диа- пазон в элемент newSpan. Поскольку элемент span относится к классу hi lite, то он при- обретает все стили, заданные для класса. / NN7 и Mozilla (по крайней мере до версии 1.4) неправильно выполняют этот ме- /н« заметку тод при использовании диапазонов, полученных на основе объектов selection * или диапазонов, не выровненных в элементе. <html> <head> <title>Range.surroundContents() Method</title> «style type="text/css"> .hilite {background-color:yellow; color:red; font-weight:bold} </style> «script type="text/javascript"> var newSpan = document.createElement("span"); newSpan.className = "hilite"; function highlightselection() { var sei, rng; try { sei = window.getSelectionO; 1076 Часть IV. Объекты языка JavaScript
if (Isel.isCollapsed) { rng = sel.getRangeAt(O); rng.surroundcontents(newSpan.cloneNode(false)); } } catch(err) { alert("Vital Range or Selection object services are not yet implemented in this browser."); } } </script> </head> <body> <hl>Range.surroundcontents 0 Method</hl> chr /> <p onmouseup="highlightSelection()">These paragraphs contain text that you can select. Selections are surrounded by span elements that share a stylesheet class selector for special font and display characteristics.</p> <p onmouseup="highlightselection 0">Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </body> </html> См. также: методы selection.getRangeAt (), Range . extraContents (). toString() Возвращаемое значение: строка Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safaril+ С помощью метода toString () можно извлечь копию основного текста, расположенно- го в текущей области. Полученным таким образом текстом не управляет ни один из сущест- вующих в дереве документа дескриптор HTML или узел. Этим методом также можно пользо- ваться для получения текста на основе выделения, создаваемого пользователем, после преобразования этого текста в текстовую область. Пример Используйте встроенный в приложение The Evaluator объект rng для изучения метода toString (). Введите в верхнее текстовое поле следующее выражение. rng.selectNode(document.getElementByld("myP")) mg. toString () Если вы введете в верхнее поле rng, то увидите содержимое диапазона. Но не позволь- те ввести себя в заблуждение. В верхнее текстовое поле вводятся исполняемые выражения. Назначение объекта диапазона текстовому полю приводит к внутреннему выполнению мето- да toString(). См. также: методы selection. getRangeAt (), Range. extraContents (). Глава 35. Текстовые объекты тела страницы 1077
Объект selection Свойства Методы Обработчики событий anchorNode addRange() anchoroffset clear() focusNode collapse() focusoffset collapseToEnd() isCollapsed collapseToStart() rangeCount containsNode() type createRange() typeDetail deleteFromDocument() empty() extend() getRangeAt() removeAllRanges() removeRange() selectAllChilren() toString() Синтаксис Доступ к свойствам и методам объектов элемента selection следующий. (IE4+) [window.]document.selection.свойство|метод() (NN6+/Moz) window.selection.свойство|метод() Описание объекта Объект selection представляет собой свойство объекта document, которое обеспечи- вает Доступ сценария к любому тексту документа или средствам управления текстом, исполь- зуемым сценарием или посетителями. Объект selection, состоящий из одного или более символов, всегда выделяется на странице; более того, только один объект selection может быть активным в текущее время. Когда на странице посетителю дается указание выделить текст для выполнения с ним оп- ределенного действия, можно (и нужно) воспользоваться преимуществами, предоставляемыми объектом selection. Наиболее удобный случай применения объекта selection (сточки зрения обработки) — это событие onmouseup. Такое событие срабатывает после каждого отпус- кания кнопки мыши, при этом сценарий может анализировать объект document. selection на включение в него выделяемого текста (с помощью свойства type). Если вы собираетесь выполнить действие с выделением, то, возможно, у вас не будет воз- можности сделать это сразу, щелкнув на кнопке или ссылке. В некоторых версиях браузеров и операционных систем щелчок на одном из элементов страницы автоматически приводит к отмене выделения текущего элемента или текста. 1078 Часть IV. Объекты языка JavaScript
В браузере NN6+/Moz объект selection представлен в дереве узла документа, при этом происходит определение начальной и конечной точек выделения. Когда посетитель медленно перемещает указатель мыши вдоль текста, узел, в котором производится выделение, получает статус анкерного, а узел, содержащий конечную точку выделения, — активного. Для выделе- ния, которое выполняется двойным или тройным щелчком, направление между анкерным и ак- тивным узлами задается принимаемой по умолчанию системой письма (например, слева напра- во в русском языке). В большинстве случаев в браузере NN6+/Moz объект selection представлен так же, как и объект Range в модели W3C DOM, который содержит методы сжа- тия и расширения выделения. Однако, в отличие от области, текст, сжимаемый с помощью объек- та selection, выделяется на странице. Если ваши сценарии должны управлять узлами внутри выделения, то используйте метод getRangeAt () объекта selection, возвращаю- щий объект Range, граничные точки которого совпадают с граничными точками выделения. Свойства anchorNode focusNode Значение: ссылка на узел Только чтение Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Эти два свойства возвращают ссылку на узел, с которого начинается (anchorNode) и закан- чивается (focusNode) выделение. Если выделение изменить с помощью метода addRange (), то эти свойства определяют границы последнего добавленного диапазона. См. также: свойства anchoroffset и focusOffset. anchoroffset focusOffset Значение: целочисленное Только чтение Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Эти два свойства возвращают количество символов или узлов между началом выделения, а также анкерным (anchoroffset) и активным (focusOffset) узлами. Символы исполь- зуются в текстовых узлах, а узлы — в узлах элементов. Если выделение изменяют с помощью метода addRange (), то эти свойства определят смещение текущего добавленного диапазона. См. также: свойства anchorNode и focusNode. isCollapsed * Значение: булево Только чтение Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Это свойство возвращает булево значение, которое определяет равенство или неравенство анкерного узла активному узлу. Если границы одинаковы, то свойство принимает значение true (выделение имеет нулевую длину). См. также: свойства anchorNode и focusNode. rangeCount Значение: целочисленное Только чтение Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Глава 35. Текстовые объекты тела страницы 1079
Это свойство возвращает количество объектов Range, содержащихся в выделении. Выде- ление, создаваемое пользователями вручную, всегда включает один объект Range. Метод addRange () позволяет включить в выделение несколько объектов Range. См. также: метод getRangeAt (). type Значение: строка Только чтение Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Свойство type возвращает элемент Text, но только при условии существования выделе- ния на странице. В противном случае свойство возвращает значение None. Сценарий исполь- зует эту информацию для определения существования выделения на странице. if (document.selection.type == "Text") { // процедура выделения } Компания Microsoft в своей документации обращает внимание на то, что это свойство иногда возвращает значение Control, что связано с режимом редактирования значения. Пример Листинг 35.7 содержит пример использования нескольких объектов selection в IE. По- сле создания выделения (выберите первый переключатель) вы можете ознакомиться со зна- чением свойства selection, type и до, и после создания объекта (отображается в строке состояния). После удаления выделения свойство type должно принять значение None. <html> <head> <title>selection Object«/title> «script type="text/javascript"> function processselection() { if (document.choices.process[0].checked) { status = "Selection is type:" + document, selection, type; setTimeout("emptySelectionO", 2000); } else if (document.choices.process[1].checked) { var rng = document.selection.createRange(); document.selection.clear(); } } function emptySelectionO { document.selection.empty(); status = "Selection is type: " + document.selection'.type; } </script> </head> <body> <hl>IE selection Object«/hl> <hr /> «form name="choices"> «input type="radio" name="process" checked="checked" />De-select after two seconds«br /> «input type="radio" name="process" />Delete selected text. 1080 Часть IV. Объекты языка JavaScript
</form> <p onmouseup="processSelection()">Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur.</p> </body> </html> См. также: метод TextRange. select (). typeDetail Значение: см. текст Только чтение Совместимость: WinIE5.5+, MacIE-, NN-, Mozl+, Safari- Это свойство служит заполнителем для приложений, в которых используются компонен- ты браузера. Таким образом, в указанном свойстве сохраняется дополнительная информация о выделении. См. также: свойство type. Методы addRange (ссылкаНаДиапазон) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод используется для добавления диапазона в выделение на странице. С его по- мощью выделение может пополняться несколькими объектами Range. См. также: метод removeRange (). clear() Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Чтобы удалить из документа текущее выделение, воспользуйтесь методом clear (). Для посетителя метод clear () выполняет действие, аналогичное присвоению свойству TextRange. text пустой строки. Отличие между этими способами заключается в том, что метод clear () можно использовать, не создавая текстовую область для выделения. После удаления выделения свойством selection. type возвращается значение None. Пример Пример использования метода clear () приведен в листинге 35.7. См. также: метод selection. empty (). collapse(ссылкаНаУзел, смещение) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Глава 35. Текстовые объекты тела страницы 1081
Данный метод сворачивает текущее выделение в точку, определяемую аргументами. Пер- вый аргумент определяет текстовый узел или узел элемента, в который перемещается сверну- тый диапазон. Второй аргумент указывает на количество символов или узлов, на которые пе- ремещается свернутый узел в определенном первым аргументом узле. См. также: методы collapseToEnd () и collapseToStart (). collapseToEnd() collapseToStart() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Указанные методы сворачивают текущее выделение в точку конца или начала выделения, соответственно. См. также: метод collapse (). containsNode (ссылкаНаУзел, флаг) Возвращаемое значение: булево Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Данный метод возвращает булево значение, указывающее на включение определенного узла в текущее выделение. Первый аргумент определяет анализируемый узел, а флаг указыва- ет на то, как включается узел в выделение: полностью или нет (обычно в качестве аргумента флаг передается null). createRange() Возвращаемое значение: объект textRange Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Чтобы создать текстовую область для пользовательского выделения в браузере IE, следует применить метод createRange () объекта selection. Точно не известно, почему метод для объекта selection называется createRange (), в то время как текстовые области для других действительных объектов создаются с помощью метода createTextRange (). Ре- зультатом работы обоих методов является окончательно обработанный объект TextRange. Пример Примеры использования метода createRange () приведены в листингах 15.36 и 15.45. См. также: объект TextRange. deleteFromDocument() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод удаляет текущее выделение из дерева узлов документа. См. также метод: removeRange (). empty() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- 1082 Часть IV. Объекты языка JavaScript
Метод empty () предназначен для отмены текущего выделения в браузере IE. После сня- тия выделения свойство selection, type возвращает значение None. Метод empty () ра- ботает так же, как и команда UnSelect, запускаемая с помощью метода execCommand () для документа. Если выделение создается на основе объекта TextRange (с помощью метода TextRange. select ()), то метод empty () применяется только для видимого выделения; он не влияет на текстовую область. Пример Пример использования метода empty () приведен в листинге 35.7 (ранее в этой главе). См. также метод: selection. clear (). extend (ссылкаНаУзел, смещение) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Данный метод расширяет границы выделения до указанного узла и элемента в узле. На- чальная точка (анкерный узел) выделения остается неизменной; изменяется только конечная точка (активный узел) выделения. getRangeAt(индексДиапазона) Возвращаемое значение: объект Range Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Указанный метод определяет объект Range в выделении по индексу (rangeindex). С по- мощью свойства rangeCount можно легко определить количество диапазонов в выделении. См. также метод: rangeCount (). removeAllRanges() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод удаляет все диапазоны из выделения; выделение становится пустым. Вместо выполнения этого метода, вы можете приравнять свойство rangeCount к нулю. См. также: метод: removeRange (). гemoveRanges() Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Данный метод удаляет указанный диапазон из текущего выделения, но не из дерева узлов документа. См. также метод: removeAHRange (). selectAllChildren (ссылкаНаУзелЭлеменяа) Возвращаемое значение: отсутствует Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод указывает на включение в выделение указанного в аргументе узла и всех его дочерних узлов. Глава 35. Текстовые объекты тела страницы 1083
toString() Возвращаемое значение: строка Совместимость: WinlE-, MacIE-, NN6+, Mozl+, Safari- Этот метод возвращает сроковое представление выделения — содержимое тела страницы минус дескрипторы и атрибуты. Объекты Text и TextNode Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safari 1+ Свойства Методы Обработчики событий attributes* cnildNodes* appendChild()* appendData() data firstChild* lastchild* cloneNode()* deleteData() hasChildNodes()* length* localName* insertBefore()* insertData() namespaceURI* nextSibling* nodeName* nodeType* nodeValue* normalize()* removeChild()* replaceChild()* replaceData() splitText() ownerDocument* parentNode* prefix* previousSibling* substringData() * См. главу 15. Синтаксис Доступ к свойствам и методам объектов этих элементов. (IE5+/W3C) [window. ] document. getElementByld (" идентификатор”) . ссылкаНа Текс - товыйУзел. свойство | метод() Описание объектов Описание особенностей объекта Text W3C DOM и NN6+ такое же однообразное и утоми- тельное, как и изучение объекта TextNode, представленного в IE5+. Все они являются однотип- ными и принадлежат к объектам документа— текстовым узлам, содержащим текст элементов HMTL (информация о назначении текстовых узлов в иерархической структуре объектов документа приведена в главе 14). Создание нового текстового узла с помощью сценария выполняется одина- 1084 Часть IV. Объекты языка JavaScript
ково в обоих объектных моделях— с помощью метода document. createTextNode (). Рас- смотрение особенностей этих двух объектов не будет простым, поскольку версия W3C DOM яв- ляется строго объектно-ориентированной (в ней текстовый узел— это экземпляр объекта CharacterData, который, в свою очередь, содержится в объекте Node). Аналогичный объект в IE не настолько сложен и структурирован. Например, объект Text в W3C DOM имеет же свойства и методы, которые представлены для CharacterData и Node; объект TextNode в IE обладает только теми свойствами и методами, которые необходимы для управления исклю- чительно средствами DOM, представленными Microsoft. Вызов методов объектов выполняется одинаково, поскольку имена объектов никогда явно не указываются в сценарии. Наоборот, операторы сценария всегда ссылаются на текстовые узлы другими способами, (например, с помощью свойств дочерних узлов элемента или переменной, которой присваивается результат выполнения метода document. createTextNode ()). Как отличалось, объекты используют ряд общих свойств и методов. Объект Text в W3C DOM имеет несколько методов, при вызове которых в именах указываются “данные”. Эти свойства и методы заимствованы у объекта CharacterData, также представленного в W3C DOM. Они рассматриваются в следующих разделах этой главы. Всегда проверяйте, поддер- живает ли соответствующий браузер свойства и методы, рассматриваемые ниже. Свойства data Значение: строка Чтение/Запись Совместимость: WinIE5+, MacIE5+, NN6+, Mozl+, Safaril+ Свойство data содержит строку, включающую в себя текстовый узел. Его значение иден- тично свойству nodevalue текстового узла. Для получения подробной информации о свой- стве nodeValue обратитесь к главе 15. Пример В сценарии демонстрации возможностей свойства nodeValue по замене текста (глава 1) вы можете использовать и свойство data. См. также: свойство nodevalue, характерное для всех объектов элементов. Методы appendData (11 текст") deleteData(смещение, количество) insertData (смещение, 11 текст") replaceData (смещение, количество, 11 текст") substringData(смещение, количество) Возвращаемое значение: см. текст Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ С помощью этих шести методов объекта Text W3C DOM в сценарии обеспечивается управление текстом внутри текстового узла. Методы, изменяющие данные узла, автоматиче- ски изменяют значения как свойства data, так и свойства nodeValue. Глава 35. Текстовые объекты тела страницы 1085
Назначение этих методов очевидно в большинстве случаев. Любой метод, предусматриваю- щий использование параметра смещение, использует получаемое целочисленное значение для обозначения начальной точки операции удаления, вставки или замены текста в существующем текстовом узле. Смещение задается с “нулевым отсчетом”, что подразумевает равенство пара- метра смещение для первого символа строки текста узла. Параметр количество — это дру- гое целочисленное значение, однако оно отображает количество символов в обрабатываемом тексте. В качестве примера рассмотрим текстовый узел, содержащий такие данные. abcdefg Этот узел может представлять на странице элемент или только что созданный узел, значе- ние которого успешно присвоено переменной, еще не вставленной на страницу. Для удаления трех символов этого текстового узла необходимо выполнить следующий оператор. ссылкаНаТекстовыйУзел.deleteData(0,3) В результате содержимое узла будет иметь такой вид. defgh Как и для метода replaceDataО, длина текста, заменяющего исходную часть, не должна совпадать со значением параметра количество. Параметр количество совместно с параметром смещение определяет текст, который удаляется и заменяется новым. Метод substringData () аналогичен методу строка. substr () базового языка JavaScript. В нем параметры отображают смещение, с которого начинается чтение строки и количество считываемых символов. При выполнении метода substringData () для текстового узла вы получите тот же результат, что и при использовании метода nodevalue, substr О, но только в том случае, когда оба метода запускаются из стандартного объекта текстового узла. Только один из вышеописанных пяти методов (substringData ()) возвращает строку. Пример Страница, представленная листингом 35.8, позволяет в полной мере изучить методы appendData(), deleteData(), insertData(), replaceData(), substringData() в NN6+/Moz/Safari. Текстовый узел, который выполняет методы, представлен простым пред- ложением, сохраненным в элементе р. Каждый метод связан с кнопкой, а также двумя-тремя текстовыми полями, в которые вводятся его аргументы. Пусть вас не смущает длина листин- га. Каждая операция метода выполняется в отдельной функции, поэтому весь код страницы довольно объемный. Каждый метод имеет строгое ограничение на применение. Чтобы обработать их, все ме- тоды вызываются в конструкции try/catch. Исключения перенаправляются в функцию handl eErrors (), которая отображает на экране соответствующие предупреждения. <html> <head> <title>Data Methods of a W3C Text' Objectc/title> <script type="text/javascript"> f unc t i on doAppend(form) { var node = document.getElementByld("myP").firstChild; var newString = form.appendStr.value; try { node.appendData(newString); } catch(err) { 1086 Часть IV. Объекты языка JavaScript
handleError (err) ,- } } function doDelete(form) { var node = document.getElementByld("myP").firstChild; var offset = form.deleteOffset.value; var count = form.deleteCount.value; try { node.deleteData(offset, count); } catch(err) { handleError(err); } } function dolnsert(form) { var node = document.getElementByld("myP").firstChild; var offset = form.insertoffset.value; var newString = form.insertStr.value; try { node.insertData(offset, newString); } catch(err) { handleError(err); } } function doReplace(form) { var node = document.getElementByld("myP").firstChild; var offset = form.replaceOffset.value; var count = form.replaceCount.value; var newString = form.replaceStr.value; try { node.replaceData(offset, count, newString); } catch(err) { handleError(err); } } function showSubstring(form) { var node = document.getElementByld("myP").firstChild; var offset = form.substrOffset.value; var count = form.substrCount.value; try { alert(node.substringData(offset, count)); } catch(err) { handleError(err); // обработчик событий для этих методов function handleError(err) { switch (err.name) { case "NS_ERROR_DOM_INDEX_SIZE_ERR": alert("The offset number is outside the Глава 35. Текстовые объекты тела страницы 1087
allowable range."); break; case "NS_ERROR_DOM_NOT_NUMBER_ERR": alert("Make sure each numeric entry is a valid number."); break; default: alert("Double-check your text box entries."); } } «/script> </head> <body> <hl>Data Methods of a W3C Text Object«/hl> <hr / > «p id="myP" style="font-weight:bold; text-align:center"> So I called myself Pip, and became to be called Pip.«/p> «form name="choices"> «pxinput type= "button" onclick="doAppend(this.form)" value="appendData()" /> String:«input type="text" name="appendstr" size="30" />«/p> «pxinput type= "button" onclick="doDelete (this, form) " value="deleteData()" /> Offset:«input type="text" name="deleteOffset" size="3" /> Countxinput type="text" name="deleteCount" size="3" /x/p> «pxinput type="button" onclick="dolnsert(this.form)" value="insertData()" /> Offset:«input type="text" name="insertoffset" size="3" /> String:«input type="text" name="insertStr" size="30" /x/p> «pxinput type= "button" onclick="doReplace(this.form)" value="replaceData()" /> Offset:«input type="text" name="replaceOffset" size="3" /> Count:«input type="text" name="replaceCount" size="3" /> String:«input type="text" name="replaceStr" size="30" /x/p> «pxinput type="button" onclick="showSubstring(this.form)" value="substringData()" /> Offset:«input type="text" name="substrOffset" size="3" /> Countxinput type="text" name="substrCount" size="3" /x/p> </form> </body> </html> См. также: методы объектов элементов appendChild (), removechild (), re- placeChild (). splitText(смещение) Возвращаемое значение: объекты Text или TextNode Совместимость: WinIE6+, MacIE5+, NN6+, Mozl+, Safaril+ Метод splitTextO выполняет сложные действия довольно быстро. Целочисленный параметр смещение представляет индекс символа в текстовом узле (отсчет начинается с ну- ля), с которого текущий узел делится на два узла. После выполнения метода для текущего текстового узла, последний будет содержать только текст, начинающийся с начальной точки и заканчивающийся индексом смещения. Данный метод возвращает ссыпку на текстовый узел, данные которого начинаются с символа смещения и заканчиваются последним симво- лом исходного узла. Посетители не замечают никаких изменений в используемом тексте: этот 1088 Часть IV. Объекты языка JavaScript
метод влияет только на структуру узлов документа. Применение этого метода приводит к то- му, что элемент HTML, содержащий только один текстовый узел, в результате содержит два текстовых узла. Обратное действие (слияние объектов текстовых узлов в единый объект) вы- полняется методом normalize () браузераNN6+ (глава 15). Пример Используйте приложение The Evaluator для изучения метода splitText О. Вначале удо- стоверьтесь, что у элемента существует туЕМ один дочерний узел и его свойство nodevalue равно значению all. document.getElementByld("туЕМ").childNodes.length document.getElementByld("myEM").f irstChild.nodeValue Далее разделите текстовый узел на две части после первого символа. document.getElementByld("myEM").firstChild.splitText(1) Оба текстовых узла включены в элемент. document.getElementByld("myEM").childNodes.length Каждый текстовый узел содержит “свою” часть исходного текста. document.getElementByld("myEM").f irstChild.nodeValue document.getElementByld("myEM").lastChild.nodeValue Если вы работаете в NN6+/Moz/Safari, то восстановите текстовые узлы с помощью сле- дующих выражений. document.getElementByld("myEM").normalize() document. getElementByld ("myEM" ) . childNodes. length См. также: метод normalize () (глава 15). Объект TextRange Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Свойства Методы Обработчики событий boundingHeight boundingLeft boundingTop boundingWidth htmlText collapse() compareEndPoints() duplicate() execCommand() expand() offsetLeft* f indText() offsetTop getBookmark() text getBoundingClientRect() getClientRects* inRange() isEqual() moved moveEnd() Глава 35. Текстовые объекты тела страницы 1089
Окончание таблицы Свойства Методы Обработчики событий moveStart() moveToBookmark() moveToElementText() moveToPoint() parentElement() pasteHTMLO queryCommandEnabled() queryCommandlndeterm() queryCommandState() queryCommandSupported() queryCommandText() queryCommandValue() scrollIntoView() select() setEndPoint() * См. главу 15. Синтаксис Создание объекта TextRange. var rangeRef = document.body.createTextRange(); var rangeRef = buttonControlRef.createTextRange(); var rangeRef = textControlRef.createTextRange(); var rangeRef = document.selection.createTextRange(); Доступ к свойствам и методам объекта TextRange. (IE4+) rangeRef. свойство | метод([параметры] ) Описание объекта В отличие от большинства объектов, рассмотренных в третьей части данной книги, объект TextRange в IE не связан ни с одним специфическим элементом HTML. Объект TextRange — это абстрактный объект, представляющий текстовое содержимое на странице (включая содержи- мое текстовых элементов управления формы) между начальной и конечной точками (границами области). Посетителю не обязательно знать о существовании объекта TextRange, поскольку не существует требований, предъявляемых к объекту TextRange по физическому выделению тек- ста на странице (хотя объект TextRange и может использоваться для добавления к сценариям средств автоматического выделения текста; сценарий также может преобразовать выделение, созданное посетителем, в объект TextRange для дальнейшей обработки). Назначение объекта TextRange — это добавление сценариев средствами проверки, вне- сения изменений, замены и вставки содержимого страницы. В IE начальная и конечная точки объекта TextRange определяются специфическим образом в зависимости от положения 1090 Часть IV. Объекты языка JavaScript
символов внутри элемента, в котором создается область (обычно это элемент body, хотя также могут быть и определенные текстовые элементы управления). Место расположения символов текста страницы никоим образом не зависит от кода элементов, которые представ- лены дескрипторами HTML. Именно этот фактор и отличает объект TextRange от других методов и свойств элементов HTML, позволяющих изменять или копировать текст элементов (например, свойства innerText и outerText). Начальная точка объекта TextRange мо- жет находиться в одном элементе, в то время как конечная — в другом. В качестве примера рассмотрим следующий фрагмент HTML-кода. <P>And now to introduce our <EM>very special</EM> guest:</P> Текст, выделенный полужирным шрифтом, представляет содержимое объекта TextRange. Видно, что область пересекает границы элемента таким образом, что свойства элемента HTML становятся неудобными при проведении замены содержимого области другим текстом. Однако даже в данном случае наблюдаются определенные проблемы. Простая замена текста области другим текстом делает обязательным в сценарии (или браузере) упорядочивание результата в соответствии с элементом ет. Проблема возникает по той причине, что объект TextRange управляет только текстом, но никак не элементами. (Ваш текстовый процессор будет иметь по- добную проблему, если создаваемое выделение начинается с курсивного начертания, а заканчи- вается полужирным, и вы при этом еще пытаетесь заменить фразу другим фрагментом.) Важной характеристикой объекта TextRange является возможность включения в об- ласть нескольких элементов или ии одного. Если начальная и конечная точки области нахо- дятся в одной и той же позиции, то в этом случае область выступает в роли точки введения текста. Когда объект TextRange представляет текст внутри элементов управления, метод select () объекта TextRange используется для отображения места введения текста в оп- ределенной сценарии части. Поэтому с помощью средств объекта TextRange можно сде- лать так, чтобы сценарий постоянно отображал курсор введения текста в конце существую- щего текста в диалоговом окне или в текстовом поле при активизации элемента управления. Управление текстовыми областями Для создания объекта TextRange воспользуйтесь методом createTextRange () объекта document. body или любого другого объекта элемента управления. Если необходимо пре- образовать выделенный текст в текстовую область, то для этого выполните специальный ме- тод createRange () объекта document. selection. Независимо от того, как создается область, она включает в себя весь текст объекта, используемого для ее получения. Другими словами, начальная точка области будет находиться в самом начале текста, а конечная — в самом конце. Отметьте, что при создании объекта TextRange на основе элемента BODY текст, находящийся внутри элементов управления, не является частью текста объекта TextRange (так как при ручном выделении текста страницы содержимое поля ие выделяется). После создания объекта TextRange (назначенного переменной) обычно выполняются стандартные действия, включающие запуск многих привычных методов объекта, предназна- ченных для уменьшения размера области. Некоторые методы (move (), moveEnd (), movestart () и setEndPoint ()) предусматривают ручное указание места расположения начальной и конечной точек. Параметры некоторых методов задаются в виде количества слов и даже предложений, поэтому не каждое действие приводит к утомительному подсчету сим- волов. Еще один метод, moveToElementText (), автоматически включает область в соот- ветствующий именованный элемент. Часто используемый метод collapse () размещает на- чальную и конечную точки в одном и том же месте— в начале или в конце текущего выделения. Такой подход используется в том случае, когда в сценарии повторяются операции обработки области (подсчет слов, поиск и замена). Метод expand () позволяет расширить Глава 35. Текстовые объекты тела страницы 1091
область таким образом, чтобы в нее поместить целые слова, предложения или же другую об- ласть, находящуюся за пределами точки вставки. Вероятно, наиболее “мощным” методом является f indText (). Он позволяет сценарию выполнить одноразовый или глобальный по- иск, а также замену текстовых фрагментов страницы. После помещения необходимого текста в область в сценарии будут доступны дополнительные методы управления выделениями. К выполняемым операциям добавляется прокрутка содержимого страницы, которая позволяет посетителю видеть выделенный текст (scrollIntoViewO), а также представление текста на экране (select ()), что обеспечивает с ним наглядную об- ратную связь, необходимую для предотвращения внештатных ситуаций (например, для встав- ки курсора в текстовые элементы управления). Доступ к полной библиотеке дополнительных команд можно получить с помощью метода execCommand (). К таким операциям относится копирование текста в буфер и форматирование содержимого страницы, которое проводится в результате изменения свойств таблиц стилей. Чтобы заменить текст области новым фрагмен- том, полученным сценарием, измените свойство text данной области. Использование объекта TextRange является довольно сложной задачей, поскольку для ее выполнения необходимо пользоваться сложными комбинациями операторов. Обычно для управ- ления объектом TextRange требуется выполнить три основных действия. 1. Создать текстовую область. 2. Установить начальную и конечную точки. 3. Изменить или переместить область. Как только вы научитесь управлять этим объектом, то сразу поймете, какой высокий уро- вень гибкости он предоставляет в сценарии, по крайней мере, при изменении содержимого страницы. Детальная информация об использовании объекта TextRange в сценарии приве- дена ниже в разделах, посвященных отдельным свойствам и методам. Совместимость с браузерами Объект TextRange доступен только IE4+ для Windows. Браузеры IE5+ для Мас не пре- дусматривают поддержку TextRange. В W3C DOM и NN6+ применена иная концепция построения объектов области, задейст- вующая объект Range. Однако основные способы управления объектом Range остаются та- кими же, как и для объекта TextRange: создание, установка начальной и конечной точек, изменение области. Версия W3C (как и сама W3C DOM) наиболее подходит для работы с ие- рархической структурой узлов документа. Свойства и методы объекта Range, в основном, ориентированы на управление узлами, терминологии объекта Range отлична от используе- мой для объекта TextRange, представленного в IE. В настоящее время еще неизвестно, ко- гда будет применен (и будет ли вообще применен) в IE объект Range, характерный &rmW3C. Отметим, что объект Range испытывает недостаток в нескольких методах, которые эффек- тивно используются для управления объектом TextRange, в частности, методах f indText () и select (). С другой стороны, примененный в NN6+/Moz объект Range поддерживается в браузерах для любых ОС. Возникает резонный вопрос: почему бы не создать сценарий, который мог бы управлять обоими типами объектов. Несмотря на то что основная последовательность операций, вы- полняемых с объектами, общая для всех браузеров, синтаксические структуры для этого ис- пользуются разные. В табл. 35.1 представлен итоговый набор свойств и методов, используе- мых обоими браузерами, а также соответствующая им терминология (иногда доступ к значе- нию свойства одного объекта можно получить с помощью метода другого объекта). Возьмите 1092 Часть IV. Объекты языка JavaScript
на заметку то, что способы перемещения отдельных граничных точек не представлены в таб- лице, поскольку соответствующие методы каждого объекта (например, метод moveStart () объекта TextRange соответствует методу setstart () объекта Range) используют разные пространственные принципы. Таблиц&35.1. Общие характеристики TextRange и Range Объект TextRange Объект Range text toString() collapse() compareEndPoints() duplicate() moveToElementText() parentElement() collapse() compareEndPoints() clone() selectcontents() commonparent Совместное управление текстовой областью в двух рассматриваемых объектных моделях одной страницы обеспечивается ветвлением сценария для каждого типа объекта или создани- ем отдельного программного интерфейса приложения, которые позволяют активизировать специальные функции, выполняющие ветвление. Для IE также необходимо написать сцена- рий, в котором устраняются ошибки сценария, вызванные применением объекта в MacOS или других операционных системах, не принадлежащих к семейству Windows. Свойства boundingHeigth boundingLe f t boundingTop boundingWidth Значение: целочисленное Только чтение Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Каждая текстовая область имеет физический объем и расположение на странице, даже ес- ли невозможно увидеть выделение на странице. Курсор введения текста (речь идет о сжатой текстовой области) представляет собой прямоугольник; его высота идентична высоте строки основного текста, в котором представлена выделенная область, а ширина равна нулю. При использовании свойств boundingHeight и boundingWidth объекта TextRange текстовую область прямоугольника можно измерять в пикселях. Если текстовая область состоит из нескольких параллельно расположенных линий, определение размера прямоугольника сво- дится к вычислению размера отдельных маленьких прямоугольников, содержащих текст (способ, идентичный заключению текста в поле — см. описание объекта TextRectangle в конце этой главы). Таким образом, даже если область состоит из одного символа в конце строки и другого, находящегося в начале следующей строки, рабочий прямоугольник будет настолько широк, насколько широким является элемент абзаца. Прямоугольник текстовой области имеет физическое расположение на странице. Верхняя левая координата прямоугольника (в зависимости от границ окна браузера) описывается с помощью свойств boundingTop и boundingLeft. На практике текстовые области, соз- Глава 35. Текстовые объекты тела страницы 1093
данные для выделений, в IE при прокрутке страницы могут представлять недостоверные зна- чения свойства boundingTop. Для получения достоверных результатов необходимо исполь- зовать свойства of f setTop и of f setLef t. Пример В листинге 35.9 приведен простой пример использования свойств boundingHeigth, boundingLef t, boundingTop, boundingWidth (и двух свойств смещения) объекта TextRange. После выделения текста в абзаце значения всех шести свойств отображаются в таблице. Если изменить размер окна с помощью обработчика onresize, то значения этих свойств будут автоматически обновлены. Например, если вы щелкнете в абзаце, не перетаскивая указатель мыши, то свойство boundingWidth примет значение ноль. Эта операция эквивалентна назначению объекта TextRange в качестве точки вставки. <html> <head> <title>TextRange Object Dimension Properties</title> • <style type="text/css"> td {text-align:center} .propName {font-family: Courier, monospace} </style> <script type="text/javascript"> function setAndShowRangeData() { var range = document.selection.createRange(); Bl.innerText = range.boundingHeight; B2.innerText = range.boundingWidth; B3.innerText = range.boundingTop; B4.innerText = range.boundingLeft; B5.innerText = range.offsetTop; B6. innerText = range. of f setLef t } </script> </head> <body onresize="setAndShowRangeData()"> <hl>TextRange Object Dimension Properties</hl> <hr /> <p>Select text in the paragraph below and observe the "bounding" property values for the TextRange object created for that selection.</p> <table id="results" border="l" cellspacing="2" cellpadding="2"> <tr> <th>Property</th> <th>Pixel Value</th> </tr> <tr> <td class="propName">boundingHeight</td> <td class="count" id="Bl">&nbsp;</td> </tr> <tr> <td class="propName">boundingWidth</td> <td class="count" id="B2">&nbsp;</td> </tr> <tr> 1094 Часть IV. Объекты языка JavaScript
<td class="propName">boundingTop</td> <td class="count" id="B3">&nbsp;</td> </tr> <tr> <td class="propName">boundingLeft</td> ctd class="count" id="B4">&nbsp;c/td> </tr> <tr> ctd class="propName">offsetTop</td> ctd class="count" id="B5">&nbsp;c/td> c/tr> ctr> ctd class="propName">offsetLeftc/td> ctd class="count" id="B6">&nbsp;c/td> c/tr> c/table> chr / > cp onmouseup="setAndShowRangeData()">Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod temper incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseruntmollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit.c/p> c/body> c/html> См. также: свойства объектов элементов offsetLeft, offsetTop (глава 15). htmlText Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Свойство htmlText возвращает HTML-текст, находящийся в текстовой области. Если начальная и конечная точки области находятся на границах элемента, то дескрипторы HTML этого элемента становятся частью значения свойства htmlText. Если же область начинается в одном элементе и заканчивается в другом, то дескрипторы, определяющие текст в заключи- тельной части, становятся частью htmlText. Это свойство имеет статус Только для чтения, поэтому HTML-код нельзя вставлять или заменять в текстовой области (детальная информа- ция об управлении HTML-кода приведена при описании метода pasteHTML () и команды вставки, выполняемой методом execCommand () в следующем разделе). Пример В приложении The Evaluator вы сможете детально изучить свойство htmlText. Введите в верхнее текстовое поле следующее выражение, а с результатами ознакомьтесь в нижней области. а = document.body.createTextRange() Далее используйте метод findText () для установки начальной и конечной точки тек- стовой области, включающей слово all, которое представляет элемент ет, включенный в элемент туР. а.findText("all") Глава 35. Текстовые объекты тела страницы 1095
Данный метод возвращает true, если текст найден и включен в текстовую область. Для проверки этого определите значение свойства text области. а.text Поскольку текстовая область содержит весь текст элемента, свойство html Text включа- ет дескрипторы элемента. а.htmlText Если в дальнейшем вы будете определить другие текстовые фрагменты, описываемые свойствами text и htmlText, то сначала восстановите текстовую область, включающую в себя все тело страницы. а.expand("textEdit") Вы ознакомитесь с методом expand () далее в этой главе. См. также: свойство text. text Значение: строка Чтение/Запись Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Свойство text предназначено для получения или изменения строки видимых символов, составляющих текстовую область. Браузер регулирует отдельные проблемы, вызванные из- менением области, имеющей вложенные элементы. Как правило, вложенный элемент (и лю- бое связанное с ним форматирование) удаляется, а новый текст становится частью текста контейнера, хранящего начальную точку текстовой области. Кроме того, если область начи- нается в середине одного элемента и заканчивается в тексте родительского элемента, то деск- риптор, включающий в себя начальную точку, охватывает весь текст. Пример Пример использования свойства text для замены найденного текста приведен в лис- тинге 35.11, в котором рассматривается метод f indText (). См. также: свойство htmlText. Методы collapse О Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Уменьшение текущего размера текстовой области до размера курсора введения символов позволяет выполнить метод collapse (). Данный метод более важен, чем может показаться на первый взгляд, особенно при использовании его в функции, обрабатывающей текст тела страницы или большую часть текста документа. Например, при выполнении обычного цикла подсчета слов изначально создается область, включающая в себя весь текст тела документа (или текст элемента textarea). Если область создана, ее начальная точка находится в начале тек- ста, а конечная — в самом конце. Чтобы подсчитать слова, в начальной точке необходимо свер- нуть область до размеров курсора. Затем с помощью метода expand () задайте в качестве со- держимого области первое слово просматриваемого текста (далее счетчик увеличивается, если метод expand () возвращает значение true). Вокруг первого слова образуется область. Да- лее необходимо сжать текущую область, чтобы поиск продолжался со следующего слова. За- пустите метод collapse () еще раз, но на этот раз изменив его исходные параметры. 1096 Часть IV. Объекты языка JavaScript
Необязательный параметр метода collapse () — это булево значение, которое позволя- ет проводить сжатие в начале или в конце текущей области. Работа этого метода по умолча- нию приводит к возвращению значения true, что означает следующее: пока не произойдет изменение значения, метод collapse () будет сжимать текстовую область до размеров кур- сора, располагаемого перед исходной областью. Данный вариант достаточно эффективно применяется в примере с подсчетом слов, поскольку текстовая область сжимается в начале текста перед началом вычислений. Однако для последующего перемещения по словам тек- стовой области ее необходимо сжать таким образом, чтобы курсор отображался после теку- щего слова. В методе collapse () следует указать второй параметр false. Пример В листингах 35.11 и 35.14 вы детально ознакомитесь с методом collapse (). См. также: методы RangeCollapse (), TextRange. expand (). compareEndPoints("текст", ссылкаНаОбласть) Возвращаемое значение: целочисленное (-1, 0 или 1) Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Создание сложных объектов TextRange и присвоение их различным переменным не вызывает затруднений. Для сравнения относительного расположения начальной и конеч- ной точек двух областей необходимо использовать метод compareEndPoints (). Одна область представляет собой объект, который используется для активизации метода compareEndPoints (), а другая область является вторым параметром метода. Порядок па- раметров не имеет значения, поскольку первый параметр метода определяет, какая точка и в какой области будет сравниваться. Первый параметр принимает значение одной из четырех строк: StartToEnd, StartToStart, EndToStart и EndToEnd. Эти значения определяют точку текущей области, сравниваемую с точкой заданного в качестве второго параметра. Для примера рассмотрим текст тела стра- ницы, который содержит две области, определенные с помощью такого выражения. It was the best of times. Первая текстовая область (в данном случае ее значение присвоено переменной rngl) ото- бражается полужирным начертанием, а вторая (mg2) — полужирным курсивом. Другими сло- вами, переменная rng2 вложена в переменную rngl. С помощью параметра StartToStart метода compareEndPoints () можно сравнить расположение начальных точек rngl и rng2. var result = rngl. compareEndPoints ("StartToStart" , rng2) Возвращаемое методом compareEndPoints () значение, как правило, целочисленное. Если расположение обеих рассматриваемых точек совпадает, то возвращается значение нуль. Если первая точка находится перед второй, то возвращаемое значение будет -1. Если же первая точка расположена после второй, то значение будет равно 1. Из рассмотренного выше при- мера следует, что начальная точка rngl находится после начальной точки rng2, следова- тельно, методом возвращается значение -1. При изменении оператора таким образом, чтобы он запускался для rng2, как показано ниже var result = mg2.compareEndPoints("StartToStart", rngl), можно получить результат 1. На практике этот метод применяется для получения информации о том, совпадают ли две области, совпадает ли одна и та же точка обеих областей и начинается ли одна область там, где заканчивается другая. Глава 35. Текстовые объекты тела страницы 1097
Пример Страница, представленная листингом 35.10, предназначена для проведения операций сравнения. В ее нижнем абзаце содержится элемент span, в который включен объект Text- Range. В этом объекте после загрузки страницы (функция init ()) сохраняется текст эле- мента span. Фиксированная область — это удобная точка отсчета при выделении текста аб- заца. После создания выделения выполняются все четыре версии метода compareEnd- Points О, с помощью которого сравниваются начальная и конечная точки выделения с фиксированной областью. В первом столбце таблицы указывается значение, возвращенное методом, а в третьем приведено более понятное описание этого значения. Чтобы ознакомиться с работой страницы, выделите первое слово в фиксированной облас- ти (дважды щелкните на нем). Как видите, начальные точки в обоих случаях (выделение и область) одинаковы— метод возвращает значение 0. Поскольку во всех случаях метод compareEndPoints () выполняется по отношению к фиксированной области, любое срав- нение осуществляется с точки зрения этой области. Таким образом, в первом столбце табли- цы для параметра StartToEnd указывается, что начальная точка фиксированной области располагается перед конечной точкой выделения (значение -1). Вы можете создать и другие типы выделений. Текстовый фрагмент, который начинается перед фиксированной областью и заканчи- вается в области. Текстовый фрагмент, который начинается в фиксированной области и заканчивается за пределами области. Текстовый фрагмент, который начинается и заканчивается в фиксированной области. Текстовый фрагмент, который начинается и заканчивается перед фиксированной областью. Текстовый фрагмент, который начинается и заканчивается после фиксированной области. Изучите все без исключения варианты выделений и возвращаемые методом значения, чтобы понять, как он работает. <html> <head> • <title>TextRange.compareEndPoints() Method</title> <style type="text/css"> td {text-align:center} .propName {font-family:Courier, monospace} #fixedRangeElem {color:red; font-weight:bold} </style> «script type="text/javascript"> var fixedRange; function setAndShowRangeData() { var selectedRange = document.selection.createRange(); var resultl = fixedRange.compareEndPoints("StartToEnd", selectedRange); var result2 = fixedRange.compareEndPoints("StartToStart", selectedRange); var result! = fixedRange.compareEndPoints("EndToStart", selectedRange) var result4 = fixedRange.compareEndPoints("EndToEnd", 1098 Часть IV. Объекты языка JavaScript
selectedRange); Bl.innerText = resultl; comparel.innerText = getDescription(resultl); B2.innerText = result2; compare2.innerText = getDescription(result2); - B3.innerText = results,- compares.innerText = getDescription(results); B4.innerText = result4; compare4.innerText = getDescription(result4); } function getDescription(comparisonvalue) { switch (comparisonvalue) { case -1 : return "comes before"; break; case 0 : return "is the same as"; break; case 1 : return-"comes after"; break; default : return "vs."; function init() { fixedRange = document.body.createTextRange(); fixedRange.moveToElementText(fixedRangeElem); } </script> </head> cbody onload="init()"> chi>TextRange.compareEndPoints() Method</hl> chr /> cp>Select text in the paragraph in various places relative to the fixed text range (shown in red). See the relations between the fixed and selected ranges with respect to their start and end points.c/p> <table id="results" border="l" cellspacing="2" cellpadding="2"> ctr> cth>Propertyc/th> <th>Returned Value</th> cth>Fixed Range vs. Selection</th> </tr> <tr> ctd class="propName">StartToEndc/td> ctd class="count" id="Bl">&nbsp;c/td> ctd class="count" id="Cl">Start of Fixed cspan id="comparel">vs.c/span> End of Selectionc/td> c/tr> ctr> ctd class="propName">StartToStartc/td> ctd class="count" id="B2">&nbsp;c/td> ' ctd class="count" id="C2">Start of Fixed cspan id="compare2">vs.c/span> Start of Selectionc/td> Глава 35. Текстовые объекты тела страницы 1099
</tr> <tr> <td class="propName">EndToStart</td> ctd class="count" id="B3">&nbsp;</td> <td class="count" id="C3">End of Fixed cspan id="compare3">vs.</span> Start of Selectionc/td> c/tr> ctr> ctd class="propName">EndToEndc/td> ctd class= "count" id="B4">&nbsp,-</td> ctd class="count" id="C4">End of Fixed cspan id="compare4">vs.</span> End of Selection</td> c/tr> c/table> chr /> cp onmouseup="setAndShowRangeData0">Lorem ipsum dolor sit, cspan id="fixedRangeElem">consectetaur adipisicing elit c/span>, sed do eiusmod temper incididunt ut labore et dolore aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> с/body> c/html> См. также: метод Range. compareEndPoints (). duplicate() Возвращаемое значение: объект TextRange Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Метод duplicate () возвращает объект TextRange, являющийся моментальной копи- ей текущего объекта TextRange. В некотором отношении между двумя объектами сущест- вует односторонняя связь. При изменении свойства text копии без перемещения начальной и конечной точек исходной области, последняя приобретает свойства нового текста. Однако если переместить начальную или конечную точки оригинала, то свойства text и htmlText, соответственно, изменятся (а копия будет сохранять исходные характеристики, даже после изменения оригинала). Таким образом, описанный метод можно использовать при создании аналога текста одной отдельной части документа в других его частях. Пример Вы можете использовать приложение The Evaluator для изучения метода duplicate (). Начните с создания объекта TextRange, который содержит текст элемента myP. а = document.body.createTextRange() а.moveToElementText(myP) Далее создайте копию исходной области и сохраните ее в переменной Ь. b = a.duplicate() Этот метод не возвращает значение, поэтому в области результатов страницы сообщение не выводится. Переместите исходную область так, чтобы ее точка вставки располагалась в конце тела страницы, и сверните область в конечную точку. а. expand (’"textedit" ) a.collapse(false) 1100 Часть IV. Объекты языка JavaScript
Вставьте в эту точку копию объекта. a.text = b.text Прокрутите страницу вниз и ознакомьтесь со вставленным текстом. См. также: методы Range. clone (), TextRange. isEqual (). execCommand("имяКоманды"[, флаг[, значение] ]) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- B IE4+ для Win32 сценарии могут получить Доступ к достаточно большому количеству команд; управляющих точками вставки, абстрактными текстовыми областями и выделения- ми, представленными объектом TextRange. Доступ к этим командам обеспечивается с по- мощью метода execCommand (), который запускается объектами TextRange и document (подробные сведения о методе document. execCommand () приведены в главе 18; см. так- же список команд по управлению документом и выделением, представленный в табл. 18.3). Первый обязательный параметр— это имя команды, которую необходимо выполнить. Только набор предопределенных команд предоставляет сценариям уникальные возможности, которые нельзя получить с помощью объектной модели IE и средств таблиц стилей. Большое значение имеет команда, позволяющая копировать содержимое текстовой области в буфер обмена. Другие команды предназначены для изменения стилей или вставки дескрипторов HTML в позиции сжатой текстовой области. Последние операции рекомендуется реализовы- вать с помощью других средств, однако они включены в табл. 35.2 для полноты изложения (информация о других командах приведена в табл. 18.3). ОДадде 35<2. Команды метода TextRange. execCommand () Команда Параметр Описание Bold нет Помещает текстовую область в пару дескрипторов <ь> Copy нет Копирует текстовую область в буфер обмена Cut нет Копирует текстовую область в буфер обмена и удаляет его из элемента управления или документа Delete нет Удаляет текстовую область InsertButton идентификатор строки Вставляет дескриптор <button> в точке курсора, присваивает атрибуту id значение параметра Insert.Fieldset идентификатор строки Вставляет дескриптор <f ieldset> в точке курсора, присваивает атрибуту id значение параметра InsertHoritontalRule идентификатор строки Вставляет дескриптор <hr> в точке курсора, присваивает атрибуту id значение параметра Insertl Frame идентификатор строки Вставляет дескриптор <iframe> в точке курсора, присваивает атрибуту id значение параметра InsertlnputButton идентификатор строки Вставляет дескриптор < input t уре=11 but ton" > в точке курсора, присваивает атрибуту id значение параметра Insertinputcheckbox идентификатор строки Вставляет дескриптор «input type=" checkbox" > в точке курсора, присваивает атрибуту id значение параметра Глава 35. Текстовые объекты тела страницы 1101
Продолжение табл. 35.2 Команда Параметр Описание InsertlnputFileUpload идентификатор строки Вставляет дескриптор <input type= "Fileupload" > в точке курсора, присваивает атрибуту id значение параметра InsertInputHidden идентификатор строки Вставляет дескриптор cinput type="hidden"> в точке курсора, присваивает атрибуту id значение параметра InsertInputimage идентификатор строки Вставляет дескриптор «input type="image'> в точке курсора, присваивает атрибуту id значение параметра InsertInputPassword идентификатор строки Вставляет дескриптор «input type= "password" > в точке курсора, присваивает атрибуту id значение параметра InsertInputRadio идентификатор строки Вставляет дескриптор «input type="radio"> в точке курсора, присваивает атрибуту id значение параметра InsertInputReset идентификатор строки Вставляет дескриптор « input type= " reset" > в точке курсора, присваивает атрибуту id значение параметра InsertInputSubmit идентификатор строки Вставляет дескриптор < input type=" submi t" > в точке курсора, присваивает атрибуту id значение параметра InsertInputText идентификатор строки Вставляет дескриптор < input type=" text" > в точке курсора, присваивает атрибуту id значение параметра InsertMarquee идентификатор строки Вставляет дескриптор «marquee > в точке курсора, присваивает атрибуту id значение параметра InsertorderedList идентификатор строки Вставляет дескриптор «о1 > в точке курсора, присваивает атрибуту id значение параметра Insertparagraph идентификатор строки Вставляет дескриптор «р> в точке курсора, присваивает атрибуту id значение параметра InsertSelectDropdown идентификатор Вставляет дескриптор «select type="select-one"> строки в точке курсора, присваивает атрибуту id значение параметра insertSelectListbox идентификатор строки Вставляет дескриптор «select type="select- muitiple" > в точке курсора, присваивает атрибуту id значение параметра InsertTextArea идентификатор Вставляет дескриптор <textarea> в точке курсора, строки присваивает атрибуту id значение параметра InsertUnorderedList идентификатор строки Вставляет дескриптор <ul> в точке курсора, присваивает атрибуту id значение параметра Italic нет Помещает текстовую область в пару дескрипторов <i> Overwrite булево Задает режим вставки текста: перезапись (true) или добавление (false) Paste нет Вставляет текущее содержимое буфера обмена в точку курсора или выделение 1102 Часть IV. Объекты языка JavaScript
Окончание табл. 35.2 Команда Параметр Описание Playimage нет Запускает просмотр динамических изображений, если они присвоены атрибуту dynsrc элемента img Refresh нет Перезагружает текущую страницу Stopimage нет Останавливает просмотр динамических изображений, если они присвоены атрибуту dynsrc элемента img Underline нет Помещает текстовую область в пару дескрипторов <и> Второй необязательный параметр — это булев флаг, дающий указания команде отобра- жать любые средства пользовательского интерфейса, которые могут быть связаны с коман- дой. Значение этого флага, принятое по умолчанию, — false. В третьем параметре некото- рые команды задают значение атрибута, необходимое для нормального выполнения команды. Например, во время вставки нового абзаца в точке курсора происходит присвоение атрибуту id элемента р значения идентификатора. В этом случае синтаксис кода команды имеет вид. myRange.execCommand("InsertParagraph", true, "myNewP"); Метод execCommand () возвращает булево значение true, если команда успешно вы- полнена; соответственно, false,— если не выполнена. Некоторые команды могут возвра- щать значения (например, определяющие тип шрифта выделения), однако Доступ к возвра- щаемым значениям можно получить только с помощью метода queryCommandValue (). Команды, представленные в табл. 35.2, управляют текстовыми областями, однако сущест- вуют дополнительные команды, управляющие целыми выделениями (табл. 18.3), они зачас- тую намного эффективнее при первичной обработке текстовой области. Например, рассмот- рим функцию, задачей которой является нахождение каждого экземпляра обычного слова в документе и выделение его фона желтым цветом. Такая функция использует средства мето- да f indText {) текстовой области для нахождения каждого экземпляра. Затем метод select () выделяет соответствующий текст, и только после этого выполняется команда BackColor. Рассмотрим следующий код. function hilitelt(txt) { var mg = document.body.createTextRange(); for (var i = 0,- rng. findText (txt) ; i++) { rng.select(); rng.execCommand("BackColor", "false", "yellow"); rng.execCommand("Unselect"); //подготовка к следующему поиску rng.collapse(false); } } В данном случае метод execCommand () используется для изменения HTML-содержимого эффективнее, чем операция заключения существующего текста внутри нового дескриптора. Не- достатком данного метода можно считать то, что способ назначения цвета фона текстовому фрагменту в данном случае недостаточно гибкий (IE помещает текст в дескриптор <f ont> с ат- рибутом style,которому присвоено значение background-color:yellow). Вероятно, этот спЬсоб несколько отличается от того, который вы реализовали бы самостоятельно. Пример Приложение The Evaluator успешно применяется для изучения метода вставки текста в буфер обмена компьютера. Начните с создания текстовой области для элемента myP. а = document.body.createTextRange() a.moveToElementText(myP) Глава 35. Текстовые объекты тела страницы 1103
Далее используйте команду execCornmand О для копирования этой области в буфер обмена, а.execCommand("Сору") Чтобы проверить, занесен ли текст в буфер обмена, воспользуйтесь командой Вставить (Paste) меню Правка (Edit). См. также: некоторые методы команд запросов объекта TextRange. expand("единица") Возвращаемое значение: булево Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Обычный метод expand () может расширить любую область (сжатую или нет) на сле- дующий символ, слово, предложение или даже отдельную область (например, область вокруг текста элемента body, если она создана методом document. body. createTextRange ()). Параметром метода является строка, задающая текстовый элемент, на который расширяются внешние границы области: character, word, sentence или textedit. При успешном завершении операции метод возвращает значение true; иначе — false. При запуске для сжатой области метод expand () сначала определяет слово или предло- жение, окружающее курсор. Однако эта операция выполняется недостаточно точно. Если су- ществует текст, предшествующий предложению, к которому должно произойти расширение, но этот текст не заканчивается точкой, метод expand () расширяет границы до тех пор, пока не найдет следующую точку или начало области. В листинге 15.14 показано, как на практике реализуется этот “феномен”. При расширении от точки курсора на символ, метод расширяет область до следующего символа в направлении, заданном используемой системой письма. Если точка курсора находится в конце области, то область не может расшириться в строну следующих элементов. В этом случае метод expand () возвращает значение false. Нередко встречаются ситуации, когда в большом сценарии необходимо взаимно заменить начальную и конечную точки исходной области в процессе многократного выполнения мето- дов collapse () и expand (). Расширение до целой области — это способ, с помощью ко- торого можно начать управление текстом сразу после создания выделенной области. Пример Пример использования метода expand () приведен в листинге 15.14. См. также: метод TextRange. collapse (). f indText ("искомаяСтрока" [, диапазонПоиска, флаги]) Возвращаемое значение: булево Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Одним из наиболее часто используемых методов объекта TextRange является findText О, назначение которого состоит в просмотре текстовой области от начальной точки до конечной с целью поиска необходимого объекта (в строке поиска различие строч- ных и прописных символов не проводится). Если экземпляр найден в области поиска, то об- ласть сжимается до размеров найденного экземпляра и на ней фокусируется внимание посе- тителя. В этом случае метод возвращает значение true; в противном случае метод возвращает значение false; перемещения начальной и конечной точек области не происхо- дит. В вышеописанной операции осуществляется поиск текста, реально представленного на странице, а не текста атрибута или дескриптора. 1104 Часть IV. Объекты языка JavaScript
Необязательные параметры позволяют управлять дополнительными средствами управле- ния поиском. Существует возможность ограничения диапазона области, в которой проводит- ся поиск. Параметр диапазонПоиска содержит целочисленное значение количества симво- лов диапазона поиска, отсчитанное от начальной точки. Чем больше это значение, тем в большей части области проводится поиск. Отрицательные значения изменяют направление поиска— он выполняется от текущей начальной точки. Если необходимо провести поиск в обратном направлении до начала области (однако при этом не известно, как далеко нахо- дится начальная точка области) определите произвольное большое число, которое гарантиро- вано больше количества символов до начальной точки. Необязательный параметр флаги указывает, учитывается ли в процессе поиска регистр сим- волов (например, строчные и прописные буквы), и/или выполняется поиск только целых слов. Этот параметр содержит обычное целочисленное значение, в котором суммируются числа для обоих флагов. Результирующее значение будет представлено по-разному в зависимости от ко- личества флагов и их состояний. Значение для поиска отдельных слов — 2; при необходимости различать регистр — 4. Если вы хотите применить только один флаг, то укажите соответствую- щее число. Заметьте, что для одновременного задания обоих флагов следует использовать оператор побитового исключающего ИЛИ (л), который возвращает максимальное значение 6. Общепринятое назначение метода findText О — это поиск и замена текста, а также форматирование определенного экземпляра строки внутри области. Итеративный пропесс поиска предусматривает определенный уровень контроля за ходом выполнения операции. Поскольку поиск всегда начинается с начальной точки текущей области, перемещение точки начала поиска в конец последней найденной строки является обязательным. Это перемеще- ние позволяет в следующем сеансе метода findText О просмотреть не всю исходную об- ласть сначала, а только непросмотренную ее часть. Поскольку метод findText () не позво- ляет переопределять точку поиска для текущей области и продолжает просмотр начальной области, то с помощью метода collapse (false) необходимо обязательно переместить начальную точку поиска в конец последней найденной строки. Для выполнения повторного поиска можно воспользоваться циклом while или for. Воз- вращаемое булево значение метода f indText () может выступать в роли условия выполне- ния цикла. Если количество успешных попыток выполнения цикла не имеет значения для сценария, то в данном случае лучше использовать конструкцию while. while (rng.findText(searchstring)) { mg. collapse (false) ; } Также можно воспользоваться циклическим счетчиком for, который обеспечивает под- счет найденных экземпляров строк. for (var i = 0; findText(searchstring); i++) { rng.collapse(false); } Некоторые операции управления областью (например, набор команд, запускаемых мето- дом execCommand ()) требуют, чтобы до их запуска выделение уже существовало. Поэтому будьте готовы к использованию метода select () после того, как метод findText () найдет искомую область текста. Пример В листинге 35.11 приведен код страницы, в котором показано два способа выполнения операции поиска и замены текста, в которой учитываются такие параметры, как регистр сим- волов и нахождение полного слова. Оба подхода требуют создания объекта TextRange для Глава 35. Текстовые объекты тела страницы 1105
всего тела страницы, хотя его начальная точка будет смещена в начало элемента div, содер- жащего искомый текст. Одна из функций, выполняющая операцию замены и вставки текста, запрашивает у пользо- вателя разрешения на замену всех найденных экземпляров искомого текстового фрагмента. Ме- тоды select () и scrollIntbViewO вызывают с целью показать пользователю заменяе- мый текст. Обратите внимание, что даже после отказа от замены текста фрагмент сворачивается в конечную точку найденной области, чтобы новый поиск начинался со следующего слова. Если бы в коде страницы не использовался метод collapse (), то поиск в данном случае превра- тился бы в бесконечный цикл нахождения одного и того же текста. Поскольку учет количества операций поиска не ведется, то в данном случае используется программная конструкция while. Вторая функция поиска текста заменяет все найденные экземпляры и выводит сведения об их количестве. Количество замененных экземпляров искомого текста представлено счетчи- ком цикла после завершения всех итераций (совпадений больше не найдено). <html> <head> <title>TextRange.findText() Method</title> «script type="text/javascript"> // глобальная переменная диапазона, используемая в Undo var rng; // возвращение аргументов третьего параметра findTextО function getArgs(form) { var isCaseSensitive = (form.caseSensitive.checked) ? 4 : 0; var isWholeWord = (form.wholeWord.checked) ? 2 : 0; return isCaseSensitive Л isWholeWord; } // запрашиваемый поиск и замена function sAndR(form) { var srchString = form.searchstring.value; var replString = form.replaceString.value; if (srchString) { var args = getArgs(form); rng = document.body.createTextRange(),- rng.moveToElementText(rights); clearUndoBuffer(); while (rng.findText(srchString, 10000, args)) { rng. select () ,- rng.scrollIntoViewO ; if (confirm("Replace?")) { rng.text = replString; pushUndoNew(rng, srchString, replString); } rng.collapse(false); } } I/ незапрашиваемый поиск и замена со счетчиком function sAndRCount(form) { var srchString = form.searchstring.value; var replString = form.replaceString.value; 1106 Часть /V. Объекты языка JavaScript
var i; if (srchString) { var args = getArgs(form); rng = document.body.createTextRange(); rng.moveToElementText(rights); for (i = 0,- rng.findText (srchString, 10000, args)'; i++) { rng.text = replString; pushUndoNew(rng, srchString, replstring); rng.collapse(false); } if (i > 1) { clearUndoBuffer(); } } document.getElementByld("counter").innerText = 1; } // НАЧАЛО КОДА БУФЕРА ОТМЕНЫ // глобальные переменные буфера var newRanges = new Array(); var origSearchString; // сохранение исходной строки писка и закладок каждого // замененного диапазона function pushUndoNew(rng, srchString, replString) { origSearchString = srchString; rng.movestart("character", -replString.length); newRanges[newRanges.length] = rng.getBookmark(); } // очистка массива и строки поиска function clearUndoBuffer() { document.getElementByld("counter").innerText = "0"; origSearchString = ""; newRanges.length = 0; } // выполнение отмены function undoReplace() { if (newRanges.length && origSearchString) { for (var i = 0,- i < newRanges.length; i++) { rng.moveToBookmark(newRanges[i]) ; rng.text = origSearchString; } document.getElementByld("counter").innerText = i; clearUndoBuffer(); } </script> </head> <body> <hl>TextRange.findText() Method«/hl> <hr /> <form> <p>Enter a string to search for in the following text: <input type="text" nartie="searchString" size="20" value="Law" /> &nbsp; «input type="checkbox" name="caseSensitive" />Case-sensitive &nbsp; «input type="checkbox" name="wholeWord" />Whole words only</p> Глава 35. Текстовые объекты тела страницы 1107
<p>Enter a string with which to replace found text: <input type=’'text" name="replaceString" size="20" value="legislation" /></p> <pxinput type= "button" value="Search and Replace (with prompt)" onclick="sAndR(this.form)" /x/p> <pxinput type="button" value="Search, Replace, and Count (no prompt)" onclick="sAndRCount(this.form)" /> <span id="counter">0</span> items found and replaced.</p> <pxinput type="button" value="Undo Search and Replace" onclick="undoReplace()" /></p> </form> <div id="rights"> <h2xa id="articlel" name="articlel">ARTICLE I</ax/h2> <p>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.</p> <h2xa name="article2">ARTICLE II</ax/h2> <p>A well regulated militia, being necessary to the security of a free state, the right of the people to keep and bear \ arms, shall not be infringed.</p> <h2xa name= "articles ">ARTICLE III</ax/h2> <p>No soldier shall, in time of peace, be quartered in any house, without the consent of the owner, nor in time of war, but in a manner to be prescribed by law.</p> <h2xa name="article4">ARTICLE IV</ax/h2> <p>The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures shall not be violated, and no warrants shall issue, but upon probable cause, supported by oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized.</p> <h2xa name="articles">ARTICLE V</ax/h2> <p>No person shall be held to answer for a capital, or otherwise infamous crime, unless on a presentment or indictment of a grand jury, except in cases arising in the land or naval forces, or in the militia, when in actual service in time of war or public danger; nor shall any person be subject for the same offense to be twice put in jeopardy of life or limb; nor shall be compelled in any criminal case to be a witness against himself, nor be deprived of life, liberty, or property, without due process of law; nor shall private property be taken for public use, without just compensation.</p> <h2xa name="article6">ARTICLE VI</ax/h2> <p>In a?1 criminal prosecutions the accused shall enjoy the right to a speedy and public trial, by an impartial jury of the state and district wherein the crime shall have been committed, which district shall have been previously ascertained by law, and to be informed of the nature and cause of the accusation; to be confronted with the witnesses against him; to have compulsory process for obtaining witnesses in his favor, and to have the assistance of counsel for his defense.</p> <h2xa name="article7">ARTICLE VII</ax/h2> <p>In suits at common law, where the value in controversy 1108 Часть IV. Объекты языка JavaScript
shall exceed twenty dollars, the right of trial by jury shall be preserved, and no fact tried by a jury shall be otherwise re-examined in any court of the United States, than according to the rules of the common law.</p> <h2xa name= "articles">ARTICLE VIII</ax/h2> <p>Excessive bail shall not be required, nor excessive fines imposed, nor cruel and unusual punishments inflicted.</p> <h2xa name="articles">ARTICLE IX</ax/h2> <p>The enumeration in the Constitution, of certain rights, shall not be construed to deny or disparage others retained by the people.</p> <h2xa name="articlelO">ARTICLE X</ax/h2> <p>The powers not delegated to the United States by the Constitution, nor prohibited by it to the states, are reserved to the states respectively, or the the people. </p> </div> </body> </html> Предоставление доступа к функции поиска и замены текста — это только половина зада- чи. Вам еще предстоит обеспечить в сценарии поддержку функции отмены выполненных из- менений. С этой целью в сценарий вставлен код “буфера”, в котором сохраняются сведения о состоянии документа до замены текста. Этот “буфер” представлен двумя переменными. Первая переменная, originsearchstring,— это обычная строка, которая используется при проведении поиска данных. В ней сохраняется текст, который в случае отмены действия вставляется вместо замененного текста. Вторая глобальная переменная представляет собой массив закладок объекта TextRange (см. метод getBookmark () далее в этой главе). В массиве сохраняются ссылки, которые рядовому пользователю практически ни о чем не скажут, зато браузер эффективно использует их для быстрого нахождения мест вставки зате- нененного текста. Значения двух глобальных переменных сохраняются при вызове метода pushUndoNew (), который выполняется при каждой операции замены текста. Установка свойства text текстовой области выполняется таким образом, что она свора- чивается в конечную точку нового текста. Поскольку закладка включает сведения о заменен- ном тексте, перед ее сохранением начальная точка текстовой области должна смещаться об- ратно в начало замененного. Функция pushlntoNew () получает строку с замененным текстом, а метод movestart () использует количество символов в последней. После сохранения в массиве всех закладок отмена действий выполняется в обычном цикле for, вставленном в функцию undoReplace (). Проверив существование данных в “буфере” отмены, функция просматривает массив закладок и заменяет сохраненным в них текстом ра- нее замененный текст документа. Преимущество использования закладок состоит в том, что отмена действий выполняется только по отношению к тексту, ранее измененному командой поиска-замены. См. также: метод TextRange. select (). getBookmark() Возвращаемое значение: строка Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- B контексте объекта TextRange закладка отличается от того средства, которое вы исполь- зуете в браузере для сохранения ссылок на наиболее часто посещаемые узлы (добавление новых элементов в список избранных Web-страниц). Наоборот, закладка представляет собой строку, определяющую текстовую область, в том числе сведения о ее расположении в документе, тексте Глава 35. Текстовые объекты тела страницы 1109
и т.д. Просматривать эту строку бесполезно, так как она содержит данные, представленные в битовой форме. Никакой полезной информации из этой строки вы не получите, если, ко- нечно, рассматривать ее с точки зрения обычного языка. Однако закладка предоставляет сце- нарию возможность сохранения текущего состояния текстовой области таким образом, что к ней можно было вернуться в следующем сеансе работы. Метод getBookmark () возвра- щает строковое представление копии текущей текстовой области. Некоторые другие опера- торы сценария могут корректировать объект TextRange в соответствии с используемой спецификацией закладки с помощью метода moveToBookmark () (см. далее в этой главе). Пример Листинг 35.11 содержит пример использования метода getBookmark () в операции по- иска и замены текста (при создании массива закладок). В этом же примере метод moveTo- Bookmark () применяется для отмены выполненных действий. См. также: метод TextRange. moveToBookmark (). inRange(ссылкаНаОбласаль) Возвращаемое значение: булево Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Существует возможность сравнения физической протяженности текста двух различных областей. Эта задача выполняется с помощью метода inRange (). Вы просто запускаете ме- тод в большей из двух областей и передаете ссылку, представленную в качестве основного параметра метода, на меньшую область. Если заданная параметром область находится в об- ласти или эквивалентна той текстовой области, в которой запускается метод, то методом воз- вращается значение true; в противном случае— false. Пример Используйте приложение The Evaluator для ознакомления с методом inRange (). Сле- дующие выражения генерируют две текстовые области: для элемента туР абзаца и элемента туЕМ, вложенного в первый. а = document.body.createTextRange() а.moveToElementText(туР) b = document.body.createTextRange() b.moveToElementText(туЕМ) Поскольку текстовая область для элемента туР больше другой, то вызов для нее метода inRange () приводит к возвращению значения true. a.inRange(b) Если обратить последнее выражение, то можно заметить, что больший элемент не вклю- чен в меньший. b. inRange(а) См. также: метод TextRange. inEqual (). isEqual(ссылкаНаОбласть) Возвращаемое значение: булево Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Если сценарий имеет ссылки на два независимо инициированных объекта TextRange, то для проверки идентичности этих двух объектов можно использовать метод isEqual (). Ука- 1110 Часть IV. Объекты языка JavaScript
занный метод ищет совпадение текста, требуя, чтобы для двух областей он совпадал посим- вольно. При этом содержимое одной области считается идентичным содержимому исходной области (например, содержимое элементов управления или основного текста). Для определе- ния того, содержится ли одна область в другой, без метода inRange () просто не обойтись. Пример Изучить метод is Equal () вам поможет все то же приложение The Evaluator. Начните с создания двух текстовых областей: для элемента туР абзаца и элемента туЕМ, вложенно- го в первый. а = document.body.createTextRange() а.moveToElement(туР) b = document.body.createTextRange() b.moveToElement(myEM) Поскольку обе области выключают в себя разные текстовые диапазоны, то они не равны. Выполните следующее выражение. a.isEqual(b) Если изменить границы первой области так, чтобы она включила только элемент туЕМ, то текстовые области станут равными. a.moveToElement(myEM) a.isEqual(b) См. также: метод TextRange. inRange (). move (11 единица" [, количество]) Возвращаемое значение: целочисленное Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Метод move () выполняет две операции. Во-первых, метод преобразует текущую тексто- вую область в курсор и располагает его в месте конечной точки текущей области. Потом он перемещает курсор относительно символа, слова или предложения в необходимом направле- нии. Первым параметром метода выступает строка, определяющая элемент смещения (character, word, sentence или textedit). Значение textedit перемещает курсор вначале или конец всей исходной области. Если пренебречь вторым параметром, то по умолчанию его значение будет равно 1. В противном случае необходимо определить цело- численное значение, представляющее количество элементов, на которое сжатая область должна перемещаться вперед (при положительном значении) или назад (при отрицательном значении). Метод возвращает целочисленное значение, отображающее точное количество элементов, на которые можно переместить курсор. Если определить большее количество эле- ментов, чем содержится в области, то возвращаемое значение предоставит точную информа- цию о том, насколько далеко можно переместить курсор. Отметьте, что область все еще остается сжатой после выполнения метода move (). Рас- ширение области вокруг определенного текста — это задача других методов. Также метод move () можно использовать в сочетании с методом select () для пози- ционирования курсора ввода текста в текстовом окне или области. Таким образом можно на- писать сценарий для текстового поля, в котором после активизации или загрузки всей стра- ницы курсор размещается в конце введенного текста. Функция, выполняющая эти действия, представлена ниже. function setCursorToEnd(elem) { if (elem) if (elem.type && (elem.type=="text" || Глава 35. Текстовые объекты тела страницы 1111
elem.type=="textarea")){ var rng = elem.createTextRange(); rng.move("textedi t"); rng.select 0; } } } Впоследствии можно запустить этот метод в функции обработчика событий onfocus текстового поля. cinput type="text"...onfocus="setCursorToEnd(this)"> Вышеописанная функция включает несколько уровней проверки наличия ошибок; напри- мер, запуск функции действительным объектом, выступающим в качестве параметра, а также использование свойства type объекта, значение которого может содержать текстовую об- ласть, созданную для его содержимого. Пример Приложение The Evaluator представляет собой идеальную среду для изучения метода move (). Чтобы увидеть, как этот метод определяет количество элементов, на которое сме- щается указатель мыши, создайте текстовую область, включающую элемент myP. а = document.body.createTextRange() a.moveToElementText(myP) Далее введите следующее выражение для сворачивания и перемещения диапазона обрат- но на 20 слов. ' - a.move("word", -20) Щелкните на кнопке Evaluate и изучите полученные результаты. Значение 2 0 отобража- ется до тех пор, пока метод не сместит область на 20 слов. Достигнув начала тела страницы, в качестве результата метод возвратит значение 0. См. также: методы TextRange. moveEnd (), TextRange. movestart (). moveEnd (11 единица" [, количество] ) movestart(единица"[, количество] ) Возвращаемое значение: целочисленное Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Методы moveEnd () и movestart () подобны методу move (), однако каждый из них выполняется либо только в начальной, либо только в конечной точке текущей области, соот- ветственно. Другими словами, область не сжимается после перемещения точки. Эти методы предоставляют возможность расширить или сжимать область на необходимое количество элементов, перемещая только одну из границ области. Первым параметром выступает строка, определяющая элементы смещения (character, word, sentence или textedit). Значение textedit перемещает курсор в начало или в конец исходной текстовой области. Таким образом, если необходимо переместить конечную точку текущей области в конец тела страницы (или текстового элемента управления), исполь- зуйте метод moveEnd (" text edit"). Если пренебречь вторым параметром, то его значение по умолчанию будет равно 1. В противном случае можно определить целочисленное значе- ние, отображающее количество элементов, на которые сжатая область перемещается вперед (положительное значение) или назад (отрицательное значение). Перемещение любой точки за пределы области приводит к сжатию и перемещению последней в положение, определенное методом. Метод возвращает целочисленное значение, отображающее точное количество 1112 Часть IV. Объекты языка JavaScript
элементов, на которые можно переместить курсор. Если указать большее количество элемен- тов, чем реально существует символов, то возвращаемое значение предоставит информацию о том, насколько вы ошиблись. Пример Используйте приложение The Evaluator для знакомства с методами moveEndO и move- Start (). Начните с создания текстовой области и включения в нее элемента туЕМ. а = document.body.createTextRange() а.moveToElementText(туЕМ) Чтобы ознакомиться с тем, как перемещение указателя сказывается на тексте области, введите в нижнее поле значение а и просмотрите свойства текстовой области. Особое внима- ние обратите на свойства htmlText и text. Далее введите следующее выражение, чтобы сместить конец области на одно слово вперед. а.moveEnd("word") Щелкните на кнопке List Properties, чтобы удостовериться во включении в область сле- дующего после элемента ет слова. Введите каждое из приведенных ниже выражений в верхнее поле и изучите полученные результаты, а также свойства области (кнопка List Properties). a.moveStart("word", -1) а.moveEnd("sentence") Обратите внимание, что значение по умолчанию 1 приводит к смещению области в нача- ло текущего предложения. Если переместить начальную точку обратно на одно предложение, то отсутствие точки перед элементом туР приведет к неожиданным результатам. Наконец, сместите начальную точку обратно на 20 символов и понаблюдайте за тем, как она достигает начала элемента body. a.movestart("word", -20) В определенный момент возвращается значение 0. Это происходит в случае достижения начальной точкой начала страницы (дальше ей смещаться попросту некуда). См. также: методы TextRange. move (). moveToBookmark("строка") Возвращаемое значение: булево Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Если снимок текстовой области сохранялся в переменной (с помощью метода getBook- mark ()), то в этом методе в качестве параметра используется строка закладки, определяю- щая то состояние текстовой области, в котором она находилась при создании. При успешном выполнении метода возвращается значение true, и в текстовую область заключается строка текста, первоначально сохраненного с помощью метода getBookmark (). Содержимое тек- стовой области может изменяться до такой степени, что его восстановление станет невоз- можным. В этом случае методом возвращается значение false. Пример Пример использования метода moveToBookmark () был приведен ранее в этой главе в листинге 35.11. С его помощью отменяются выполненные в тексте документа изменения. См. также: метод TextRange. getBookmark (). Глава 35. Текстовые объекты тела страницы 1113
moveToElementText (ссылкаНаОбъектЭлемента) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Самый быстрый способ заключить текстовую область в HMTL-элемеит страницы состоит в выполнении метода moveToElementText (). Любая действительная ссылка на объект элемента HTML принимается как основной параметр, однако не пытайтесь использовать в ней строковую версию идентификатора (по крайней мере до тех пор, пока она не помещена в метод document. getElementByld () (IE5+). После того как границы области будут за- ключены в элемент, свойство области htmlText представит полные дескрипторы элемента. Пример Примеры применения метода moveToElementText () вы найдете в этой главе в лис- тингах 35.10 и 35.11. См. также: метод TextRange. parentElement (). moveToPoint (х, у) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Метод moveToPoint () уменьшает текущую текстовую область до размеров курсора и перемещает его в указанное положение текущего окна или фрейма браузера. С помощью горизонтальной (х) и вертикальной (у) координат, заданных в пикселях в качестве парамет- ров, можно управлять местом расположения сжатой области. Место расположения определя- ется относительно окна, а не документа, который можно прокрутить в любом направлении. Выполнение метода moveToPoint () — это эквивалент щелчка посетителя в окне браузера. Для расширения сжатой текстовой области перед введением в нее символа, слова, предложе- ния используется метод expand (). / Применение метода moveToPoint () в текстовой области, определенной для /нацмену элементов управления формы, может вызвать сбой в работе браузера. Метод ока- • зывается безопасным для объекта document. body даже тогда, когда значения координат х, у совпадают с областью текстового элемента управления. Однако такое размещение текстовой области не вызывает установку курсора в элементе управления формы. Пример Используйте приложение The Evaluator для изучения метода moveToPoint (). Начните с создания текстовой области, в которую включен весь объект body. а = document.body.createTextRange() Выполните метод moveToPoint (), чтобы переместиться в текстовую область результатов. a.moveToPoint(100,100) Если ввести в нижнее поле а и ознакомиться с его свойствами, то htmlText и text бу- дут пустыми, поскольку точка вставки не имеет отображаемого на экране содержимого. Если, например, вы сместите начальную точку области назад на символ, то эти свойства будут за- полнены данными элемента body (расположенными перед элементом text area). Введите следующее выражение в верхнее поле и выполните его несколько раз. a.moveStart("character" , -1) Теперь введите в нижнее поле а и повторно изучите его свойства. См. также: методы TextRange. move (), TextRangeMoveStart (), TextRangeMoveEnd (). 1114 Часть IV. Объекты языка JavaScript
parentElement() Возвращает: ссылку на объект элемента Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Метод parentElement () возвращает ссылку на следующий внешний контейнер эле- мента HMTL, содержащий границы области. Если границы текстовой области находятся на границах обычного элемента, то метод parentElement () возвращает ссылку на его объект. Если границы расположены в разных элементах, то объект, возвращаемый методом, пред- ставляет элемент, содержащий текст наименьшей вложенной части области. В отличие от ме- тода expand () и других методов перемещения области, “понимающих” текстовые конст- рукции (слова и предложения), метод parentElement () предназначен только для управления объектами элементов. Поэтому если область сжата в курсор в основном тексте, то ее с помощью метода parentElement (), представляющего собой параметр метода move- ToElementText (), можно расширить, чтобы заключить элемент HTML. rng.moveToElementText(rng.parentElement()); Пример И вновь вы можете использовать приложение The Evaluator для детального знакомства с методом parentElement (). Создайте текстовую область, включающую элемент туЕМ. а = document.body.CreateTextRange() а.moveToElementText(туЕМ) Введите следующее выражение в нижнее поле, чтобы ознакомиться с объектом, возвра- щаемым изучаемым методом. а.parentElement() Если прокрутить список до свойства outerHTML, то легко заметить, что родительским для текстовой области будет элемент туЕМ. Сместите конечную точку области на одно слово. а.moveEnd("word") Поскольку добавленное слово принадлежит элементу туР, то теперь свойство outerHTML будет равно именно ему. См. также: методы TextRange. expand (), TextRange. move О , TextRangeMove- Start (), TextRangeMoveEnd(). past eHTML ("HTML-текст") Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Несмотря на то, что метод execCommand () выполняет команды, вставляющие элементы HTML в текстовую область, вероятно, было бы намного проще вставить полностью сформирован- ный HMTL-код в текущую текстовую область (допускается, что вы работаете с текстовой областью вместо даже более простых значений свойства outerHTML объекта элемента). Вставка строки, представленной в виде параметра, осуществляется с помощью метода pasteHTML (). Тщательно проанализируйте ситуацию перед тем, как использовать метод pasteHTML (). HTML-текст, вставляемый в текстовую область, требует от метода размещения дополнитель- ных дескрипторов вокруг содержимого (они используются для обеспечения достоверности результирующего HTML-кода). Например, если вы пытаетесь заменить текстовую область, содержащую часть текста элемента Р элементом LI, метод pasteHTML () разделит элемент Р на две части, поскольку элемент Р не является контейнером для отдельного элемента LI. Глава 35. Текстовые объекты тела страницы 1115
Это разделение может нарушить иерархическую структуру документа, так как разделенный элемент Р предполагает использование одного и того же идентификатора для обеих частей. Существующие ссылки на элемент Р будут нарушены, так как теперь ссылка возвращает мас- сив двух одноименных объектов. Пример В приложении The Evaluator можно смело экспериментировать с методом pasteHTML (). Цель следующих выражений— изменить дескриптор <ега> на <span>, атрибут style ко- торого устанавливает цвет исходного текста таким же, как и в элементе em. а = document.body.createTextRange() а.moveToElementText(myEM) Вы можете подставить HTML-данные в метод pasteHTML в виде аргумента, однако на- много удобнее (с точки зрения будущего тестирования сценария) пользоваться временной пе- ременной. b = "<span style='color:red’>" + a.text + "</span>" Мы применили текст текущей текстовой области, поскольку он не изменяется. Вставим в текущую область новые HTML-данные. a.pasteHTML(Ь) В результате элемент em будет удален из объектной модели, но его заменит элемент <span>. Узнаем HTML-код элемента myP. myP.innerHTML Как отмечалось ранее, метод pasteHTML () — это не единственный способ вставки и за- мены HTML-кода в документе. Но он эффективен, когда пользователь выбирает на страни- це текст, требующий замены, поскольку в данном случае можно использорать метод docu- ment . selection. createRange!), чтобы создать на основе выделения текстовую область. См. также: метод insertAdjacenHTML (), свойство outerHTML. queryCommandEnabled("имяКоманды") queryCommandlndeterm (" имяКоманды") queryCommandState("имяКоманды") queryCommandSupported("имяКоманды") queryCommandText("имяКоманды") queryCommandValue("имяКоманды") Возвращаемое значение: см. метод document. queryCommandEnabled () Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Описание метода document. queryCommandEnabled () приведено в главе 18. select() Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- Метод select () проводит выделение текста внутри границ текущей области. В некоторых операциях (например, запрашиваемого поиска и замены), пользователь может отобразить текст текущей области путем выделения той части, которая должна быть заменена. В некоторых дру- гих операциях, особенно в командах, выполняемых методом execCommand (), управление 1116 Часть IV. Объекты языка JavaScript
осуществляется только для выделенного текста документа; Таким образом, использование объекта TextRange после применения метода select () предоставляет возможность задать границы области так, чтобы можно было обработать текст любой командой. Текст, выделенный с помощью метода select (), становится объектом selection (рассмотрен выше в этой главе). Пример Пример использования метода select () приведен в листинге 35.11 ранее в этой главе. См.также: объект selection. setEndPoint("тип", ссылкаНаОбъектКапде) Возвращаемое значение: отсутствует Совместимость: WinIE4+, MacIE-, NN-, Moz-, Safari- B отличие от метода moveEnd (), задающего конечную точку текущей области в виде ко- личества символов, слов, предложений, а также целой области, с помощью метода setEnd- Point () можно задать расположение границы (не обязательно конечной) текущей области относительно границы другой текстовой области, ссылка на которую задается в качестве вто- рого параметра. Первый параметр определяет одну из четырех возможных ситуаций. Прини- маемое значение управляет тем, какая из границ текущей области должна изменять свое рас- положение, а также какую границу другой области считать точкой отсчета. В табл. 35.3 представлены четыре возможных типа этого параметра и их значения. Тэвлчм 35.3. Типы метода BetEndPointO Тил Описание StartToEnd Перемещает начальную точку текущей области в конец другой области StartToStart Перемещает начальную точку текущей области в начало другой области EndToStart Перемещает конечную точку текущей области в начало другой области EndToEnd Перемещает конечную точку текущей области в конец другой области Отметим, что метод перемещает только одну границу текущей области за один сеанс ра- боты. Если вы хотите сделать обе границы идентичными, необходимо дважды запустить дан- ный метод (причем один раз с параметром StartToStart, а другой — с EndToEnd). Если быть точными, то метод isEqual () для этих областей возвратит значение true. Однако при задании граничной точки с помощью метода setEndPoint () можно столк- нуться с некоторыми неожиданными результатами, когда преобразованная текстовая область “растягивает” составные элементы. Не удивляйтесь, если новый текст HTML расширенной области не будет содержать дескрипторы внешних контейнеров элемента. Пример Примените приложение The Evaluator для изучения метода setEndPoint (). Создайте две независимые текстовые области: для элементов туЕМ и туР. а = document.body.createTextRange() a.moveToElementText(туР) b = document.body.createTextRange() b.moveToElementText(myEM) Перед смещением граничных точек сравните HTML-содержимое областей. а.htmlText b.htmlText Глава 35. Текстовые объекты тела страницы 1117
Переместите начальную точку области а в место расположения конечной точки области Ь. a.setEndPoint("StartToEnd", Ь) Если вы ознакомитесь с HTML-кодом области а а.htmlText, то заметите, что дескриптор <р> из а пропал. Это прекрасный пример ошибочного исполь- зования метода setEndPoint (), вызванного рассмотрением только видимого на странице текста, а не самих дескрипторов. См. также: методы TextRange. moveEnd О , TextRange. movestart (), Text- Range.moveToElementText(). Объект TextRectangle Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Свойства Методы Обработчики событий bottom left right top Синтаксис Доступ к свойствам объекта TextRange. [window.]document.all.идентификатор.getBoundingClientRect().свойство [window.]document.all.идентификатор.getClientRects()[i].свойство Описание объекта Объект TextRectangle добавляет к сценарию концепцию, описанную в спецификации HTML 4.0. В соответствии с ней отображаемый текст элемента занимает прямоугольную об- ласть на странице, достаточную по размеру для заключения всего текста. Для одного слова высота прямоугольника равна размеру шрифта, используемого для отображения слова, а его ширина не является большей, чем длина строки текста. Для последовательности слов, состав- ляющих сложные строки, высота прямоугольника зависит от количества строк, а ширина — от расстояния между крайней левой и крайней правой границей символов (даже в том случае, когда прямоугольник включает другой текст, не являющийся частью элемента). Извлекая объект TextRange с помощью метода getBoundingClientRect (), помни- те, что этот объект заключается в прямоугольную область с текущими размерами. Изменение размеров страницы вызывает изменение размеров существующего прямоугольника, содер- жащего текст элемента. Однако копия объекта TextRange, созданная раньше, останется прежней (значения ширины и высоты не будут изменяться, что не отражает физического пре- образования элемента). После изменения размеров окна или внесения изменений в содержи- мое страницы любой зависимый объект TextRange необходимо повторно скопировать для измененного элемента. 1118 Часть IV. Объекты языка JavaScript
Свойства bottom left right top Значение: целочисленное Чтение/Запись Совместимость: WinIE5+, MacIE-, NN-, Moz-, Safari- Координаты четырех границ, заданные в пикселях, определяют расположение любого объекта TextRectangle. Эти координаты определяются относительно окна или фрейма, в котором отображается страница. Если необходимо выровнять элемент с внедренными объектами Text - Rectangle, то при задании значений координат следует учесть прокрутку тела страницы. На наш взгляд, левый край TextRectanle не всегда включает крайние левые пиксели отображаемого текста. Вам следует учитывать этот факт при выравнивании настоящего эле- мента относительно TextRectangle. Пример На странице, представленной листингом 35.12, вы можете щелкнуть на четырех вложен- ных элементах, что позволит изучить принципы управления объектом TextRectangle. При щелчке на одном из элементов свойства объекта TextRectangle используются для уста- новки размера позиционируемого элемента, который выделяет пространство прямоугольника. Будьте внимательны и не перепутайте прямоугольник, который отображается на экране с са- мим объектом TextRectangle. Операции изменения размера позиционируемого элемента и отображения его на экране вы- полняются с помощью отдельной функции (setHiliter ()). Она вызывается в функции обра- ботки события onclick (handleclickО). В результате обработчик onresize вызывает код, получающий размер текущего прямоугольника, на котором выполнен щелчок, и изменяю- щий соответствующим образом позиционируемый элемент. Удалите из дескриптора <body> об- работчик onresize и понаблюдайте, что же произойдет после йзменения размера окна браузера. <html> <head> <title>TextRectangle Object</title> «script type="text/javascript"> // сохранение ссылки на последний элемент, // на котором выполнен щелчок var lastElem; var rectLeftCorrection = 2; // обработка щелчков function handleclick() { । var elem = event.srcElement; if (elem.className && elem.className == "sample") { lastElem = elem; setHiliter(); } else { Глава 35. Текстовые объекты тела страницы 1119
hideHiliter(); } } function setHiliterO { if (lastElem) { var textRect = lastElem.getBoundingClientRect(); hiliter.style.pixelTop = textRect.top + document.body.scrollTop; hiliter.style.pixelLeft = textRect.left + document.body.scrollLeft - rectLeftCorrection; hiliter.style.pixelHeight = textRect.bottom - textRect.top; hiliter.style.pixelwidth = textRect.right - textRect.left; hiliter.style.visibility = "visible"; } } function hideHiliter() { hiliter.style.visibility = "hidden"; lastElem = null; } </script» </head> <body onclick="handleClick()" onresize="setHiliter()"> chl>TextRectangle Objectc/hl> chr /> <p>Click on any of the four colored elements in the paragraph below and watch the highlight rectangle adjust itself to the element's TextRectangle object.c/p> <p class="sample">Lorem ipsum dolor sit amet, cspan class="sample" style="color:red”>consectetaur adipisicing elitc/span>, sed do eiusmod temper cspan class="sample" style="color:green">incididunt ut labore et dolore cspan class="sample" style="color:blue">magna aliquac/span>. Ut enim adminim veniam, quis nostrud exercitation ullamcoc/span> laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit involuptate velit esse cilium dolore eu fugiat nulla pariatur.c/p> cdiv id="hiliter" style="position:absolute; background-color:salmon; z-index:-l; visibility:hidden"> c/div> c/body> с/html> См. также: методы объектов элементов getBoundingClientRect О, getClient- RectsO (глава 15). 1120 Часть IV. Объекты языка JavaScript
Приложения
Справочник по объектам браузера и JavaScript
Приложение А. Справочник по объектам браузера и JavaScript 1123 Базовый язык JavaScript/JScript/ECMAScript Array"3,12 зо constructorм-,Е4 concat( array?/*4-|Е4 length jotnfchar*)^4 prototype 55 reverseOIE4 ShHtON4-W5-5 slicefi.G]) IE4 sortfeompereFunc/E4 spticefijL items I?44’W55 toLocaleString() Ne> W5.5 toStringn,E4 unshiftO*44-W5,5 Date 29 constructorN4, IE4 getFuHYearO*44’142 prototype N3.|E4 getYearO getMonthO getDateO getDayO getHouraO getMinutesO getSecondsO gefnmeO getMilKsecondsQ *44, JS- getUTCFutfYearf)*44, & getUTCMonthQf*>J2 geMTCDate(/*4-J2 getUTCDayf/44-142 getUTCHoursf/44’ J2 getUTCMmutesO*44”42 getUTCSecondsO 142 getUTCMiilisecondsO *44,142 setYearfvat) setFutlYearf из//44”42 setMonth( val) setDatefvat) setDayfva/) setHourafva/) setMinutesf val) setSecondsf val) setMilfeecondsf из//44,142 setTimefvat) setUTCFullYearf va/)N4,J2 setUTCMonthf та//44-142 setUTCDatefKa//*4’142 setUTCDayfva//44”42 setUTCHoursfwe//44-142 setUTCMinutesf та//44- & setUTCSecondsf та//44- & setUTCMilliseconds( та//44"42 getTknezoneOffsetf) toDateStringf)7/5,5 toGMTStringf) toLocateOateStringO W5,5, ** toLocaieStringO toLocaleTimeString() W5-5- ** toStringO tonmeStnng(),E5-5 toUTCStringf/44- J2 Date.parsefdEtteString “) Date.UTC(date values) String 27 constructor M>IE4 anchorfanchorNa^") length bigO prototype*44’142 btinkf) ЬоИО charAtf index) charCodeAt([/])N4-,E4 concat( string?/44-IE4 fixed() fontcolorf# rrggbb) fontsize(1to7) fromCharCodefnf,../1)-*44’IE4 indexOffstr" [,/]) italicsO lastlndexOfC st? [,/]) link( URL) localeCompareQ W5,5 matchfragexp)*44’IE4 replacef regexp, str/44’IE4 searchf regexp)*44-IE4 slicef i J/44’IE4 small () sptit(char>N3,(2), IE4 strikef) sub() substrf start,length/*4’IE4 substringf intA, IntB) sup() toLocaleLowerCase() W5,5 toLocaleUpperCasef) n6’ W5,5 toLowerCase Q toStringO*44’|Ё4 toUpperCase Q valueOfO*44’,Ё4 l-I «I ill 1|И Hilt hlil Regular Expressions"4,IB 42 global compilef regexp) ignoreCaseM5’W5,5 execfstring”/® input (1), IE5.S teste string') lastindex str. match (regexp) multiline <1)’W55 str. replace( regexp,str) lastMatch W5,5 str. search( regexp) lastParen П)-W5,5 str.splftf regexp[, limit)) leftcontext n),W5.5 prototype rightContext (1) source (l)₽foperty of the*»*: RegExp object. (2)Retume an anay wMTi properties: index, input, [0], [1], -in]. Boolean"3 32 28 constructor*44’^4 toStringO*44-^4 prototype valueOfO*44, IE4
C 2004 Danny Goodman (www.damtyn.cotn). All Rights Reserved. Math1” . 28 Е absfvai) LN2 acos( vai) LN10 astn(vai) L0G2E atan(vai) LOG10E atan2(va/f, val2) PI ceil( val) SQRT1_2 cos( val) SORT2 exp(val) floor(va/) tog(val) max(va/7, va!2) mh(va/1, val2) powfva/7, power) randomf) roundfvai) sin( vai) sqrtfvaO tan{vai) (1 |AH propertw t methods are of the Matic Math obiect. NumberN3J2 28 consUuetof JE4 toExponentiaK rt*. "W MAX_VALUE'E4 toHxedfj^NeJeis MINVALUE IE* toLocaleStrtngO *>. =.•« NaNIE4 „.toSWngdzadx])1*' IE4 NEGA^VEJNRNrrY!E4toProdEion( ws.5 POSmVEJNFINITY'E' valueOfO"3' prototype Function”31* 33 arguments applyf this, argsArray/*6' W5,5 arityM ceii( ^Уз[,а/рТ[,.,.афЛЩ/*'W5-5 caller toStringO constructorN4’IE4 valueOfO length prototype Globals 34 decodeURIfencodedURI"^.W5 5 decodeURIComponerrtC encComp"/*6' W5-5 encodeURieUfflSfrihg't*’W55 encodeURIComponentC compString •)№ W5'5 escapef string* [,1 J) evalf string") isFmitef number)*4-,E4 isNaN( expression) Numberfstrirtg)*4'|E4 parseFtoatfstrirtg") parselntCstring1 [,radir]) Statements toStnng{[ radix]) H unescapef string") const unwatchfpropjN4 var watch {prop, handter/*4 1,1 Controi Statements 31 •л(condition) { statementsIfTrue ) it (condition) { statemen tsIfTme }else{ statementsifFalse result = condition ? exprl. expr2 for ([init expr]; {condition ]; [update expr)) { statements for {var in object) { I with (object) { statements I statements while (condition) { i do [ statement I statements } | } while (condition f*4'IE4 switch {expression) { case labelN : statements [break] [default: statements] jN4, IE4 label: N4, IE4 continue [ label]**4'IE4 break [iabe/jN4’ ’E4 try{ statement to test } [catch (errortnfd) { statements if exception occurs in try block И [finally { statements to run, exception or not }JN6, ws throw value N6< W5 Error"3*'5 prototype toStringO constructor description W5 file Name hneNumber^6 messaoe N6-lE55 name™-IE5-5 number^*5
1124 Часть V. Приложения Operators 32 Comparison = Equals s= **4-|E4 Strictly equals 1= Does not equal != M>IE4 Strictly does not equal > Is greater than >= Is greater than or equal to < Is less than <- Is less than or equal to Arithmetic % -та/ Plus (and string concat) Minus Multiply Divide Modulo Increment Decrement Negation Assignment = Equals += Add by value -= SUrtract by value •= Multiply by value /= Divide by value %= Modulo by value «= Left shift by value »= Right shift by value >»= Zero fill by value &= Bitwise AND by value |= Bitwise OR by value *= Bitwise XOR by value Boolean ^Itwiee AND NOT Bitwise AND Bitwise OR Bitwise XOR Bitwise NOT Left shift Right shift Zero fill right shift Miscellaneous delete**4-^4 inNe, W5.5 „w,„ instanceof N6-W5 Instance of new Series delimiter Property ctroyer Item in object typeof**3-IE3 void**3- 'E3 Object creator Object self-reference Value type Return no value Свойства объекта стиля в IE4+, NN6+ style Е4М6 26 JavaScript and Browser Objects Quick Reference Appendix A JavaScript Bible, 5th Edition by Danny Goodman How to Use This Quick Reference This guide contains quick reference info for the core JavaScript language, the original document object model (2 pp), the IE4+DHTML object model (4 pp), and the W3C DOM object mode 1(4 pp) as implemented in IE5+, NN6, Mozilla, and Safari browsers. All- uppercase object names refer to HTML elements (IE4+ and W3C DOMs). The three columns in each box list the object’s propertiesjnethods, and event handlers in that order. Read the compatibility guides for each section. Numbers in the upper right comers of object squares are chapter numbers in which the object is covered in detail. Basic browser and operating system notation codes are as follows: N — Netscape Navigator (including Mozilla when N6 or higher) IE — MS Internet Explorer W — Windows MSDE M — Macintosh MSIE See the accompanying file for printing and collating instructions in booklet or broadside configurations. Text & Fonts cotor'E4-**6 font'E4-**6 (ontFamilyIE4- ** fontSizeIE4- ** foraiSizeAdjusf *45- ** fontStretch MS- ** fontstyleIE4’ ** fontvariantIE4’** fontWeightIE4- ** letterspacingIE4- ** lineBreakIE5 lineHeightIE4- ** sM5, N6 mbyAlign,E5 rubyOvertiangJE5 rubyPosition Iе5 textAlign IE4- **® textAlignLasl |Е5Л textAutospace 775 textDecorationIE4- *« jcoi link IE-Only textDecorationLineThrough lE-omy textDecorationNone lE-ofly textDecorationOverline lE-omy textDecorationUnderline 1Е-Оп*У textindentIE4- **® textJustify IE5 textJustifyTrim,E5 ‘ textKashidaSpace IE5-5 textOverflow we textshadow *45- ** textTransforrniE4’**6 textUnderllnePosItton ,E5-5 unicodeBidt ** whiteSpaceIE4- **® wo rd Break 775 wo rd Spacing*44' **6-776 wordwrap7^-5 writingMode 7755 Positioning bottom *E5,N6 height Iе4-**6 left Iе4-**6 pixe Bottom lE/W-Only pixelHeight IE-Only pixelLeft IE-Only porelRIght lE/W-Oniy pixelTop IE-Only pixelwidth IE-omy posBottom iE/w-omy posHeight IE-Only posLeft'E-Oniy posRight lE/W-Only posTop IE-Only posWidth IE-Only position !E4’ **® right’E5’**6 top’E4- **e Width^4-**6 zlndexIE4’ *B border*E4- **e borderflottomIE4’ ** borderLeft^4- ** borderflightIE4- **6 borderTop*E4- **6 borderBottomColorIE4’ **® borderteftColorIE4- **® borderRlghtColorIE4’ ** botderTopCoto<*E4-« iStyleIE4- ** borderLeftStyiefE4- ** borderRightStyleIE4- ** borderTopStyleIE4- ** borderBottomWidthIE4- **e IborderteftWIdthIE4-**® borderflightwidthIE4- ** borderTopWidthIE4- **® borderCoior*E4- ** borderstyleIE4- ** bordetWkfth^4-**6 marginIE4- **® marginBottomIE4- ** margin LeftIE4- **® marginRight^4’**6 marginTopIE4’** outline^**6 outlinecolorM5- ** outlinestyle M5- ** outlinewidth «5- ** paddingIE4- ** paddingBottomIE4- *» eftIE4- ** paddingRight IE4> ** paddingTopIE4- ** Mine Display & Layout dear Iе4-**6 dp|E4.N6 cHpBottom 775 dipLeft775 dipRight775 сйрТор775 content*45- ** counterincrement H5- ** counterResetM5- ** cssFloatM5- ** cursorIE4- ** direction ** displayIE4- **® filter774 layoutG rid 775 layoutG ridChar775 layoutGridUne 775 layoutGridMode775 layoutGridType775 markerOffset*45’ ** marks*45-**6 maxHerght W5-** maxWidth*45- ** minHeight*45-N6-776 minWidth *45- ** MozOpacity**6 overflow^4-**6 overflowX775 overflow?775 styleFloat IE-Only rtrcalAl IE4, N6 visibility ®4’ ** width1**-**6 zoom*®-5 Tables borderCollapse *45- ** borderspacing M5- ** ptionSide ** emptyCeHs **5- ** tabteLayoutIE5- ** Lists liststyle IE4- ** listStylelmage IE4-**® listStylePosition IE4-** listStyleType IE4- **6 Printing orphans M5-Ne widows'45-**6 page*45-**6 terIE4- ** pageBreakBeforeIE4- ** (side *45- ** size**6 Background backgroundIE4-146 i backgroundAttachmentIE4- **® backgroundcolorIE4-**® i backgroundimageIE4- ** gackgroundPosition IE4- **® backgroundPositionX IE-Only , У IE-Only . backgroundRepeat IE4, ** Miscellaneous accelerator775 behavior775 cssTextIE4’**® imeMode 7/5 Scrollbars scrollbar3dUghtColor 77515 Яог7755 scroObarBaseColor W5.5 idowColor 77515 scrolltoFaceCotor7755 (for 77515 scrolbarShadowColor W5-5 scroRbarTrackColor W5.5
Приложение А. Справочник по объектам браузера и JavaScript 1125 Базовая DOM (NN2+, IE3+), страница 1 из 2 window 16 appCore*46 dientinformation IE4 clipboardData closed №. IE4 componentsnj46 controllers!] № crypto № defaultSletus dialogArguments IE4 d alogHeightW4 dialogLeftIE4 dialogTopIE4 dialogWidth W4 directories M>(s) document eventIE4 externalW4 IrameElementW5-5 frames[] history innerHeight htf InnerWIdth M length №. IE4 loading N4-Only location locationbar ^.(S) menubar N4>(s) atertfmsg*) ( evf./unc)^ back/)*44 Ыиг^- IE4 captureEvents(type) *44-°п|У clearlnterval(ID)IE4 clearTlmeout(ID) doseO confirmCmsg-) creat ePopupO"5,5 detach EventC evf ,ftmc)IE5 dlsableExtemalCaptureO N4-Only enableExtemalCaptureO N4-Only execScriptC expfs't.tangl)^4 find([‘sfr*][,case, bkwdW4 fireEvent(’ evflfivtObf]^5-5 focusO143’IE4 forwardO^4 handleEvent( evenf)144-0^ homeO*44 moveByfAx.ay)144. IE4 moveTofx.yf4 -IE4 navigatef) open (URL, 'name', 'specs ")(1) Xs) printON4. IE5 prompt(’msg-,-rep/y")^ release Even ls( onabort*46 onafterprinfW5 onbeforeprintw5 onbeforeunloadIE4 onblur№. IE4 onchange*46 ondick № ondose*46 ondragdrop*44-0^ onerro/43- IE4 onfocus №. IE4 onhelpIE4 onkeydown*46 onkeypress ** onkeyup*46 onload onmousesdown № onmousemove ** onmouseout ** onmouseover № onmouseup*46 onmove*44^*1** on reset*46 onresi26 M>IE4 onscrollIE4 onselect*46 onsubmit ** onunload name navigator N6’IE4 offscreenBuffering 1 opener ,E3>N3 outerHeight M outerWidth M pageXOffset M pageYOffset M parent personalbar pkcsll ** prompter*46 retumValue W4-M5 screen **,E4 screen LeftW5 screen Top 7/5 screenX screenY ** scrollbars scrollX N6 scrollY ** setl sidebar*44-^) status statusbar м-(5) toolbar h*4,(S) top window resi2eBy(A x.Ay)*’4’0^'IE4 < resi2eTo( width,height/*4"0^’IE4 IE4 routeEventf event/k-oniy scroll( x.yp3-IE4 scrollBy(A ХДу/*4'IE4 scrolTTo( x.y)*44-IE4 sstActiveQ W5.5 setlnterval( tunc, msec [,args])N4'IE4'(2) setTimeout/ func, msec [.anjs]/2) > sbowHelpO*44 showModalDialogO IE4 showModelessDialog() 7/5 si2eToContent() № stopQ*44 (l)New window specs tor al browsers, height, width, toobar. location, dkectortes, status, menubar, scroffcars, resizable, eopyhtetory Ackfl specs for N4+: ahreysLoweredfS), aiwaysRaisedfS), dependent, hotkeys, innerHeight, innerWWh, outerHeight, outertMdfo, screenX, screenY. tffiebarfS), z-tock(S) Addt specs for IE4+-channefmode, futecreen, left, top, Addtspee tor KS+ title. N6 + Includes left, top, (2)Optiona< args parameter added to N4,3rd parameter to IE4 is for scripting lan^age document 18 link (<а href=...x/a> ) 19 alinkColor anchorsO applets!]*43,IE4 bgColor cookie domain №.,E4 embedsO*43- IE4 fgColor formsfl height*44 imagesQ №. IE4 lastModified layersfl N4-°n|y linkColor linksQ location <1) referrer title URL№. IE4 vlinkCdor width M capture Events( type)*44’0’11* (None) ctearO doseO getSeiectionO N4,t2l handleEvent( evenf)N4'On(y open('mi'metype • [.rep/ace]/3) releaseEventsf /урен4Юп1У routeEventf event )*w-Oniy write( 'string') writelnCstring") (1) Replaced by the URL property in Navigator 3. (2) M4 has a document.setection property to retrieve the currently selected text (2) mimetype parameter new to M4, but only text/html* type sujporterf________ layerN4Onl, 39 above loadCflfename", y) onblur background moveAbovef layerObj) onfocus below moveBelow( layerObf) onload bgColor moveBy(Ax, Ay) onmouseout dip. bottom moveTo(x, y) onmouseover dip. height dip.left clip.right clip.top clip.width document left name pageX pageY parentLayer siblingAbove sibling Below src top visibility 2lndex moveToAbsolute( x, y) resl2eBy(Ax, Ay) resi2eTo( width, height) onmouseup location hash host hostname href pathname port protocol search assignC UHL') (None) reload([uncondfflona/ ])N3,IE4 replace(,UF?L’)N3'IE4 hash host hostname href pathname port protocol search target textN4-°n,y XN4-Only yN4-Only (None) did ondblclick M4,(1),IE4 onmousedown M-IE4 onmouseout M>IE4 onmouseover onmouseup M>IE4 (1) Not implemented in NN4/Mac. anchor (<a name-..x/a>) name*44’IE4 (None) textN4-Only XN4-Only yN4-Only border complete height hspace lowsrc name src vspace width XN4-Only yN4-Only (None) (None) imaged1»*4 onabort onerror onload (1) Implemented in IE3.01/Macintosh but not Windows until IE4. area^4 19 20 20 hash host hostname href pathname port protocol search target (None) onclick “ onmouseout onmouseover history 17 current(s>’(1) length next<s)'H) previous back() forwardO gotjnt ('URL') (None) (1) Avtetabte to NN4+/MozBa wfth signed scrtpte.
^MO^Dann^oodn JSB5 form 21 action handleEvent evt)N4 on resetN3'IE4 elements!] reset()N3-IE4 onsubmit encoding submit!) length method name target button, reset, submil 22 form clickO onclick name handleEvent evt)^ onmousedownм-IE4 typeN3'IE4 onmouseup м-IE4 value ' checkbox 22 checked defaultChecked form name typeN3, IE4 value click!) handleEvent evt)^ onclick onmousedown IE4 onmouseup IE4 radio 22 checked click() onclick defaultChecked handleEvent! evt)r'*3 onmousedownм-IE4 form onmouseupN4’^4 length » name typeN31 IE4 text, textarea, password, hidden 23 Часть V. Приложения defaultvalue П) blur() onblur form focusO onchange name handleEvent! evt)N4 onfocus type”3-IE4 value (2) select) onkeydown |E4 onkeypress N4’IE4 onkeyup IE4 ____________________________ on select (1) Not avatebte for textarea object (2) Password value property returns empty string in NN2 file input control1”’111"54 24 form ЫигО onblur name focus() onfocus type handleEvent evf)^4 onselect value_____________setectQ_________________________________________ (1) Aso called the «eUptoad object. ^™ИИ,И*И =
Базовая DOM (NN2+, IE3+), страница 2 из 2 select 24 length blur!)*43’IE4 onblur name focus!)*43' IE4 onchange options!!] hand eEvent( evt)*44 onfocus op tlonsfij.defaultSelected op tions[i].index opbons[ij.seiected options[lj.text options!!], value selectedlndex type**, *E4 navigator 38 appCodeName javaEnabted()431 144 appMinorVersion IE4 preference! name[, va/])N4'<s) appName taintEnabted() IE4 appVersion browserLanguaoeIE4 cooloeEnabled IE4 cpuClass IE4 language*44 mimeTypesQ *43, щ online'E4 oscpu*46 platform N4’IE4 plugmsH^3- product**6 productSub ** securityPolicy M systemLanguageIE4 4 userAgent userLanguageIE4 userProfile'^4 vendor*46 vendorSub*46 Original DOM Compatibility Guide Baseline browsers for this section are NN2, WinIE3/Jl, and MacIE3.01. An item with no notation is compatible back to that level, and is found in all new scriptable browsers since then. Notations indicate the browser and version in which the property, method, or event handler was introduced. mimeTypeN3M4 38 description (None) enabledPlugin type suffixes pluginN3M4 38 name refresh!) filename description length scree пЩ|^4 38 Except for the window and navigator objects (whose listings cover all browsers and versions), new features listed in this section cover only through NN4 (and IE4 when they matched a new NN4 feature). Notations are as follows: N3 — New in NN3 N4 — New in NN4 J2 — New in IE3, JScripLdll ver.2 IE4 — New in IE4, all OSes (S) — Requires signed scripts (NN) Additional window and navigator object notations are. W4 — IE4+/Windows only W5 — IE5+/Windows only IE5 — IE5+all OSes W5.5 — IE5.5+/Windows only W6 — 1E6+/Windows only M4 — TE4+/Mac only M5 — IE5+/Mac only N6 — New in NN6 & Mozilla Except for items marked N4-Only (which are not carried over into NN6), an item listed for an early browser is also available in the IE4+ and/or W3C DOM object models. “(None)" means that no methods or events exist for the current object through IE3 and NN4. availHeight (None) availLeft 0) availTopO) availWidth bufferDepthl2) cokwDepth noothingEnabled (2) height pixelDepth updateinterval <2) width (1)N4+ only. (2)VyinlE44 o<Vy
Приложение А. Справочник по объектам браузера и JavaScript 1127 IE4+ DHTML РОМ, страница 1 из 4 О 2004 Danny Goodman (www.daanyg.com). АП Rights All HTML Elements 15 FRAMESET 16 document 18 accessKey aHO behavfortJmsO775 canHaveChildren 775 canHaveHTML 7755 children className clientHeight dientLeft dientTop dientWidth con entEd liable 775 5 currentstyleIE5 dataFld ««.MS dataFormatAs W4.M5 dataSrc774'*45 disabled document filters}]774 hideFocus*75-5 addBehavlor}’ URL*) 775 applyElement} e/ernftype})*75 attachEvent}’ evT.func)775 blurO clearAttnbutesO 775 dick}) componentFromPoint( x,y)W5 contains} elem) detachEvent}’ evt*June)775 fireEvent}’ evf’f.evt])*75-5 focus}) getAdjacentText})775 getAttribute} ’ atti*[,case ]) get BoundingClient Reel}) 775 getClientRects})775 getExpression})775 InsertAdjacentElement}) 775 insertAdjacentHTML}) InsertAdJacentText}) item} index[, subindex ])<1) mergeAttnbutes})775 releaseCapture})*75 removeAttribute}’artrtf,case]) ’ removeBehavior} /О)775 removeExpression}’ protff^ removeNode} children )*»5 replaceAdJacerrtText}’ toe’,txt*)’ replaceNode} new)775 scrolllntoView} top) setActive})w5-5 setAttribute}' atfr’.va/Lcase]) setCapture} container)^5 setExpressionC prof, swapNode} node)*75 tags} *tagf) I1) umsCURV)775^1) innerHTML innerText — isContentEditable 775 5 removeBehavior} IDf* isDisabled 775 5 -------*"-----’—" • isMultiUne W5-5 isTextEdit774 lang language tengthv) offset Height offsetLeft offsetParent offsetTop offsetwidth outerHTML outerText parentElement parentTextEdit readyState recordNumber*74 runtimestyle IE5 scopeName 775 scrollHeight scrollLeft scrollTop scrollWidth sourceindex style tabindex tagName tagUm*75 title uniquelD775 onactivate *75-5 onbeforecopy 775 onbeforecut775 onbeforedeactivate W5 5 onbeforeeditfocus 775 onbeforepaste 775 onblur onclick oncontextmenu 775 oncontrolselect 7755 опсору775 oncut7/5 ondbldick ondeactivate W55 ondrag775 ondragend775 ondragenter775 ondragleave 775 ondragover775 ondragstart775 ondrop*75 onfilterchange W4 orrfocus onfocusin wef2) onfocusout W^2) onhelp774-”5 onkeydown onkeypress onkeyup onlosecapture 775 onmousedown , onmouseenter W5-5 ‘expr*,'lang')775 onmouseleave 775 5 on mo use move onmouseout onmouseover onmouseup on mo use wheel776 on move W5.5(2) onmoveend *75-5<2> onmovestart W5-5(2) onpaste775 onpropertychange 775 onreadystatechange onresize onresizeend 775 5 onresizestart W5-5 onselectstart border borderColor cols frameBorder frameSpacing rows activeElement alinkCojor FRAME allowTransparency 776 borderColor contentwindow 7755 frameBorder height, width marginHeight W6.MS marginwidth name noResize scrolling src IFRAME 16 16 |W5 align allowTransparency 776 contentwindow 775 5 height, width hspace, vspace longdesc W6-M5 marginHeight marglnWktth name scrolling BASE 36 href target color face size BASEFONT 36 anchors}] applets}] bgColor body charset compatMode 776 cookie defaultCharset design Mode 775 doctype M5 domain embeds}] expando fgColor fileCreatedDate file Modified Date fileSize forms[] frames}] imagesO lastModified linkCotor links}] location media*75-5 mimeType775 nameProp776 namespaces}] 7755 parentwindow pluginsn protocol readyState referrer scripts]] security W5-5 selection style Sheets}] title uniquelD URL URLUnencoded 77515 vtinkColor attach EventC evf ,func)IE5 ctearf) clearAttributes})IE5 dose() createElement}’ rag') crea eE ventObject ([ evt))775-5 createStyieShee (Г URL’prxfex]]) detach Eventf evT^/nc)tE5 elementFrom Point} x,y) execCommand}’ сгтхП.и/Ц.агд)) focus}) mergeAttnbutes} obf)^ openfCm/meType '[/eptace]) queryCommandEnabled}’ cmd’) queryCommandlndterm}* cmd') queryCommandState}' cmd') queryCommandSupported}’ cmd') queryCommandText}' cmd’) queryCommandValue}' cmd') recalcfaW/Tag)775 reteaseCapture}) ,E5 setActive}) 7755 writeCsfr*) writetnCstr*) onactivate 775-5 onbeforecut775 onbeforedeactivate *75-5 onbeforeeditfocus 775 onbeforepaste775 onclick oncontextmenu 775 oncontrolselect W5-5 oncut ondblclick ondeactivate 7755 ondrag775 ondragend775 ondragenter775 ondragleave 775 ondragover775 ondragstart*75 ondrop775 onhelp774-*45 onkeydown onkeypress onkeyup onmousedown onmousemove onmouseout onmouseover onmouseup onpaste onpropertychange 775 onreadystatechange onresizeend 775-5 onresizestart W5-5 onselectionchange 7755 onstop1E5 META (1)Property or method of all object collections (2) IE content editing mode only. popup»51 16 document hide}) (None) isOpen show}) charset content httpEquiv name url TITLE 36 text BODY 18 alink createC ont rol Range}) ™ onAfterPrint775 background createTextRange}) on Before Print775 bgCokx doScroll})* scroilAction 'J)775 bgProperties bottomMargin leftMargin, rightMargin link noWrap scroll scrollLeft, scrollTop text topMargin vLink on Sc roll
1128 Часть V. Приложения IE4+ DHTML DOM, страница 2 из 4 FORM 21 A (anchor/link) 19 IMG 20 acton resetO onreset autocompleteW5 submitf) onsubmit [] encoding enctype length method name target hash i host hostname href Methods mimeType name nameProp pathname port protocol protocoLong rel rev search target urn align (None) onabort alt onerror border onload complete dynsrc flteCreatedDate W4-M5 it! ' Jhi JDdi- W4-M5 fileSize W4.M5 fileUpdatedDate ws.5,ms height href hspace is Map loop lowsrc mimeType W6 name nameProp 7/5 protocol src start useMap vspace width LABEL 35 htmIFor (None) (None) BUTTON 22 INPUT (button, reset, submit, radio, checkbox) (See original object model button, reset, submit, radio, and checkbox object listings.) IE4+ DHTML DOM Compatibility Guide The baseline browser for this section is MSIE 4. An item with no notation is compatible back to that level for all OS versions. Notations as follows: W4 — IE4+/Windows only W5 — IE5+/Windows only IE5 — IE5+ all OSes W5.5 — 1Е5.5+/ Windows only W6 — IE6+/Windows only M5 — IE5+/Mac All HTML element objects share items from “All HTML” box on Page 1. “(None)” means no special methods or INPUT (image) 22 complete (None) (None) form name src type AREA 20 alt (None) (None) coords hash host hostname href noHref pathname port protocol ! search shape target INPUT (text, password, hidden) 23 (See original object model text, password, and hidden object listings.) maxLength (None) onafterupdateW4 readonly onbeforeupdateW4 size onerrorupdateW4 TEXTAREA 23 events for the current object. (See original object model textarea object listing.) cols createTextRangeO onafterupdateW4 readonly onbeforoupdateW4 rows onerrorupdateW4 wrap OL 37 compact start type MAP 20 areasQ (None) onscroll SELECT 24 UL 37 (See original object model select object listing.) length item( index [.subindex (None) multiple namedltemCKfjW6 size optons[i].add( eiem[, index]) value optons[ij.removeO compact type MARQUEE 35 behavior startO onbounce bgColor stopf) onfinfeh direction onstart height hspace loop scrollAmount scrollDelay trueSpeed vspace 1 width LI 37 OPTION 24 type defaultSelected (None) (None) form selected text value DL, DT, DD, DIR, MENU compact
Приложение А. Справочник по объектам браузера и JavaScript 1129 IE4+ DHTML РОМ, страница 3 из 4 TABLE 37 align background bgColor border borderCotor borderCokxOark borderCdorLight caption cellPadding cellsQWS cellSpacing colsO datePageSize frame height rowsfl rules tBodiesD tFoot tHead width createCaptionO createTFootO createTHeadO deteteCapfcn() deleteRow(i) deteteTFootQ deteteTHeadO firstPageOIE5 insertRow(A lastPageO'^5 moveRowf srclndex, destlndex )^ nextPage()W4,M5 previousPagef) W4-M5 refreshO onscroll TBODY, TFOOT, THEAD 37 align deleteRow(i) (None) bgColor insortRowp) rows moveRow( srclndex ,destlndex) vAlign COL, COLGROUP 37 align span vAlign width CAPTION 37 align vAlign C 2004 Danny Goodman (www.dannyg com). Ail Rights Reserved. H1...H6 35 align HR 35 align color noShade size width BR 35 dear FONT 35 color face size IE4+DHTML DOM Compatibility Guide The baseline browser for this section is MSIE 4. An item with no notation is compatible back to that level for all OS versions. Notations as follows: W4— IE4+/Windows only W5 — IE5+/Windows only IE5 —IE5+all OSes W5.5 — IE5.5+/Windows only M5 — IE5+/Mac All HTML element objects share items from “All HTML” box on Page I. “(None)” means no special methods or events for the current object. This Quick Reference does not contain listings for Microsoft’s separate XML DOM. TextRange"' 35 boundlngHeight boundingLeft boundingTop boundingWidth htmiText offsetLeft offsetTop text collapsefl start]) compare End PointsC type',range) duplicated execCommandC emd"[,lt<,va/]]) expand(" unit*) findText(’str*[,scope, flags]) getBookmark() getBou nding ClientRectQ getCllentRects() inRange( range) tsEqual( range) move(‘ unit‘[,count]) moveEndC un/f*[, count]) moveStartC unft‘[,count]) moveToBookmarkC bookmark •) moveToElementText( elem) moveToPointf x,y) parentElementO pasteHTMLC HTML Text") queryCommandEnabledC cmd') queryCommandlndetermC cmd") queryCommandStateC cmd') queryCommandSupportedC cmd’) queryComrpandT ext(’ cmd’) queryCommandValueC cmd") scrolllntoViewO seiectO setEndPointr type’,range) (None) TextRectangle"5 35 bottom left right top (None) (None)
ИЗО Часть V. Приложения С 2004 Danny Goodman (www.dffltnyg.com). AU Rights Reserved JSB5 event altKey altLeft,E5-5 behavtorCookie **s 5 behaviorPart W5-5 bookmarks**4 boundElements button cancelBubble clientx clientY contentoverflow ctrlKey ctriLeftIE5-5 data Fid**4 dataTransterW5 from Element keyCode nextPage W5-5 offsetx offsetY propertyNamew5 qualifier**4 reason**4 recordset**4 repeatws returnValue saveType W55 screenX screenY shiftKey shiftLeft,E5-5 srcElement src Alter**4 srcUrn**5 toElement type wheelDataW6 IE4+ DHTML DOM, страница 4 из 4
Приложение А. Справочник по объектам браузера и JavaScript 1131 W3C DOM (IE5+, NN6+, Mozilla, Safari), страница 1 из 4 W3C DOM Compatibility Guide Baseline browsers for this section ад_ . 1Б5, NN6, Mozilla I, and Safari 1. An item with no notation is compatible with these browsers (except,occasionally Safari). Some items are new to Netscape 7 (N7) and Mozilla or WinIE6 (W6). Observe footnotes for items missing from IE, and see the book’s text for Safari details. All HTML element objects share items from “All HTML” box on Page I. “(None)” means no special methods or events for the current object. IFRAME 16 contentDocument <1) longDesc M5,we marginHeight margin Width scrolling src (1)Nct implemented in IE through 6. BODY 18 alink (None) (None) background bgColor link scrollLeft, scrolITop N7,(i) text vLink (1)Originated in IE Object Model, but implemented in N7/MozHla for convenience,
1132 Часть V. Приложения у — Good™ All.^.tam^ FIELDSET, LEGEND 21 align (None) (None) form________________ LABEL 35 accessKey formM5-w® (None) (None) htmIFor BUTTON 22 INPUT (button, reset, submit, radio, checkbox) (See original object model button, reset, submit, radio, and checkbox object listings.) disabled INPUT (image) 22 disabled form name src type (None) (None) _____________INPUT (text, password, hidden)________________________23 (See original object model text, password, and hidden object listings.) disabled (None) (None) maxLength readonly size W3C DOM (IE5+, NN6+, Mozilla, Safari), страница 2 из 4 IMG 20 align (None) alt border complete height href hspace isMap long Desc(1> lowsrc lowSrcC1) name naturalHeight, naturalWkfth N6 src use Map vspace width onAbort onError onLoad (l)Not implemented in IE through 6. I OL 37 UL 37 compact start type compact type DL, DT, DD, DIR, MENU LI 37 compact type value A (anchor/link) 19 charset 0) coords 1 hash j host hostname href hreflangt1) name pathname port protocol rel ч rev search shaped) target typeO) (1)Not implemented in IE through 5.5 AREA 20 alt coords hash host hostname href noHref pathname port protocol search shape target MAP 20 areas name
Приложение А. Справочник по объектам браузера и JavaScript 1133 W3C DOM (IE5+, NN6+, Mozilla, Safari), страница 3 из 4 TABLE 37 H1...H6 35 align createCapttonQ onscroll bgColor ereateTFootO border createTHeadO caption deteteCaptionO cefPadding deteteRow(fl cellSpacing deteteTFootO frame deteteTHeadO height insertRow(») rowsfl rotes summary'*6 tBodies tFoot tHead width align HR 35 align color noShade size width BR 35 clear FONT 35 TBODY, TFOOT, THEAD 37 color face 1 size align deteteRowfr) (None) bgColor insertRowf») ch'*6 chOffWe vAlign BLOCKQUOTE, Q 35 citeM5,W6 TR 37 align deteteCell( i) (None) bgColor insertCell( i) celtefl ch*® chOff*»6 rowindex section Rowindex vAlign COL, COLGROUP37 align ch™6 chOffW® span vAlign width CAPTION 37 JSB5 Range11’ 35 collapsed ctoneContentsQ**7 (None) commonAncestorContainer doneRangeO"7 endContainer collapse^ start]) endOffset compareBoundaryPoints! type.src'r7 startcontainer compareNodef node) startOffet comparePoint( node, offset) createContextualFragmentC text”) deleteContents() detach () extractContentsO insertNode( node)**7 intersectsNode( node) isPointlnRange( node, offset) setectNodef node) selectNodeCon ents( nods) setEnd( node, offset) setEndAfter( node) setEndBefore( node) setStart( node, offset) setStartAfter( node) setStartBefore( node) surroundContents( node)**7 toStringO (1)Not implemented in IE through 6. Text'1’35 data appendData("texr) (None) length deleteData( offset, count) insertData( offset ;texf) replaceData( offset,count,‘text’) splitText( offset) substringData( offset, count) (1)Not implemented in IE through 6 align vAlign Node Types ELEMENT.NODE 1 ATTRIBUTE-NODE 2 TEXT.NODE 3 CDATA_SECTION_NODE 4 ENTITY_REFERENCE_NODE 5 ENTITY-NODE 6 PROCESSING JNSTRUCTION_NODE 7 COMMENT-NODE 6 DOCUMENT-NODE 9 DOCUMENT_TYPE_NODE 10 DOCUMENT_FRAGMENT_ NODE t1 NOTATION-NODE 12 selection11’ 35 anchorNode addRange( range) (None) anchorOffset clearSelection() focusNode collapsef node,offset) focusOffset coHapseToErxK) is Collapsed collapseToStart() rangeCount containsNode( node,recurse) date eFromDocumentO extend( node, offset) getRangeAtQ removeAURangesO removeRange (range) selectAIIChlldren( node) toStringO (1)Not knptomwted in IE throufX' 6.
52 © 2004 Danny Goodman (www.dannyg com) All I Часть V. Приложения JSB5 STYLE 26 media (None) (None) type styleSheet 26 cssRulesfl doteteRulef indexp) (None) disabled insertR^'rufe’ .index p) href media ownerNode!1) ownerRule П) parentStyleSbeet title type (1 )Not implemented in IE through 5.5. cssRule 26 cssText (2) (None) (None) parentStyteSheet (2) selectorText style typel’l W3C DOM Compatibility Guide (1)Not implemented in IE through 6. (2)Not implemented in IE through S, but implemented in lES/Mac. Baseline browsers for this section are E5, NN6, Mozilla 1, and Safari 1 An item with no notation is compatible with these browsers (except occasionally Safari). Some items are new to Netscape 7 (NT) and Mozilla or WinlE6 (W6). Observe footnotes for items missing from IE, and see Ле book's text for Safari details. All HTML element objects share items from “All HTML" box on Page 1. “(None)” means no special methods or events for the current object. LINK 36 (None) (None) disabled href hreflang media rel rev sheet <1> target type (l)Not implemented m IE through 6. SCRIPT 36 defer (None) (None) event htmIFor src text type W3C DOM (IE5+, NN6+, Mozilla, Safari), страница4 из 4 altKey bubbles button cancelBubble cancelable charCode clientx clientY ctrlKey currentTarget detail event Phase tsChar keyCode layerX layerY metaKey originalTarget pageX pageY relatedTarget screenX screenY shiftKey target timeStamp type view event'” 25 inrtEventf type’.bubble,cancelable ) (None) InltKeyEventf type’, evtArgs) inftMouseEventf type’, evtArgs) initMutationEventC type’, evtArgs) initUIEventC type’, evtArgs) preventDef auit() stopPropagationf) (1)Not implemented in IE through 6. EMBED 40 align height name width (None) onload onscroll APPLET 40 OBJECT 40 afign alt™6 archive W6 code CodeBase data height hspace name type use Map**6 vspace width align alt**6 baseURI1*7 border**6 code CodeBase codeType contentDocument 0) height hspace name object type width (1)Not implemented in IE through 6.
Зарезервированные слова JavaScript Каждый язык программирования содержит встроен- ный словарь зарезервированных слов, которые нельзя использовать в качестве имен переменных. Поскольку функция JavaScript представляет собой объект и вызывается с помо- щью имени объекта, нельзя использовать зарезервированные слова в качестве имен функций. Словарь зарезервированных слов Netscape подобен используемому в языке Java, хотя мно- гие приведенные в нем слова не используются в JavaScript. Не забывайте о том, что зарезервированные слова JavaScript за- висят от регистра символов. Вы можете использовать заре- зервированные слова в качестве имен объектов или перемен- ных в своих сценариях, однако если вы введете их в другом регистре, это запутает пользователей, которые попытаются разобраться в вашем сценарии (и даже вас самих). abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchroni z ed this throw throws transient true try typeof var void volatile while with
Ответы к упражнениям ia 1Н>) этом пРиложении вы найдете ответы к упражнени- ям, которые приведены в конце глав 4-12 части П этой книги. Глава 4 1. Приложение музыкального проигрывателя и кальку- лятора температуры — это достойные использования JavaScript задачи. Несмотря на то, что приложение музыкального проигрывателя воспроизводит готовые файлы, которые уже сохранены на сервере, вам при- дется решить еще много серьезных задач. Необходимо создать пользовательский интерфейс, провести предва- рительную загрузку изображений, получить информа- цию об используемых надстройках — LiveAudio, Windows Media Player или QuickTime. С этой точки зрения, калькулятор температуры — более завершен- ное приложение, поскольку при его создании не ис- пользуются данные с сервера. Количество посетителей Web-узла регистрируется и обновляется на сервере, поэтому обычно эта задача выполняется с помощью специального CGI-прило- жения. Чтобы получить лучшее клиентское приложе- ние, подсчитывающее посетителей Web-узла, необхо- димо “научить” его отправлять конечному пользова- телю отчет о том, сколько раз он уже посетил текущий узел. Для решения этой задачи привлекаются данные cookie (глава 16). Приложение комнаты бе- сед требует специального места на сервере, откуда устанавливаются соединения с конечными пользова- телями, посещающими приложение. Поэтому исклю- чительно клиентскими средствами создать комнату бесед практически невозможно.
а) Правильно, поскольку это одно слово. Слитный формат подходит как нельзя лучше. б) Правильно, поскольку символ подчеркивания допускается использовать между словами. в) Неправильно, поскольку идентификатор нельзя начинать с цифры. г) Неправильно, поскольку пробелы использовать нельзя. д) Неправильно, поскольку символы апострофа и многие другие символы пунктуации использовать нельзя. 3. Диаграмма приведена ниже. Ссылка на элемент абзаца имеет следующий вид. document.getElementByld("formPar") 4. Общие: • оба имеют тип узлов, полученных из базового узла DOM; • оба могут выступать дочерними для родительских узлов, представляющих собой контейнеры. • Разные: • узел элемента создается из дескриптора, а текстовый узел не имеет собственного дескриптора; • текстовый узел не может быть родительским ни для какого другого узла. S. cinput type="button" name="Hi" value="Howdy" onclick="alert ('Hello to you, too!')"> Глава 5 1. «script type="text/javascript"> document.write("Hello, world. ") ; Приложение В. Ответы к упражнениям 1137
и --> </script> 2. <html> <body> < script type="text/j avascript"> document.write("Hello, world.") ; П --> </script> </body> </html> 3. <html> <body> «script type="text/javascript"> // вывод приветственного сообщения document.write("Hello, world.") 11 -> </script> </body> </html> 4. Решение заключается в том, что оба обработчика событий вызывают отдельные функции. Кроме того, вы можете сделать так, что обработчики будут вызывать метод alert О. <html> <head> <title>An onload script«/title> «script type="text/javascript"> function done() { alert("The page has finished loading."); } function alertuser() { alert("Ouch!"); } II --> </script> </head> «body onload="done()"> Here is some body text. <form> «input type="button" name="oneButton" value="Press Me!" onclick="alertuser()"> </form> </body> </html> а) На странице отображается два текстовых поля. б) Пользователь вводит текст в первое поле и переходит к другому полю, чтобы вы- звать обработчик события onchange. в) Функция отображает во втором поле значение первого поля, представленное в верхнем регистре. 1138 Часть V. Приложения
Глава 6 1. а) Правильно. б) Неправильно. Переменная должна быть представлена одним словом, например howMany или how_many. в) Правильно. г) Неправильно. Имя переменной не может начинаться с цифры. Если необходимо различать подобные переменные по именам, то поместите числовое значение в ко- нец имени: addressl. 2. а) 4 б) 40 в) "4020" г) "Robert" 3. Используются функции parselnt () и parseFloat (). Преобразуемые строки под- ставляются в качестве параметров функций. parselnt(document.forms[0].entry.value) 4. Оба значения текстового поля строковые; их необходимо преобразовать в числа перед арифметическим сложением. Функцию parseFloat () можно использовать в выраже- нии присвоения значения (например var valuel = parseFloat (document.ad- der . inputA. value)) или выражении суммирования (document. adder. output. value = parseFloat(valuel) + parseFloat(value2)). 5. Конкатенация означает объединение двух строк в одну. Глава 7 1. Поскольку в функции ссылка указывает на текстовое поле entry формы entry Form, то обязательно используйте эти имена в атрибутах name соответствующих дескрип- торов HTML. <html> <head> «script type="text/javascript"> var USStates = new Array(51) USStates[0] = "Alabama" USStates[1] = "Alaska" USStates[2] = "Arizona" USStates[3] = "Arkansas" USStates[4] = "California" USStates[5] = "Colorado" USStates [6] = "Connecticut" USStates[7] = "Delaware" USStates [8] = "District of Columbia" USStates[9] = "Florida" USStates[10] = "Georgia" USStates[11] = "Hawaii" Приложение В. Ответы к упражнениям 1139
USStates [12] USStates[13] USStates [14] USStates[15] USStates[16] USStates[17] USStates[18] USStates[19] USStates[20] USStates[21] USStates[22] USStates[23] USStates[24] USStates[25] USStates[26] USStates[27] USStates [28] USStates[29] USStates[30] USStates[31] USStates [32] USStates [33] USStates [34] USStates[35] USStates[36] USStates[37] USStates[38] USStates[39] USStates [40] USStates[41] USStates[42] USStates[43] USStates [44] USStates[45] USStates[46] USStates [47] USStates [48] USStates [49] USStates[50] "Idaho" "Illinois" "Indiana" "Iowa" "Kansas" "Kentucky" "Louisiana" "Maine" "Maryland" "Massachusetts" "Michigan" "Minnesota" "Mississippi" "Missouri" "Montana" "Nebraska" "Nevada" "New Hampshire" "New Jersey" "New Mexico" "New York" "North Carolina" "North Dakota" "Ohio" "Oklahoma" "Oregon" "Pennsylvania" "Rhode Island" "South Carolina" "South Dakota" "Tennessee" "Texas" "Utah" "Vermont" "Virginia" "Washington" "West Virginia" "Wisconsin" "Wyoming" var stateEntered = new Array(51) stateEntered[0] = 1819 stateEntered[1] = 1959 stateEntered[2] = 1912 stateEntered[3] = 1836 stateEntered[4] = 1850 stateEntered[5] = 1876 stateEntered[6] = 1788 stateEntered[7] = 1787 stateEntered[8] = 0000 stateEntered[9] = 1845 stateEntered[10] = 1788 stateEntered[11] = 1959 stateEntered[12] = 1890 stateEntered[13] = 1818 stateEntered[14] = 1816 stateEntered[15] = 1846 stateEntered[16] = 1861 1140 Часть V. Приложения
stateEntered[17] = 1792 stateEntered[18] = 1812 stateEntered[19] = 1820 stateEntered[20] = 1788 stateEntered[21] = 1788 stateEntered[22] = 1837 stateEntered[23] = 1858 stateEntered[24] = 1817 stateEntered[25] = 1821 stateEntered[26] = 1889 stateEntered[27] = 1867 stateEntered[28] = 1864 stateEntered[29] = 1788 stateEntered[30] = 1787 stateEntered[31] = 1912 stateEntered[32] = 1788 stateEntered[33] = 1789 stateEntered[34] = 1889 stateEntered[35] = 1803 stateEntered[36] = 1907 stateEntered[37] = 1859 stateEntered[38] = 1787 stateEntered[39] = 1790 stateEntered[40] = 1788 stateEntered[41] = 1889 stateEntered[42] = 1796 stateEntered[43] = 1845 stateEntered[44] = 1896 stateEntered[45] = 1791 stateEntered[46] = 1788 stateEntered[47] = 1889 stateEntered[48] = 1863 stateEntered[49] = 1848 stateEntered[50] = 1890 function getStateDate() { var selectedState = document.entryForm.entry.value; for ( var i = 0; i < USStates.length; i++) { if (USStates[i] == selectedState) { break; } } alert("That state entered the Union in " + stateEntered[i] с/script> c/head> cbody> cform name="entryForm"> Enter the name of a state: cinput type="text" name="entry" /> cinput type="button" value="Look Up Entry Date" one1ick="getStateDate()" /> c/body> c/html> 2. В определении этой функции существует несколько недостатков. В первом условном выражении if пропущены скобки. Фигурные скобки также пропущены во втором вложенном выражении if. . .else. Более того, фигурные скобки не заданы для всей Приложение В. Ответы к упражнениям 1141
условной конструкции. Ниже приведен правильный вариант кода. Изменения введены полужирным начертанием. function format(ohmage) { var result । if (ohmage >= 10e6) { ohmage = ohmage I 10e5; result = ohmage + " Mohms"; } else { if (ohmage >= 10e3) { ohmage = ohmage I 10e2; result = ohmage + ” Kohms" } else { result = ohmage + ” ohms"; } } alert(result); } 3. Представим один из вариантов. for (var i = 1; i < tomatoes.length; i++) { if (tomatoes[Ц.looks == "mighty tasty") { break } var myTomato = tomatoes[i] 4. Новый вариант определяет другую локальную переменную для имени собаки. <html> <head> «script type="text/javascript"> var aBoy = "Charlie Brown" // глобальная var hisDog = "Snoopy" // глобальная function sampleFunctionO { // использование неточного варианта var WallacesDog = "Gromit" // local version of hisDog var output = WallacesDog + " does not belong to " + aBoy + ". <br>" document.write(output) } </script> <body> «script type="text/javascript"> demo() // выполняется при загрузке документа document.write(hisDog + " belongs to " + aBoy + ".") </script> </body> </html> 5. В приложении используется три параллельных массива. Само оно структурировано подобно решению, предложенному в первом упражнении. Постарайтесь разобраться в приведенном ниже коде. <html> <head> «script type="text/javascript"> var planets = new Array(4) planets[0] = "Mercury" planets[1] = "Venus" 1142 Часть V. Приложения
planets[2] = "Earth” planets[3] = "Mars" var distance = new Array(4) distance[0] = "36 million miles" distance[1] = "67 million miles" distance[2] = "93 million miles" distance[3] = "141 million miles" var diameter = new Array(4) diameter[0] = "3100 miles" diameter[1] = "7700 miles" diameter[2] .= "7920 miles" diameter[3] = "4200 miles" function getPlanetDataO { var selectedPlanet = document.entryForm.entry.value; for ( var i = 0; i < planets.length; i++) { if (planets[i] == selectedPlanet) { break; var msg = planets[i] + " is " + distance[i] +. " from the Sun and " msg += diameter[i] + " in diameter. "; document.entryForm.output.value = msg; } </script> </head> <body> < form name="entryForm"> Enter the name of a planet: «input type="text" name="entry" /> «input type="button" value="Look Up a Planet" onclick="getPlanetData()" /> <br /> 1 «input type="text" size=70 name="output" /> </body> </html> Глава 8 а) Близко, но неточно. Ссылки на массив задаются в множественном числе. window.document.forms[0 ]. б) Неправильно. Объект self соответствует окну, a entryForm должна соответ- ствовать форме. Где же документ? Он должен задаваться ссылкой self.document.entryForm.entryField.value. в) Правильно. г) Неправильно. Пропущена ссылка на document. д) Правильно, если newWindow — это переменная, содержащая ссылку на вложен- ное окно. 2. window.status = "Welcome to my Web page." 3. document.write("<hl>Welcome to my Web page.«/hl>") Приложение В. Ответы к упражнениям 1143
4. Сценарий в разделе body вызывает функцию, которая возвращает текст, введенный в диалоговом окне prompt (). «html? <head> «script type="text/javascript"? function askNameO { var name = prompt("What is your name, please?","") return name } «/script:» «/head? «body? «script type="text/javascript">. document.write("Welcome to my web page, " + askNameO + ".") «/script? «/body? «/html? 5. Адрес URL получен из свойства href объекта locat ion. «html? «head? «script type="text/javascript"? function showLocationO { alert("This page is at: " + location.href); } «/script? «/head? «body onload="showLocation()"? Blah, blah, blah. «/body? «/html? Глава 9 1. В листинге 9.1 используйте текстовый объект, поскольку только он принимает участие во всем преобразовании. «html? «head? <title?Text Object value Property«/title? «script type="text/javascript"? function upperMe(field) { field.value = field.value. toUpperCase () ,- } «/script? «/head? «body? «form onsubmit="return false"? «input type="text" name="convertor" value="sample" onchange="upperMe(this)"? «/form? «/body? «/html? В листинге 9.2 кнопка вызывает функцию, управляющую другим элементом формы. Используйте объект формы. «html? «head? 1144 Часть V. Приложения
<title>Checkbox Inspector«/title> «script type="text/javascript"> function inspectBox(form) { if (form.checkThis.checked) { alert("The box is checked."); } else { alert("The box is not checked at the moment."); )1 </script> </head> <body> <form> «input type="checkbox" name=" checkThis ">Check here«br> «input- type="button" value="Inspect Box" onclick="inspectBox(this.form)"> </form> </body> </html> В листинге 9.3 кнопка вновь вызывает функцию, которая управляет другими элемен- тами формы. Используйте объект формы. <html> «head> <title>Extracting Highlighted Radio Button«/title> «script type="text/javascript"> function fullName(form) { for (var i = 0; i < form.stooges.length; i++) { if (form.stooges[i].checked) { break; } } alert("You chose " + form.stooges[i].value + "."); } </script> </head> <body> <form> <b>Select your favorite Stooge:</b> «input type="radio" name="stooges" value="Moe Howard" checked>Moe «input type="radio" name="stooges" value="Larry Fine" >Larry «input type="radio" name="stooges" value="Curly Howard" >Curly«br> «input type="button" name="Viewer" value="View Full Name..." onclick="fullName(this.form)"> </form> </body> </html> В листинге 9.4 все действия вызываются объектом select. В функции используйте только этот объект. <html> <head> <title>Select Navigation«/title> «script type="text/javascript"> function goThere(list) { location = list.options[list.selectedlndex].value; } Приложение В. Ответы к упражнениям 1145
«/script:» </head> <body> <form> Choose a place to go: «select name=’’urlList" onchange="goThere(this)"> «option selected value="index.html">Home Page «option value="store.html">Shop Our Store «option value="policies">Shipping Policies «option value="http://www.google.com">Search the Web </select> «/form> </body> </html> 2. Ниже приведено несколько способов ссылки на объект текстового поля. document.getElementByld("email") document.forms[0].elements[0] document.forms["subscription"].elements[0] document.subscription.elements[0] document.forms[0].elements["email"] document.forms["subscription"].elements["email"] document.subscription.elements["email"] document.forms[0].email document.forms["subscription"].email document.subscription.email Ссылка document, all .email (любые ссылки, начинающиеся c document. all) поддерживается только в IE. В Mozilla и Safari она не обрабатывается. В W3C D0M ис- пользуются ссылки, в которых задействован метод getElementByTagName (). По- скольку текстовое поле располагается на единственной форме страницы, то оно является первым элементом input страницы. Таким образом, в качестве ссылки можно ис- пользовать выражение document.body.getElementsByTagName("input") [0]. 3. Ключевое слово this соответствует объекту текстового поля, поэтому this .value соответствует свойству value этого объекта. function showText(txt) { alert(txt); } 4. document.accessories.accl.value = "Leather Carrying Case"; document.forms[1].acc.value = "Leather Carrying Case"; 5. Объект select вызывает функцию, выполняющую необходимые операции. «html> <head> «title>Color Changer«/title> «script type="text/javascript"> function setcolor(list) { var newColor = list.options[list.selectedlndex].value; document.bgColor = newColor; } </script> «/head> <body> «form> Select a background color: 1146 Часть V. Приложения
«select onchange=”setColor(this)"> «option value="red">Stop «option value="yellow">Caution «option value="green">Go </select> </fortn> </body> </html> Глава 10 1. Используйте метод строка. indexOf () для поиска символа @ в значении поля. <html> <head> <title>E-mail Validator«/title> «script type="text/javascript"> function checkAddress(form) { if (form.email.value.indexOf("@") == -1) { alert("Check the e-mail address for accuracy."); return false; } return true; } </script> </head> <body> «form onsubmit="return checkAddress(this)"> Enter your e-mail address: «input type="text" name="email" size=30>«br> «input type="submit"> </form> </body> </html> 2. Помните, что подстрока вычисляет, но не включает второй параметр функции. Пробе- лы рассматриваются как символы. myString.substring(0,3) // результат = "Net" myString.substring(13,18) // результат = "gator" myString.substring(4,12) // результат = "cape Nav" 3. Пропущенный цикл отображен полужирным начертанием. Вы также можете исполь- зовать оператор приращения в переменной count для добавления 1 к каждой букве " е ". function countE(form) { var count = О; var inputstring = form.mainstring.value.toUpperCase(); for (var 1=0; 1 < inputstring.length; i++) { If (Inputstr.char At(1) == "e") { count += 1; } } var msg = "The string has " + count; msg += " instances of the letter e."; alert(msg); } Приложение В. Ответы к упражнениям 1147
4. Формула произвольного значения одной кости приведена в главе. «html» «head» <title»E-mail Validator«/title» «script type="text/javascript"> function roll(form) { form.diel.value = Math.round(Math.random() * 5) + 1; form.die2.value = Math.round(Math.random() * 5) + 1; } «/script» «/head» «body» «form» «input type="text" name="diel" size=2> «input type="textn name="die2" size=2»«br» «input type="button" value="Roll the Dice" onelick="roll(this.form)"» </form> «/body» «/html» 5. Если в вычислениях вы используете метод Math, round (), то не забывайте, что он вызывается для экземпляра объекта Math. Другой метод Math. ceil () также может пригодиться, поскольку он округляет дробные значения. <html> «head> «title»Waiting for Santa«/title> «script type="text/javascript"» function daysToXMASO { var oneDay = 1000 * 60 * 60 * 24; var today = new Date(); var XMAS = new Date("December 25, 1998"); var diff = XMAS.getTime() - today.getTime(); return Math.ceil(diff/oneDay); } «/script» «/head» «body» «script type="text/javascript"» document.write(daysToXMAS() + " days until next Christmas.") «/script» «/body» «/html» Глава 11 1. onload="parent.currCourse = 'historylOl’" 2. <Framesets> 1148 Часть V. Приложения
3. Все три фрейма — “сестры” по отношению друг к другу; они имеют один родитель- ский фрейм. parent.mechanics.location.href = "french201M.html" parent.description.location.href = "french201D.html” 4. Сценарий в одном из документов пытается сослаться на объект selector в одном из фреймов, но документ еще полностью не загружен, поэтому объект не представлен в модели браузера. 5. Из вложенного окна свойство opener ссылается на фрейм, вызывающий метод window. open (). При расширении ссылки на родительский фрейм она включает оба объекта: opener .parent. location. Глава 12 1. При загрузке документа дескриптор <img> создает объект изображения документа. Объект в памяти, выделенной браузеру, создается с помощью конструктора Image (). Оба объекта имеют одинаковые свойства. При указании в качестве src адреса URL объект из памяти загружается в кэш браузера (изображение кэшируется). 2. var janelmg = new Image(100,120); janelmg.src = "jane.jpg"; 3. document.images["people"]-src = janelmg.src; 4. Следующие выражения выполняются во всех W3C DOM-совместимых браузерах. var newElem = document.createElement("а"); var newText = document.createTextNode("Next Page"); newElem.href = "page4.html"; newElem.appendChild(newText); document.getElementByld("forwardLink").appendChild(newElem); Приложение В. Ответы к упражнениям 1149
Internet-ресурсы, посвященные JavaScript и DOM Создание сценариев на языке JavaScript вызвало бур- ный интерес в Internet-сообществе. Рекомендуемые для посещения ресурсы, упомянутые в данном приложении, были актуальны на начало 2003 года. Но с тех пор прошло несколько лет. Web-узлы быстро устаревают, а в отдельных случаях даже перестают существовать. Очень часто они так- же изменяют свои URL-адреса. Приготовьтесь к тому, что вам придется изрядно постараться, чтобы найти свежую ин- формацию по интересующему вопросу. Узел поддержки и обновлений для книги Самый свежий список исправлений и замечаний к англоя- зычному изданию этой книги вы найдете на Web-узле автора. http://www.dannyg.сот/supportI index.html Если в процессе изучения листингов этой книги у вас воз- никло много вопросов, то сначала поищите ответы на них в разделе Support Center указанного узла. Как уже рассказыва- лось ранее, вам совсем не обязательно вводить код листингов (JavaScript и HTML). Если после копирования кода примеров второй части вы так и не смогли добиться ожидаемого результа- та (и решение проблемы не изложено в разделе Support Center), то отправьте полученный проект, а также краткое описание проблемы (не забудьте указать версию используемого браузера и операционной системы) по адресу dannyg@dannyg. com (предположительно на английском языке). К сожалению, я не имею возможности отвечать на общие вопросы по JavaScript, а также не могу советовать, как лучше применить приведен- ные в книге примеры в реальной жизни.
Группы новостей Самый быстрый способ получения ответа на интересующий вас вопрос — это задать его в группе новостей. Ниже приведен список известных мне популярных групп новостей, по- священных в том числе и JavaScript. comp.lang.j avascript microsoft.public.scripting.j script microsoft.public.windows.inetexplorer.ie5.programming.dhtml microsoft.public.windows.inetexplorer.ie5.programming.dhtml.scripting microsoft.public.inetsdk.programming.scripting.j script netscape.public.mozilla.dom netscape.public.mozilla.j seng Перед тем, как задать свой вопрос, обязательно ознакомьтесь со списком наиболее часто задаваемых вопросов (FAQs), приведенных в следующем разделе. В архивом всевозможных групп новостей вы сможете ознакомиться, задав поиск в таком популярном диалоговом сред- стве, как Google Groups. Страница поиска Google Groups расположена по следующему адресу. http://groups.google.com/ Введите в верхнее поле ключевое слово или фразу, но постарайтесь ограничить список групп новостей несколькими элементами. Например, если поведение свойства стиля borderCol lapse в IE вам кажется странным, то введите в строку поиска borderCollapse, а затем укажите выполнить операцию только в одной из групп новостей (форуме) — скажем, comp. lang. j avascript. Если вы отправили свой вопрос в группу новостей, то можете рассчитывать на быстрый и квалифицированный ответ, сопровождаемый разъяснениями в коде, (если, конечно, таковой содержался в вопросе). Самым важным аспектом является правильное толкование возникшей проблемы другим пользователям. Постарайтесь максимально детально изложить возникшие трудности, не забыв указать браузер, который вы использовали для выполнения сценариев. Наиболее часто задаваемые вопросы (FAQs) Каждая новая технология требует времени на изучение широким кругом разработчиков и пользователей. Как и любым другом случае изучение JavaScript и DHTML сопровождается непрерывным потоком одних и тех же вопросов, задаваемых разными пользователями. Их количество только увеличивается и разработчикам Web-узлов приходится уделять немало времени на ответы постоянно задаваемых вопросов. Перед тем, как отправить свой вопрос в форум или конференцию, внимательно изучите раздел FAQ (часто задаваемые вопросы), вполне возможно он уже содержит ответ на. Ниже приведено две ссылки на узлы, содержа- щие разделы с наиболее часто задаваемыми вопросами по JavaScript. javascript.faqts.com developer.irt.org/script/script.htm Ответы на менее часто задаваемые вопросы — задаваемые ранее или рассматриваемые в других разделах — вы найдете с помощью современных поисковых средств. Документация Web-узлы, на которых приведена официальная документация по браузерам разных вер- сий, разбросаны по всей Всемирной паутине. Поэтому, в приведенных ниже ресурсах вы най- дете ссылки только на самые известные Web-узлы, посвященные указанной тематике. Приложение Г. Internet-ресурсы, посвященные JavaScript и DOM 1151
Microsoft содержит документацию, предназначенную для разработчиков в огромной базе данных, именуемой MSDN (Microsoft Developer Network). Начните поиск необходимой ин- формации со следующего узла. http://msdn.microsoft.сот/workshop/ Эта страница представляет собой портал на Internet-ресурсы, содержащие описание JavaScript и методов разработки клиентских сценариев, в общем случае озаглавливаемый на- званием “Web-разработка”. Уделите особое внимание разделу Scripting (Разработка сценариев). В нем приведено много технических статей и рекомендаций разработчиков Microsoft, в том числе и относительно применения JScript (воплощение JavaScript в представлении Microsoft). Ссылки на ресурсы, описывающие технологии, которые используются для разработки сценариев в браузере Netscape, приведены на следующем портале. http://developer.netscape.com/docs/ Весьма интересная документация по написанию сценариев, а также описание будущих технологий содержатся на таком Web-узле. http://www.mozilla.org/docs Наконец, с промышленными стандартами технологий HTML, CSS и ECMAScript вы также можете познакомиться, не отходя от экрана своего компьютера. Примите к сведению, что приведенные на указанных ниже узлах документы рассчитаны в первую очередь на разработ- чиком серьезного программного обеспечения, как браузеры, редакторы WYSIWYG и т.д. По- этому, изучая приведенные на Web-узлах, постарайтесь соблюдать душевное спокойствие и не расстраивайтесь, если многое так и останется для вас загадкой. http://www.ecma-international.org/publications/standards/ECMA-262.НТМhttp://www.w3.org/TR/html4 http://www.w3.org/Markup http://www.w3,org/TR/REC-CSS2 http://www.w3.org/DOM/ Учтите, что описание элемента в технологии промышленного масштаба не указывает на его поддержку во всех современных браузерах. В реальной жизни сначала нужно добиться призна- ния промышленных технологий и только после этого рассчитывать на их поддержку браузерами. World Wide Web Количество независимых Web-узлов, посвященных JavaScript, может удивить даже опытно- го посетителя Всемирной паутины. Многие узлы нормально функционируют только в ночное время, а потому оставляют мало надежд тем, кто привык работать в дневное время. Если вы хо- тите познакомиться с реальными примерами использования сценариев, которые не вошли в настоящую книгу, то обратитесь к традиционным поисковым средствам. Чтобы сузить об- ласть поиска, указывайте критерии максимально детально. В дополнение к узлам Netscape и Microsoft (а также многочисленным статьям, приведенным на узле http: / /www. dannyg. сот/ pubs / index. html), обратите свой взор на следующие ресурсы. http://builder.com http://www.webreference.com Эти узлы нельзя считать достаточными для всестороннего изучения JavaScript и DHTML, применяемых в Web-разработке. Не стоит полагаться в программировании на мнение одного или нескольких изданий. Сначала изучите все основные точки зрения и только после этого приступайте к собственным изысканием. В этом вам помогут ссылки на Web-узлы и группы новостей, приведенные выше. 1152 Часть V. Приложения
Дополнительные главы на компакт-диске
глммм ГАДВА ;« Ww ечэ^эт/^^р.' и6я»«лс*сга 17M0ASI фСДЧВ'НМЭ* ГЛА^52
Предметный указатель А Acrobat Reader, 40 ADO-свойства, 775 В BBEdit, 53 С CGI, 63; 68; 652; 925 CGI-программа, 652 CGI-сценарий, 69 cookie, 546 доступ, 548 получение, 550 сохранение, 548 функции, 551 CSS, 49; 209; 811 класс, 173 D Decision Helper, 67; 160 DHTML, 50; 67; 211 DOM, 48; 70; 196 Dreamweaver, 52 E ECMA, 48; 94 ECMA-262, 94 ECMAScript, 48; 177 F FrontPage, 52 FTP, 522 G GMT, 150; 549; 908 H HTML, 38 динамический, 50; 67 HTML-код вставка, 331 HTTP, 522 J JavaScript, 40 версии, 176 история, 41 назначение, 42; 68 особенности, 192 JScript, 41 L LiveScript, 40 M MacOS X, 55 Macromedia Flash, 40 R .RGB, 830 S SGML, 38 T The Evaluator Jr., 99; 191 u Unicode, 784 URI, 323; 568; 832; 1026 URL-адрес, 512; 767 URN, 356 UTC, 908
V VBScript, 41 w W3C, 49; 196 W3C DOM, 212; 538 Web-технологии, 37 тенденции развития, 46 Windows, 54 WWW, 522 WYSIWYG, 52 X XHTML, 38 A Авторизация, 311 Адрес, 512 Активизация объекта, 306; 349; 375 поля, 694 Активная область, 415 Альтернативное содержимое, 627 Анимация, 39 Анкер, 516; 542; 613 Аргумент, 79; 110 Арифметические операторы, 979 Атрибут, 119 action, 660; 673 enctype, 657 ID, 264; 585 language, 84; 178; 269 method, 657; 658; 673 name, 76; 135; 664 size, 699; 715 src, 84; 181 title, 821 type, 84; 178 value, 135; 674; 680; 715; 726 свойства, 322 создание, 579 удаление, 341; 342 Б Базовая объектная модель, 203 Базовый язык, 146 Бегущая строка, 433 Безопасный массив, 1037 Бессерверный сценарий, 42 Бета-версия браузера, 190 Библиотека объектов, 207 сценариев, 181; 232 функций, 1008 Бинарный оператор, 975 Браузер, 38; 53 определение версии, 182 совместимость, 46 Буквенное обозначение, 926 Булево значение, 907 Булевы операторы, 983; 984 Буфер обмена, 402 Буферизация страницы, 418 В Ввод кода документа, 598 Версия JavaScript, 176 браузера, 182 Ветвление, 185 сценария, 229 Видеоклип, 39 циклическое воспроизведение, 633 Вложенная строка, 109 функция, 998 Вложенный метод, 893 слой, 567 Внешний интерфейс, 64 Возврат каретки, 711 Возвращаемое значение, 120 Восьмеричные числа, 897 Временная зона, 908 Всплывание события, 749 Всплывающее меню, 511 Вставка, 365 HTML-кода, 331 элемента, 329 Встроенные объекты, 193 Выделение, 574; 694 анкерное, 1079 Вызов метода, 79 функции, 1004 Выполнение сценария прекращение, 600 Выравнивание, 626 Выражение, 97; 1032 1160 Предметный указатель
вложенное, 948 регулярное, 880 обновления, 951 Вырезание, 365 Выход из цикла, 954 Выходной поток, 127 Вычисление выражения, 97 даты, 152 проверка, 99 Вычисляемый стиль, 813 Г Генерирование случайных чисел, 902 Гиперссылка, 613 Глобальная переменная, 110; 1005 функция, 1024 Граница, 847 изображения, 628 Группа переключателей, 138 элементов, 734 д Данные, 95 безусловное получение, 527 интерактивные, 65 отображение, 256 отправка на сервер, 681 передача, 140 перенаправление, 658 преобразование типов, 100 проверка, 65; 143; 707 связывание, 285 сортировка, 258 тип, 95 Данные диалогового окна, 474 Дата добавление, 565 преобразование, 916 проверка, 920 строковая, 914 формат, 915 Двунаправленная модель событий, 225 Деактивизация, 694 Действие по умолчанию, 751 Декодирование, 894 Дерево узлов, 76 Дескриптор, 575 <а>, 183 <агеа>, 622 <form>, 560; 657 <frame>, 491 <img>, 166; 622 <input>, 659 <layei>, 566 <link>, 811 <noscript>, 182 <object>, 254 <script>, 58; 83; 178 <script for>, 179 <style>, 811 комментария, 58 размещение, 84 Детектирование объектов, 187 Диалоговое окно данные, 474 свойства, 474 Динамический HTML, 67 стиль, 228 Динамическое содержимое, 230 Длина, 829 Длинные строки, 869 Добавление прототипа, 1019 Документ, 538 заголовок, 575 загрузка, 72; 88 иерархическая структура, 70; 119 многофреймовый, 156; 426 навигация, 532 настройка цветов, 540 объектная модель, 48; 69 открытие, 592 перезагрузка, 527 прокрутка, 463 с анкерами, 516 сведения, 569 тип данных, 556 Домен, 549 Доступ к cookie, 548 к свойствам формы, 132 Дочерний узел, 76; 247; 261 фрейм, 156 элемент, 248 Е Единицы измерения, 829 Предметный указатель 1161
ж Журнал, 531 3 Заголовок документа, 575 Загрузка фреймов, 396 Задержка, 439; 471 Закрытие окна проверка, 404 Запись, 531 cookie, 547 Заполнение массива данными, 925 Заполнитель, 570 Запрос данных, 459 команды, 593 Захват события, 337; 437; 576;.74О отключение, 740 Защищенный спенарий, 452 Значение, 95 булево, 907 возвращение, 120 комбинированное, 832 по умолчанию, 697 сравнение, 978 И Идентификатор, 75; 588 id, 76 Иерархическая структура, 70; 155; 119; 197 Иерархия наследования, 200 узлов, 215 Извлечение подстрок, 148 числа, 898 Изменение регистра, 147 Изображение, 165; 563; 622; 690 выравнивание, 626 граница, 628 динамическое, 630 загрузка, 629 имя, 634 исходный размер, 635 кэширование, 636 низкого разрешения, 633 предварительная загрузка, 166 Импорт таблицы стилей, 812 Имя каталога класса, 249 объекта, 75 окна, 417; 454 переменной, 97 события, 771 Индекс, 113 Ивдекс опции списка, 723 Индексная страница ветвления, 185 Инипиализапия переменной, 96 Интерактивные данные, 65 Интерфейс внешний, 64 интерактивный, 63 Исключение, 963 Исключительная ситуация, 945; 963 механизм обработки, 964 переход, 968 Исходный код, 57 размер изображения, 635 К Карта изображения, 640; 644; 646 именованных узлов, 322 Каскадная таблица стилей, 49; 209 Категории операторов, 976 Клавиша-модификатор, 761; 770; 773; 792 Класс, 197 имя, 249 Кнопка, 671; 689; 775 Reset, 673 Submit, 673 на форме, 658 определение, 775 Код клавиши, 784 документа, 598 Кодированный URL, 1026 Кодировка, 545 Коллекция frames, 159 Команды запросов, 593 Комбинированные значения, 832 Комментарий, 87; 180; 1032 Компактный массив, 926 Комплексные операторы, 990 Комплексные решения, 947 Конкатенация, 59; 102; 146; 869 Консоль JavaScript, 91 Конструктор, 925 Конструкция if...else, 946 for-in, 957 try-catch-finaly, 965 1162 Предметный указатель
Координаты события, 768; 776; 798 формат, 645 Короткая обработка, 994 Кэширование, 166 изображений, 636 Л Локальная переменная, ПО; 1005 м Маркер, 959 Маркированные операторы, 958 Массив, 113; 924 areas, 647 childNodes, 246 elements, 661 styleSheets, 811 взаимосвязанный, 927 заполнение данными, 925 извлечение элементов, 114 компактный, 926 многомерный, 930 объединение, 934 параллельный, 114; 927 создание, 113; 925 сортировка, 940 элементов формы, 659 объектов, 334 Межбраузерный сценарий, 58; 184 Метод, 78; 200; 219 addBehavior(), 295 addEventListener(), 298 alert(), 146 appendChildQ, 301 applyElement(), 303 array ,concat(), 933 array.join(), 936 array.slice(), 939 array.sort(), 939 array.toStringO, 944 attachEvent(), 305 blur(), 306 charAt(), 875 charCodeAtQ, 875 clear(), 577 clearAttributes(), 309 createPopup(), 444 click!), 310 ck>neNode(), 310 componentFromPointO, 311 contains(), 313 deleteRuleQ, 823 detachEvent(), 305; 314 dispatchEvent(), 314 escape(), 1026 eval(), 1027 execCommand() fireEvent(), 316 focus(), 306; 319 fromCharCodeO, 876 getAdjacentText(), 319 getAttribute(), 320 getAttributeNodeO, 321 getAttributeNodeNSO, 323 getAttributeNSO, 323 getBoundingClientRect(), 323 getClientRects!), 326 getElementsByTagName!), 326 getElementsByTagNameNSO, 327 getExpression(), 327 hasAttribute!), 328 hasAttributeNS!), 328 hasAttributes!), 328 hasChildNodes!), 328 hasOwnProperty!), 1023 insertAdjacentElement(), 329 insertAdjacentHTMLO, 331 insertAdjacentTextO, 331 insertBefore!), 332 isPrototypeOf!), 1023 isSupported(), 333 item(), 334 lastlndexOf!), 879 localeComparef), 879 mergeAttributesO, 335 normalize!), 336 match!), 879 open!), 592 releaseCaptureO, 337 removeAttribute!), 341 removeAttributeNode!), 341 removeAttributeNSO, 342 removeBehavior!), 342 removeChild!), 343 removeEventListener!), 298; 343 removeExpression!), 343 removeNode!), 344 removeRule!), 822 replaceAdjacentText!), 345 replaceChild!), 346 replaceNode!), 346 scrollIntoView!), 349 Предметный указатель 1163
search(), 884 setActive(), 349 setAttributeO, 350 setAttributeNode(), 341; 351 setAttributeNodeNSf), 351 setAttributeNS(), 352 setCapture(), 337 setExpression(), 352 sliceO, 884 submit!), 666 substr(), 887 substring!), 888 swapNode(), 355 tags!), 355 toLowetCaseO, 890 toString(), 890 toUpperCaseO, 890 unescapeO, 1027 ums(), 356 watch(), 1032 window.open() write(), 59 аргумент, 79 вложенный, 893 вызов, 79 параметр, 79 форматирования, 892 Многократно вложенные конструкции if...else, 949 Многомерные массивы, 930 Многофреймовый документ, 66; 156; 426 Модальное окно, 477 Модель объектов, 198 событий, 761 перехвата событий, 205 н Набор данных, 926 символов, 545 фреймов, 413; 498; 517 Навигационная панель, 160 Навигация по документу, 532 Надстройка, 39; 572 Названия фильтров, 863 Наследование, 197; 200; 396 объектов, 194 прототипа, 1020 Начальное выражение, 951 Нежелательная прокрутка, 465 Немодальное окно, 481 Несоизмеримые типы данных, 977 Новые концепции DOM, 215 О Область граница, 1090 действия, 111 изображения, 643 объекта, 323 Обмен данными, 523 Обозначение буквенное, 926 Обработка исключительных ситуаций, 945; 963 событий, 233 Обработчик события, 78; 201 onactivate, 357 onbeforecopy, 357 onbeforecut, 358 onbeforedeactivate, 357; 359 onbeforeeditfocus, 359 onbeforepaste, 359 onblur, 360 onchange, 139; 140 onclick, 138; 187; 361 oncontextmenu, 364 oncontrolselect, 364 опсору, 364 oncut, 364 ondblclick, 366 ondeactivate, 357 ondrag, 367 ondragenter, 372 ondragleave, 372 ondragover, 372 ondragstart, 373 ondrop, 373 onerror, 419 onfilterchange, 374 onfocus, 375 onhelp, 376 onkeydown, 377 onkeypress, 377 onkeyup, 377 onload, 124 onlosecapture, 382 onmousedown, 383 onmouseenter, 384 onmouseleave, 384 onmousemove, 385 onmouseout, 385 onmouseover, 385 onmouseup, 383 onpaste, 386 onpropertychange, 388 onreadystatechange, 390 1164 Предметный указатель
onresize, 390 onresizeend, 390 onresizestart, 390 onselectstart, 391 onsubmit, 142 Обратный отсчет, 440 Обтекание текста, 604 Общие объекты, 236 Объединение, 102; 146 массивов, 934 строк, 869 Объект, 77 area свойство alt, 645 свойство areasf], 647 свойство coords, 645 свойство hash, 646 свойство host, 646 свойство hostname, 646 свойство href, 646 свойство pathname, 646 свойство port, 646 х свойство protocol, 646 свойство search, 646 свойство shape, 645 свойство target, 646 Array, 931 методы, 932 свойство length, 931 свойство prototype, 931 Attribute, 242 body, 601 метод createControlRange(), 607 метод createTextRange(), 607 метод doScroll(), 607 обработчик события onafterprint, 608 обработчик события onbeforeprint, 608 обработчик события onscroll, 608 свойство aLink, 602 свойство background, 602 свойство bgColor, 602; 603 свойство bgProperties, 603 свойство bottomMargin, 603 свойство leftMargin, 603; 604 свойство link, 602; 604 свойство no Wrap, 604 свойство rightMaigin, 603; 605 свойство scroll, 605 свойство scrollLeft, 605 свойство scrollTop, 605 свойство text, 602; 606 свойство topMargin, 603; 606 свойство vLink, 602; 606 Boolean, 907 button метод click(), 675 обработчик события onclick, 675 обработчик события onmousedown, 676 обработчик события onmouseup, 676 свойство form, 674 свойство пате, 674 свойство type, 674 свойство value, 674 Checkbox, 677 метод click(), 681 обработчик события onclick, 681 свойство checked, 678 свойство defaultChecked, 679 свойство type, 680 свойство value, 680 cssRule, 811; 824 currentstyle, 827 dataTransfer, 781 Date методы, 151 document метод clear(), 577 метод close(), 578 метод createAttribute(), 579 метод createCommentO, 579 метод createDocumentFragment(), 579 метод createElement(), 129; 580 метод createEventO, 581 метод createEventObject(), 581 метод createRangeO, 581 метод createStyleSheet(), 582 метод createTextNode(), 583 метод createTreeWalker(), 584 метод elementFromPoint(), 585 метод execCommand(), 586 метод getElementBy!d(), 129; 588 метод getElementsByName(), 589 метод getSelection(), 590 метод handleEventf), 591 метод open(), 592 метод queryCommandComnlandStateO, 593 метод queryCommandEnabledO, 593 метод queryCommandIndterm(), 593 метод queryCommandSupported(), 593 метод queryCommandText(), 593 метод queryCommandValueO, 593 метод recalc(), 594 метод releaseEvents(), 594 метод routeEvent(), 595 метод write(), 129; 595 метод writeln(), 595 метод captureEventsf), 576 Предметный указатель 1165
метод write(), 127 обработчик события onselectionchange, 599 обработчик события onstop, 599 свойство activeElement, 539 ! свойство anchors!], 542 свойство applets, 544 свойство bgColor, 540; 544 свойство body, 544 свойство characterSet, 545 свойство charset, 545 свойство compatMode, 546 свойство cookie, 546 свойство defaultCharset, 555 свойство defaultview, 556 свойство designMode, 556 свойство doctype, 556 свойство documentElement, 557 свойство domain, 557 свойство embeds, 557 свойство expando, 558 свойство fgColor, 540; 558 свойство fileCreatedDate, 558 свойство fileModifiedDate, 558 свойство fileSize, 558 свойство forms[], 126; 560 свойство frames[], 562 свойство height, 562 свойство ids[], 563 свойство images[], 126; 563 свойство implementation, 564 свойство lastModified, 565 свойство layers!], 566 свойство linkColor, 540; 567 свойство links[], 568 свойство location, 568 свойство media, 570 свойство mimeType, 571 свойство nameProp, 571 свойство namespaces!], 571 свойство parent Window, 571 свойство plugins[], 572 свойство protocol, 572 свойство referrer, 572 свойство scripts!], 573 свойство security, 574 свойство selection, 574 свойство styleSheets!], 575 свойство tags[], 575 свойство title, 575 свойство URL, 568; 575 свойство URLUnencoded, 575 свойство vlinkColor, 540; 576 свойство width, 562; 576 свойство alinkColor, 540 DocumentType, 556 error метод toString!), 974 свойство constructor, 973 свойство description, 973 свойство filename, 973 свойство lineNumber, 973 свойство message, 973 свойство name, 974 свойство number, 974 event свойство altKey, 773 свойство altLeft, 774 свойство behaviorCookie, 774 свойство behaviorPart, 774 свойство bookmarks, 774 свойство boundElements, 774 свойство button, 774 свойство cancelBubble, 776 свойство clientX, 776 свойство clientY, 776 свойство ctrlKey, 773 свойство ctrlLeft, 774 свойство dataField, 774 свойство dataTransfer, 781 свойство fromElement, 783 свойство keyCode, 784 свойство nextPage, 786 свойство offsetX, 776 свойство offsetY, 776 свойство propertyName, 786 свойство qualifier, 774 свойство reason, 774 свойство recordset, 774 свойство repeat, 787 свойство retumValue, 787 свойство saveType, 788 свойство screenX, 776 свойство screenY, 776 свойство shiftKey, 773 свойство shiftLeft, 774 свойство srcElement, 788 свойство srcFilter, 789 свойство srcUm, 790 свойство toElement, 783; 790 свойство type, 790 свойство x, 776 свойство у, 776 совместимость, 759 filter, 261; 856 form метод handleEvent(), 664 метод reset(), 665 1166 Предметный указатель
метод submit(), 665 обработчик события onreset, 666 обработчик события onsubmit, 667 свойство acceptCharset, 660 свойство action, 660 свойство autocomplete, 660 свойство checked, 136 свойство elements!], 133; 660 свойство encoding, 663 свойство enctype, 663 свойство length, 663 свойство method, 663 свойство name, 664 свойство target, 664 frame свойство allowTransparency, 492 свойство borderColor, 492 свойство contentDocument, 492 свойство contentwindow, 493 свойство frameBorder, 493 свойство height, 494 свойство longDesc, 494 свойство marginHeight, 494 свойство margin Width, 494 свойство name, 495 свойство noResize, 495 свойство scrolling, 495 свойство src, 497 свойство width, 494 frameset свойство border, 499 свойство borderColor, 499 свойство cols, 499 свойство frameBorder, 502 свойство frameSpacing, 502 свойство rows, 499 history метод back(), 531 метод forward(), 531 метод go(), 533 свойство current, 530 свойство length, 530 свойство next, 530 свойство previous, 530 iframe свойство align, 504 свойство allowTransparency, 505 свойство contentDocument, 505 свойство contentwindow, 505 свойство height, 506 свойство hspace, 506 свойство longDesc, 506 свойство marginHeight, 506 свойство marginWidth, 506 свойство name, 507 свойство scrolling, 507 свойство src, 507 свойство vspace, 506 свойство width, 506 Image обработчик события onload, 641 обработчик события у, 641 свойство align, 626 свойство alt, 627 свойство border, 627 свойство complete, 691 свойство dynsrc, 629 свойство fileCreatedDate, 631 свойство fileModifiedDate, 631 свойство fileSize, 631 свойство fileUpdateDate, 631 свойство height, 631 свойство href, 632 свойство hspace, 632 свойство isMap, 632 свойство longDesc, 633 свойство loop, 633 свойство lowsrc, 633 свойство mimeType, 634 свойство name, 634 свойство nameProp, 634 свойство naturalHeight, 635 свойство naturalWidth, 635 свойство protocol, 635 свойство src, 636; 691 свойство start, 639 свойство type, 691 свойство useMap, 640 свойство vspace, 632; 640 свойство width, 631; 640 свойство х, 640 свойство complete, 628 свойство у, 640 input, 709; 735 Layer, 206; 566 label свойство htmlFor, 670 location, 124 метод assign(), 526 метод reload!), 526 метод replace!), 528 свойство hash, 515 свойство host, 516 свойство hostname, 520 свойство href, 520 свойство pathname, 521 Предметный указатель 1167
свойство port, 522 свойство protocol, 522 свойство search, 522 Math метод floor(), 150 метод random(), 150 свойства, 901 namespace, 571 navigator, 71; 125 Node, 321 number методы, 905 свойство constructor, 904 свойство MAX_VALUE, 904 свойство MIN_VALUE, 904 свойство NaN, 905 свойство NEGATIVEJNFINITY, 904 свойство POSITIVE_INFINITY, 904 свойство prototype, 905 Object, 1022 optgroup свойство label, 733 option свойство label, 732 password, 708 popup метод hide(), 510 метод show(), 510 свойство document, 509 свойство isOpen, 509 radio методы click(), 688 обработчик события onclick, 689 свойство checked, 685 свойство defaultChecked, 687 свойство length, 687 свойство name, 688 свойство type, 688 свойство value, 688 Range, 1057 метод cloneContents(), 1062 метод cloneRange(), 1062 метод collapse(), 1063 метод compareNodeO, 1067 метод comparePoint(), 1067 метод createContextualFragment(), 1068 метод deleteContents(), 1069 метод detach(), 1070 метод extractContents(), 1070 метод insertNode(), 1071 метод intersectsNode(), 1072 метод isPoint!nRange(), 1073 метод selectNodeQ, 1073 метод selectNodeContentsQ, 1073 метод setEnd(), 1074 метод setEndAfter(), 1075 метод setEndBefore(), 1075 метод setStart(), 1074 метод setStartAfter(), 1075 метод setStartBeforeQ, 1075 метод surroundContents(), 1076 метод toStringO, 1077 метод compareBoundaryPoints(), 1064 свойство collapsed, 1059 свойство commonAncestorContainer, 1060 свойство endContainer, 1060 свойство endOffset, 1061 свойство Startoffset, 1061 rule, 824 runtimeStyle, 827 screen, 429 selection метод addRangef), 1081 метод clearQ, 1081 метод collapse(), 1081 метод collapseToEnd(), 1082 метод collapseToStart(), 1082 метод containsNodef), 1082 метод createRangef), 1082 метод deleteFromDocumentO, 1082 метод emptyO, 1082 метод extend(), 1083 метод getRangeAtf), 1083 метод removeAllRanges(), 1083 метод removeRangesf), 1083 метод selectAHChildrenO, 1083 метод toStringO, 1084 свойствр anchorNode, 1079 свойство appendData, 1085 свойство data, 1085 свойство deleteData, 1085 свойство focusNode, 1079 свойство insertData, 1085 свойство isCollapsed, 1079 свойство rangeCount, 1079 свойство replaceData, 1085 свойство splitText, 1088 свойство substringData, 1085 свойство type, 1080 свойство typeDetail, 1081 select метод add(), 729 метод item(), 729 метод namedltemO, 729 метод options|HHfleKc|.add(), 729 метод орйоп8[индекс].гетоуе(), 729 1168 Предметный указатель
метод removeO, 729 обработчик события onchange, 730 свойство length, 722 свойство multiple, 722 свойство options[], 722 свойство орОопь(индекс].defaul tSelected, 723 свойство optionsfmuieKc].index, 723 свойство орйоп5[индекс].selected, 724 свойство options[HWieKc].text, 725 свойство options [индекс], value, 726 свойство selectedlndex, 727 свойство size, 728 свойство type, 728 свойство value, 728 String метод alert(), 146 метод chartAt(), 148 метод index0f(), 147 метод substringO, 148 свойство constructor, 873 свойство length, 873 свойство prototype, 874 style свойство media, 814 свойство type, 815 styleSheet метод addlmportO, 822 метод addRule(), 822 метод deleteRule(), 823 метод insertRule(), 823 метод removeRuleO, 822 свойство cssRules, 816 свойство cssText, 816 свойство disabled, 817 свойство href, 818 свойство id, 818 свойство imports, 818 свойство media, 818 свойство ownerNode, 819 свойство ownerRule, 819 свойство owningElement, 819 свойство pages, 820 свойство parentStyleSheet, 820 свойство readonly, 820 свойство rules, 821 свойство title, 821 свойство type, 822 Tabular Data Control, 254 text метод blur(), 702 метод focus(), 703 метод selectf), 703 обработчик события onafterupdate, 705 обработчик события onbeforeupdate, 705 обработчик события onblur, 705 обработчик события onchange, 707 обработчик события onerrorupdate, 705 обработчик события onfocus, 705 обработчик события onselect, 705 свойство defaultValue, 696 свойство form, 697 свойство maxLength, 698 свойство name, 698 свойство readonly, 699 свойство size, 699 свойство type, 700 свойство value, 700 textarea метод createTextRange(), 712 свойство cols, 712 свойство rows, 712 свойство wrap, 712 TextNode, 1084 « TextRange, 1090• TreeWalker метод firstChild(), 611 метод lastChildO, 611 метод nextNodeO, 612 метод nextSiblingO, 611 метод parentNodeO, 611 метод previousNodeO, 612 метод previousSiblingO, 611 свойство currentNode, 611 свойство expandEntityReference, 611 свойство filter, 611 свойство root, 611 свойство whatToShow, 611 VBArray, 1037 window, 118 имя, 417 метод alert(), 122; 435 метод back(), 436 метод captureEventsf), 437 метод clearlnterval(), 439 метод cleaiTimeout(), 439 метод close(), 441 метод confirm(), 123; 442 метод execScript(), 444 метод find(), 445 метод forward(), 436; 445 метод handleEvent(), 445 метод home(), 446 метод moveByO, 446 метод moveTo(), 446 метод navigate(), 449 метод open(), 450 Предметный указатель 1169
метод print(), 456 метод promptO, 123; 458 метод releaseEvents(), 460 метод resizeBy(), 460 метод resizeTo(), 460 метод routeEvent(), 462 метод scroU(), 463 метод scrollBy(), 465 метод scrollToQ, 465 метод setlnterval(), 467 метод setTimeout(), 471 метод showModalDialogO, 473 метод showModelessDialogO, 473 метод sizeToContent(), 484 метод stop(), 484 window.clipboardData методы, 403 window.extemal методы, 411 window.location, 514 активизация, 349; 375 анкера, 613 даты, 150; 909 документа, 47; 71; 116; 125; 535 изображения, 165; 622 кнопки, 136; 671 набора фреймов, 497 окна, 71; 400 окна документа, 118 определение, 187 ошибки, 972 переключателя, 137 пользовательский, 1009 правила свойство cssText, 825 свойство parentStyleSheet, 825 свойство readonly, 825 свойство selectorText, 825 свойство style, 826 свойство type, 826 связывание, 74 скрытого поля, 709 слоя, 206 события метод initEvent(), 807 метод initKeyEvent(), 807 метод initMouseEvent(), 807 метод initMutationEvent(), 807 метод initUIEvent(), 807 метод preventDefault(), 808 метод stopPropagation(), 809 методы, 760 свойство bubbles, 793 свойство button, 793 свойство cancelBubble, 794 свойство clientX, 797 свойство clientY, 797 свойство currentTarget, 800 свойство data, 766 свойство detail, 802 свойство isChar, 802 свойство keyCode, 794 свойство layerX, 767; 797 свойство layerY, 767; 797 свойство metaKey, 792 , свойство modifiers, 770 свойство originalTarget, 802 свойство pageX, 767; 797 свойство pageY, 767; 797 свойство relatedTarget, 802 свойство screenX, 767; 797 свойство screenY, 767; 797 свойство shiftKey, 792 свойство target, 770; 804 свойство timeStamp, 805 свойство type, 771; 806 свойство view, 807 свойство which, 771 свойство altKey, 792 свойство eventPhase, 802 свойство cancelable, 794 свойство charCode, 794 свойство ctrlKey, 792 создание, 199 списка, 139; 713 ссылки свойство charset, 617 свойство coords, 617 свойство hash, 617 свойство host, 617 свойство hostname, 617 свойство href, 618 свойство hrefLang, 618 свойство Methods, 618 свойство mimeType, 618 свойство name, 619 свойство nameProp, 619 свойство pathname, 617 свойство port, 617 свойство protocol, 617 свойство protocolLong, 619 свойство rel, 619 свойство rev, 619 свойство search, 617 свойство shape, 617 свойство target, 620 1170 Предметный указатель
свойство text, 620 свойство type, 620 свойство urn, 620 свойство х, 621 свойство у, 621 статичный, 149; 224 стиля, 810 строки, 146 фильтра, 856 флажка, 136 формы, 131; 650 функции метод apply(), 1002 метод са11(), 1002 метод toStringO, 1003 метод valueOf(), 1003 свойство arguments, 999 свойство arity, 1000 свойство caller, 1000 свойство lengtt, 1002 целевой, 744 экрана, 71 объект элемента списка, 731 обработчик события onbeforeprint, 485 onbeforeunload, 485 ondragdrop, 486 onerror, 487 onhelp, 487 onload, 488 onmove, 489 onresize, 489 onunload, 490 свойство appCore, 402 clientinformation, 402 clipboardData, 402 closed, 403 components, 405 Components!], 402 controllers, 405 controllers!], 402 crypto, 405 defaultstatus, 405 dialogArguments, 406 dialogHeight, 406 dialogLeft, 407 dialogTop, 407 dialogWidth, 406 directories, 408 document, 410 event, 410 external, 410 frameElement, 411 frames, 412 history, 414 innerHeight, 415 innerWidth, 415 loading, 416 location, 417 locationbar, 408; 417 menubar, 408 name, 417 navigator, 417 offscreenBuffering, 418 onerror, 418 opener, 162; 421 outerHeight, 415; 423 outerWidth, 415; 423 pageXOffset, 423 pageYOffset, 423 parent, 426 personalbar, 408; 428 pkcsll, 405 prompter, 402 returqValue, 428 screen, 428 screenLeft, 429 screenTop, 429 screenX, 429 screenY, 429 scrollbars, 408; 430 scrollMaxX, 430 scrollMaxY, 430 scrollX, 430 scrollY, 430 self, 431 sidebar, 402; 432 status, 122; 432 statusbar, 408; 434 toolbar, 408; 434 top, 434 window, 435 Объектная модель, 48; 69; 196 комбинирование, 227 поколение, 213 типы, 204 Объектно-ориентированная модель, 220 Объектные операторы, 987 Объекты базового языка, 146 встроенные, 193 Оглавление, 64; 525 Ограничивающий прямоугольник, 323 Окно активная область, 415 Предметный указатель 1171
ввода данных, 459 загрузка данных, 454 запроса, 123 изменение размера, 461; 489 имя, 417; 454 методы, 119 модальное, 407 открытие, 450 перемещение, 447 подтверждения, 123; 443 предупреждения, 122 родительское, 156; 394 свойства, 119; 413 создание, 120; 452 ширина и высота, 415 элементы управления, 409 Операнд, 102 Оператор, 87; 102; 975 const, 1033 continue, 954 delete, 987 if, 106 if...else, 107 in, 988 instanceof, 989 mailto:, 660 new, 989 parent, 395 self, 431 switch, 960 this, 990 top, 395 try-catch-finally, 965 typeof, 991 var, 96; 1034 void, 992 with, 958 арифметический, 102; 979 булев, 983 выполнение, 87 дополнения, 147 категории, 975 комплексный, 990 маркированный, 95 3 немедленного выполнения, 88 объектный, 987 побитовый, 986 приращения, 982 присвоения, 96; 981 сравнения, 102; 976 условный, 106 Описание типов документов, 212 Определение даты, 152 кнопки, 775 свойств, 1017 Опции списка, 716 изменение, 719 удаление, 729 Отключение захвата события, 740 фрейма, 396 Открытие документа, 592 окна, 450 Отмена всплывания, 751 Отображение данных, 256 Отправка формы, 142: 656 Отпускание кнопки, 373 Отслеживание события, 746 Отступ, 632; 847 Ошибка сценария, 90; 419 просмотр, 90 п Панель каталогов, 408 управления, 469; 532 Параллельный массив, 927 Параметр, 79 метода, 59 передача, 468 страницы, 854 фона, 603 функции, 109; 999 Пароль, 708 Первый сценарий, 56 Переадресация события, 747; 751 Передача объекта, 141 данных, 140 событий, 739 форм и элементов в функции, 653 Перезагрузка документа, 527 страницы, 55 формы, 665 Переключатель, 684 выбор, 718 длина, 687 установка, 686 Переменная, 95 глобальная, 110; 1005 1172 Предметный указатель
значение, 96 имя, 97 инициализация, 96 локальная, 110 область действия, 111 параметров, 1007 создание, 96 строковая, 869 Перемещение окна, 447 Перенаправление данных, 658 Перетаскивание, 367; 767 Перехват события, 206; 577 Переход к исключительным ситуациям, 968 Печать, 457; 854 Побитовые операторы, 986 Поведение, 211; 295; 774 отключение, 342 текстовых объектов, 134 Поддержка JavaScript, 182 Подокно создание, 422 Подпись, 734 Подсчет дней, 917 Подтверждение, 442 Позиционирование, 844 Поиск в параллельном массиве, 928 данных, 64 строк, 147 циклический, 929 Поколения DOM, 213 Поле, 847 ввода пароля, 708 ввода файла, 735 Полоса прокрутки, 607; 852 Получатель свойств, 1017 Получение свойств стиля, 813 Пользовательская функция, 997 Пользовательский метод добавление, 1015 Пользовательский объект, 1009 Поток выходной, 127 Правило, 824 типы, 827 Предварительная загрузка изображений, 166 Предотвращение всплывания события, 750 Предупреждение, 122; 436; 475 Прекращение выполнения сценария, 600 Преобразование даты, 916 одного изображения в другое, 860 символов, 876 строк в числа, 101; 898 типов данных, 100 чисел в строки, 101; 899 Приемник событя, 225; 298 Приложение Decision Helper, 67; 160 The Evaluator, 191 Принципы совместимости, 192 Принятие решений, 67; 160; 946 Приоритет, 184 операторов, 992 Проверка вычислений, 99 данных, 707 дат, 920 загрузки фреймов, 396 закрытия окна, 404 правильности данных, 143 Программное обеспечение, 52 Прокрутка, 463 изображения, 463 нежелательная, 465 предотвращение, 609 расстояние, 606 страницы, 349; 605 фрейма, 496 Просмотр свойств, 957 Простой документ, 72 Простые решения, 946 Протокол, 522; 572 mailto:, 656 Прототип, 194; 874; 932 Пустой фрейм, 397 Путь, 549 Р Равенство несоизмеримых типов данных, 977 Раздел документа, 85 заголовка, 85 тела, 85 Разделение строки, 884 Размещение сценариев, 83 события, 771 текста, 345 Расширение, 210 Расширенная модель, 205 Расширяемое свойство, 558 Регистр, 147 Регулярное выражение, 880 Рекурсия, 1008 Родительский узел, 77 Предметный указатель 1173
Родительское окно, 156; 394; 571 Ролловер, 166; 168 С Сведения о документе, 569 о файле, 559; 631 Свободное определение типов, 193 Свойства акустические, 855 атрибута, 322 вида и макета документа, 839 границ и полей, 847 диалогового окна, 474 дополнительные, 855 макета документа, 839 позиционирования, 844 полосы прокрутки, 852 события, 738 списков, 851 стиля, 828 страницы и печати, 854 таблиц, 853 текста и шрифта, 832 фона, 846 формы, 132 Свойство, 78; 199; 217 accessKey, 239 all, 241 anchors, 542 attributes, 242 behaviorUrns, 243 canHaveChildren, 244 canHaveHTML, 245 childNodes, 246 children, 248 className, 249 clientHeight, 250 clientLeft, 251 clientTop, 251 clientWidth, 250 complete, 628 contentEditable, 252 cookie, 546 currentstyle, 253 dataFld, 253 dataFormatAs, 253 dataSrc, 253 defaulChecked, 679 dir, 259 disabled, 259 document, 260 filters!], 261 firstChild, 261 height, 263 hideFocus, 264 id, 264 innerHTML, 223; 265 innerText, 265 isContentEditable, 267 isDisabled, 267 isMultiLine, 268 isTextEdit, 269 lang, 269 language, 269 lastChild, 261 length, 270 localName, 270 namespaceURI, 270 nextSibling, 271 nodeName, 272 nodeType, 272 nodeValue, 274 offsetHeight, 274 offsetLeft, 275 offsetParent, 276 offsetTop, 275 offsetwidth, 274 outerHTML, 278 outerText, 278 ownerDocument, 280 nodeValue, 274 parentElement, 280 parentNode, 281 parentTextEdit, 282 prefix, 270 previousSibling, 271 readyState, 283 значения, 283 recordNumber, 284 runtimeStyle, 286 scopeName, 286 scrollHeight, 287 scrollLeft, 288 scrollTop, 288 scrollwidth, 287 sourceindex, 288 style, 289 tabindex, 289 tagName, 291 tagUm, 292 title, 292 type, 661 uniquelD, 293 width, 263 изменение, 354; 388 расширяемое, 558 1174 Предметный указатель
Связывание данных, 285 объектов, 74 Серверный сценарий, 38 Символ преобразование, 876 специальный, 870 Синтаксический анализ, 898 Синхронизация фреймов, 397 Система исчисления, 899 Системные цвета, 831 Скрытие сценария, 180 Скрытое поле, 709 Слой, 206; 566 вложенный, 567 Случайное число, 902 Смещение, 1088 страницы, 424 Событие, 210; 368; 694; 737 всплывание, 749 двунаправленная модель, 225 захват, 337; 437; 576; 740 изменение, 761 клавиатуры, 379; 762 координаты, 768; 776; 798 обработка, 233; 300 обработчик, 80 освобождение, 741 отключение захвата, 740 отмена всплывания, 751 отмена захвата, 382 отслеживание, 746 переадресация, 746 передача, 739 перехват, 577 предотвращение всплывания, 750 приемник, 225; 298 расположение, 771 свойства, 738 создание, 581 типы, 576; 763 Совместимость, 189; 1092 принципы, 192 объектов event, 759 стандартов, 233 Содержимое узла, 221 элемента, 208 Создание атрибута, 579 окна, 120 фрейма, 393 элемента, 580 Сообщение в строке состояния, 406; 432 об ошибке, 91 Сортировка внешних данных, 258 массивов, 940 Составные решения, 947 Специальные символы, 870 Список, 713; 851 именованных узлов, 334 Справочная система, 376; 488 Сравнение значений, 978 моделей событий, 761 Среда разработки, 53 Срок службы, 549 Ссылка, 568; 573; 613 на объект, 75; 121; 157 на событие, 758 на фрейм, 394 на элемент, 215 на элементы управления формы, 652 Старые браузеры, 86; 179; 764 Статичный объект, 149; 224 Стиль, 575 вычисляемый, 813 динамический, 228 категории, 829 получение свойств, 813 свойство, 828 accelerator, 855 background, 846 backgroundAttachment, 846 backgroundColor, 846 backgroundimage, 847 backgroundposition, 847 backgroundPositionX, 847 backgroundpositionY, 847 backgroundRepeat, 847 behavior, 855 border, 847 borderBottom, 848 borderBottomColor, 848 borderBottomStyle, 848 borderBottomWidth, 849 borderCollapse, 853 borderColor, 849 borderLeft, 848 borderLeftColor, 848 borderLeftStyle, 848 borderLeftWidth, 849 borderRight, 848 borderRightColor, 848 borderRightStyle, 848 Предметный указатель 1175
borderRightWidth, 849 marginTop, 850 borderSpacing, 853 markerOffset, 842 borderStyle, 849 marks, 842 borderTop, 848 maxHeight, 842 borderTopColor, 848 maxWidth, 842 borderTopStyle, 848 minHeight, 842 borderTopWidth, 849 min Width, 842 borderWidth, 849 mozBorderRadius, 850 bottom, 844 mozBorderRadiusBottomLeft, 850 captionSide, 853 mozBorderRadiusBottomRight, 850 clear, 839 mozBorderRadiusTopLeft, 850 clip, 839 mozBorderRadiusTopRight, 850 clipBottom, 839 mozOpacity, 850 clipLeft, 839 orphans, 854 clipRight, 839. outline, 850 clipTop, 839 outlineColor, 850 color, 832 outlineStyle, 851 content, 839 outlineWidth, 851 counterIncrement, 839 overflow, 842 counterReset, 840 overflowX, 843 cssFloat, 840 overflowY, 843 cssText, 855 padding, 851 cursor, 840 paddingBottom, 851 direction, 840 paddingLeft, 851 display, 840 paddingRight, 851 emptyCells, 853 paddingTop, 851 filter, 841 page, 854 ( font, 833 pageBreakAfter, 854 fontFamily, 833 pageBreakBefore, 854 fontSize, 833 pageBreaklnside, 854 fontSizeAdjust, 833 pixelBottom, 845 fontStretch, 833 pixelHeight, 845 fontStyle, 834 pixelLeft, 845 fontVariant, 834 pixelRight, 845 fontWeight, 834 pixelTop, 845 height, 845 pixelWidth, 845 imeMode, 855 posBottom, 845 layoutGrid, 841 posHeight, 845 layoutGridChar, 841 position, 846 layoutGridLine, 841 posLeft, 845 layoutGridMode, 841 posRight, 845 layoutGridType, 842 posTop, 845 left, 844 posWidth, 845 letterSpacing, 834 quotes, 835 lineBreak, 834 right, 844 lineHeight, 834 rubyAlign, 835 listStyle, 851 rubyOverhang, 835 listStylelmage, 852 rubyPosition, 835 listStylePosition, 852 scrollbar3dLightColor, 852 listStyleType, 852 scrollbarArrowColor, 852 margin, 849 scrollbarBaseColor, 852 marginBottom, 850 scrollbarDarkShadowColor, 852 marginLeft, 850 scrollbarFaceColor, 852 marginRight, 850 scrollbarHighlightColor, 852 1176 Предметный указатель
scrollbarShadowColor, 852 scrollbaiTrackColor, 852 size, 854 styleFloat, 843 tableLayout, 853 textAlign, 835 textAlignLast, 835 textAutospace, 836 textDecoration, 836 textDecorationBlink, 836 textDecorationLineThrough, 836 textDecorationNone, 836 textDecorationOverline, 836 t^xtDecorationUnderline, 836 textindent, 836 textJustify, 836 textJustifyTrim, 837 textKashidaSpace, 837 textOverflow, 837 textShadow, 837 textTransform, 837 textUnderlinePosition, 837 top, 844 unicodeBidi, 838 verticalAlign, 843 visibility, 843 whiteSpace, 838 widows, 854 width, 844; 845 wordBreak, 838 wordSpacing, 838 wordwrap, 838 writingMode, 838 zlndex, 846 zoom, 844 создание, 582 Стороны прямоугольника, 831 Страница загрузка, 534 контекстно-зависимая, 525 кэширование, 418 перезагрузка, 55 прокрутка, 349; 605 смещение, 424 фон, 603 Страница ветвления, 185 Строка, 146; 868 извлечение части, 887 объекдинение, 146 разделение, 884 состояния, 432 сообщение, 406; 432 Строковые даты, 914 переменные, 869 Стоковый объект прототип, 874 текст, 146 Структура управления, 106 Структурированные данные, 924 Схема узлов, 261 Сценарий, 573 анализ, 58 бессерверный, 42 ветвление, 229 защищенный, 452 исходный код, 57 межбраузерный, 50; 58 отсроченный, 88 серверный, 38 скрытие, 86 создание, 52 Счетчик цикла, 952 т Таблица, 853 истинности оператора И, 984 оператора ИЛИ, 984 стилей, 172; 575; 582; 810 импортированная, 812 Текст возвращение, 590 замена, 345 обтекание, 604 отображение, 59 расположение, 345 Текстовая область, 709; 1090 Текстовое поле, 693 выделение, 704 значение, 701 подстановка в функцию, 701 Текстовый объект, 134; 692 редактор, 53 узел, 73; 583 Текущее время, 472 Тело страницы, 601 Тип браузера, 186 данных, 95; 556 преобразования, 861 события, 576; 763 узла, 217 Точечный синтаксис, 75; 197 Предметный указатель 1177
У Узел, 76; 216 документа, 77 дочерний, 76; 247; 261; 302 замена, 346 методы, 219 родительский, 77 свойства. 217 содержимое, 221 текстовый, 73; 583 типы, 217 Унарный оператор, 975 Универсальная функция, 1009 Универсальное имя ресурса, 356 Универсальный идентификатор ресурса, 323 Управление строками, 147 табличными данными, 254 Управляющая структура, 106; 194; 945 Управляющее выделение, 364 Условие, 950; 951 Условное выражение, 950 Условный оператор, 106 Учет временной зоны, 914 Ф Файл MagicCookie, 547 сведения, 559; 631 Фильтр, 2i0; 261; 374; 856 название, 863 преобразования, 859 статический, 858 Флажок, 677 состояние, 678 Фон, 846 параметры, 603 страницы, 603 цвет, 730 Форма, 132; 560; 650; 921 добавление, 72 изменение атрибутов, 657 отправка, 142; 666; 673 перезагрузка, 665 пример, 561 Формат даты, 915 • Форматирование текста, 892 чисел, 896 Фрейм, 66; 393; 562 дочерний, 156 загрузка, 396 исходный код, 398 оглавления, 501 отключение, 396 отображение/скрытие, 500 прокрутка, 496 пустой, 397 синхронизация, 397 создание, 393 Функция, 88; 109; 996; 997 decodeURI(), 1025 decodeURIComponent(), 1025 encodeURI(), 1025 encodeURIComponent(), 1025 escape(), 1026 eval(), 1027 isFinite(), Ю28 isNaNQ, 1028 Number(), 1028 parseFloat(), 1028 parselnt(), 1028 toStringO, 1029 unescape(), Ю26 unwatch(), 1032 watch(), 1032 анонимная, 997 аргументы, ПО вложенная, 998 вызов, ПО; 1004 глобальная, 1024 параметры, 109; 999 передача параметров, 468 передача форм и элементов, 653 преобразования чисел, 898 просмотра свойств, 957 создание, 997 строковая, 891 универсальная, 1009 Функция-конструктор, 925 ц Цвет, 830 системный, 831 ссылки, 540; 602 фона, 730 Целевой объект, 744 Целое число, 101; 895 Цикл, 105; 108; 951 do-while, 956 for, 951 while, 955 1178 Предметный указатель
выход, 954 продолжение, 954 Циклический поиск, 929 ч Число, 895 извлечение, 898 с плавающей точкой, 101; 895 случайное, 902 форматирование, 896 целое, 895 ш Шестнадцатеричные числа, 897 Шрифт динамическое изменение, 1043 щ Щелчок, 310; 675 э Эквиваленты условных значений, 947 Экземпляр, 197 Элемент а, 613 anchor, 613 area, 643 blockquote свойство cite, 1040 body, 600 br, 1041 свойство clear, 1041 button, 671 fieldset, 668 font, 1042 свойство color, 1042 свойство face, 1044 свойство size, 1044 form, 136 frame,-398; 490; 503 frameset, 497 hr, 1046 свойство align, 1046 свойство color, 1048 свойство noShade, 1048 свойство size, 1049 свойство width, 1049 iframe, 159 img, 622 input, 136; 659 label, 669; 1050 свойство accessKey, 1050 свойство form, 1050 свойство htmlFor, 1050 legend, 668 link, 613 map, 646 marquee, 1051 метод start(), 1055 метод stop(), 1055 обработчик события onbounce, 1055 обработчик события onfmish, 1056 обработчик события onstart, 1056 свойство behavior, 1051 свойство bgColor, 1053 свойство direction, 1053 свойство height, 1054 свойство hspace, 1054 свойство loop, 1054 свойство scrollAmount, 1054 свойство scrollDelay, 1054 свойство trueSpeed, 1055 свойство vspace, 1054 свойство width, 1054 object, 254 optgroup, 733 option, 731 select, 139; 713 selection, 1078 style, 814 вставка, 329 выбор, 585 изменение цвета, 541 расположение при вставке, 329 содержимое, 208 создание, 74; 580 статический, 846 Элемент управления, 132; 306; 408; 651 Я Язык базовый, 46 разметки документов, 38 программирования, 94 Предметный указатель 1179
Если JavaScript умеет это делать, значит, и вам это под силу... Научитесь создавать Web-страницы с динамическим содержимым. Оснастите свои документы внешне присоединяемыми каскадными таблицами стилей. Добейтесь эффективного интерактивного взаимодействия с пользователями. Улучшите свои проекты новыми средствами форматирования, внедряемыми моделями, Java-аплетами и даже XML-данными. Воспользуйтесь советами нового в команде Дэнни Гудмана эксперта по JavaScript — Майкла Моррисона и найдите свой стиль написания сценариев, с помощью которого ваши Web-страницы станут непревзойденными шедеврами. Как начинающие, так и опытные программисты найдут в этом полностью переработанном издании много нового и полезного, того, чего нет в других источниках В этой книге вы найдете подробное описание возможностей JavaScript! • Быстрое знакомство с основами создания сценариев и краткое описание основных средств языка • Изучение концепций JavaScript и DOM с помощью авторского приложения The Evaluator • Применение новейших Web-технологий — XHTML, DOM, CSS и XML — для создания привлекательных и эффектных страниц Calculate Resistor Values from Color Codes Поразите 1 посетителей Web-узла программируемыми формами и изображениями • Управление межбраузерными DHTML- приложениями, максимально эффективными в Internet Explorer 6, Mozilla, Safari и других современных браузерах • Включение в содержимое страниц пользовательских объектов, XML-данных и средств других клиентских технологий • Индивидуальный подход к разработке и подготовке проектов JavaScript, удовлетворяющих запросы самой широкой аудитории пользователей GiantCo Sales Results 2000 На компакт-диске: • Дополнительные 22 главы на русском языке, в которых рассматриваются новые объекты DOM, JavaScript и XML, динамический HTML, методики проверки данных, надстройки, средства защиты информации, разработки и отладки профессиональных Web-приложений и многое другое • Более 300 готовых к использованию примеров сценариев, демонстрирующих принципы управления объектами DOM и JavaScript • Девять полноценных приложений, написанных на JavaScript - , к - 0 4** http://www.wiley.com/compbooks http://www.dialektika.com Систег<м«е требования: ctv гри ожен *е Д Уро-ень: от на и ающих до о ы х геол- зова елей Ка ФИ" V.'eb-p р 6or»a/Ja» " ipt И ледлекмиид w <w.dialektiLa.com ©WILEY wilcy.com