JavaScript. Энциклопедия пользователя
 966-7992-00-04 [PDF]

  • 0 0 0
  • Suka dengan makalah ini dan mengunduhnya? Anda bisa menerbitkan file PDF Anda sendiri secara online secara gratis dalam beberapa menit saja! Sign Up
File loading please wait...
Citation preview

тм



Ричард Вагнер, Аллен Вайк



Исчерпывающее руководство об основном языке сценариев для создания полнофункциональных Web-приложений Исследуется связь JavaScript с другими Web-технологиями как со стороны клиента, так и со стороны сервера



^ Jr



Своевременные решения



Объектно-ориентированная методология и ее воплощение в "JavaScript Фундаментальные основы языка JavaScript Операторы, управляющие структуры, функции и базовые объекты Исчерпывающий анализ объектной модели документов Объекты, используемые со стороны клиента и со стороны сервера Помещение на Web-страницы эффектов, характерных для динамического HTML Устойчивая работа сценариев в браузерах Netscape Navigator и Microsoft Internet Explorer



Сопровождающий CD-ROM Исходные тексты всех примеров, рассмотренных в книге Полезные инструментальные средства независимых разработчиков Многое другое



SAMS



PUBLISHING www.diasoft.kiev.ua



Аллен Вайк и др. JAVASCRIPT. ЭНЦИКЛОПЕДИЯ ПОЛЬЗОВАТЕЛЯ



то ргово-издательский дом



1 DiaSoft Киев • Москва • Санкт-Петербург 2001



JavaScript



тм



THIRD EDITION R. Allen Wyke, et al.



SAMS A Division of Macmillan USA 201 West 103rd Street Indianapolis, Indiana 46290



UNLEASHED



энцикло торгово-издательский торгово-издательски и ним дом



DiaSoft —-



Основана в 1996 г.



Аллен Вайк и др.



avaScript Киев • ООО "ТИД" ДС" . 2001



тм



УДК 004.43(031) ББК 32.973.26-018.1 В 14 ВАЙК Аллен и др. В14 JavaScript. Энциклопедия пользователя: Пер.с англ./Аллен Вайк.— К.: ООО "ТИД" ДС", 2001.— 480с. ISBN 966-7992-00-04 Книга JavaScript. Энциклопедия пользователя является наиболее полным учебным и справочным руководством повеем версиям языка JavaScript, включая JavaScript 1.5 и JScript 5.O. На сегодняшний день JavaScript представляет собой самый распространенный язык для написания сценариев, обеспечивающих поддержку интерактивного содержимого Web-страниц. Книга охватывает широкий спектр вопросов, начиная с основ языка и заканчивая сложными вопросами практического применения технологий Web-дизайна. Подробно рассматриваются: взаимодействие JavaScript и HTML; типы данных, операции, выражения и операторы; основы объектно-ориентированной методологии и ее реализация в JavaScript; объекты со стороны клиента и сервера; DHTML; технологии написания устойчивого и надежного кода; методика отладки кода. Особое внимание в книге уделяется вопросам достижения безопасности Web-приложений. Книга изобилует множеством практических примеров, которые покрывают всю специфику разработки Web-сайтов с использованием JavaScript.Справочник по базовым языковым объектам превращает книгу в истинное настольное руководство. Сопровождающий CD-ROM содержит исходные коды всех примеров, рассмотренных в книге, а также множество другой полезной информации. JavaScript. Энциклопедия пользователя рассчитана на широкий круг разработчиков Web-приложений. Учебное издание



ББК 32.973.26-018.1



ВАЙК Аллен и др. JAVASCRIPT. ЭНЦИКЛОПЕДИЯ ПОЛЬЗОВАТЕЛЯ Головний редактор Ю.Н.Артеменко Верстка Г.А.Булавка Головний дизайнер О.А.Шадрт Здано на складання 20.07.2001. Шдписано до друку 20.09.2001. Формат 84x108/16. Патр офсетний. Гарнггура Тайме. Друк офсетний. Умовн.друк.арк. 34,80. Обл.-вид.арк. 34,80 Тираж 2000 прим. Замовлення № 1-158. ТОВ "ТВД" ДС", 04053, Кшв-53, вул. Артема 25, а/я 100, тел./факс (044) 212-1254. e-mail: [email protected], http://www.diasoft.kiev.ua. Свщоцтво про внесения суб'екта видавничо'1 справи до Державного реестру видавщв, вигхтвниюв i розповсюджувач!в видавничо'1 продукцн: сер!я — ДК, №558 вщ 09.08.2001р. Отпечатано в соответствии с качеством предоставленных диапозитивов на ОАО «Белоцерковская книжная фабрика» 09117, г. Белая Церковь, ул. Леся Курбаса, 4



Authorized translation from the English language edition published by Sams Copyright ©2001 All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Russian language edition published by DiaSoft Publishing. Copyright © 2001 Лицензия предоставлена издательством Sams Corporation, подразделение Macmillan Computer Publishing. Все права зарезервированы, включая право на полное или частичное воспроизведение в какой бы то ни было форме. ISBN 966-7992-00-4 ISBN 0-672-31763-Х (англ.)



© Перевод на русский язык. ООО "ТИД" ДС", 2001 © Sams Corporation, 2001 © Оформление. ООО "ТИД" ДС", 2001 Гигиеническое заключение № 77.99.6.953.П.439.2.99 от 04.02.1999



Оглавление Введение Часть I. Знакомство с JavaScript Глава 1. JavaScript и World Wide Web



13 15 16



Знакомство с JavaScript 16 Десять заповедей JavaScript, которые должен знать каждый создатель сценариев 17 JavaScript можно внедрить в HTML 17 JavaScript зависит от среды 18 JavaScript — интерпретируемый язык 19 JavaScript — слабо типизированный язык 19 Javascript —объектно-ориентированный язык .... 19 JavaScript — язык, управляемый событиями 20 JavaScript — это не Java 20 JavaEicript —многофункциональный язык 20 JavaSicript — развивающийся язык 20 Сферы использования JavaScript 20 Четыре фазы развития World Wide Web 21 Фаза 1. Символьный гипертекст 21 Фаза 2. Графически-ориентированные статические HTML-документы 21 Фаза 3. Динамические HTML-документы 21 Фаза 4. Активные HTML-документы 22 Среда разработки Web-приложений 22 Клиентская часть 23 Серверная часть 25 Что можно сделать при помощи JavaScript? 27 Клиентские приложения 27 Проверка допустимости данных 27 Создание интерактивных форм 27 Клиентские таблицы поиска 27 Поддержка состояния 27 Работа с Java-аплетами, элементами управления ActiveX и подключаемыми модулями 27 Поддержка JavaScript со стороны браузеров 28 Netscape Navigator 28 Microsoft Internet Explorer 28 Другие браузеры 28 Сравнение JavaScript и JScript 28 Что такое VBScript? 28 Программирование в VBSript 30 Резюме .. ..31



Глава 2. Совместная работа JavaScript и HTML Основы HTML Текущая ситуация Основы HTML Структура HTML-документа Основное об атрибутах Внедрение JavaScript в HTML Атрибуты дескриптора



S#160;

S#160;





http : //www . samspublishing . com



и ' • Q liiiirti .м •' • -



Adobe Acfobtit Reader **.0 lor Macintosh ReaclMo



mstaHing) Acfobat Reader 4.0 tof Macintosh



ККШКЗЩ] ii^i,.-:''*...ml 1 сей ||»;„, j



РИСУНОК 1.10. Просмотр файла PDF при помощи подключаемого модуля.



Клиентские языки сценариев РИСУНОК 1.9. У/ио это — Java-аплет или элемент управления ActiveX?



РЕСУРС Информация по ActiveX может быть найдена в Internetцентре Microsoft no адресу http://www.microsoft.com/ com.



Последние штрихи магии клиентской части завершают клиентские языки сценариев. На сегодняшний день основным таким языком является JavaScript, тем не менее компания Microsoft выдвигает собственную альтернативу — VBScript. Наибольшей популярностью VBScript пользуется в кругу разработчиков на Visual Basic. В конце главы можно найти краткое сравнение возможностей JavaScript и VBScript.



Подключаемые модули Netscape



Серверная часть



Подключаемые модули (plug-ins) — это несколько другая технология, тем не менее представляющая собой клиентское расширение Web-браузера. Подключаемые модули существенно расширяют возможности браузера Netscape Navigator, связанные с поддержкой дополнительных типов данных. В частности, подключаемые модули применяются для вывода на экран файлов различных МШЕ-типов (multipurpose Internet mail extension, многоцелевые почтовые расширения). После запуска Netscape Navigator начинает поиск подключаемых модулей в папке program\plugins с целью их регистрации. Вызов подключаемых модулей выполняется по мере необходимости, когда обнаруживается файл МШЕ-типа. После инсталляции подключаемые модули становятся добавочными модулями браузера и совершенно не нуждаются во взаимодействии с пользователем для своего запуска. В действительности они необходимы для таких мультимедиа-данных, как звук, видео, графика. На рис. 1.10 показан подключаемый модуль, позволяющий просматривать файлы Adobe Acrobat в рамках



Серверная часть среды разработки Web-приложений состоит из собственно Web-сервера плюс расширения серверного программного обеспечения. Как будет показано несколько позже, эти расширения могут принимать различные формы и работать с различными технологиями. На рис. 1.11 показаны взаимосвязи внутри серверной части.



Серверы Web-сервер загружается после отправки со стороны клиента запроса на требуемые HTML-документы, после чего возвращает их для просмотра. Программное обеспечение сервера — это приложение, выполняющееся на машине с установленным протоколом TCP/IP. Среди наиболее популярных серверов находятся Netscape Enterprise Server (NES), Microsoft Internet Information Server (IIS) и Apache. Серверные расширения Собственно Web-сервер обеспечивает передачу статических HTML-страниц клиенту при запросе, а также мно-



Знакомство с JavaScript Часть I



жество других функций. С другой стороны, некоторые серверные расширения обеспечивают возможности, не реализованные в самом сервере. К таким возможностям относятся CGI, серверные API, JavaScript и Java. Клиенты Расширения



доступа со стороны сервера потребовалось бы создать библиотеку DLL, а не отдельный выполняемый модуль ЕХЕ. Использование серверных API обладает своим преимуществом — потоки оказываются гораздо более эффективными по сравнению с CGI-программами. CGI требует, чтобы для каждого клиентского запроса выполнялся отдельный экземпляр программы. Это приводит не только к большим издержкам, но также и к ограничению максимального объема совместно используемых данных. Недостаток использования серверного API заключается в том, что полученное решение окажется специфическим для конкретного сервера. Созданная ISAPI DLL не будет работать с сервером Netscape. Разумеется, если работа связана постоянно лишь с одним сервером, упомянутый негативный момент сводится на нет. Серверный JavaScript



РИСУНОК 1.11. Серверная часть.



CGI Интерфейс общего шлюза (CGJ, Common Gateway interface) представляет собой стандарт де-факто для организации взаимодействия внешних программ с Webсерверами. Запуская CG F-программы и сценарии на сервере, можно генерировать динамически создаваемое содержимое и отображать его пользователю. Типовой сценарий заключается в генерации запроса из формы HTML и отправка его серверу. Запрос запускает CGI-программу или сценарий, размещенный в специальном каталоге на сервере. CGl-программа обрабатывает запрос и возвращает HTML-документ с результатами. CGI-программа может разрабатываться на любом языке программирования: Java, C++, Visual Basic, PHP, т.е. на том, что способно продуцировать код, могущий выполняться на Web-сервере. В мире Unix CGI-сценарии принято составлять на языках, подобных Perl или языкам командных оболочек Unix. Серверные API Другой способ интеграции с сервером предполагает использование его собственного интерфейса прикладного программирования (API, Application Programming Interface). Два наиболее используемых API такого рода - Netscape Server API (NSAPI) и Misrosoft Internet Server API (ISAPI). API обеспечивают более тесную интеграцию с сервером. Например, в случае Windows для



Повышенное внимание к JavaScript связано с возможностями, реализуемыми языком на стороне клиента. Однако, с не меньшим успехом JavaScript можно использовать и в качестве серверного инструментального средства разработки сценариев. Как и следовало ожидать, первой средой подобного рода является Netscape. Среда Netscape SSJS (Server-Side JavaScript) позволяет использовать сценарии для построения Web-приложений, управляемых Netscape-сервером. Кроме того, существует несколько серверных расширений для языка JavaScript, которые обеспечивают дополнительные возможности генерации динамического HTML, взаимодействия с клиентом, доступа к внешним файлам на сервере и подключения к базам данных SQL (LiveWire). Следует отметить, что в ответ компании Netscape, Microsoft поддерживает JScript в качестве серверного языка сценариев в рамках Active Server Pages. Java За последние месяцы Java существенно сдала свои позиции на серверной стороне. Компания Sun выпустила технологию под названием Java Server Pages (JSP), которая призвана быть конкурентом ASP и SSJS. В настоящее время компании Sun и Netscape объявили о создании своего рода союза, именуемого iPlanet, цель которого заключается, помимо прочего, в интеграции JSP и SSJS в единую технологически мощную среду. Вы, наверное, слышали о Java-сервлетах (Java Servlets). Сервлеты представляют собой небольшие компоненты, более всего похожие на элементы управления ActiveX в среде ASP, которые могут активизироваться как готовые страницы либо использоваться для построения страниц. Это позволяет разработчикам направить накопленные знания Java (который намного проще в изу-



JavaScript u World Wide Web Глава 1



чении, нежели С) на построение быстродействующих, надежных, не зависящих от платформы компонентов, предназначенных для создания страниц.



Что можно сделать при помощи JavaScript? После краткого знакомства с технологиями разработки Web-приложений самое время посмотреть на роль клиентской части JavaScript в Web-приложениях.



Клиентские приложения JavaScript можно использовать для разработки полного клиентского приложения. Хотя JavaScript и не столь всеобъемлющий язык, каковым является Java, тем не менее, он проявляет существенные возможности при работе с дескрипторами HTML и связанными с ними объектами. Одно из наиболее известных приложений JavaScript, h Idaho Design's ColorCenter (http://www.hidaho.com/c3), показано на рис. 1.12. Данное приложение применяется для выбора цветов элементов, видимых в браузере, с возможностью их предварительного просмотра в отдельном фрейме. Создание аналогичного приложения с помощью Java сопряжено с гораздо большими сложностями, связанными с необходимостью взаимодействия с HTML. Очевидно, что в отдельных случаях JavaScript обеспечивает практически идеальную основу для разработки приложений.



ляются ли значения, введенные пользователем, корректными, или, скажем, соответствуют ли они требуемому формату. Гораздо эффективнее провести проверку данных в JavaScript, нежели передавать на сервер незавершенные данные. Подобного рода подход эффективен не только для пользователя, вводящего данных, но также и для сервера. При этом появляется уверенность, что передаваемые на обработку серверу данные являются полностью корректными.



Создание интерактивных форм JavaScript также используется для "оживления" форм HTML. Одна из задач оживления связана с проверкой достоверности данных. Другая предполагает реализацию дополнительных возможностей, недоступных в HTML, как то поддержка информации в строке состояния, открытие второго окна браузера для отображения, скажем, справочной информации и т.п.



Клиентские таблицы поиска Помимо проверки достоверности данных, один из способов уменьшения потребности доступа к серверу заключается в использовании JavaScript для генерации и поддержки клиентских таблиц поиска. Следует помнить, что в таком случае данные должны встраиваться в сам HTML-документ, поэтому использование таблиц поиска должно сводится к небольшим информационным базам данных, предназначенным только для чтения.



Поддержка состояния



гг :|Choose colors from the palette below. Select Background, Text, Link hve Link. Visited Link or Texture above to set the corresponding colcTE/textures. The current link colors arc shown on the right. The current BQDYtagis shown below:



isit texture and graphics sites by selecting them from the drop-down list above and clicking Go, " visiting a site, collect images by clicking the right mouse button (Mac users click and hold) and el':ctmg "Copy this Image Location" from the pop-up menu. Then click on the text entry box ne;rt to Add button, and paste the image location there (Ctrl-v in Windows). Finally, click Add to add the to your collection. (This is easier than it sounds I) ColorCenter will remember your image selections and display them under Textures whenever you return. is a beta version of ColorCenter. Please letrtie



iwifyou encounter any bugs or othe



РИСУНОК 1.12. hldaho Design's ColorCenter.



Проверка допустимости данных JavaScript обеспечивает для Web-разработчиков возможность выполнять проверку допустимости данных, вводимых пользователем, без необходимости обращения к серверу. Внутри кода JavaScript можно определить, яв-



В Web-среде, не поддерживающей концепцию состояния, JavaScript применяется для поддержки состояния при обмене между сервером и клиентом. Основной способ поддержки состояния связан с использованием наборов cookies (информации, сохраняемой браузером на стороне клиента). JavaScript обеспечивает как поиск, так и хранение cookie-наборов на клиентской части. Более детальная информация по работе с cookies может быть найдена в главе 30.



Работа с Java-аплетами, элементами управления ActiveX и подключаемыми модулями По мере развития JavaScript, возрастают возможности работы с клиентскими расширениями, включая Javaаплеты, элементы управления ActiveX и подключаемые модули Netscape. Несложно получить доступ к свойствам объектов Java и ActiveX, равно как и запускать их методы. Точно так же несложно определить, установлен ли конкретный подключаемый модуль. Обладая подобной возможностью, JavaScript становится своего



Знакомство с JavaScript



Часть I



рода "клеем", соединяющим вместе HTML, аплеты и клиентские расширения.



(JavaScript 1.4), Opera (JavaScript 1.1), Be's NetPositive 2.1 (экспериментальная версия).



Поддержка JavaScript со стороны браузеров По сравнению с другими приложениями браузеры относительно небольшие части программного обеспечения, однако постепенно они превращаются в мощные приложения, воплощающие в себе все достижения Webтехнологий. Браузер — это окно в Web, поэтому каким бы потенциалом на обладал бы JavaScript, однозначно плохо, если браузер не обеспечивает поддержку этого языка. Ниже будут рассматриваться особенности поддержки JavaScript в доступных на сегодняшний день браузерах. Поскольку JavaScript — язык интерпретируемый и внедряемый в HTML-документы, он всецело зависит от работы программного обеспечения браузера. Устаревшие браузеры не знают, что делать с таким кодом, и попросту проигнорируют его.



Netscape Navigator К середине 90-х годов компания Netscape стала одной из самых влиятельных в Web-индустрии. Она не только открыла для рынка различные технологические нововведения, но и объединилась с другими лидерами индустрии, такими как Sun, имея целью продвижение различных технологий в передние ряды Web. Поскольку разработчиком J a v a S c r i p t является Netscape, вполне можно ожидать, что наилучшим в плане поддержки языка сценариев станет именно браузер Navigator. Navigator 2.0 был первым браузером, поддерживающим JavaScript. Выпущенные позже версии привнесли важные усовершенствования в сам язык. Поскольку Navigator был перемещен в Mozilla.org, т.е. в зону Open Source (открытого исходного кода) Netscape, можно быть уверенным, что разработчики со всего мира в конечном итоге создадут практически идеальный браузер. На рис. 1.13 показана бета-версия Mozilla (Netscape Navigator 5) с отображенной начальной страницей Mozilla.org.



Microsoft Internet Explorer Microsoft Internet Explorer 3.0 — первый браузер, созданный другой компанией, включающий в себя поддержку JavaScript. Более ранние версии Internet Explorer не обладают поддержкой JScript, т.е. реализации JavaScript от компании Microsoft.



Другие браузеры На момент написания книги существовало лишь три браузера, поддерживающих JavaScript: Sun's Hotlava 3.0



I



JilP-T*^ M oiifj a 3SYw-v



j -!.:,• | |I



!,K.m№.-i [)'j-i



. : ,| f !



mozillrj.



IIIUi.1 2 6 . fanu ai У 3 ОЦ! ,



Milestone 13 Released M13is our Alp: la release. It should be fuucbitul encvigli for evctydaj'use by testers so we encourage you te use it dafly and find ax many bugs as possible is we wcrfc to release a beta. Use ЬцваПд lo report fcugs. Open Source С rypto Announced Thaaks to related US export regulations, we can now host security and ctyptographie code. F«rmore detail», see aur



РИСУНОК 1.13. Mozilla/Netscape Navigator 5.



Сравнение JavaScript и JScript Как упоминалось ранее, JavaScript — не единственный язык сценариев, доступный в Web. На этой арене могут выступать еще два участника: JavaScript/JScript и VBScript. Хоть данные языки и отдалились от действительно конкурентно-способных языков (создается впечатление, что на данный момент они просто дополняют друг друга), все же нелишним будет сравнить все достоинства и недостатки JavaScript и VBScript. Ниже рассматривается, что есть VBScript, как он соотносится с JavaScript, и для примера приводится простое VBScriptприложение. ПРИМЕЧАНИЕ



Последние исследования показывают, что количество Web-сайтов, использующих VBScript, составляют незначительную часть в общем числе сайтов, поддерживающих JavaScript.



Что такое VBScript? VBScript представляет собой язык сценариев для Web, разработанный компанией Microsoft, полностью параллельный языку JavaScript. Все, что находится в основе VBScript, существенно отличается от первоистоков JavaScript. В то время как JavaScript создавался практически "с нуля", слабо основываясь на C++ и Java, VBScript принадлежит к языковому семейству Visual Basic. Среди членов данного семейства: V i s u a l Basic распространенный язык п р о г р а м м и р о в а н и я для Windows, Visual Basic for Applications — макроязык для Microsoft Office и других приложений. Если когда-либо доводилось разрабатывать программное обеспечение на



JavaScript u World Wide Web Глава 1



V i s u a l Basic, гораздо быстрее получится освоить VBScript. ПРИММАНИЕ Наиболее актуальная информация по VBScript находится на сайте Microsoft по адресу http:// www.msdn.microsoft.com / scripting.



Встроенный язык HTML Как и JavaScript, VBScript является языком написания сценариев, внедренным в HTML-файлы. Подобно JavaScript, VBScript использует дескриптор



Самое интересное, что можно почерпнуть из приведенного выше примера, так это то, что синтаксис двух языков совершенно одинаков. Если изменить параметр type на "text/javascript", результат останется тем же. Объектная модель Одним из наиболее важных факторов при сравнении JavaScript и VBScript является идентичная базовая объектная иерархия, хотя в других версиях могут существовать и различия. Для Web-разработчика, использующего оба языка, это — весьма приятный сюрприз, поскольку гораздо проще использовать синтаксически разные языки, нежели принципиально различные парадигмы. Преобразование кода JavaScript в код VBScript или наоборот, как правило, носит построчный характер. В этих двух языках написания сценариев идентичны не только объектные модели, но также и способ работы с HTML-объектами. Подобно JavaScript, VBScript может реагировать на события, генерируемые HTML-объектами. Например, в следующем примере после нажатия кнопки Convert (листинг 1.2) все буквы текста, введенного в поле myText, преобразуются в прописные.















Та же страница, но с использованием VBScript, выглядит следующим образом: Листинг 1.3. Пример на VBScript.















Более сложные типы данных На первый взгляд может показаться, что возможности работы с типами данных в VBScript существенно ограничены. Но это лишь кажется, и причина состоит в том, что VBScript имеет только один тип данных — variant. При дальнейшем знакомстве с VBScript станет ясно, что поддержка типов данных здесь оказывается гораздо мощнее, нежели в JavaScript. Тип variant содержит информацию о значении, с которым он работает, поэтому в различных ситуациях имеется возможность запросить этот тип данных. Иными словами, если переменная типа variant используется как строка (см. следующий пример), VBScript рассматривает ее (myVar) как строковое значение.



Листинг 1.2. Пример на JavaScript.



myVar = "Stringl" + "String2"







Рассмотрим пример VBScript-функции. Подпрограмма showTextQ вызывает функцию getText(), которая возвращает значение текстового объекта TextField:



В JavaScript определен только один процедурный тип — метод (также называемый функцией), в котором ключевое слово function используется вне зависимости от того, возвращается или нет значение в вызываемую процедуру.



Программирование в VBSript Для поверхностного ознакомления с программированием в VBScript воспользуемся простейшим примером. В листинге 1.4 выполняется умножение двух значений, введенных пользователем, и отображение результата в диалоговом окне предупреждения: Листинг 1.4. Пример программы на VBScript.



Wizard



Stump the Wizard

Without connecting to a. backend server or



JavaScript u World Wide Web Глава 1 using a Java applet, the Browser Wizard will multiply the two numbers . . .



First Number:



Second Number:



"



Вызов функции JavaScript... Функции JavaScript исключительно просты в использовании! Вот и все, что было.



./ i



РИСУНОК 5.5. Вызов функции в JavaScript.



_



Базовое подмножество языка JavaScript Часть II



Начав с главного сценария, JavaScript, как обычно, выполняет первую строку, а затем попадает на вызов функции disp!ayMessage(). Выполняется поиск функции в памяти и переход на ее первую строку. После вывода на экран фразы Функции JavaScript исключительно просты в использовании! отображается разрыв строки. Как только функция завершается, выполнение программы возобновляется с точки, где она приостановилась по причине обращения к функции. Как видно на рис. 5.5, каждая строка текста отображается в определенной последовательности. Если у вас громоздкая программа, несколько раз выводящая сообщение на экран, вызовы функции можно вставить в любых требуемых местах. Если позже потребуется изменить текст сообщения, это делается лишь в одном месте. Поменяйте его внутри тела функции, и приложение полностью обновится. Преимущества использования функций подробно описываются в главе 8.



Резюме JavaScript сделал серьезный взнос в набор инструментальных средств Web-разработчика. Именно в этом языке доступны многие вещи, кажущиеся невозможными для CGI, подключаемых модулей и Java. JavaScript обеспечивает взаимодействие с пользователем во время просмотра HTML-документа.



Сценарии помещаются непосредственно в HTMLдокументы и обрамляются парой дескрипторе»



После исследования кода, представленного в листинге 6.1, важно понять, в какой момент увеличивается значение переменной i — перед или после вычисления выражения. В первом примере переменная result получает первоначальное значение i плюс 1. Во втором примере результат устанавливается равным первоначальному значенигс i до выполнения инкремента i. Два следующих примера работают аналогичным образом, однако применительно к операции декремента. Результаты вычислений этих четырех примеров показаны на рис. 6.2. Хотя это может показаться и ненужным, рассмотренные особенности принесут несомненную ПОЛЬЗУ при записи повторяющихся частей сценария. Данная тема освещается в главе 7. Унарная операция отрицания (-) применяется в случаях, когда требуется заменить положительное значение на отрицательное и наоборот. Она названа унарной, т.к. работает только с одним операндом. Если, например,



•ЛИЯ РИСУНОК 6.2. Операции инкремента и декремента из



J



листинга 6.1.



Противоположность также истинна, т.е. при отрицании отрицательного числа результат будет положительным. В обоих примерах операция отрицания не изменяет значения переменной х, которое остается равным 5. Операция взятия по модулю обозначается знаком процента (%). Найти модуль двух операндов означает найти остаток после деления первого операнда на второй. В примере х = 10 % 3 переменная х получит значение 1, поскольку результатом деления 10 на 3 будет 3 с остатком 1. При помощи операции взятия по модулю можно легко определить, что одно число является множителем другого: при этом модуль этих двух чисел будет равен 0. Это истинно, например, для выражения х = 25 % 5. 25 разделить на 5 равно 5 без остатка, значит х будет равно 0. ПРЕДУПРЕЖДЕНИЕ В ряде случаев Netscape Navigator возвращает неправильные значения, когда имеет дело с дробями. Например, 10/3 должно вернуть 3 '/ 3 . В окне консоли Netscape в качестве результата вычисления 10/3 отображается 3.3333333333333335. Небольшая погрешность в шестнадцатом знаке после десятичной точки связана со способом, по которому дроби хранятся в памяти компьютера. Microsoft Internet Explorer решает эту проблему, отображая только 14 знаков после запятой. В этом случае результатом того же вычисления будет 3.33333333333333.



Операции сравнения Операции сравнения используются именно для сравнения выражений. Выражения, которые используют one-



Базовое подмножество языка JavaScript Часть II рации сравнения, отвечают на вопрос, связанный с двумя значениями. Ответом может быть true или false. Два знака "равно" (==) обозначают операцию равенства. Использовать операцию равенства между двумя операндами — означает определить, являются ли значения этих двух операндов равными. Листинг 6.2 демонстрирует способ отображения результатов при выяснении равенства двух переменных. Листинг 6.2. Использование операции равенства.



Onepawm сравнения







Необходимо убедиться, что при написании программы используется именно требуемая операция. Еще раз следует подчеркнуть, что операция равенства (==) проверяет, являются ли два значения равными, тогда как операция присваивания (=) устанавливает значение переменной. В случае использования не той операции интерпретатор JavaScript даст об этом знать. На рис. 6.3 показаны результаты выполнения кода из листинга 6.2. В табл. 6.1 приведен список всех операций сравнения. Таблица 6.1. Операции сравнения. Операция



Описание Операция равенства. Возвращает true, если операнды равны между собой.



!=



Операция неравенства. Возвращает true, если операнды не равны между собой. Операция "больше". Возвращает true, если значение левого операнда больше значения правого операнда. Операция "больше либо равно". Возвращает true, если значение левого операнда больше либо равно значения правого операнда.



РИСУНОК 6.3. Операция равенства из листинга 6.2. Операции сравнения обычно используются в JavaScript для принятия решений. Они помогают выбирать путь, по которому будет следовать сценарий. Более подробно эта темя рассматривается в главе 7. ОПЕРАЦИИ СРАВНЕНИЯ В РЕАЛИЗАЦИИ JAVASCRIPT 1.2 В NAVIGATOR До появления JavaScript 1.1 язык был очень терпим к сравнению операндов различных типов. Например, при сравнении числа 7 со строкой "7" JavaScript сначала преобразовывал, или приводил, операнд строки к числу и затем выполнялось сравнение. Для примера с 7 и "7", операнды считались равными. В JavaScript 1.2 программист должен сначала преобразовать строку в числовую форму либо число в строку. Если этого не сделать, JavaScript никогда не скажет, что они равны. Листинг 6.3 показывает способ сравнения строки и числа, который возвращает одни и те же результаты для всех версий JavaScript. На рис. 6.4 приведена реакция JavaScript 1.2 на три различных сценария. Листинг 6.3 может запускаться только в браузерах, поддерживающих JavaScript 1.2, например, в Netscape Navigator 4.0-4.04. Листинг 6.3. Тестирование различных версий JavaScript.



cpasHeHra











Строковые операции Набор строковых операций, доступный в JavaScript, включает все операции сравнения и операцию конкатенации (+). При помощи операции конкатенации строки соединяются вместе в одну длинную строку (см. листинг 6.4). Листинг 6.4. Конкатенация строк.



JavaScript Unleashed











JavaScript 1.0и 1.1 x == 3 true у =="7": true JavaScript 1.2 x == 3: false у =="7"; false JavaScript 1.3 и выше x--3 true у == "7": true Универсальный код для всех версий. х - 0 == 3: true "" + у == "7". true



1



Ё



•-. i ;



РИСУНОК 6.4. Сравнение строк и целых чисел из листинга 6.3.



Сначала сценарий выполняет инициализацию трех переменных, хранящих три части Web-адреса. Затем все три части соединяются вместе и разделяются необходимыми точками, присутствующими во всех Web-адресах. Далее выполняется проверка, содержит ли sumOfParts определенный адрес Internet. Рисунок 6.5 отражает тот факт, что JavaScript при сравнении строк учитывает регистр символов. Сравне-



Базовое подмножество языка JavaScript Часть II



ние выполняется слева направо, по ASCII-кодам каждого символа в обеих строках. Если все коды соответствуют друг другу, строки равны. Все прописные буквы имеют коды, меньшие, чем их эквиваленты в нижнем регистре, потому и последнее сравнение в листинге 6.3 возвращает true.



Part a is equal to "www". Part b is equal to 'company*. Part с is equal to "con)'. Is sumQfParts equal to WWW.COMPANY.COM? false Is sumQfParts equal to www.cooipany.com? tme IssumOfParts greater than WWW, COM PAN Y.CQM?tme



РИСУНОК 6.5. Результат выполнения кода излистинга 6.4.



Условные операции Две операции ? и : используются для формирования условных выражений. Эти условные операции выполняют те же действия, что и оператор if. Условное выражение возвращает одно из двух значений, в зависимости от логического значения какого-то выражения. Например, следующее условное выражение будет сообщать пользователю; что он — миллионный посетитель страницы:



var resultMsg = (numHits = 1000000) ^щитом!" : "На щите."; alert(resultMsg);



? "Со



При условии, что numHits равен 1000000 в любом месте программы, это выражение возвращает строку "Со щитом!"; в противном случае - "На щите.". Вторая строка приведенного примера отображает результат для пользователя при помощи функции alertQ. Условное выражение может применяться для возврата данных любого типа, например, number или boolean. Следующее выражение возвращает строку или число в зависимости от значения useString: var result = useString ? "семь" document.write(result);



: 7;



Булевы операции Булевы операции (также называемые логическими) используются в дополнение к выражениям, возвращающим логические значения. Действие этих операций проще понять, изучив их использование совместно с операциями сравнения. Таблица 6.2 содержит описание трех булевых операций. Приведены примеры с синтаксисом expressioni [operator] expression2 и с [operator]expression.



Операция typeof Операция typeof возвращает тип данных, хранящихся в операнде в текущий момент времени. Это оказывается особенно полезным при выяснении, была ли определена переменная. Рассмотрим следующие примеры: typeof unescape возвращает строку ^'function", typeof undeflnedVariable возвращает строку "undefined".



Таблица 6.2. Булевы операции. Операция



Описание



&&



Логическая операция И (конъюнкция). Возвращает true, если оба выражения expressioni и expressions имеют значения true. В противном случае возвращается false. Рассмотрим примеры: (1 > 0) && (2 > 1) возвращает true. (1 > 0) && (2 < 1) возвращает false.



||



Логическая операция ИЛИ (дизъюнкция). Возвращает true, если хотя бы одно из значений expressioni или expression2 равно true. Если ни одно из expressioni и expressions не равно true, возвращается false. Рассмотрим примеры: (1 > 0) || (2 < 1) возвращает true. (1 < 0) 11 (2 < 1) возвращает false. Логическая операция НЕ (отрицание) —унарная операция, которая возвращает противоположное значение булева выражения. Если expression равно true, возвращается false, а если expression — false, возвращается true. Эта операция не изменяет значения выражения, поскольку работает подобно арифметической операции отрицания. Рассмотрим примеры: ! (1 > 0) возвращает false. ! (1 < 0) возвращает true.



Операции Глава 6



может быть переменная, функция или целый объект), принадлежащему определенному объекту. Синтаксис операции таков:



typeof 33 возвращает строку "number", typeof "A String" возвращает строку "string", typeof true возвращает строку "boolean",



objectName. variableName



typeof null возвращает строку "object".



ИЛИ ПРЕДУПРЕЖДЕНИЕ



objectName. f unctionName ()



Операция typeof была добавлена в Navigator 3.0 (JavaScript 1.1). Она будет работать только в JavaScript 1.1 и старших версиях браузеров.



Определение и вызов функций Функции подробно рассматриваются в главе 8. Сейчас ознакомимся с двумя операциями, имеющими отношение к функциям. Первая — операция, которая обозначается круглыми скобками и всегда следует за именем функции. Например, функция displayNameQ объявляется следующим образом: function



displayName() [ операторы]



;



displayName()



Круглые скобки показывают, что используется функция, а не другой определенный пользователем идентификатор. Вторая операция записывается символом запятой. Она используется для отделения друг от друга аргументов функции. Аргументы всегда заключаются в круглые скобки. Функция displayName() с двумя аргументами могла бы выглядеть так: displayName [ операторы ]



(argumentl,



objectName.anotherObject



Часть данных, к которой обращаются, должна стоять справа от точки. Такой способ обращения к члену структуры (к переменной, функции или объекту) обычно называется "точечной нотацией". Операция индексирования применяется при обращении к части данных из массива. Обозначается она парой квадратных скобок и позволяет получить доступ к любому элементу массива. Массивы в JavaScript реализованы в виде объектов (см. главу 10). Ниже показан синтаксис операции индексирования: arrayName[indexNumber]



Операция вызова функции также используется при вызове функции из любого места сценария:



function



ИЛИ



argument2)



{



Операции со структурами данных Операции со структурами данных — термин, который используется при классификации двух операций, необходимых для работы со структурами данных. Структуры данных — это концептуальные основы, применяемые для хранения одной или более базовых частей данных организованным способом. В JavaScript таковыми структурами являются объекты, группирующие данные для конкретных целей. Операция, уже знакомая тем, кто имел дело с объектами, обычно называется "точка". Обозначается она точкой (.) и носит название операцией взятия члена структуры. Она позволяет обращаться к члену (коим



Операция индексирования предполагает использование целого числа (индекса элемента массива) indexNumber. IndexNumber определяет индекс в arrayName и обеспечивает доступ к любому члену массива.



Поразрядные операции На аппаратном уровне данные хранятся в памяти поразрядно. Они записываются в двоичной системе счисления, в которой любое целое число может быть представлено при помощи символов 0 и 1. В зависимости от размещения, каждый единичный разряд представляет значение 2 в степени п, где п — номер разряда, считая справа. Например, целое число 12 может быть представлено двоичным кодом 1100: 21 + 1 х 2 2 + 1 х 23



О х 2° + О



12



Для хранения большого числа, скажем 237 (11101101 в двоичном коде), потребуется 8 разрядов памяти: 2



5



+ 1



2



6



+ 1 х 2



1



0 х 24



= 237



Для хранения целочисленных значений в памяти отводится 32 разряда. В памяти число 237 фактически выглядит как 00000000000000000000000011101101, но для краткости незначащие нули не указываются. Несмотря на то что целое число можно записывать в десятичном, восьмеричном или шестнадцатиричном виде, в памяти оно хранится в двоичной форме.



Базовое подмножество языка JavaScript



Часть II Для представления отрицательных значений используется крайний слева (самый старший) разряд. Взгляните на следующие примеры: 10000000000000000000000000000001 1 = -2147483647 10000000000000000000000000000011 3 = -2147483645 11111111111111111111111111111111 = 2147483647 = -1 11111111111111111111111111111110 = 2147483646 = -2



= -2147483648 + = -2147483648 + -2147483648 + -2147483648 +



Работа с двоичными представлениями целых чисел в JavaScript обеспечивается через поразрядные операции. Самая простая из поразрядных операций — унарная операция дополнения до единицы, которая обозначается тильдой (~). Она изменяет значение каждого разряда операнда на противоположное, поэтому относится к операциям отрицания. Рассмотрим, как выполняется дополнение до единицы для числа 6: X = ~6



х = ~00000000000000000000000000000110 х = 11111111111111111111111111111001 х = -7



Поразрядные логические операции Поразрядные логические операции рассматривают операнды поразрядно. Операция выполняется над каждой парой разрядов. Например, применение поразрядной операции И к числам 01111 и 11011 дает в результате число 01011. В табл. 6.3 показан ход выполнения приведенного примера.



Поразрядные операции сдвига Все поразрядные операции сдвига требуют двух операндов. Левый операнд — это целое число, разряды которого будут сдвигаться. Правый операнд задает количество разрядов, на которое необходимо сдвинуть двоичное представление целого числа. Таблица 6.4 содержит список поразрядных операций сдвига.



Таблица 6.3. Использование поразрядных логических операций. Выражение



Результат



0&1



1&1



I



1 &0



:



1&1



I



1&1



•.



Поразрядная операция И возвращает 1 , если оба операнда равны 1 . Иначе возвращается 0. Например, 15 & 27 возвращает 11 (01111 & 11011 возвращает 01011). Поразрядная операция ИЛИ возвращает 1, если хотя бы один из операндов равен 1. Иначе возвращается 0. Например, 15 | 27 возвращает 31 (01111 | 11011 возвращает 11111). Поразрядная операция ИСКЛЮЧАЮЩЕЕ ИЛИ возвращает 1, если только один из операндов равен 1, но не оба. Иначе возвращается 0. Например, 15 " 27 возвращает 20 (01111 | 11011 возвращает 10100).



Таблица 6.4. Поразрядные операции сдвига. Операция



Описание Операция сдвига влево возвращает целое число со сдвинутыми на несколько позиций влево разрядами. Появившиеся младшие разряды заполняются нулями. Два следующих примера демонстрируют сдвиг числа 15 влево на 1 и на 2 разряда: 15 « 1 возвращает 30 (1111 « 1 возвращает 11110) 15 « 2 возвращает 60 (1111 «2 возвращает 111100) Обратите внимание, что сдвиг положительного целого числа влево на п разрядов эквивалентен умножению этого числа п раз на 2. В большинстве случаев компьютер выполняет сдвиг влево быстрее умножения на 2. По этой причине, вместо многократного выполнения операции умножения обычно отдают предпочтение поразрядному сдвигу влево. Относительно небольшое увеличение скорости в конечном итоге приводит к существенной экономии. Применение сдвига влево к отрицательному целому числу приводит к отрицательному или положительному целому числу — в зависимости от значения старшего разряда после выполнения сдвига влево. Операция сдвига вправо с копированием знака (арифметический сдвиг вправо) возвращает значение целого числа со сдвигом его разрядов на несколько позиций вправо. Все пустые разряды заполняются копией крайнего левого (т.е. знакового) разряда. Копирование крайнего левого разряда гарантирует, что целое число останется положительным или отрицательным. Применение данной операции также представляет собой



Операции Глава 6



Операция



Описание более эффективный способ деления положительного четного целого числа на 2. В случае положительного нечетного целого числа арифметический сдвиг вправо — то же самое, что и деление п раз на 2 с отбрасыванием остатка. Рассмотрим следующие примеры: 15 » 1 возвращает 7 (1111 > > 1 возвращает 0111) -15 » 1 возвращает-8 (11111111111111111111111111110001 » 1 возвращает 11111111111111111111111111111000) Операция сдвига вправо с заполнением нулями возвращает значение целого числа со сдвигом его разрядов на несколько позиций вправо. При этом все пустые старшие разряды заполняются нулями. Воздействие на положительные целые числа этой операции обеспечивает тот же самый результат, что и операция логического сдвига вправо. Так получается ввиду того, что копируемый знаковый разряд для положительных целых чисел — всегда нуль. Что касается отрицательных целых чисел, то операция логического сдвига вправо изменит значение старшего разряда с 1 на 0. Результат будет всегда целым числом, большим или равным 0. Рассмотрим несколько примеров: 15 >» 1 возвращает 7 (1111 >» 1 возвращает 0111) -15>»1 возвращает 2147483640 (11111111111111111111111111110001 »> 1 возвращает 01111111111111111111111111111000)



Зачем вообще возиться с разрядами? Поразрядные операции в большинстве сценариев не нужны. Возможно, иметь дело с разрядами вообще не придется. Однако, в некоторых случаях без такой возможности не обойтись. Примером может послужить перевод числа из десятичной системы счисления в шестнадцатиричную. Это потребует некоторых дополнительных усилий, т.к. JavaScript позволяет отображать только десятичные представления чисел, хранящихся в памяти. Встроенные способы отображения чисел в других системах счисления отсутствуют. Используя поразрядные операции, преодолеть упомянутое препятствие относительно просто. Например, переменная х хранится в памяти в двоичном коде. Показанный ниже код обеспечивает вывод значения переменной х в десятичном представлении (т.е. 220): var



х



=



OxDC;



// Отображение числа document.writeln(x);



да. В 32-разрядном целом числе 4 младших разряда памяти представляют цифру младшего разряда шестнадцатиричного целого числа. Следующие 4 разряда хранят следующую цифру и т.д. Для того чтобы прочитать только 4 разряда, используется операция & и управляющее значение. Управляющее значение должно хранить 1 в каждом разряде, соответствующем читаемому разряду целого числа. Поскольку требуется значение первых 4 разрядов, управляющее значение должно содержать 1 в первых четырех разрядах. Все другие разряды должны содержать 0. Для чтения младших четырех разрядов управляющее значение должно быть равно 1111 (15 или OxF): Управляющее значение: 00000000000000000000000000001111 &



Преобразуемое целое: 00000000000000000000000011011100



=



Результат: 00000000000000000000000000001100



220



В JavaScript не существует какого-либо способа отображения 220 в шестнадцатиричном формате (т.е. DC). Функция подобного рода оказалась бы весьма полезной при оперировании с кодами цветов HTML, которые записываются в шестнадцатиричной системе. Самый простой способ получить шестнадцатиричное число — взять двоичный код целого числа и перевести его в шестнадцатиричный. Точно так же шестнадцатиричные коды достаточно просто переводятся в двоичные. Четыре разряда памяти могут определять 16 различных значений. Поскольку для записи шестнадцатиричных кодов применяются 16 цифр, для хранения каждой шестнадцатиричной цифры требуется как раз 4 разря-



Результат — это копия первых 4 разрядов преобразовываемого целого числа. Сравните его с каждой из 16 шестнадцатиричных цифр и убедитесь, что оно равно С. Чтобы найти следующую шестнадцатеричную цифру, необходимо скопировать следующих 4 разряда этого целого числа. Это лучше всего сделать путем сдвига всех разрядов целого числа на 4 позиции вправо и затем воспользоваться тем же управляющим значением: Управляющее значение: 00000000000000000000000000001111 &



Преобразуемое целое: 00000000000000000000000000001101 =



Результат: 00000000000000000000000000001101



Базовое подмножество языка JavaScript



Часть II Результат соответствует цифре D. Листинг 6.5 демонстрирует рассмотренный алгоритм целиком. Используя только операции, упомянутые ранее, можно преобразовать любое 8-разрядное число в строковое представление его шестнадцатиричного эквивалента. Для этого сначала надо присвоить переменной



intValue преобразуемое значение. Затем отобразить значение, дабы подчеркнуть тот факт, что JavaScript отображает только десятичное значение DC, т.е. 220. Далее выполняется перевод двоичной формы числа 220 в шестнадцатиричную и отображение результата (см. рис.



6.6).



Листинг 6.5. Преобразование десятичного числа в шестнадцатиричное с использованием поразрядных операций.



npeo6pasoBawie десятичного числа в шестнадцатиричное







;•>



;.,„,т«МЛ»



Mil;.



При отображении целых чисел, хранящихся в памяти. JavaScript использует их десятичные э 220 отображается в в шестнадцатиричном формате: ОС



у кого-то ведь может и не хватить памяти. Но даже принимая во внимание сказанное, волноваться по поводу нехватки памяти нужно начинать только, когда в памяти хранится достаточно много данных.



Приоритеты выполнения операций При создании выражений, которые включают более одной операции, необходимо помнить, что JavaScript не обязательно вычисляет выражение справа налево или наоборот. Каждая часть выражения вычисляется в порядке, основанном на приоритете каждой операции. Рассмотрим такой пример: РИСУНОК б.б. Преобразование десятичного числа в шестнадцатиричное. ПРИМЕЧАНИЕ В коде предыдущего примера при поиске соответствия многократно используются условные выражения. Более эффективный способ сравнения ряда чисел связан с организацией циклов (см. главу 7).



При исследовании предыдущего примера обратите внимание на то, сколько нулевых разрядов остались неиспользованными при хранении относительно небольшого числа. Это — еще одна область, в которой поразрядные операции оказываются полезными. При помощи поразрядных операций можно сэкономить память, сохраняя данные в неиспользуемой части любой переменной. Например, если сценарий работает с большой группой положительных целых чисел, не превышающих 255, то в одном 32-разрядном слове поместятся четыре таких числа. Используя простую поразрядную операцию, можно извлекать любое из этих чисел. Стоит отметить, что с такими объемами ОЗУ, которые имеют на сегодняшний день большинство компьютеров, экономия пространства обычно не стоит затраченных на его добывание усилий. С другой стороны, поскольку JavaScript разработан для выполнения на различных платформах, нельзя знать заранее, кто будет выполнять сценарий, —



х = а * ь + с а умножается на Ь, после чего полученный результат прибавляется к с. Наконец, результат сложения присваивается х. Операция умножения обладает более высоким приоритетом, нежели операция сложения, поэтому умножение выполняется первым. Если вначале необходимо выполнить сложение, выражение заключают в круглые скобки: х = а * »= &=



Базовое подмножество языка JavaScript



Часть II



Название операции



Операция



Поразрядное И Равенство Сравнение



дополнительных операции присваивания, которые на самом деле являются комбинациями арифметических или поразрядных операций с простой операцией присваивания.



< < = > > =



Поразрядный сдвиг



t ' И



Сложение/вычитание



щ щ



I . '$



Умножение/деление Отрицание/приращение Вызов/структурирование данных



23 uerpfa, ов] Длина в метрах' 23 Длина в метрах' 5



Один из эффектов, связанных с приоритетами операций, заключается в определении типа данных результата выражения. Это станет очевидным при попытке конкатенации строк и чисел (см. листинг 6.6). Листинг 6.6. Приоритеты операций и типы данных.



Приоритеты операций*:/title>







Операции с одинаковыми приоритетами вычисляются слева направо. Операция сложения обладает таким же приоритетом, что и операция конкатенации, поэтому JavaScript будет выполнять все сложения и конкатенации слева направо. Обратите внимание на показанное на рис. 6.7 результирующее окно. Два первых примера работают, как и следовало ожидать. Третий пример показывает, что может получиться, когда JavaScript по-своему учтет приоритеты. Первый знак + преобразует число 2 в строку и добавляет ее в конец "Длина в метрах: ". В результате получается строка "Длина в метрах: 2". Потом то же самое происходит с числом 3 и получается "Длина в метрах: 23". Однако, если вместо этого требуется отобразить сумму 2 и 3, следует использовать круглые скобки, тем самым увеличив приоритет 2 + 3. В этом случае оба операнда — числа, и JavaScript выполнит сложение раньше конкатенации (см. рис. 6.7).



Резюме Операции присваивания устанавливают значения переменных. Наряду с простой, JavaScript поддерживает 11



РИСУНОК 6.7. Приоритеты операций и типы данных.



Арифметические операции позволяют выполнять базовые математические операции в JavaScript. Сюда входят операции сложения, вычитания, умножения, деления и вычисления по модулю. JavaScript также включает операции инкремента и декремента — для короткой записи двух наиболее частых математических операций. Математические операции более высокого уровня также встроены в JavaScript, но к ним следует обращаться через объект Math. Операции сравнения сравнивают два значения и возвращают true или false. С их помощью выясняется, равно ли одно значение другому, больше или меньше другого, а так же и любые комбинации этих вопросов. Условные операции позволяют возвращать одно из двух значений выражений, которые могут содержать любой тип данных. Возвращаемое значение зависит от значения определенного логического выражения. Строковые операции включают в себя операцию конкатенации и все операции сравнения. Операция конкатенации используется для связывания двух строк вместе с целью формирования новой строки. Операции сравнения могут использоваться со строками для сравнения их ASCII-значений. Начиная с крайнего левого символа строки, каждая пара символов сравнивается друг с другом. Возвращается true или false. Булевы операции используются в логических выражениях. Операция И возвращает true, если оба ее операнда — true, а иначе — false. Операция ИЛИ возвращает true, если по крайней мере один из ее операндов равен true. Иначе она возвращает false. Операция НЕ возвращает true, если ее операнд false, и false, если операнд — true. Операция typeof появилась в JavaScript 1.1 и представляет собой встроенную операцию, возвращающую



Операции



Глава 6



строку, которая представляет тип данных операнда. Это особенно полезно при выяснении, была ли переменная определена. Две операции работают с объявлением и использованием функций JavaScript. Операция вызова функции (круглые скобки) всегда следует за именем функции и заключает в себе список аргументов, которые может принять функция. Операция "запятая" используется для отделения аргументов друг от друга. Для работы с массивами и другими объектами необходимы еще две операции. "Точкой" обычно обозначают доступ к элементу объекта. Это — стандартная точечная нотация. Операция индексирования используется для индексации элементов массива. Она содержит имя массива и целое число, обозначающее расположение элемента, к которому обращаются. JavaScript дает доступ к двоичному представлению любого целого числа с помощью поразрядных операций.



Поразрядная операция дополнения используется для изменения значения каждого разряда целого числа на противоположное. Поразрядные логические операции применяются для сравнения двух целых чисел. Двоичная форма операнда используется для работы с каждой парой разрядов в числах. Логическая операция выполняется над каждой парой разрядов и возвращается целое число. Поразрядные операции сдвига сдвигают разряды целого числа вправо или влево на п позиций. При сдвиге вправо JavaScript позволяет выполнить арифметический или логический сдвиг. Когда все операции в выражении имеют равные приоритеты, JavaScript вычисляет выражение справа налево. Если же приоритет операций разный, то сначала выполняется операция с самым высоким приоритетом, затем следующая по приоритету и т.д. В JavaScript каждая операция обладает совершенно определенным приоритетом.



Управляющие структуры и организация циклов В ЭТОЙ ГЛАВЕ Условные операторы Операторы организации



циклов



Метки Оператор



with



Оператор switch



Проектирование сценариев, предполагающих принятие решений во время выполнения, — наиболее интересная часть JavaScript. В сценарии, где требуется принимать решения на основе его текущего состояния, просто обеспечивают вывод вопроса и затем, в зависимости от ответа, выбирают путь. Рассмотрим для примера планирование утра моего рабочего дня. Мне доступны несколько различных вариантов, из которых на основе определенных факторов я выбираю один. Я редко готовлю еду, посему наиболее важный вопрос, который я задаю себе каждое утро, — не голоден ли я. Если да, я выбираю маршрут, проходящий через продуктовый магазин. К моменту завершения упаковки собственного завтрака я, как правило, уже немного опаздываю. Дабы восполнить потерянное время, я двигаюсь по направлению к скоростному шоссе, где могу увеличить скорость. С другой стороны, если я не голоден (что случается весьма редко), то миную продуктовый магазин и еду на работу со скоростью на 10 миль в час медленнее. Используя подобного рода планирование, можно создавать и программы на JavaScript, выполняющие различные операции в зависимости от текущего состояния. Например, в главе 6 рассматривалось, как проверить, является ли переменная равной какому-то значению или даже ряду значений. С использованием управляющих структур появляется возможность заставить программу выбирать различные пути в зависимости от результата упомянутой проверки. Итак, имеем первую тему, которой посвящена данная глава. Поскольку размеры программ неуклонно возрастают, неплохо было бы учесть немаловажный фактор — сколько времени потребуется клиенту для их загрузки. Лучший способ сэкономить на количестве исходного текста в сценарии предусматривает применение операторов



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



Условные операторы В главе 6 рассматривалась операция ?:. Эта операция используется для создания двухшагового процесса. Сначала выражение оценивается на предмет равенства true или false. Далее, в зависимости от результата, возвращается одно из двух значений. Если выражение true, возвращается первое значение, а если — false — второе. Встречаются сценарии, принимающие решение в зависимости от значения выражения, использующего операторы if и else. Однако результат будет другим. Вместо возвращения зависящего от результата значения, программа выбирает один из двух путей выполнения. Так, можно заставить JavaScript выполнять множество различных функций, зависящих от любой доступной информации.



if Оператор if относится к числу наиболее популярных. Каждый язык программирования содержит его в той или иной форме, и его использования избежать, как правило, не удается. Оператор if применяется следующим образом: if



(условие) { [ оператора]



Управляющие структуры и организация циклов Глава 7



В качестве условия может указываться любое логическое выражение. Если результат условия равен true, выполняются операторы, посему работа программы продолжается. Если условие возвращает false, операторы игнорируются и работа продолжается. В листинге 7.1 приводится сценарий, который отдел маркетинга мог бы предложить разместить на Webсайте компании. Сценарий начинается с установки visitor-Interest в одно из двух значений. В данном примере выбирается "Technical Support" (то бишь, техническая поддержка) и комментируются альтернативные варианты. Сценарий доходит до первого оператора if, который проверяет, равно ли значение visitorlnterest строке "New Products" (т.е. новый продукт). Последнее вычисленное значение этого выражения — false, поэтому блок операторов после if игнорируется. Затем сценарий доходит до второго оператора if и сравнивает значение visitorlnterest со строкой "Technical Support". Выражение возвращает true, что приводит к выполнению кода, заключенного в фигурные скобки. Независимо от того, чему равно значение visitorlnterest, последний оператор всегда выполняется, поэтому продавец Виктор Франкенштейн делает шаг к посетителю. Результирующий вывод показан на рис. 7.1. Если visitorlnterest присвоить какое-то другое значение, результат изменится. Обычно набор операторов заключается в фигурные скобки. Это придает сценарию логический вид и оказывается особенно полезным в случае вложенных опе-



раторов if (т.е. при использовании одного оператора if внутри другого).



Привет, меня зовут Виктор Франкенштейн! Сейчас доступна и техническая поддержка Однако вначале позвольте познакомить вас с новой продукцией! Наша новая продукция удовлетворит все ваши потребности!



РИСУНОК 7.1. Виктор Франкенштейн делает шаг навстречу посетителю.



Листинг 7.2 демонстрирует использование логических переменных для выбора пути, по которому пойдет сценарий. Первый оператор if оценивает переменную needslnfo. В данном случае needslnfo имела значение true, так что JavaScript выбирает первый блок if и продолжает работу в нем, т.е. выводит на экран "Наши продукты использует весь мир.". Далее очередь доходит до второго (вложенного) блока if, и оценивается needsMorelnfo.



Листинг 7.1. Использование оператора if для принятия решения.



npHHHTHe решений при помощи оператора if







Опять-таки, возвращенное значение — true, поэтому операторы внутри второго блока будут выполняться. После завершения вложенного блока if JavaScript выполняет все оставшиеся инструкции первого блока. Обратите внимание, как фигурные скобки помогают отличать отдельные блоки программы друг от друга. Из рис. 7.2 видно, что строки программы выполнялись в порядке их написания. Изменяя значения needslnfo и needsMorelnfo, можно получить три различных результата. Помните, что если needslnfo присвоить значение false, программа не сможет перейти ко второму блоку if. В этом случае значение needsMorelnfo роли не играет, поскольку оцениваться оно не будет. Извините, Виктор, но если посетителю вообще не нужна информация, ему уж точно не нужна дополнительная информация.



Я работаю на Лучшие Продукты Интернешнл! Наши продукты используются GO всем мире Я просто не могу понять, как же вы могли обходиться без них Самый простой способ заказать наши продукты - воспользоваться онлайновым магазином



if ..else Иногда одной конструкции if оказывается недостаточно. Зачастую требуется также зарезервировать набор операторов, которые будут выполняться в случае, когда условное выражение возвращает false. Это можно сделать, добавив еще один блок непосредственно после блока if:



11



(условие) { операторы else { операторы



I



Кроме того, имеется возможность скомбинировать часть else с другим оператором if. Использование такого метода позволяет оценить несколько разных возможных сценариев перед выполнением нужной операции. Изящество данного метода состоит в том, что в конце можно определить тот же сегментом else. Формат упомянутого типа оператора выглядит так: if (условие) ( оператора } else if (условие) { операторы ) else { операторы



i



Что может быть хуже придирчивого компьютера? Листинг 7.3 демонстрирует, как можно создать интерРИСУНОК 7.2. Один из трех возможных результатов.



Управляющие структуры и организация циклов Глава 7



активную Web-страницу с помощью всего лишь нескольких строк кода. Здесь жестко задано значение ключа purchaseAmount, которое определяет ход сценария. Для настоящего взаимодействования сценария с пользователями потребуется обеспечить возможность пользовательского ввода. В таком случае purchaseAmount может принимать любые значения, в зависимости от желания заказчика. Это делается с помощью JavaScript и стандартных входных HTML-объектов, таких как переключатели и текстовые объекты. В главе 17 эта проблема обсуждается более подробно. В рассматриваемом примере клиент не соизволил потратить достаточную сумму, дабы удовлетворить Виктора Франкенштейна. Условный оператор получает значение false, и программа переходит на блок else. Посмотрев на рис. 7.3, можно воочию убедиться, как настойчивый продавец "разогревает" потенциального клиента. Листинг 7.3. Блок else, соответствующий значению false.



ITpnHsmie решений при помощи оператора if











Ч-



_



try..catch



;>„;гм«„,.к



«,[„



Спасибо, однако я уверен, что у меня есть еще кое-что, от чего вы не сможете отказаться



РИСУНОК 7.3. Один из двух возможных результатов.



Три выражения, заключенные в квадратные скобки, не являются обязательными, тем не менее, если даже убрать одно из них, точка с запятой все же потребуется. Именно точка с запятой обеспечивает должное место для каждого выражения. Выражение инициализации обычно применяется в целях инициализации переменной и даже объявления, что конкретная переменная является счетчиком цикла. Выражение условия должно иметь значение true перед каждым выполнением операторов, заключенных в фигурные скобки. Наконец, выражение цикла, как правило, инкрементирует или декрементирует значение переменной, которая используется в качестве счетчика цикла.



Базовое подмножество языка JavaScript Часть II



Листинг 7.4 демонстрирует использование оператора for для организации счета от 0 до 99 с отображением каждого числа. Для того чтобы уместить результат на стандартной странице, после каждых 10 чисел выводится символ новой строки (см. рис. 7.4). Листинг 7.4. Использование цикла for для счета от 0 до 99.



IlOTUi счета от 0 до 99







;



'.'



'•



' .



! ,.



, . • , ' , < .:( Ч"



.



• ... - / ; • •• .1



' ' ',.



щает true и программа выполняет операторь; в фигурных скобках. Как только программа выполнит все операторы и достигнет закрывающей фигурной скобки, она вычисляет выражение цикла ++1. При этом i увеличивается на 1 и, таким образом, выполнение первого полного цикла завершается. Процесс начинается сначала. На сей раз JavaScript знает, что выполнять раздел инициализации для цикла уже не требуется. Выражение условия вычисляется снова. Если i все еще меньше 100, выполняется второй цикл. Выполнение набора операторов внутри блока for продолжается до тех пор, пока i не достигнет значения 100. И в 99-й раз условное выражение возвращает true; программа выполняется в последний раз. Значение i увеличивается еще раз и становится равным 100. Вычисление условного выражения дает в результате false, поэтому выполнение цикла прерывается. Управление переходит к операторам, следующим непосредственно за закрывающей фигурной скобкой. Поскольку значение i было увеличено до 100 до завершения цикла, 100 и представляет собой последнее значение i. Обратите внимание, что в соответствие с правилами, рассмотренными в главе 5, i можно использовать вне цикла.



;



i ^ .],' I '•',„,,,



Подобно операторам if, циклы for также могут быть вложенными. Листинг 7.5 содержит код прохода по каждой координате сетки 10x10. Для каждой итерации первого цикла имеют место 10 итераций вложенного цикла. В результате вложенный цикл будет выполняться 100 раз. Листинг 7.5. Пример вложенного цикла.



Числа от О до 99 0.1.2.3.1.5.6,7.8,9. 1011.12 13 14 151617 1819 20.21.22.23.24.25.26.27.23,29. 30.31.32.33,34,35.36,37.38.39, 40.41.42,43.44,45.46.47,48,49. 50.51.52.53.54.55.56.57.58.59, 60.61.62.63,64 65 66.67,68.99 70.71.72.73.74.75.76.77.78.79. 80.81.82.83.84,85,86.87,88,89, 90,91,92.93.94,95,96,97,98,99, После завершения цикла i равно 100



Bno3ieeHHbie itnicnbi







Переменной х сначала присваивается значение 0. Затем JavaScript доходит до вложенного цикла и присваивает переменной у также значение 0. Вложенный цикл отображает значения х и у и затем увеличивает у на 1. Вложенный цикл продолжается до тех пор, пока у не станет равным 10. В этот момент уже сгенерировано 10 наборов координат. Выполнение вложенного цикла прерывается и управление возвращаются ко внешнему циклу. Значение х увеличивается на 1, после чего вновь запускается вложенный цикл. JavaScript знает, что вложенный цикл необходимо начать с самого начала, в связи с чем выражение инициализации должно вычисляться повторно. Таким образом, у присваивается значение 0 и операторы выполняются еще 10 раз. Процесс продолжается до тех пор, пока х не станет равным 10 и выполнение внешнего цикла, наконец, завершается. В результате отображается 100 наборов координат (см. рис.7.5).



т ш • ••



д



|В ш



.l'y,ll,vi



. . . . . . . . . . . . . . . . . . , . (6.0).(6.1).(6,2).(6.3Ц6.4),(6.5).(6.6).(6.7Ц6.8).(6,9). [7.0).(7.1Щ,2).(7.3).(7.4).(7.5).(7.6).(7.7).(7.8).(7,9). [8.0).(8.1).(8.2).(8.3).(8.4).(8.5).(8.6),(8.7Ц8.8)Х8.9).



объектом JavaScript, независимо от его свойств. Если объект не имеет свойств, цикл не выполняется. Цикл for..in работает также и с пользовательскими объектами. Переменная пользовательского объекта JavaScript рассматривается как свойство, и поэтому для каждой из них выполняется цикл. Синтаксис выглядит так: for (свойство in объект) { операторы I



Тут свойство — это строковый литерал, сгенерированный JavaScript. При каждом проходе цикла свойству присваивается имя следующего свойства, содержащееся в объекте, и так до тех пор, пока не переберутся все свойства. В листинге 7.6 такая функциональность применяется для отображения имен и значений всех свойств объекта Document (см. рис. 7.6). || III.;



Txl.ln.lIL-.Li.n-.l.m.l.l-n.n.l..: ^.J.t



ух„



| |



location = f!le:/cybooks'jscript/pics/src-texts/7-6.html forms ~ [object FormArray] links - [object LinkArray] anchors = [object AnchorArray] applets = [object AppletArray] embeds = [object EmbedArray] images = [object Image Array] title ~ Использование цикла (or .in для вывода списка свойств объекта document URL = fite;/C]/books/jscripVpics/src-texls/7-6.html referrer = lastModified = Friday. October 13.2000 17:50 35 cookie = domain = bgColor = «fffff IgColor = «000000 ImkColor = «OOOOee vlmkColor = «551a8b alinkColor = ЯГОООО yvidlh = 598



РИСУНОК 7.6. Список свойств объекта Document вместе с их значениями.



После завершения циила х равно : 10 После завершения цикла у равно : 10



I ... ,•• a -РИСУНОК 7.5. 100 пар координат, сгенерированных в двух циклах. Поскольку каких-либо ограничений на количество вложенных циклов нет, следовательно, число координат можно увеличить до трех или, скажем, до четырех. Данный метод можно использовать для обращения к элементам многомерного массива.



forJn Для использования цикла for..in потребуются знания объектов JavaScript, исчерпывающая информация о которых может быть найдена в главе 9. Конструкция for.an предоставляет возможность выполнения набора операторов для каждого свойства объекта. Цикл for..in можно использовать с любым



ПРЕДУПРЕЖДЕНИЕ Цикл for..in работает только в версии JavaScript 1.1 и выше. Не следует забывать, что этот цикл не отличается корректной работой в Microsoft Internet Explorer 3.0 (JScript 1.0).



Листинг 7.6. Использование цикла for..in.



JavaScript Unleashed







соб гарантирует, что набор операторов, находящихся в пределах фигурных скобок, будет выполнен по крайней мере один раз.



v



while



M > |klop/763XD7J.07.hlml ~-



Оператор while действует подобно циклу for, однако не включает в себя функции инициализации и приращения переменных во время их объявления. Переменные необходимо объявлять заранее, а инкремент или декремент их определять в рамках блока операторов. Рассмотрим синтаксис while: while (выражение_условия) ( операторы



Листинг 7.7 предоставляет пример использования логической переменной в качестве флажка, определяющего продолжение выполнения цикла. Эта переменная, status, объявлена до начала цикла и ей присвоено значение true. Как только i станет равно 10, status получит значение false, после чего цикл завершается. Результат листинга 7.7, как показано на рис. 7.7, — это сумма целых чисел от 0 до 10. Листинг 7.7. Использование цикла while.



JavaScript Unleashed







do..while Начиная с JavaScript 1.2, предлагается конструкция do..while. Она работает подобно оператору while за исключением того, что условное выражение не проверяется вплоть до завершения первой итерации. Этот спо-



РИСУНОК 7.7. Результат выполнения листинге, 7.7 — одиннадцать итераций цикла while.



Листинг 7.8 содержит пример, в котором заранее неизвестно, какое значение может принять userEntry (как если бы упомянутое значение вводилось пользователем). userEntry присваивается значение 0 просто для демонстрации того, что пользователь вполне может ввести значение, которое не будет удовлетворять выражению условия. Листинг 7.8. Оператор do..while, обеспечивающий по крайней мере один проход цикла.



JavaScript Unleashed







break и continue Используя циклы, стоит обратить внимание на то, что по умолчанию цикл не прекращается, а будет выполняться до тех пор, пока определенное условие не будет равно false. Однако, иногда может потребоваться выйти из цикла до того, как он дойдет до закрывающей фигур-



Управляющие структуры и организация циклов Глава 7



ной скобки. Подобное достигается за счет помещения в блок операторов внутри цикла break или continue. Оператор break завершает выполнение цикла, в то время как continue пропускает оставшиеся операторы текущей итерации, вычисляет очередное значение выражения цикла (если таковое существует) и начинает выполнение следующей итерации. Различия между этими двумя операторами продемонстрированы в листинге 7.9, который содержит достаточно тривиальный сценарий вычисления приближенного целочисленного значения квадратного корня числа п.



ратору break, который останавливает выполнение цикла. Аппроксимация квадратного корня из 175 показана на рис 7.8. v -л



V."



1



C'.'ir-iiu'i't ^'"



.1



1



г!' -!!



.



,



^ ' (\(if'>-!i\fit^~,



.



.:



.



iii



.



! o'-'in,'"! И



£г



^



Листинг 7.9. Использование операторов break и continue.



nepaTopbi break и continue







Сначала i присваивается О, цикл начинается и отображается значение i. Затем сценарий убеждается, что n не является отрицательным числом. Если n отрицательно, цикл прерывается и выполняется остаток программы после закрывающей фигурной скобки. Если n положительно i умножается на то же i и результат сравнивается с п. Если результат меньше n, i сохраняется как наилучшее текущее приближение квадратного корня из п. Затгм оператор continue пропускает оставшуюся часть текущей итерации и возобновляет работу цикла с момента приращения i. Как только квадрат i превысит значение п, сценарий пропускает continue и переходит к one-



1:1



I



12 !: И Сделано1 Цепочисш



|ение. не превышающее квадратный корень иэ 175 = 13



РИСУНОК 7.8. Внешний вид окна после того, как цикл переходит к оператору break и останавливается.



Метки Начиная с версии JavaScript 1.2, в языке появился метод обозначения более специфического места перехода при использовании операторов break и continue — метки. Метку можно помещать перед любой управляющей структурой, которая содержит другие операторы. Это позволяет перейти из рамок условного оператора либо цикла на совершенно определенное место программы. Пример применения меток показан в листинге 7.10. Листинг



7.10.



Использование



меток.



_



Mcnonb3osaHKe MeTOK







В листинге 7.10 цикл for "помечен" пользовательским идентификатором loopX. Это позволяет покидать цикл for либо, наоборот, продолжать его вне зависимости от вложенности. Та же метка loopX указывается в операторе break для завершения обоих циклов for. Без этой метки оператор break остановил бы только цикл, генерирующий значения для у. На рис. 7.9 показан результат работы программы, когда х и у достигают, соответственно, значений 3 и 8.



Все пары х у между (0 0) и (3,8): (0.0) (0.1) (0.2) (0.3) (0.4) (0.5) (0.6) (0.7) (0.8) (0.9) (1.01(1.1) (1,2) (1.31 (1.4) (1.5) (1.6) (1.Г)(1.8)(1.9) [2.0) (2.1) (2.2) (2.3) (2.4) (2.5) (2,6) (2.7) (2.8) (2,9) (3.0) (3.1) (3.2) (3.3) (3.4) (3.5) (3.6) (3.7) (3.8) После завершения цикла х равно 3 Поспе завершения цикла у равно 8



Подобная методика применяется достаточно часто и в больших количествах. Для экономии на объеме кода все операторы, которые ссылаются на объект Document, стоит поместить в блок with. Как это сделать, показано в листинге 7.11. Поступая таким образом, можно избавиться от назойливого префикса document в ссылках на методы и свойства документа. Обратите внимание, что title и URL — это свойства объекта Document, которые должны записываться как document.title и document.URL. При использовании оператора with необходимость в ссылке на объект возникает только один раз, тем не менее, достигается гот же самый результат, что и при наборе ссылки в каждой строке. На рис. 7.10 показан результат выполнения кода из листинга 7.П. ПРЕДУПРЕЖДЕНИЕ Internet Explorer 3.0 оператор with не поддерживает.



ШЕ



•0о Е he,,



: jhle:/Dl/books/jsciipt/7-ll html



|



' ' , ' • ; -п.л f i v . - ••



!;, Заголовок этого документа выглядит как "Использование оператора with". TJRL этого документа выглядит как "fileV//D|/books/J3cript/7-1 l.html" Теперь от префикса объекта можно избавиться раз и навсегда!



РИСУНОК 7.9. Использование оператора label для выхода из вложенного цикла for.



Операторы with Оператор with применяется во избежание многократного повторения ссылки на объект при доступе к его свойствам и методам. Любые свойства или методы в блоке with, которые JavaScript не может опознать, ассоциируются с объектом, указанным в этом блоке. Синтаксис with таков: with (объект) операторы



{



Объект определяет, какой объект необходимо использовать в случае отсутствия объектной ссылки в блоке операторов. Данный оператор особенно полезен при использовании сложных математических функций, которые доступны только через объект Math. Поскольку объект Math будет рассматриваться, начиная с главы 10, здесь показан оператор with для уже знакомого объекта Document.



I 1



'• -У I



РИСУНОК 7.10. Отображение информации с использованием оператора with.



Листинг 7.11. Использование оператора with в JavaScript.



Hcnojrb3oBaHMe оператора with















ПРИМЕЧАНИЕ



,



В зависимости от конкретного браузера, пример может отобразить URL в закодированном формате.



Вторая конструкция case совпадает с текущим значением request, следовательно, выполнятся команды, перечисленные в ней. •m JavaScript Unleashed - Microsoft Internet Explorer ИИШ



•| | S-.м '



Оператор switch Оператор switch используется для сравнения одного значения с большим количеством других. На первый взгляд упомянутая задача решается только за счет применения большого числа условных операторов, однако оператор switch тут будет гораздо уместнее. Он быстрее читается и позволяет определить заданный блок инструкций, выполняющийся в случае, когда соответствие не найдено. В листинге 7.12 предполагается, что переменная request может изменяться в зависимости от требований пользователя. В данном примере request присваивается тестовое значение "Name". ПРИМЕЧАНИЕ Опера-op switch до версии JavaScript 1.2 не существовал. Листинг 7.12. Оператор switch.



JavaScript Unleashed







Вызов функции Листинг 8.1 демонстрирует вызов функции defaultColors() из второго раздела сценария. Это пример вызова функции без аргументов. После полной загрузки HTML-документа функция сохраняется в памяти и находится там "в состоянии боевой готовности". Она не будет выполняться, пока главный раздел сценария не вызовет ее следующим оператором: defaultColors()



В этой точке программа сразу же переходит на первую строку функции defauItColorsQ. После выполнения всех трех строк программа возвращается назад к точке, в которой она покинула главный раздел, и продолжает работу там. Таким образом получается такой же эффект, как и при помещении всего кода функции непосредственно в конкретную позицию программы. Теперь, когда функции присвоено имя, все, что потребуется сделать для выполнения тех же инструкций — использовать ее имя снова. Результаты описанного процесса показаны на рис. 8.1. Многократное использование какого-то кода — вот наилучшее применение функции.



Функции - это сценарии, ожидающие выполнения! Внутри defaurtColorO Все депа переделаны



_















Когда функция вызывается как getBinary(x), она получает копию значения, хранящегося в переменной х. Такой процесс называется передачей по значению (passing by value). Значение присваивается anlnteger локальной переменной данной функции. В дальнейшем эту переменную можно использовать в любом месте блока операторов как локальную. Как показано на рис. 8.2, если anlnteger изменяет значение внутри функции, это изменение не затрагивает значение переменной х, которая играет роль аргумента.



Листинг 8.2. Использование аргумента в JavaScript-функции.



*yHxmOT и apryMeHTbi







Объект RegExp В предыдущем разделе упоминалось о возможности создания функций, выполняющих вычисления и поисковые операции. В JavaScript 1.2 появился базовый объект RegExp, позволяющий выполнять регулярные выражения над строками. Поскольку глава 31 обеспечивает достаточно детальнос рассмотрение данной темы, не имеет смысла углубляться в нее сейчас. В табл. 10.4 сведены свойства и методы объекта RegExp.



Объект Array Массивы являются основой практически любого современного языка программирования, и JavaScript — тому не исключение. Здесь имеется возможность создавать массивы и работать с ними. Массив (array) — это контейнер, содержащий элементы данных. Каждый из элементов массива — отдельное значение, но все они существуют как часть массива. Доступ к ним возможен только через сам массив. В табл. 10.5 сведены все методы и свойства объекта Array.



Базовое подмножество языка JavaScript



Часть



Таблица 10.4. Методы и свойства объекта RegExp.



Тип



Элемент



Описание



Метод



compileO ехес() test() RegExp.$* RegExp.$&



Компилирует регулярное выражение для ускорения его выполнения. Выполняет поиск совпадений в строковом параметре. Проверяет наличие совпадений в строковом параметре.



RegExp.&_ RegExp.&'



Представляет input. Представляет leftContext.



RegExp.S'



Представляет rightContext.



RegExp.$+ RegExp.$1,$2,"$9



Представляет lastParen. Представляет совпавшие подстроки. Проверяет, какие возможные совпадения были найдены



Свойство



global ignoreCase input lastlndex lastMatch lastParen



Представляет multiline. Представляет lastmatch.



Проверяет, игнорировался ли регистр во время поиска. Строка, в которой осуществляется поиск с помощью регулярного выражения. Определяет индекс, с которого начинается поиск следующей строки.



leftContext



Последние совпавшие символы. Последняя совпавшая подстрока, взятая в круглые скобки. Подстрока, предшествующая последнему совпадению.



multiline



Проверяет, должен ли выполняться поиск во множестве строк.



rightContext source



Подстрока, следующая за последним совпадением. Шаблон строки.



Таблица 10.5 Методы и свойства объекта Array. Тип



Элемент



Описание



Метод



concat() joint)



Соединяет элементы существующего массива. Метод появился в JavaScript 1.2. Соединяет все элементы массива в одну строку.



рор() push()



Удаляет последний элемент массива. Добавляет элементы в конец массива. Изменяет порядок следования элементов в массиве. Метод появился в JavaScript 1.2.



reverse() shift()



Свойство



Удаляет элементы в начале массива. Метод появился в JavaScript 1.2.



slice()



Возвращает часть массива. Метод появился в JavaScript 1.2



sort() splice()



Сортирует элементы в массиве.



toSource() toString()



Вставляет и удаляет элементы из массива. Метод появился в JavaScript 1.2. Преобразует элементы в строку с квадратными скобками. Метод появился в JavaScript 1.3. Преобразует элементы массива в строку.



unshift()



Добавляет элементы в начало массива. Метод появился в JavaScript 1.2.



valueOf()



Возвращает массив элементов, отделенных запятыми.



index



Возвращает индекс совпадения в строке для массива, созданного в соответствие с регулярным выражением. Появилось в JavaScript 1.2. Для массива, созданного в соответствие с регулярным выражением свойство возвращает исходную строку. Появилось в JavaScript 1.2.



input length



Количество элементов в массиве.



prototype



Позволяет добавлять свойства к экземплярам объекта Array. Свойство появилось в JavaScript 1.1.



Основные объекты языка



Глава 10 ПРИМЕЧАНИЕ



8. PowerBuilder



Несмотря на то что в строго типизированных языках все значения элементов массива должны иметь одинаковый тип, в JavaScript это необязательно. Массив может содержать данные различных типов, точно так же как объект имеет свойства разных видов.



9. Paradox



ПРЕДУПРЕЖДЕНИЕ В JavaScript массив не является родным объектом — объект Array появился только в JavaScript 1.1. Для определения массива в JavaScript требовалось создавать функцию. Заметьте, что он не будет обладать всей функциональностью родного объекта Array. function createArray(size) { this.length = size; for (var i = 1; i ") ; objWindow.document.write("Employee Summary Information Sheet "); objWindow.document.write("" + this.FirstName + " " + this.LastName + ""); objWindow. document.write ("Contact Information ") ; objwindow.document.write("

Home Phone: " + this.HomePhone + "

"); objWindow.document.write("

Ext. : " + this.Ext + "

"); objwindow.document.write("

Email: " + this.EmailAddress + "

"); ob jwindow. document .write ("Project Information ") ; objWindow.document.write ("

Current Project: " H- this .project.ProjectName + "

"); objWindow.document.write("

Client: " +• this.Project.Client.ClientName + "

"); 11 4- this.Project.Client.Address + "

"); objWindow.document.write("

Client: 11 + this. Project. Client. City + ", " + objWindow.document.write("

Client: this.Project.Client.State + " " + this.Project.Client.zip + "

"); + this.Project.DevTool + "

") objwindow.document.write("

Developmnt Tool Used: objWindow.document .write ("") ; objwindow.document.close();



Ссылка на дочерний объект выполняется в соответствие с точечной нотацией. Таким образом, на адрес клиента можно сослаться через this.Project.CHent.Address. Точечная нотация позволяет легко и просто отследить код с момента определения пути для используемых методов и свойств, поскольку предполагает указание пути к тому или иному методу либо свойству. Совершенно несложно добраться до родительских объектов (имена которых находятся слева перед первой точкой), проходя через множество дочерних до тех пор, пока не встретится искомый метод или свойство. Как только определены конструкторы для каждого из объектных типов, приступайте к созданию экземпляров employee, project и client. CoastTech = new client("Coastal Techonology", "100 Beacon Hill", "Boston", "MA", "01220"); Coastal = new project("CoastalOl", CoastTech, "JavaScript") ; Allen = new employee("Allen", "Wyke", "617/555W 1212", "100", "[email protected]", "Coastal");



Параметр project в определении объекта сотрудника и параметр client в определении объекта проекта далеко не строки; они — суть имена вновь созданных объектов. Обязательно примите во внимание порядок создания объектов. Поскольку объект Allen использует объект проекта Coastal в качестве параметра, создание экземпляра Coastal должно происходить в первую очередь, иначе возникнет ошибка. По тем же соображени-



ям, сначала потребуется создать экземпляр CoastTech объекта client и только затем заняться созданием проекта Coastal. После создания экземпляров объектов обратитесь к Allen.showSummaryInfo() для отображения окна, показанного на рис. 11.3. В листинге 11.5 показан исходный код для этого примера.



Employee Summary Information Sheet Thelma Turner Contact Information Home Phone: 556-236-0202



Ext: 100 Email; [email protected]



Project Information Current Project: CoastalOl Client Coastal Techonology Address: 100 Beacon Hill City, State, Zip: Boston, MA 01220 Development Tool Used: JavaScript



РИСУНОК 11.3. Страница с краткой информацией о сотруднике.



Листинг 11.5. Пример использования объектов employee, client и project.



Using the book object











Динамическое создание объектов Возможность создания объектов непосредственно в коде существенно расширяет возможности разработчика. Во всех рассмотренных ранее примерах объекты создавались посредством оператора new во время загрузки окна. А какие же действия потребуется предпринять для создания объектов во время выполнения? Объектно-ори-



ентированные среды программирования позволяют создавать экземпляры "на лету". JavaScript позволяет создавать объекты "на лету", однако все же с рядом определенных ограничений. Сначала планировалось создать обобщенную функцию, которая бы создавала экземпляры при каждом ее вызове. Если замысел увенчается успехом, исчезнет необходимость в использовании операторов new, и объекты



Базовое подмножество языка JavaScript Часть II можно будет создавать на основе информации, введенной пользователем. Идея метода выглядит приблизительно так: function addEmployee(ObjectName,FirstName, LastName) { ObjectName = new employee(FirstName, LastName); В идеальном случае метод должен был создавать экземпляр объекта и присваивать ему имя на основе значения параметра ObjectName. К сожалению, попытка успехом не увенчалась. JavaScript не позволяет имени экземпляра объекта быть переменным. Вместо этого в качестве имени объекта используется ObjectName. Например, если Frank определен как объектная ссылка, то следующее выражение будет полностью корректным: function addFrank(FirstName, LastName) ( Frank = new employee(FirstName, LastName);



empList[i] = new employee(FirstName, LastName, HomePhone, Ext, EmailAddress); Используя приведенный выше метод, можно создавать экземпляры объектов, базируясь на вводе пользователя и динамическом создании объекта за счет вызова addEmpIoyeeObjectQ. Например, при помощи формы, представленной на рис. 11.4, пользователь может вводить основную информацию о сотрудниках. После щелчка на кнопке Add создается новый экземпляр объекта. В листинге 11.6 показан исходный код для данной формы.



Dynamic Object Creator



1



Несмотря на невозможность динамического именования реализованных объектов, объект можно создать как элемент массива-контейнера. Это означает, что можно предусмотреть массив employeeList, который будет хранить все созданные объекты employee. Таким образом, можно изменить метод addEmpIoyeeQ, использовав вместо него что-то наподобие: function addEmployeeObject(FirstName, LastName, HomePhone, Ext, EmailAddress) { РИСУНОК МЛ. Динамическое создание объектов. Листинг 11.6. Динамическое создание объектов.



Intranet Employee Oatabase



Dyanamic Object Creator

Enter employee information in the form below and click the Add button. Press the Show All button to view a list of all employees you have entered.





First Name:



Last Name:



Home Phone:



Ext. :



Email Address:















Кнопка Show All (Показать всех) позволяет просмотреть все объекты, созданные в течение сеанса. На рис. 11.5 показан список объектов employee, экземпляры которых уже были созданы. 6 1-158



ПРИМЕЧАНИЕ Объекты типа массивов не поддерживались Netscape Navigator вплоть до его версии 3.0. Учтите это при создании сценариев для версии 2.0.



Базовое подмножество языка JavaScript Часть II



Объектный прототип позволяет добавлять свойства и методы к каждому экземпляру объектного типа. Если бы требовалось к каждому объекту Book добавить новое свойство recommended со значением true, следовало бы воспользоваться кодом, показанным ниже:



Object Description Tom smith 555-1221 129



[email protected]



book.prototype.recommended = True;



Tim Smith



Протестировать все можно, вызвав alert(cnBook. recommended). Результат тестирования показан на рис. 11.6.



555-1222



130



Leon Openhlemer 111-1112



132 leon@rny,coni



»»...!».



.аа»;-«д>ял



РИСУНОК 11.5. Список созданных динамически объектов.



Расширение экземпляров объектов Раз уж JavaScript является слабо типизированным языком, он весьма гибок в плане описания объектов. Определение экземпляра любого объекта можно расширить, объявив новое свойство и присвоив ему значение. В качестве примера добавим в экземпляр cnBook объекта Book из предыдущей главы свойство Series. Экземпляр cnBook создается следующим образом: cnBook = new book("Chronicles of Narnia", "C.S. «Lewis", "1-53231-128-1", "Children's Fiction", 5) ;



Где-то в сценарии поместите код добавления свойства Series: cnBook.Series = "True";



Подобная технология применима только к экземплярам объектов, но не к объектному типу. С другой стороны, браузеры, поддерживающие как минимум JavaScript 1.1, позволяют расширять созданные объекты с использованием объектных прототипов, синтаксис которых выглядит так: объектныйТип.prototype.имяСвойства;



РИСУНОК 11.6. Вывод на экран значения свойства с использованием alert().



Резюме



JavaScript поддерживает возможность создания пользовательских объектов в клиентских сценариях, что делает язык более гибким и позволяет структурировать код в соответствие с объектно-ориентированной методологией. В главе были рассмотрены различные аспекты создания и реализации объектных типов. Читатели почерпнули информацию о том, как можно расширить функциональность обычных объектов за счет создания составных объектов, т.е. того, что носит название "объектов внутри других объектов". Составные объекты используются для инкапсуляции данных, простирающихся на большое количество уровней. По аналогичному же принципу строятся реляционные базы данных с отношениями "один-ко-многим". В добавок ко всему, читатели узнали о расширении экземпляров объектов с использованием прототипов объектов.



Серверная часть JavaScript



В ЭТОЙ ГЛАВЕ Использование архитектуры клиент/сервер Разработка серверных приложений JavaScript Базовые серверные объекты



Несмотря на то что JavaScript играет ключевую роль именно со стороны клиента, зачастую этот язык программирования используется при создании серверных приложений (с помощью Netscape Server-Side JavaScript, SSJS). SSJS, как и его эквивалент для клиентской стороны, представляет собой набор объектов, функций и методов, расширяющих стандарт ECMAScript. Применительно к разработке Web-приложений, он используется в качестве серверного языка сценариев, заменяющего CGI и другие технологии. ПРИМЕЧАНИЕ Оригинальное название серверной части JavaScript выглядит как LiveWire. Начиная с Netscape Enterprise Server 3, LiveWire был погружен в сервер, после чего перестал существовать в виде отдельного продукта. LiveWire на данный момент реализует функциональность подключения к базам данных. ПРИМЕЧАНИЕ SSJS работает только на Netscape-серверах, поэтому в настоящий момент нельзя использовать с другими Webсерверами. Компания Microsoft поддерживает JScript в собственном сервере Active Server Pages (ASP), однако эти расширения серверного языка отличаются от SSJS. И вообще, не стоит забывать, что Java Server Pages (JSP) — это совершенно другая технология.



Прежде чем углубиться в SSJS, необходимо разобраться, как создавать приложения типа сервер/клиент. SSJS вместе с используемым для управления этими прил о ж е н и я м и менеджером приложений ( A p p l i c a t i o n Manager) в клиент-серверной модели представляют сервер. Клиентом является браузер или приложение, куда отправляется информация. Изучение технологии клиент/сервер существенно повысит уровень ваших знаний.



Использование архитектуры клиент/ сервер Клиент и сервер представляют собой различные сущности, независимые друг от друга до тех пор, пока клиенту не понадобится информация от сервера. Концепция клиент/сервер усовершенствовалась до такой степени, что вышла за пределы сервера, служившего просто хостом для HTML-страниц. Серверная часть Web-приложения может быть истинным сервером, поддерживающим обработку приложения и хранение баз данных. Хранение обычных статических документов кануло в лету.



Web-приложения с клиент-серверной архитектурой Разработка Web-приложений типа клиент/сервер отличается от традиционного процесса разработки в рамках архитектуры клиент/сервер. Так сложилось, что сервер рассматривается в качестве разновидности сервера баз данных, используемого для хранения и обработки запросов данных от клиента. В клиент-серверной технологии для Web сервер не обязательно должен быть базой данных, это просто Web-сервер, используемый для обработки, администрирования и выполнения вычислений в HTML-документах. Все еще существует возможность разделения функциональности между клиентом и сервером, тем не менее, обработка централизована на сервере. Двухуровневая структура приложений Разрабатываемое приложение необходимо разбить на две четко определенных части. Это как раз и есть дву-



Базовое подмножество языка JavaScript



Часть II



хуровневая структура для архитектуры типа клиент/сервер. Первая часть представляет собой пользовательский интерфейс (UI), или внешний интерфейс, который обеспечивает связь пользователя с приложением. Вторая часть — сервер, где проходит основной процесс выполнения. Благодаря наличию клиентской части JavaScript, выполнение можно разделить между клиентом и сервером в соответствии с требованиями приложения. В обычной среде было бы разумнее перенести как можно большую часть обработки на клиентскую часть, поскольку необходимо располагать определенной степенью управления конфигурацией и настройкой машин пользователей. Такое разделение может сделать сам разработчик, по своему усмотрению, в зависимости от возможностей клиентской стороны, загрузки сервера и сетевого трафика. Сервер — это обрабатывающий механизм приложений. Он управляет и хранит большое количество данных, выполняет интенсивные и крупномасштабные вычисления, а также системную обработку. Возможность изоляции двух частей системы, обеспечивающая их независимость друг от друга, внесли существенную долю в развитие широкомасштабных систем баз данных. Упомянутая возможность привносит дополнительную гибкость в процесс разработки приложений.



N-уровневая структура приложений Л'-уровневая методология применяется с целью преодоления ограничений двухуровневой структуры. УУ-уровневая архитектура предусматривает разбиение пользовательского интерфейса, обработки и хранения данных на отдельные уровни, еще больше разделяя рабочий поток. Клиент отвечает за пользовательский интерфейс и несложную обработку, а сервер — за хранение данных. При этом существенная обработка и вычисления (или бизнес-правила) перемещаются на средний уровень. Такие возможности позволяют вносить изменения в бизнес-правила, не оказывая влияния на пользовательский интерфейс и базы данных. По сравнению с обычной средой приложений, в среде Web-разработки клиентский компьютер (и Web-браузер, и рабочая станция) управляется в гораздо меньшей степени. Очень сложно оценить, как проходят процессы на клиентской части. Более разумно запускать процессы на серверной части, потому как необходимо контролировать среду, обеспечивая тем самым предсказуемые результаты. С другой стороны, обычные приложения типа клиент/сервер сталкиваются с некоторыми проблемами, незнакомыми для клиент-серверных Web-приложений. В обычных приложениях баз данных типа клиент/сер-



вер при изменении клиентского модуля повторное распределение целого приложения не требуется, поскольку клиентом является Web-страница и модификации распространяются автоматически при ее следующей загрузке. Браузер инициирует транзакцию путем отправки серверу запросов на выполнение некоторых операций, на получение информации из баз данных, на определенные вычисления, на запуск процессов либо на выполнение функций SSJS. Прежде чем продолжать, клиент должен дождаться ответа от сервера. Процессы серверной части обеспечивают хранение кода в едином централизованном сервере. Это позволяет более быстро выполнять требуемые модификации и увеличивает скорость прохождения процессов, поскольку все они выполняются на сервере.



Как не попасть в западню С использованием JavaScript связан ряд вопросов касаемо архитектуры типа клиент/сервер. В зависимости от предпочтений, обработка в JavaScript может распределяться между клиентом и сервером. Скорость обработки со стороны клиента зависит от клиентской среды, памяти, быстродействия и других внутренних факторов, в то время как на сервере скорость зависит от трафика в Internet и запущенных процессов на сервере. В этой связи неплохой идеей будет разделение обработки между различными элементами с акцентированием внимания на сервере, как на более известной и предсказуемой сущности. ПРИМЕЧАНИЕ Размышляя над дизайном архитектуры на ранних стадиях разработки Web-приложений, можно создавать более устойчивые приложения, что ускорит выполнение процессов.



Передача информации между клиентом и сервером Связь клиента с сервером в Web-среде — очень важный вопрос, которому стоит уделить особое в н и м а н и е . В отличие от клиент-серверной среды в обычных сетях, Web-среда не обеспечивает постоянной связи с сервером, устанавливая вместо этого взаимодействие через протоколы HTTP с использованием TCP/IP.



От клиента к серверу Самый важный обмен информацией между клиентом (браузером) и сервером — это клиентские запросы. Сама природа HTTP требует, чтобы браузер клиента отправлял на сервер запросы на любую необходимую информацию. Сервер не может самостоятельно инициировать переход или подключение к HTTP-документу.



Серверная часть JavaScript



Глава 12



Формат HTTP-запроса к серверу может быть базовым запросом HTML-страницы или запросом, включающим информацию содержимого либо данные, которые должны быть обработаны или отправлены на сервер. К тому же, часть информации, содержащаяся в запросе (называемая "телом"), включает в себя данные (содержимое) функций или полей HTML-документа, с которыми будет работать сервер. HTTP-запросе содержит три основных группы информации: •



Строка запроса (GET, HEAD, POST), URL и версия HTTP.



• Пары имя/значение для таких полей, как accept, refer, if-modified, user-agent, content-type, contentlength. • Содержимое — информация (данные), отправленная на сервер для обработки. От сервера клиенту После отправки клиентом на сервер запроса определенной информации, сервер, в свою очередь, отправляет клиенту сообщение, содержащее запрашиваемую информацию. HTTP-ответы обладают тем же форматом, однако в конце содержат возвращаемый HTML-документ (ответ). HTTP-ответ содержит три основных группы информации: • Строка ответа • Заголовки ответа • Данные ответа Серверная строка ответа имеет синтаксис версии HTTP, код состояния (код возврата из трех цифр) и строку ответа текста (не используемую браузером, но участвующую в интерпретации документа). Все сказанное выглядит следующим образом: НТТР/1.1 200 ОК Server: Netscape-Enterprise/3.5.1G Date: Wed, 19 Apr 2000 17:13:33 GMT Content-type: text/html Connection: close



Строка ответа предоставляет браузеру начальную информацию о том, что можно ожидать далее, если пройти ответ до самого конца. Версия HTTP сообщает о том, как начать интерпретацию документальной части ответа, а код состояния — что можно ожидать после возврата. Например, код состояния ответа, равный 200, означает "ОК" (то бишь, "все будет хорошо"). ПРИМЕЧАНИЕ Сущестзует великое множество кодов ответа (наподобие 200, 302, 404), которые имеют отношение к состоянию и возвращаемому содержимому документа.



Данные ответа, или "тело", — это последняя часть HTTP-ответа. Они хранятся в формате, определенном content-type. Значение этих данных зависит от кода состояния, возвращаемого в заголовке ответа. Как правило, данные ответа имеют форму HTML-документа, который и будет отображаться в браузере клиента.



Управление сеансами Одно из преимуществ Web и технологии разработки Web-приложений в то же время является и существенным препятствием для приложений, требующих взаимодействия клиента и сервера. Поскольку сервер оперирует в среде, не поддерживающей концепцию состояний, выполнение происходит гораздо быстрее, однако при этом сервер должен полностью полагаться на клиента в том плане, что клиент сам должен напоминать, кто он есть и когда он производит запрос. Эволюция HTML от статических страниц к интерактивным приложениям повлияла на среды, не обладающие состоянием, заставив искать способы осуществления поддержки состояния. Поскольку клиент не связан постоянно с Web-сервером, возникает немаловажная проблема: как сообщить Web-серверу, кто является клиентом при его повторном подключении к серверу и отправке запроса. Если бы подключение Web-приложений к серверу было бы постоянным, то разработка Web-приложений была бы столь же простой, как и разработка приложений типа клиент/сервер. Существует несколько методов управления сеансами, среди которых — использование клиентских cookieнаборов, кодирование URLn IP-адреса на сервере. Первых две технологии предполагают полную поддержку состояния со стороны клиента и определенную помощь со стороны сервера. В случае технологии, связанной с IP-адресами, поддержку информации осуществляет сервер, а клиент лишь оказывает в этом помощь. Cookie-наборы Cookie-наборы обеспечивают механизм сохранения клиентской информации на Web-сервере, предусматривающий идентификацию. Эта информация может быть использована в будущих подключениях к серверу. Cookie-наборы — это методология поддержки состояния клиентов. Сервер сохраняет информацию о клиенте на клиентской части, а затем клиент отправляет сохраненную информацию обратно на сервер вместе с каждым HTTP-запросом. Cookie-наборы хранятся в текстовом файле на клиентском дисковом устройстве. Сервер, как средство отслеживания состояний клиентов, может помещать информацию в cookie-набор столько раз, сколько это позволяет браузер. Различные браузеры по-разному работают с cookie-наборами. Некоторые (скажем, Navigator)



Базовое подмножество языка JavaScript Часть II



имеют только один файл cookie, в который все сервера записывают информацию, помечая его разделы специальными именами URL по мере сохранения и обновления. Другие браузеры, такие как Internet Explorer, сохраняют информацию в различных файлах каталога cookie. ПРЕДУПРЕЖДЕНИЕ Размер файла cookie ограничен. Передаваться клиенту и сохраняться на его стороне может только определенный объем информации. Сей факт ограничивает количество информации, которую может сохранять каждый сервер, и число Web-серверов, сохраняющих информацию на клиентском компьютере.



Всегда существует вероятность ошибочного удаления файла cookie (это всего лишь текстовый файл). В этом случае сервер потеряет информацию о состоянии, поэтому клиенту для стабилизации своих отношений с сервером придется все начать сначала. Поскольку cookie-информация хранится на клиентской части, то серверные элементы повлиять на нее не могут. Это позволяет клиенту выполнить повторную отправку запроса, даже если первый раз на сервере возникали какие-то проблемы. Другое преимущество cookiesнаборов заключается в том, что сервер не обязан хранить информацию о клиенте; после первоначального запроса информации сервер вообще может "забыть" о клиенте. Cookie-наборы приводят к увеличению трафика, поскольку с каждым запросом сервер должен отправлять и получать дополнительную информацию. Cookie-информация передается в соответствие с методологией пар имя/значение, используя для этого протокол передачи cookie-информации. Кодирование URL Кодирование клиентского URL для поддержки информации о состоянии взаимодействия клиент-сервер предусматривает отправку пары имя/значение (name/value) или уникальных ключевых полей информации как части строки URL в клиентском HTTP-запрос. Подобный способ сохранения информации о состоянии выгоден для серверов так же как и cookie-наборы, поскольку в данном случае серверы не должны сохранять какуюлибо информацию. ПРИМЕЧАНИЕ Использование данного процесса для поддержки клиентского состояния требует, чтобы построение URL было динамическим каждый раз, когда генерируется запрос. Разумеется, размеры URL при этом существенно возрастают.



Использование метода кодирования клиентских URL обеспечивает значительную гибкость, если существует потребность в поддержке состояния. В отличие от cookie-наборов, кодирование URL не зависит от конкретного браузера. Поскольку разработчик не ведает, какой конкретно браузер получает доступ к серверу, то это, пожалуй, наилучший способ поддержки состояния. IP-адреса на сервере Третий способ поддержки состояния — сохранение IPадреса и информации о состоянии на сервере. Это означает, что сервер должен иметь доступ к базам данных или к совместно используемой памяти, где будет сохраняться информация. Хранение информации о состоянии основано на IP-адресах клиента. Информация используется и хранится только совершенно определенным сервером. Из-за множества недостатков, такой способ поддержки состояния используется только в определенных случаях: •



Должно быть известно, что клиенты обладают постоянными IP-адресами



• Приложение поддерживает только один сервер Практика динамического распределения IP-адресов для машин, которые выполняют Web-браузеры, делает невозможным внедрение данного способа хранения состояния. Кроме того, невозможна также и поддержка множества Web-серверов.



Разработка серверных приложений JavaScript После того как все особенности серверной части языка JavaScript рассмотрены, можно приступить к исследованию процесса разработки приложений в этой среде с использованием SSJS. На рис. 12.1 показаны все детали упомянутого процесса.



Создание исходных файлов Первый шаг к построению серверного приложения JavaScript связан созданием исходных файлов, которые бывают двух видов: •



Исходные HTML-документы. Эти документы могут быть статическими либо страницами с кодами JavaScript. Их расширения — .htm или .html.



• Библиотечные файлы JavaScript. Их расширение .js. Эти файлы служат в качестве библиотек функций JavaScript. Использовать HTML-дескрипторы внутри них не требуется.



Серверная часть JavaScript Глава 12



if (client. oustid = null) { write ("Вы не имеете идентификатора"); ) else { write ("Ваш идентификатор — " + client . custid) ; )



РИСУНОК 12.1. Процесс разработки серверных приложений JavaScript.



Второй путь встраивания кода не предусматривает использование дескриптора , поскольку код находится внутри другого HTML-дескриптора. Если необходимо поместить выражение JavaScript внутрь HTML-дескриптора, код окружается обратными кавычками (\Q). Эти кавычки весьма полезны при работе с объектами Link, Anchor и Form. Например, генерирование HTML-кода с созданной "на лету" ссылкой, которая включает заранее введенный пользователем Webадрес, достигается при помощи такого кода: Доиашняя *•* страница



Рассмотренные файлы необходимы, поскольку, в отличие от клиентской части JavaScript, до помещения на Web-сервер SSJS следует откомпилировать в байткоды. Упомянутая необходимость предварительной компиляции рассматривается с одной стороны как достоинство, а с другой — как недостаток использования JavaScript на серверной части. Достоинство заключается в том, что именно по причине предварительной компиляции операция выполнение существенно ускоряется. Однако, одновременно, это же и недостаток, поскольку большая часть того, что создается в SSJS, должно быть обязательно W e b - п р и л о ж е н и я м и , а не обычными страницами (как раз страницы и требуются большинству разработчиков). HTML-документы Зачастую разработчики практикуют внедрение кода JavaScript в HTML-документы. Однако внедрение серверной части JavaScript в HTML-файл может существенно изменить результат. Существуют два пути внедрения JavaScript в HTML-документы. Первый путь заключается в применении дескрипторов и . В любом случае, использование этих дескрипторов напоминает дескрипторы , применяемые на клиентской части JavaScript. Например, требуется сгенерировать строку, которая отображает ID (идентификатор) лица, ранее переданный через форму. Для этого можно прибегнуть к дескриптору :



При внедрении серверного JavaScript-кода в HTMLдокумент, пользователь видит только результат выполнения кода, но не сам код. Именно в этом и заключается различие между серверной и клиентской частями JavaScript, которое можно заметить только во время просмотра исходного файла в любом Web-браузере. Листинг 12.1 содержит исходный код HTML с внедренным кодом JavaScript. Во время выполнения приложения (см. листинг 12.2) это именно то, что будет лицезреть клиент при просмотре исходного кода в Webбраузере. (Результат отображения показан на рис. 12.2.) Несколько позже в главе будет рассматриваться объект Client. Сейчас достаточно будет отнестись к выражениям как к свойствам недавно созданного и определенного объекта. Листинг 12.1. Внедренный серверный сценарий.



Feedback



"Superiffic"



Feedback



Confirmation



Dear client . firstName,



Thank you for submitting feedback about our product. If you have asked us to contact you, we will be using the following information:



E-mail: client.email



Базовое подмножество языка JavaScript Часть II Telephone: client.phone



FAX: client.fax



Rupert Mydryl
Manager, Customer



Services







'If any of this information is incorrect, please go back to the feedback form and change it. We thank you for taking the time to help us be a "superiffic" company.



jj I m I '



т .'"""I1



"Supcriffic" Feedback Confirmation Sincerely ,



Dear Charles. Tnank y«j for flibrniterefeftaback about o«rr>r4uel IT you have asked us to contact you. vrf win be i '.m& the Mowing information:



Rupert Mydryl
Manager, Customer



E-mail: rnappy@»nilei.enin Telephone: 308-555-1212 FAX: 808-555-5050



Services



If any of Dm information ц incorrect, please go back to the feedback Form and change it We thank you for caking the time to help u* be a 'supenffic* company.







Eupeit hlvdryl Uiaagrr. Customer Services



Листинг 12.2. Результирующий документ, передаваемый клиенту.



Feedback



"Superiffic"



Feedback



РИСУНОК 12.2. HTML-документ в браузере.



Библиотечные файлы JavaScript Confirmation



Dear Charles :



Thank you for submitting feedback about our product. If you have asked us to contact you, we will be using the following information :



E-mail : chappyg smiles . com



Telephone: 808-555-1212



FAX: 808-555-5050



If any of this information is incorrect, please go back to the feedback form and change it. We thank you for taking the time to help us be a "superiffic" company.



Sincerely,



I



В любой серьезной среде разработки необходимо где-то размещать общие функции, которые можно вызывать из различных исходных файлов. Так же как и клиентская часть, серверная версия JavaScript позволяет размещать код JavaScript во внешних файлах, имеющих расширения .js. Внутри библиотечного файла JavaScript должны находиться функции, но не HTML. Ссылки на эти функции можно производить внутри HTML-файла. После компиляции SSJS-приложения компьютер разрешает все вызовы внешних функций путем просмотра .js-файлов, включенных в приложение.



Подготовка приложения В отличии от клиентской части, процесс разработки серверной части требует компиляции исходных файлов в файлы приложений .web. По этой причине большинство разработок SSJS — это Web-приложения. Далее поговорим о том, как создавать приложения и запускать их в Netscape Enterprise Server (NES).



Активизация серверной части JavaScript Для того чтобы пользователи смогли получить доступ к приложению, потребуется активизировать серверную часть в экземпляре Enterprise Server. Для этого необходимо получить доступ к Enterprise Administration Server и выбрать серверный экземпляр, в котором и будет выполняться активизация SSJS. Как только появится



Серверная часть JavaScript



Глава 12 Server Manager для данного экземпляра, выберите вкладку Programs и щелкните на элементе меню Server Side JavaScript. Все что потребуется предпринять на этой странице (см. рис. 12.3) — так это выбрать соответствующий переключатель для активации SSJS и решить, требуется ли запрашивать пароль администратора при доступе к Server-Side JavaScript Application Manager (весьма неплохая идея). Не забудьте сохранить и применить произведенные изменения. После перезапуска экземпляра Enterprise Server, как того требует Administration Server, доступ к Application Manager (см. рис. 12.4) можно получить с использованием показанного ниже URL. www.yourinstance.com необходимо заменить на соответствующее имя сервера: http://www.yourinstance.com/appmgr Итак, среда Server-Side JavaScript уже запущена, можно подготовить и запустить свое приложение.



i I j « ь т ш •* к.



Компиляция приложений После создания исходных файлов для приложения, их необходимо откомпилировать. Компилятор, входящий в состав NES, создает из HTML-документа и библиотечных файлов JavaScript файл .web, содержащий последовательность байткодов. Для компиляции приложения потребуется перейти в командную строку и запустить программу компилятора JavaScript Application Compiler (jsac). B NES 4.0 этот исполняемый модуль расположен в подкаталоге bin\https\bin. Вот варианты запуска компилятора: jsac [-cdv] [-1 кодоваяТаблица] [-а версчяЯзака] -о двоичнайфайл [-1] исходныйфайл! [-1] исходныйфайл2... jsac [-cdv] [-а версияЯзыка] -о двоичютфайл -f файлВключения jsac [-cdv] [-а версияЯзыка] -о двоичнъшфайл -р каталог ~f файлВключения -г файлРегтистрацииОшибок Рассмотрим допустимые опции, передаваемые в командной строке: -а Версия языка JavaScript, например "1.2". -с Выполнять только проверку синтаксиса без генерации файла двоичныйФайл. -d Активизировать режим отладки. -f Включение файла, заданного именем файлВключения.



- i^.j jj]&j yiiij ,.,



Adivala the Server Side Javnscnpt appllcdllon environment?



-h Вывести справочную информацию по опциям командной строки компилятора.



•.. : ahsl!£ui i'-iWitf -'



-i a Javascript Application V—



РИСУНОК 12.3. Активизация Server-Side JavaScript в Netscape Enterprise Server 4.



a



Web File Palb: d/nettcap^ Default Page: huine html Initial Page: start html Bdt-inMa] Dataha» Col



Определить имя исходного файла (исходныйфайл).



-1 Имя набора символов (например, iso-8859-l или x-sjis). -о Определить имя создаваемого файла .web как двоичныйФайл. -р Текущий путь при обработке файлов. -г Перенаправить вывод сообщений об ошибках в указанный файл (файлРегистрацииОшибок). -v Компилировать с расширенными сообщениями. Например, следующее командная строка компилирует (с расширенным выводом) приложение SSJS в файл policy.web, используя три исходных HTML-файла (index.htm, toc.htm, polpage.htm) и два библиотечных файла JavaScript (jsroutines.js и jsdates.js): jsac -v -о policy.web index.htm toc.htm polpage.htm jsroutines.js jsdates.js СОВЕТ



РИСУНОК 12.4. Менеджер приложений Server-Side JavaScript.



После активизации Server-Side JavaScript на Web-сервере, можно осуществлять удаленную компиляцию приложений, выполнив доступ к программе jsacRemote, посту-



Базовое подмножество языка JavaScript



Часть II



пающей вместе с Application Manager. Просто введите URL в свой экземпляр Enterprise Server и воспользуйтесь /jsacremote в качестве пути для доступа к приложению.



страницей, когда клиент получает доступ к приложению. Эта информация необязательна. •



Инсталляция приложений Для инсталляции приложения на сервере с использованием Server-Side JavaScript Application Manager, щелкните на вкладке Add Application. После выбора этой вкладки в правом фрейме окна отобразится HTML-форма, которую потребуется заполнить (см. рис. 12.5).



• External Libraries (Внешние библиотеки). Если приложение использует внешние библиотеки (например, библиотеки динамической компоновки, или DLL), введите здесь полный путь доступа к ним. •



РИСУНОК 12.5. Добавление приложения.



Заполните форму, основываясь на следующей информации: • Name (Имя). Введите имя приложения. Оно необходимо для доступа к приложению после его инсталляции. Например, если имя приложения — fireball, a URL сервера — www.junebug.com, доступ к нему можно получить так: http://www.junebug.com/fireball ПРЕДУПРЕЖДЕНИЕ



Убедитесь, что приложению не присваивается имя, совпадающее с именем существующего каталога на сервере. Если совпадение имеет место, клиент не сможет получить доступ к этому каталогу сервера. • Web File Path (Путь к .web-файлу). Введите полный путь и имя файла Web-приложения. •



Default Page (Страница по умолчанию). Введите имя HTML-файла, который будет служить страницей по умолчанию для приложения. Страница по умолчанию отображается, когда клиент, получивший доступ к приложению, не определяет файл в запросе.







Initial Page (Начальная страница). Введите имя HTML-файла, который будет служить начальной



Built-in Maximum Database Connections (Максимальное число встроенных соединений баз данных). Введите максимальное количество одновременных сое д и н е н и й , которые допускаются сервером баз данных, выполняющимся под управлением операционной системы NY Server.



Client Object Maintenance (Поддержка объекта Client). Это поле определяет режим поддержки постоянства объекта Client. Допустимые варианты включают: client-cookie, client-url, server-ip, servercookie и server-url.



По заполнении информации о приложении, щелкните на кнопке ОК в нижней части с т р а н и ц ы . Application Manager проверит введенные значения на предмет наличия ошибок и затем выполнит инсталляцию приложения на сервере. После инсталляции потребуется вернуться на вкладку Applications и убедиться, что ваше приложение в списке присутствует. Запустите приложение, щелкнув на Run. Доступ к приложению производится путем ввода адреса URL, где находится Enterprise Server, и следующего за этим URL имени приложения, отделенного наклонной чертой вправо. Рассмотрим пример вызова приложения туАрр: http: //www.mysite.com/myApp



ПРИМЕЧАНИЕ



?ff



После внесения определенных изменений в исходные тексты приложения и его повторной компиляции, при помощи Application Manager перезапустите приложение, чтобы изменения возымели действие.



Исправление ошибок Теперь, когда запуск произведен, следует получить доступ к приложению, дабы убедиться, что все работает предсказуемым образом. Если это действительно так, можно разрешать доступ к приложению и другим пользователям. Если же возникают какие-то проблемы, потребуется запустить отладчик приложений и выяснить, в чем же дело. Общая отладка При работе с клиентской и серверной частями JavaScript, можно прийти в некоторое замешательство, поскольку



по идее отлаживать необходимо как серверную, так у клиентскую часть. Внутри Application Manager существует отладчик, доступ к которому можно получит! путем выбора приложения из списка и щелчка на кнопке Debug. В результате открывается новое окно браузера с фреймом (или окном) трассировки, как показано на рис. 12.6. Окно трассировки отображает текущие объекты и их свойства. Также можно прибегнуть к услугам встроенной функции debug(), действующей подобно функции write(), для вывода в окно трассировки результатов вычисления JavaScript-выражения.



l,.fcyj



На.м-



;••.



!,v,™..,



Ht*:f.Wfi



- |



••'S.nfv



*,-,.WdeN^'^—



РЯ



',М>



%_,,,ЛЙ.„,„.



JiT.rWW.J^



Код состояния



Описание



0



I



Ошибок нет. Недостаточно памяти.



2



Объект не инициализирован.



3



Ошибка преобразования типов. Незарегистрированная база данных.



6



Ошибка, выданная сервером. Сообщение от сервера.



7



Ошибка от библиотеки поставщика.



8



Потеря связи.



9



Операция считывания завершена.



10



Неправильное использование объекта. Столбец не существует.



5



12



Неправильное размещение внутри объекта (ошибка выхода за границы).



13 15



Неподдерживаемая возможность. Нулевая ссылка. Объект базы данных не найден.



16



Отсутствует необходимая информация.



17



Объект не поддерживает множественное чтение. Объект не поддерживает удаление.



14



,к-,.;Г' •'.-.••»•••



Ошибки, связанные с базами данных Большинство методов, используемых для взаимодействия с базами данных, возвращают код состояния. Код состояния представляет собой целое число от 0 до 27. Код 0 уведомляет о том, что команда выполнена успешно, в то время как другие значения, перечисленные в табл. 12.1, указывают на ошибки, возникающие на сервере. Объект базы данных имеет четыре отладочных мег тода, которые возвращают код ошибки и соответствующее сообщение от сервера баз данных. Значения того,



ЫЫ



Таблица 12.1. Коды состояния баз данных.



11



РИСУНОК 12.6. Отладчик Server-Side JavaScript Application Л/anager.



ffft



Глава 12



что возвращается, зависит от сервера баз данных. В табл. 12.2—12.5 перечислены возвращаемые значения для четырех поддерживаемых SSJS баз данных SQL.



4 , ,



Серверная часть JavaScript







19 21 22 23 24 25



26



Объект не поддерживает вставку. Объект не поддерживает обновление. Объект не поддерживает обновление. Объект не может поддерживать индексы. Объект не может быть удален. Неправильное подключение. Объект не поддерживает привилегии. Объект не поддерживает курсоры. Открытие невозможно.



Таблица 12.2. Библиотека ошибок производителя Informix (код состояния 7). Метод



Что возвращает



majorErrorMessage()



Vendor Library Error: errorMsg (Ошибка библиотеки производителя: errorMsg) (errorMsg — это текст от Informix). ISAM Error: errorMsg (Ошибка ISAM: errorMsg) {errorMsg — текст кода ошибки ISAM от Informix либо пустая строка (""), если ошибки ISAM нет).



minorErrorMessageQ majorErrorCode()



Код ошибки Informix.



minorErrorCode()



Код ошибки ISAM либо нуль, если ошибки нет.



Базовое подмножество языка JavaScript Часть



Таблица 12.3. Ошибки сервера Oracle (код состояния 5). Метод



Что возвращает



majorErrorMessageO minorErrorMessage() majorErrorCode()



Server Error: errorMsg (Ошибка сервера: errorMsg) (errorMsg — трансляция кода возврата Oracle).



minorErrorCode()



Код ошибки операционной системы, переданный OCI.



Имя сервера Oracle. Возвращает код, переданный Oracle Call-level Interface (OCI).



Таблица 12.4. Библиотека ошибок производителя Sybase (код состояния 7). Метод



Что возвращает



majorErrorMessage()



Vendor Library Error: errorMsg (Ошибка библиотеки производителя: errorMsg) (errorMsg — это текст ошибки, полученный от DB-Library). Текст ошибки операционной системы (в соответствие со спецификацией библиотеки DBLibrary).



minorErrorMessage() majorErrorCode() minorErrorCode()



Номер ошибки DB-Library. Степень серьезности ошибки (в соответствие со спецификацией библиотеки DB-Library).



Таблица 12.5. Ошибки сервера Sybase (код состояния 5) Метод



Что возвращает



majorErrorMessage()



Server Error: errorMsg (Ошибка сервера: errorMsg) (errorMsg — текст, возращенный сервером SQL). Если степень серьезности ошибки и номер сообщения равны 0, возвращается только текст сообщения.



minorErrorMessage() majorErrorCodef)



Имя сервера SQL.



minorErrorCodeQ



Уровень серьезности (в соответствие со спецификацией сервера SQL).



Номер сообщения сервера SQL.



Базовые серверные объекты JavaScript Теперь, когда имеется представление о работе модели клиент/сервер в пространстве Internet и особенностях функционирования серверной части JavaScript, можно перейти к рассмотрению объектов, доступных при построении приложений (рис. 12.7). Основная цель серверных объектов заключается в управлении постоянными данными. Внутри Web-среды, не поддерживающей концепцию состояний, эти объекты могут постоянно хранить различные типы данных для разных запросов одного и того же клиента, для запросов множества клиентов и даже для различных приложениях SSJS.



Объект Server Объект Server используется для управления глобальными данными о самом сервере. Этот объект всегда присутствует на сервере SSJS и создается при его запуске. Он разрушается при завершении сервера. Встроенные методы и свойства объекта Server перечислены в табл. 12.6.



Запрос L | (request) Ц РИСУНОК 12.7. Структура базовых серверных объектов JavaScript.



Серверная часть JavaScript



Глава 12 Таблица 12.6. Встроенные методы и свойства объекта Server.



Тип



Элемент



Описание



Метод



lock() unlockO host hostname



Блокирует код во время выполнения манипуляций с данными с одним потоком. Освобождение ранее заблокированного кода. Строка, определяющая имя сервера, субдомена и домена Web-сервера. Полное имя сервера (включая порт); то же самое, что и объединение свойств host и port. Серверная версия JavaScript и платформа. Номер порта используемого сервером. Используемый Internet-протокол, присутствующий в адресе URL до первого двоеточия.



Свойство



jsVersion port protocol



Для того чтобы глубже понять работу методов lock() и unlock(), изучите следующий раздел, посвященный объекту Project. Методы этого объекта действуют совершенно аналогично.



Объект Project Объект Project разработан с целью поддержки информации о приложениях на клиентской части и обеспечения постоянства до тех пор, пока приложение на сервере не будет закрыто. Данный объект не содержит свойств, но только два метода, описанные в табл. 12.7. Таблица 12.7. Встроенные методы объекта Project. Метод lock()



unlock()



Описание Блокирует код во время выполнения манипуляций с данными, к которым подключен только один поток. Освобождает ранее заблокированный код.



Благодаря многопользовательской природе Web, к приложению SSJS могут одновременно получить доступ сотни и тысячи пользователей. В результате, вполне вероятна ситуация, когда большое число пользователей одновременно пытаются выполнить чтение или запись в объект Project. SSJS обеспечивает скрытое блокирование на весь период чтения и записи значения свойства. ПРИМЕЧАНИЕ Начиная с Netscape Enterprise Server 4.01, для объектов Project и Server скрытое блокирование не реализуется, как это имело место в предыдущих версиях.



Скрытая блокировка в данном случае не срабатывает, однако, для достижения требуемой цели можно прибегнуть к услугам метода lock() объекта Project. Метод lock() обеспечивает явную блокировку объекта вплоть до вызова метода unlock(). Например, для установки нового номера накладной можно использовать такой код: project, lock () ; project.invoiceNum += 1; project.unlock();



Если в этот момент доступ к объекту Project пытается получить другой клиент, ему придется ожидать завершения текущего процесса. ПРИМЕЧАНИЕ SSJS гарантирует отсутствие внутри экземпляра Project взаимной блокировки (или коллизии), когда два объекта блокируют базу данных. Это достигается автоматическим освобождением всех блокировок после отработки клиентского запроса.



Объект Client Как было показано, объекты Request существуют только в определенные моменты времени. Поскольку взаимодействие клиента с серверным приложением предполагает наличие более одного запроса, для поддержки состояния в течение серии запросов используется объект Client. Новые экземпляры объекта Client создаются каждый раз, когда новый клиент получает доступ к приложению. Подобно Project, объект Client не имеет свойств, но лишь только два метода, краткое описание которых приводится в табл. 12.8. Таблица 12.8. Встроенные методы объекта Client. Метод



Иногда требуется явная блокировка. Примером может послужить установка начального значения для увеличивающегося номера, скажем, накладной, которое хранится в свойстве. Для это необходимо прочитать старое значение, прибавить к нему какую-то величину и присвоить новое значение свойству.



destroy)) expiration!)



Описание Метод явно разрушает объект и все свойства, поддерживаемые объектом. Метод позволяет изменять 10-минутное по умолчанию истечение времени действия объектов Client на другой промежуток времени.



Базовое подмножество языка JavaScript Часть II Объект Client разработан таким образом, чтобы саморазрушаться по прошествии определенного промежутка времени. Основная причина заключается в том, что требуется поддерживать состояние в клиентских запросах, однако совершенно невозможно определить, какой запрос является последним. Поскольку никто не желает оставлять в памяти множество неиспользованных объектов Client, необходимо автоматически разрушать объект по истечению определенного промежутка времени. Время жизни объекта по умолчанию — 10 минут. Это значение можно изменить при помощи метода expiration(). Например, для увеличения периода времени до 20 минут потребуется записать следующий код: client.expiration(1200); Для изменения упомянутого времени метод expiration() должен вызываться на каждой странице приложения. Страницы, не имеющие обращения к expiration(), будут использовать значение времени по умолчанию.



Листинг 12.3. Регистрационная форма.



PeracTpauHH



Registration







Please provide the following contact information:



Name



Title







if (request. FullName != null) ( cLog = new File ("d:/netscape/suitespot/server4/logs/contlog. txt") ; project. lock() ; if (cLog.open("a") = true) { cLog.write(request. FullName + ","); cLog. write (request. Title + ","); cLog. write (request. Organization + ","); cLog. write (request. Email + ","); cLog. closet) ; ) pro ject. unlock () ; i



Registration



Please provide the following contact information : Name



name="Email"Xbr>







ОбъеКТ SendMail



бы пользователям возможности по отправке почтовых сообщений. Методы и свойства SendMail перечислены Еще один весьма полезный объект SendMail позволяет в табл. 12.13. отправлять сообщения через почтовый сервер. Как и Подобно объекту File, SendMail создается с исполъпредп слагалось, при помощи этого объекта можно созованием оператора new: здавать страницы приложения, которые предоставляли var myMessage = new SendMail ();



Базовое подмножество языка JavaScript



Часть II Таблица 12.13. Методы и свойства объекта SendMail.



Тип



Элемент



Метод



errorCodeQ



Описание Возвращает целочисленное представление кода ошибки, возникшей во время отправки сообщения. Возвращает строку, связанную с кодом ошибки, возникшей во время отправки сообщения.



errorMessage()



Свойство



send()



Отправляет электронную почту.



Вес



Разделенный запятыми список адресатов, получаемых скрытую точную копию сообщения.



Body Сс



Основной текст сообщения. Разделенный запятыми список адресатов, явно получаемых точную копию сообщения.



Errorsto



Имя пользователя, которому будут адресоваться сообщения об ошибках при отправке. Значение по умолчанию совпадает со значением свойства From.



From



Обязательное имя отправителя сообщения.



Organization



Название компании-отправителя или любая информация о ней.



prototype



Позволяет создавать новые свойства и методы для объекта SendMail.



Replyto



Имя пользователя, используемое вместо свойства From в качестве адреса, куда будет отправляться ответное сообщение.



Smtpserver



Имя хоста или IP-адрес SMTP.



Subject



Предмет сообщения.



То



Список получателей сообщения, разделенный запятыми



Объекты баз данных Одно из преимуществ серверной части JavaScript заключается в возможности взаимодействия с базами данных. Как упоминалось ранее, LiveWire вызывает SSJS, для чего, собственно, последний и используется. В настоящий момент LiveWire относится к функциональным средствам доступа к базам данных в среде SSJS. Чуть ниже будут рассматриваться базовые объекты, обеспечивающие упомянутый доступ.



Объект Database Объект Database инкапсулирует всю функциональность взаимодействия с реляционными базами данных. У данного объекта определено всего лишь одно свойство, в то



время как большинство действий реализуется через методы. Таблица 12.14 содержит краткие описания всех методов. Если до этого приходилось работать с базами данных в других языках программирования, несложно заметить, что JavaScript обладает практически всеми средствами взаимодействия с базами данных.



Объект DbPool Объект DbPool, появившийся в Netscape Enterprise Server 3, очень напоминает объект Database с тем лишь отличием, что этот объект представляет целиком весь пул подключений к базе данных. После создания такого пула, из него можно вытаскивать необходимые соединения. В табл. 12.15 представлены методы и свойство данного объекта.



Таблица 12.14. Методы и свойства объекта Database.



Тип



Элемент



Метод



begin TransactionQ



Начинает транзакцию SQL.



commitTransactionO



Выполняет текущую транзакцию SQL.



connect()



Подключает приложение к заданной базе данных.



connectedO



Возвращает true, если связь между приложением и базой данных установлена.



cursor()



Создает объект Cursor для заданной SQL-оператора SELECT.



disconnect()



Разрывает связь с базой данных.



execute()



Выполняет заданный оператор SQL. Используется для операторов SQL, которые не возвращают курсор.



majorErrorCode()



Главный код ошибки, возвращаемый сервером баз данных или ODBC.



Описание



Серверная часть JavaScript



Глава 12



Тип



Свойство



Элемент



Описание



majorErrorMessage()



Сообщение, соответствующее главному коду ошибки, возвращаемое сервером баз данных или ODBC.



minorErrorCode()



Вторичный код ошибки, возвращаемый библиотекой поставщика.



minorErrorMessage()



Сообщение, соответствующее вторичному коду ошибки, возвращаемое библиотекой поставщика.



rollbackTransaction()



Выполняет откат текущей транзакции SQL.



SQLTable()



Генерирует HTML-таблицу для вывода на экран результатов запроса SELECT.



storedProc()



Создает объект Stproc и запускает выбранную хранимую процедуру.



stored ProcArgs()



Создает прототип хранимой процедуры DB2, ODBC или Sybase.



toStringf)



Возвращает строку, представляющую заданный объект.



prototype



Позволяет добавлять методы и свойства к экземплярам объектов Database.



Таблица 12.15. Методы и свойства объекта DbPool.



Тип



Элемент



Описание



Метод



connect))



Подключает пул приложения к заданной базе данных.



connected()



Возвращает true, если пул подключен к базе данных.



connection!)



Захватывает доступное соединение из пула.



DbPool()



Создает пул соединений с базами данных.



disconnect!)



Закрывает все соединения с базами данных в пуле.



majorErrorCode()



Главный код ошибки, возвращаемый сервером баз данных или ODBC.



majorErrorMessage!)



Сообщение, соответствующее главному коду ошибки, возвращаемое сервером баз данных или ODBC.



Свойстзо



minorErrorCode()



Вторичный код ошибки, возвращаемый библиотекой поставщика.



minorErrorMessage()



Сообщение, соответствующее вторичному коду ошибки, возвращаемое библиотекой поставщика.



storedProcArgsQ



Создает прототип хранимой процедуры DB2, ODBC или Sybase.



toStringO



Возвращает строку, представляющую заданный объект.



prototype



Позволяет добавлять методы и свойства к экземплярам объектов DbPool.



Объект Connection



Объект Cursor



Объект Connection появился в Netscape Enterprise Server 3 и представляет собой связь, взятую из резерва связей с базами данных. Создается этот объект с помощью вызова метода DbPool.connection (). В таблице 12.16 представлены методы и свойство данного объекта.



Данный объект создается за счет вызова методов Connection.cursor() или database.cursor(). Поскольку запрос к базе данных требует вернуть курсор, этот объект содержит ссылку на строки, возвращаемые в результате выполнения запроса. В таблицу 12.17 сведены методы и свойства этого объекта.



Таблица 12.16. Методы и свойство объекта Connection.



Тип



Элемент



Описание



Метод



beginTransactionQ commitTransactionO



Выполняет текущую транзакцию SQL.



connected!)



Возвращает true, если связь между приложением и базой данных установлена.



cursor!)



Создает объект Cursor для заданной SQL-оператора SELECT.



execute!)



Выполняет заданный оператор SQL. Используется для операторов SQL, которые не возвращают курсор. Главный код ошибки, возвращаемый сервером баз данных или ODBC.



majorErrorCodeQ



Начинает транзакцию SQL.



Базовое подмножество языка JavaScript



Часть II Тип



Свойство



Элемент



Описание



majorErrorMessage()



Сообщение, соответствующее главному коду ошибки, возвращаемое сервером баз данных или ODBC.



minorErrorCode()



Вторичный код ошибки, возвращаемый библиотекой поставщика.



minorErrorMessage()



Сообщение, соответствующее вторичному коду ошибки, возвращаемое библиотекой поставщика.



release ()



Освобождает соединение, возвращая его в пул.



rollbackTransactionO



Выполняет откат текущей транзакции SQL.



SQLTable()



Генерирует HTML-таблицу для вывода на экран результатов запроса SELECT.



storedProc()



Создает объект Stproc и запускает выбранную хранимую процедуру.



toStringO



Возвращает строку, представляющую заданный объект.



prototype



Позволяет добавлять методы и свойства к экземплярам объектов Database.



Таблица 12.17. Методы и свойства объекта Cursor.



Тип



Элемент



Описание



Метод



closet)



Закрывает курсор и освобождает занимаемую им память.



coiumnName()



Принимает проиндексированную позицию столбца и возвращает соответствующее имя столбца.



columnsQ



Возвращает количество столбцов в рамках курсора.



deleteRow()



Удаляет текущую строку таблицы.



insertRowQ



Вставляет новую строку в таблицу.



Свойство



next()



Перемещает экземпляр объекта Cursor из текущей строки на следующую.



updateRow()



Обновляет текущую строку указанной таблицы.



columnName



Представляет имена столбцов, возвращаемых курсором.



prototype



Позволяет добавлять методы и свойства к экземплярам объекта Cursor.



Объект Resultset Данный объект (результирующий набор) создается после вызова метода Stproc.resultSet(). В нем сохраняются результаты выполнения хранимой процедуры. В случае выполнения процедур в базах данных DB2, Oracle, Sybase и ODBC объект Resultset возвращается для каждого оператора SELECT. В сервере Infomix будет возвращаться только один объект Resultset. В табл. 12.18 перечислены методы и свойства данного объекта.



Объект Stproc Объект Stproc создается в результате вызова методов Connection.storedProc() или database.storedProc() и вы-



полняет хранимую процедуру в базе данных, к которой получен доступ. Убедитесь, что вызов метода close() производится по завершении выполнения процедуры. В табл. 12.19 перечислены методы и свойства объекта.



Объект BLOB Последний базовый объект, достойный рассмотрения, обеспечивает поддержку работы с Binary Large Objects (большие двоичные объекты, BLOB) в базе данных. Объект не обладает свойствами, лишь только двумя методами (см. табл. 12.20).



Таблица 12.18. Методы и свойство объекта Resultset.



Тип



Элемент



Метод



close()



Закрывает результирующий набор и освобождает занимаемую им память.



columnNameO



Принимает проиндексированную позицию столбца и возвращает соответствующее имя столбца.



columns()



Возвращает количество столбцов в результирующем наборе.



next()



Перемещает экземпляр объекта Resultset из текущей строки на следующую.



Свойство



prototype



Описание



Позволяет добавлять методы и свойства к экземплярам объекта Resultset.



Серверная часть JavaScript



Глава 12



Таблица 12.19. Методы и свойства объекта Stproc. Тип



Элемент



Метод



close()



Закрывает экземпляр хранимой процедуры, освобождая занимаемую им память.



outParamCountQ outParameters()



Возвращает количество выходных параметров процедуры. Возвращает значение определенного выходного параметра.



resultSet()



Создает новый объект Resultset.



retumValue() Свойство



Описание



prototype



Выдает значение возврата хранимой процедуры. Позволяет добавлять методы и свойства к экземплярам объекта Stproc.



Таблица 12.20. Методы объекта BLOB. Метод ЫоЫтадеО blobLink()



Описание Извлекает из базы данных и отображает экземпляр данных типа BLOB. Извлекает из базы данных и отображает HTML-ссылку, которая адресуется на экземпляр данных типа BLOB.



Резюме Перед тем как приступить к созданию Internet-приложений, следует разобраться в их архитектуре. Предварительный доступ к серверу окажет существенную помощь в выборе метода разработки приложений типа клиент/сервер. Функциональность JavaScript вместе с механизмом баз данных позволяет перевести приложения на новый качественный уровень. Отдавая предпочтение клиентской или серверной обработке, следует принять во внимание быстродействие



и функциональность приложений JavaScript. He забывайте, что двух- и я-уровневая модели обладают как достоинствами, так и недостатками, и присущими им степенью сложности и сопровождения. Данная глава продемонстрировала, что в JavaScript важна не только клиентская, но и серверная часть. С использованием Netscape Server-Side JavaScript этот язык сценариев можно применить даже для создания целых Web-приложений.



Использование DOM ЧАСТЬ



В ЭТОЙ ЧАСТИ 13. Основы объектной модели документа (DOM) 14. Управление событиями 15. Объект Window 16. Объект Document 17. Объекты Form 18. Объекты Frame 19. Другие DOM-объекты



Основы объектной модели документа (DOM) В ЭТОЙ ГЛАВЕ Понятие объектной модели документа Навигация по таблице Управление



документами



Навигация по документу



В этой главе приводятся начальные понятия, касающиеся объектной модели документа (Document Object Model — DOM) и ее назначения, характеристик, объектов и некоторых важных методов и свойств. Конечно, здесь рассматриваются только основные принципы, например, навигация по документам, а также их визуализация в виде деревьев DOM. В данной главе будут показаны важные методы DOM, которые работают непосредственно с деревьями, хотя более детальные пояснения будут даны в главе 19, где DOM-модель рассматривается с точки зрения JavaScript.



Понятие объектной модели документа Ключевые успехи Web помогают решить давно стоящие проблемы. Например, Java обеспечивает путь разработки независимых от платформы прикладных Web-приложений с помощью аплетов, тогда как DOM-модель постепенно решает другую довольно старую (хотя и не столь важную) проблему создания JavaScript-сценариев и программ на Java, переносимых в контексте Web-браузеров. Это достигается за счет использования стандартных прикладных программных интерфейсов (application programming interfaces — API), которые входят в язык определения интерфейсов (Interface Definition Language - IDL), созданный Группой управления объектами (Object Management Group — OMG), и поэтому могут использоваться любым IDL-совместимым языком. Коллективный DOM API можно считать методом стандартизации объектов в браузерах при распространении HTML- и XML-документов. Web-браузеры становятся DOM-совместимыми, причем этот процесс идет быстрыми темпами. О DOM-модели, фактически, можно сказать немногое. Она просто определяет логическую и стандартизи-



рованную структуру документа. Это дает возможность формировать, редактировать и просматривать элементы и содержимое в HTML- или XML-документах. Структура DOM — это всего лишь объектная иерархия, сопоставимая с иерархией в JavaScript или любом другом основанном на объектах языке. Различие в том, что DOM-модель имеет полезный API, который является нейтральным языком и определяет стандартный набор интерфейсов. Это не означает, что все прикладные программы DOM будут основаны на одних и тех же объектах; они должны определять собственные интерфейсы и объекты. Это возможно осуществить путем настройки приложения так, чтобы оно, например, стало DOM-совместимым. РЕСУРС По адресу www.w3.org/TR/1999/CR-DOM-Level-219991210 находится "VV3C Document Object Model (DOM) Level 2 Specification". Более ранняя спецификация уровня Level 1 также находится на этом сайте. Информация, содержащаяся в спецификации, не передается непосредственно в JavaScript или другой ЕСМА-совместимый язык создания сценариев. Приложение Е спецификации показывает привязку к соответствующему ECMAScript языку. В Web появилось большое количество учебников по DOM и множество сопроводительных статей и документов.



От DHTML к DOM Приведение Web-страниц к объектной модели имеет много стадий, но самая существенная из них — DHTML, который сом по себе является довольно незначащим по сравнению с DOM. Это потому, что DOM — стандартизированная объектная модель, которую Web-разработчики ждали очень долго. Например, если Web-разработчик должен будет модифицировать или настраивать Web-



Использование DOM



Часть III страницу с помощью объектной модели DHTML, ему в качестве руководства потребуется значительный объем информации. Причина этому — огромное число HTMLдескрипторов, свойств, методов и событий. DHTML действительно не больше, чем средства, позволяющие изменять и управлять объектами с помощью атрибутов id и name. Это далеко от стандартизации и упрощения DOM, которая инкапсулирует целый документ в объектную модель, представляя его в виде иерархии или дерева. Узлы дерева представляют собой HTML-дескрипторы и текстовые сегменты, которые они могут содержать. Полный HTML-документ хранится в этом дереве, а все объекты и их отношения отображаются как дочерние и родительские элементы, а также элементы одного уровня. В отличие от DHTML, управлять и вносить изменения в DOM-дерево документов весьма несложно. Для изменений текстовых элементов, например, просто изменяют значения узла дерева с помощью свойства nodeValue. Кроме того, существует возможность создавать, удалять и перемещать узлы в дереве DOMдокумента. (Методы, которые позволяют это делать, описываются позже, в табл. 13.2.)



Навигация по таблице Для того чтобы лучше понять структуру дерева, рассмотрим структуру DOM-дерева простой таблицы (см. рис.



13.1). Здесь показаны свойства childNodes, firstChild, lastChild, nextSibling и previousSibling. Используем их, чтобы понять структуру дерева и научиться перемещаться к любой его части. В DOM-дереве таблицы

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



Управление документами Рассмотрим некоторые основные методы DOM, которые позволяют исполнять часто встречающиеся задачи. В своем API DOM определяет методы, которые должны создавать, удалять, вставлять, перемешать, менять местами и заменять узлы или объекты. Эти методы и их аргументы, описания и возвращаемые значения, или исходящие параметры, кратко описаны в табл. 13.2. Фактически, все это довольно очевидно; метод removeNode() удаляет поддерево, встроенное в указанный узел, если deep равно true. Если же deep — false, удаляется только указанный узел, а его дочерние объекты возвращаются текущему родительскому элементу предыдущего уровня. Другой метод, зависящий от логического параметра, cloneNode(). Когда параметр равен true, копируется поддерево, а когда он — false, копируется только узел.



Таблица 13.1. Выражения для навигации. Перемещение



Выражение



Ко второй строке таблицы.



tableNode.firstChild.childNodes[1] tableNode.firstChild.childNodes[1].childNodes[0]



К первой ячейке второй строки. К содержимому второй ячейки в первой строке. К корню второй строки.



tableNode.firstChild.firstChild.childNodes[1]. firstChild Tr2Node.parentNode.parentNode или



Tr2Node. previousSibling. parentNode.parentNode или



Tr2Node.previousSibling.previousSibling.parentNode.parentNode К каждой из ячеек и затем возврат в корень.



tableNode.firstChild.firstChild.firstChild.firstChild.parentNode.parentNode. parentNode.parentNode tableNode. firstChild. firstChild. childNodes[1].firstChild. parentNode.parentNode. parentNode.parentNode tableNode.firstChild.childNodes[1].firstChild.firstChild. parentNode.parentNode. parentNode.parentNode tableNode.firstChild.childNodes[1].childNodes[1].firstChild. parentNode.parentNode. parentNode. parentNode



К каждой из ячеек.



tableNode.firstChild.firstChild.firstChild. firstChild tableNode.firstChild.firstChild.childNodes[1].firstChild tableNode.firstChild.childNodes[1].firstChild.firstChild tableNode. firstChild.childNodes[1].childNodes[1].firstChild



Основы объектной модели документа (DOM)



Глава 13



РИСУНОК 13.1. Простая структура DOM-дерева таблицы.



lchildNodes[1] II OrlaslChiid I



I childNodes[0] I



IchildNodesl



[ dilldNodeslol I



| childHuDeluxe Room



very



Поскольку вид Web-страницы также важен, для ответа на события click вместо кнопок лучше использовать изображения. Хотя изображение не способно фактически ответить на любое событие, можно имитировать событие click с помощью объекта Link. Продемонстрируем это, используя изображение вместо кнопки "View Hat" для вызова метода disp!ayHat() из предыдущего примера. Для этого определим соответствующий объект Link:



Вместо добавления кода в обработчик события onCIick ссылки, здесь используется JavaScript в качестве протокола для свойства href. Использование JavaScript: JavaScriptExpression как значение свойства href заставляет браузер выполнить выражение JavaScript вместо перехода к определенной ссылке.



Отправка формы (onSubmit) Как обсуждалось в главе 1 , одно из преимуществ использования JavaScript в HTML-формах — возможность выполнения проверки правильности данных на стороне клиента вместо перекладывания этой задачи на и без того перегруженный сервер. Проверку правильности можно выполнять для каждого поля в отдельности или для всех полей сразу. В зависимости от контекста используется один или оба метода. Для проверки правильности данных во всех полях сразу, равно как и для других задач, главное значение имеет событие submit. Это событие генерируется как раз перед отправкой HTML-формы. Добавление кода в обработчик событий onSubmit объекта Form дает возможность совершить проверку, а затем разрешить продолжение или блокировать его, уведомив об этом пользователя. Событие submit произойдет, если от обработчика событий onSubmit не возвращается значение false. Любое другое значение (true или еще что-нибудь) приведет к генерации этого события. Например, предположим, что перед отправкой формы на сервер необходимо отобразить простое сообщение для пользователя с просьбой подтвердить заполнение формы заказа шляпы Kakata. Форма в HTML определяется следующим образом:



Метод confirmOrder(), используемый в обработчике событий onSubmit формы, объявляется в разделе файла: //обработчик событий onSubmit function confirmOrder() { return confirm('Are you certain you wish to '-•order the Kakata hat?') ; I



При включении метода confirmOrder() он отображает диалоговое окно Confirm с кнопками "ОК" и "Cancel". Если пользователь нажимает на "ОК", диалоговое окно закрывается и в обработчик событий onSubmit возвращается значение true. Если пользователь нажимает на "Cancel", возвращается false. Оператор return в обработчике событий onSubmit исследует входящее значение и определяет, нужно ли продолжать обработку формы. Оператор return в назначении обработчика событий необходим для корректной работы кода. Присваивание обработчику событий onSubmit = "confirmOrder()" запускает обработку формы независимо от возвращенного из диалогового окна значения. Обработчик событий onSubmit — то же самое, что и обработчик событий onCIick объекта Submit. Оба они — события, которые можно использовать, чтобы захватить форму прежде, чем она будет обработана. Как показано на рис. 14.3, обработчик событий onCIick объекта Submit был вызван до вызова обработчика onSubmit формы. Form OnCIick Yes



OnSubmit



Yes



Ч



РИСУНОК 14.3. Установление последовательности событий для отправки формы.



Обработчик событий onSubmit — идеальное место для размещения проверки правильности данных формы до ее отправки на сервер.



Сброс формы (onReset) Может понадобится вызвать событие и при сбросе формы, а не только при отправке. Обработчик событий onReset вызывает код JavaScript, когда происходит собы-



Управление событиями



Глава 14 тие reset. Так же, как onSubmit, onReset — обработчик событий объекта Form. Для демонстрации этого снова рассмотрим форму заказа шляпы Kakata, упомянутую в прошлом разделе. После добавления нового обработчика событий к определению объекта Form код будет выглядеть так:



Мегод confirmReset(), используемый в обработчике событий onReset формы, объявляется в разделе файла: //обработчик событий onReset: function confirmReset () { return confirm ('Are you certain you wish to w clear the order form? ' ) ;



Получение фокуса (onFocus) Событие focus вызывается, когда объект поля получает фокус, т.е. когда пользователь переходит к объекту с использованием клавиши "Tab" или с помощью щелчка мыши на объекте, либо когда вызывается метод focusQ объекта. В каждый момент времени фокус может иметь только один объект. ПРИМЕЧАНИЕ JavaScript 1.1 и последующие версии расширяют возможности onFocus, включая его в качестве обработчика событий для объектов Window, Frame и Frameset. Для каждого из этих объектов обработчик событий onFocus определяет действие, которое должно выполниться при переходе фокуса. Обработчик событий OnFocus должен размещаться внутри дескрипторов объектов Window, Frame или Frameset.



ПРИМЕЧАНИЕ Обработчик событий onReset поддерживается в JavaScript 1.1 и более поздних версиях.



Изменение данных (onChange) Как упоминалось в связи с событием submit, если прикладные программы JavaScript имеют дело с данными, обычно возникает необходимость в предварительной обработке данных, введенных пользователем, во избежание проблем проверки допустимости при отправке данных серверу. В то время как submit служит для проверки сразу всех полей формы, событие change обычно наиболее важно для проверки допустимости на уровне каждого поля формы. Событие change происходит, когда изменяется значение объектов поля и когда само поле выходит из фокуса. Для решения такого рода задачи используется обработчик событий onChange для выполнения JavaScriptкода либо вызова функции для обработки события. Предположим, что необходимо добавить базовую подпрограмму проверки допустимости данных в форму ввода данных для заказа шляпы Kakata. Скажем, требуется гарантия того, что содержимое поля "State" записано буквами верхнего регистра. Объект Text определяется следующим образом:



M етод convertToUppercase() преобразовывает значение поля "State" к верхнему регистру, используя метод toUpperCase() строки: function convertToUppercase (fieldObject) ( fieldObject. value = fieldObject. value. toUpperCase ( )



Обработчик событий onFocus в этих объекта может отвечать за переключение действия. Например, он может расширять стандартное поведение объектов Text в форме. При переходе к объекту Text курсор появляется по умолчанию. Однако, во многих средах (например, в Windows), если поле уже имеет значение, то при установке фокуса на объект содержимое поля выделяется. Для получения такого поведения (см. листинг 14.1) потребуется добавить обработчики событий onFocus каждому из объектов Text и Textarea: Листинг 14.1. Использование события onFocus для полей формы. First Name: Last Name: Title: Company: Street Address: City:











Хотя можно написать отдельные обработчики событий для каждого из полей, это будет нерациональным подходом, если только процессы не оказываются совершенно разными. Вместо этого в методе se!ectContents() пользуются преимуществом ключевого слова this для ссылки на вызывающий объект. Приведенная ниже функция тогда будет использоваться в качестве глобальной для всех объектов: function selectContents (fieldObject) ( FieldObject.select(); I



Когда один из объектов Text или Textarea вызывает метод selectContentsQ, метод использует параметр



fieldObject как ссылку на вызывающий объект. Затем метод select() осуществляет выбор информации в области ввода указанного объекта.



Выход из фокуса (onBlur) Событие blur (противоположность события focus) вызывается, когда объект теряет фокус. ПРИМЕЧАНИЕ



р



Как и с обработчиком событий onFocus, JavaScript 1.1 и последующие версии расширяют возможности onBlur, включая его в качестве обработчика событий для объектов Window, Frame и Frameset. Для каждого из этих объектов обработчик событий onBlur определяет действие, которое должно выполниться, когда окно теряет фокус. Обработчик событий OnBlur должен помещаться в дескриптор объектов Window, Frame или Frameset. Например, предположим, что для формы ввода данных нужна гарантия, что пользователь не оставил пустым объект EmailText. Такую проверку можно добавить в обработчик событий onBlur данного объекта. Поскольку она воздействует на одно поле формы, можно добавить JavaScript-код только к определению объекта Text: •Cinput type=text size=30 maxlength=256 name="Email" onFocus="selectContents(this)" onBlur="if (this.value == ' ' ) { alert('You must enter ^•something. ' ) ;this.focus() ; ) " > Если пользователь попытается убрать фокус из объекта без ввода текста в данное поле, сигнальное диалоговое окно уведомит о недопустимости. Следующая команда возвращает фокус к объекту EmailText. Без этой команды курсор перешел бы к следующему полю. Несложно заметить, что onChange и onBlur — очень похожие обработчики событий. Возникает вопрос о том, когда нужно использовать один, а когда другой. OnChange больше подходит для проверки или анализа содержимого объекта и обладает преимуществом в том, что не вызывается при изменении значения пользователем. С другой стороны, для обязательных полей лучше использовать onBlur. Важно понять правильный порядок следования обработчиков событий onChange, onBlur и onFocus. Как показано на рис. 14.4, onFocus происходит при входе в поле. При выходе из него вызывается onChange, затем onBlur и, наконец, обработчик onFocus следующего входного объекта. Имейте в виду, что код, который добавляется (например, в обработчик событий onChange), может воздействовать на обработчик событий onBlur того же самого объекта. Другими словами, использовать эти три события следует с особой осторожностью.



Управление событиями



Глава 14 First Name



First Name



onFocus



ПРИМЕЧАНИЕ Обработчики событий onMouseOver и onMouseOut также поддерживаются объектом Area в JavaScript 1.1 и последующих версиях.



onChange



V onBlur



mouseOver и mouseOut позволяет изменять в строке состояния текст по умолчанию.



onFocus



РИСУНОК 14.4. Порядок следования событий от одного объекта Text до другого объекта Text.



Выделение текста (onSelect) Следующее JavaScript событие — событие select, которое происходит, когда пользователь выделяет текст в объекте Text или Textarea. Обработчик событий onSelect этих объектов выполняет JavaScript-код или вызывает указанную функцию. Независимо от способа реализации, возможности события select довольно ограничены, и большинству разработчиков оно вообще может не понадобиться.



Перемещение мыши по объектам (onMouseOver и onMouseOut) Опытный пользователь Web, вероятнее всего, будет ожидать, что перемещение мыши по тексту ссылок отобразит место назначения ссылки (обычно URL-адрес). Однако, несмотря на то, что опытные пользователи хотят видеть URL-адрес, начинающие пользователи предпочли бы вместо этого увидеть нечто менее прозаическое. Это особенно актуально в intranet-средах, где URL-адрес обычно значительно менее понятен. Захват событий



Событие mouseOver генерируется, когда пользователь помещает курсор мыши поверх объекта Link или Area. Как и следовало ожидать, onMouseOut ведет себя таким же образом, за исключением того, что событие происходит, когда курсор уводится из Link или Area. Обработчики событий onMouseOver и onMouseOut этих объектов могут затем изменять заданное по умолчанию поведение браузера. Если необходимо установить свойства status и defaultStatus окна, следует возвратить в обработчик событий значение true. Например, предположим, что требуется отобразить следующий текст в строке состояния, когда для ссылки на шляпу Kakata генерируется событие mouseOver: Click here to get the whole story about the Legend of Kakata .



Для отображения данного текста добавьте в дескриптор Link обработчик событий onMouseOver: Legend of Kakata



Метод updateStatusBar() определяется таким образом: // обработчик событий onMouseOver function updateStatusBar {) { window. status = 'Click here to get the whole w story about the Legend of Kakata1; return true \



Все рассмотренные в главе примеры содержатся в файле Register.htm. Листинг 14.2 дает полный исходный код для этих примеров.



Листинг 14.2. Исходный код для Register.htm.



Kakata Hat Registration



Legend of Kakata



Hat Order



FornK/fontx/hl>



If you would like more information on the Legend of Kakata , fill out the following form.





If you would like to see a detailed picture of the Legend of Kakata Hat before ordering, please click the following button:



Customer Information



First Name: Last Name : Title : Company:



Street Address:



City : State : Zip Code : Telephone : «Cinput type=text size=12 maxlength=12 name=" Phone" onFocus="selectContents (this) "> FAX: Email : URL :



Are you Squot ; Kakata worthy Squot;? Please use the space below to enter a thorough reason for your order .







Использование DOM Часть III Form Submission Please click the Order button to order your free Legend of Kakata hat. You will receive email confirmation of your order in 24 hours.



snbsp;









• i



href="JavaScript:displayHat{)">







СОВЕТ При захвате множества событий mouseOver и mouseOut в объекте Area обработчик событий onMouseOut вызывается при уходе из этой области, затем при входе в следующую область вызывается onMouseOver.



Загрузка документа (onLoad) Начальное открытие окна или фрейма может оказаться важным моментом времени для выполнения определенного JavaScript-кода. Событие load позволяет использовать этот момент, добавляя обработчик событий onLoad к дескриптору в случае однофреймового окна или к дескриптору в случае мультифреймового окна. Событие load выполняется, когда браузер завершает загрузку окна или всех фреймов мультифреймового окна. Объект Window — единственный объект, который может работать с этим событием. В качестве примера рассмотрим ситуацию, когда нужно гарантировать, что все пользователи intranet-сети некоторой компании используют требуемую версию Netscape Navigator. Для этого можно определить браузер, применяемый обработчиком событий onLoad и затем уведомить пользователя, правильная ли у него версия п р о г р а м м ы . В дескриптор документа добавляют обработчик событий onLoad:



Затем в дескрипторе документа определяется метод checkBrowser(): //обработчик событий onLoad function checkerowser() { if ((navigator.appName = 'Netscape') ss (navigator.appVersion = '4.0 (Win95; I)')) { noticeWindow = window. open ("", "NoticeWindow" ,



"toolbar=0,width=300,height=100,resizable=0"); noticeWindow. document. write ("Upgrade >-*Notice") ; noticeWindow. document. write ("Your '••Web Browser needs to be updated. Please "••see your supervisor before noon. ^") ) Сразу после загрузки документа выполняется JavaScriptметод. На рис. 14.5 показан вид окна Upgrade Notice для версий, не прошедших испытания.



, • Ш • ••'"• РИСУНОК 14.5. Окно Upgrade Notice открыто с помощью обработчика событий onLoad. ПРИМЕЧАНИЕ У объекта Image также есть обработчик событий onLoad. Это событие вызывается, когда браузер выводит на дисплей изображение. Обратите внимание, что данное событие происходит не в процессе загруз-



Управление событиями



Глава 14 ки изображения клиенту, а в течение вывода на дисплей этого изображения.



Выход из документа (onUnload) Событие unload (противоположное событию load) вызывается непосредственно перед выходом пользователя из документа. Как и в случае с onLoad, обработчик событий onUnload можно добавлять в дескриптор в случае однофреймового окна или в дескриптор в случае мультифреймового окна. Если есть мультифреймовое окно и множество обработчиков событий onUnload для фреймов, то обработчик событий мультифреймового окна всегда выполняется в последнюю очередь. Приведем пример использования обработчика событий onUnload для очистки среды браузера перед переходом к следующей странице. Например, предположим, что требуется закрыть окно View Hat при уходе со страницы заказа шляпы Kakata. Можно добавить onUnload к дескриптору следующим образом:



Затем определяется метод clean(): // обработчик событий onUnload function clean () {



noticeWindow.close(); I



noticeWindow — глобальная переменная, которая объявляется в дескрипторе документа и ссылается на окно Upgrade Notice, отображенное с помощью обработчика onLoad. Окно Upgrade Notice закрывается, когда пользователь покидает текущую страницу. Листинг 14.3 показывает полный исходный код для onLoad и onUnload.



Обработка ошибок (onError) Объекты окна и изображения имеют обработчик событий onError, который позволяет отслеживать ошибки, возникающие в процессе загрузки документа или изображения. Отслеженная ошибка будет либо синтаксической ошибкой JavaScript, либо ошибкой времени выполнения программы, но не ошибкой браузера (типа сообщения сервера о том, что страница не существует). Глава 33 дает полное представление об отслеживании ошибок с помощью onError. ПРИМЕЧАНИЕ



Обработчик событий onError поддерживается в JavaScript 1.1 и последующих версиях.



Листинг 14.3. Исходный код для LoadUnload.htm.



Load/Onload Example







Intranet Home Page



Использование DOM



Часть III



Прерывание загрузки изображения (onAbort)







В зависимости от размеров HTML-изображения, загрузка его может занимать много времени. В результате пользователи могут потерять терпение и остановить загрузку изображения до ее завершения. Например, пользователь может прервать процесс загрузки, щелкнув на ссылке на другую страницу или нажав кнопку "Stop" в меню браузера.







Обратите внимание, что обработчики событий — это ссылки на функции, поэтому при определении в коде не нужно добавлять к ним круглые скобки. Если бы код был определен так, как показано ниже, функция optionBQ была бы вызвана, но не назначена в качестве обработчика событий: document.forml.buttonl.onclick=optionB()



Программная генерация событий До сих пор в данной главе обсуждался ответ на события, сгенерированные пользователем (например, событие click) или системой (например, событие onllnload). В большинстве случаев код проектируется так, чтобы отвечать на эти события, как только они происходят. Однако, разработчики JavaScript не должны рассчитывать только на внешние факторы, генерирующие события. В действительности, можно вызывать возникновение некоторых из этих событий внутри кода. Например, можно смоделировать событие click для объекта Button, вызывая его метод click(). Хотя это верно для объекта Button, но, например, для объекта Link (у которого имеется обработчик событий onClick) метод click() не существует.



События таймера Множество управляемых событиями сред программирования используют событие таймера, которое является событием, вызываемым каждый раз по прошествии заданного интервала времени. Хотя JavaScript не предлагает событие типа таймера, для тех же целей можно использовать метод setlnterval объекта Window. ПРИМЕЧАНИЕ



Метод setlnterval поддерживается в JavaScript 1.2 и последующих версиях. function options()







{



Метод setlnterval многократно вызывает функцию или вычисляет выражение каждый раз по истечении указанного интервала времени (в миллисекундах). Этот метод будет выполняться, пока окно не закроется или пока не будет вызван метод clearlnterval.



Управление событиями Глава 14



Например, в листинге 14.5 метод setlnterval выполняется, когда документ открывается и начинает вызывать функцию dailyTaskQ каждые 10000 миллисекунд. Функция dailyTask() при каждом вызове проверяет время, и в 8:30 утра начинает выполняться код в операторе if, предназначенный для подачи сигнала пользователю и очистки интервала. Как только вызывается метод clearlnterval, выполнение setlnterval останавливается. Листинг 14.5. Исходный код для Timer12.htm.







При использовании JavaScript 1.1 или более ранней версии можно выполнять подобный процесс (хоть и не таким прямым способом) с помощью методов setTimeoutQ и clearTimeout(). Обычно метод setTimeout() используется для вычисления выражения по прошествии определенного промежутка времени. Это вычисление — одноразовый процесс, который не повторяется бесчисленное количество раз. Однако, поскольку в JavaScript есть возможность производить рекурсивные вызовы функции, рекурсию можно использовать для создания события таймера де-факто. Предположим, что каждое утро в 8:30 необходимо выполнить задачу, описанную немного выше. Для этого нужно иметь таймер, вычисляющий время; когда это время достигнуто, процесс запускается. Метод dailyTaskO определяется так: function dailyTaskO { var tdy = new Date () ; if ((tdy.getHoursO = 8) && (tdy.getMinutesO =30)) { performProcess()} timerlD = setTimeout("dailyTaskO ",10000) I



Метод создает объект Date, содержащий текущее время, с помощью getHours() и getMinutes(). Если они вычисляют 8:30 утра, вызывается метод performProcess().



Следующая строка — основа процесса таймера — использует метод setTimeout() для рекурсивного вызова метода dailyTaskO каждые 10000 миллисекунд. ПРИООТРЁЖЕНИЕ Этот пример демонстрирует определенные трюки в отношении таймера, и лучше быть поосторожнее с подобной реализацией процесса в реальных задачах. Осуществление такого непрерывного процесса выполнения цикла е браузере может привести, в конце концов, к нехватке ресурсов.



Для запуска таймера при загрузке документа потребуется добавить обработчик событий on Load в дескриптор HTML-документа:



Листинг 14.6 содержит полный исходный код приме-



ра. Листинг 14.6. Исходный код для Titner11.htm.







Резюме Учитывая управляемый событиями характер JavaScript, можно утверждать, что твердое понимание встроенных событий — ключ к максимальному увеличению его мощности. В главе рассматривались события и связанные с ними обработчики событий. Особое внимание уделялось событиям, наиболее полезным для разработчиков, а также определенным примерам их использования. Эти базовые знания понадобятся в следующих главах, в которых будут детально рассматриваться встроенные JavaScriptсобытия.



Объект Window В ЭТОЙ ГЛАВЕ Объект



Window



Открытие и закрытие окон Навигация между окнами Отображение



окон



сообщений



Работа с сообщениями строки состояния



Объекты браузера Navigator — это объекты самого высокого уровня в иерархии JavaScript-объектов. Эти объекты не имеют дело с HTML; они имеют дело прежде всего с браузером, например, с открытием новых окон браузера, перемещением по списку посещений или получением имени хоста из текущего URL. В этой главе подробно рассматривается объект Window (который, как было сказано, находится на вершине объектной иерархии), а также упоминается группа других объектов, хотя детальное объяснение им будет дано в следующих главах. Эта группа включает в себя объект Frame, который будет обсуждаться в главе 18. Кроме того, рассматриваются объекты Location, History и объект Navigator уровня приложения.



Объект Window Объект Window верхнего уровня, который является родителем других дочерних объектов, присутствует на каждой Web-странице, и, безусловно, в одном JavaScriptприложении их можно иметь несколько. Основные



методы объекта Window реализуют вполне очевидные функциональные возможности (см. табл. 15.1): Как было показано в главе 9, Window — объект верхнего уровня в иерархии объектов JavaScript. В отличие от других объектов, которые могут присутствовать или отсутствовать в среде выполнения, объект Window всегда присутствует — либо в мультифреймовом окне, либо в одиночном. Однако, отличие объекта Window от других заключается в том, что его часто можно просто игнорировать. Вот две причины этого. Первая причина: при работе в среде одиночного фрейма можно игнорировать явную ссылку на объект Window. JavaScript выводит ссылку в текущее окно. Например, следующие два кода эквивалентны и выдают один и тот же результат: myTitle = window.document.title myTitle = document.title Вторая причина: в силу особой структуры языка JavaScript, некоторые методы системного уровня (например, всплывающие окна сообщений или установка таймера) присвоены объекту Window.



Таблица 15.1. Основные методы объекта Window. Метод Open и Close Alert Confirm Prompt



Описание Открытые и закрытие окна браузера; есть возможность определять размер окна, его содержимое, а также наличие кнопочной панели, поля адреса и других атрибутов. Появление окна сигнального диалога с соответствующим сообщением. Появление окна диалога подтверждения с кнопками "ОК" и "Cancel". Появление окна диалога подсказки с полем текстового ввода.



Blur и Focus ScrollTo



Удаление или установка фокуса на окно. Прокрутка содержимого окна до определенной точки.



Setlnterval



Установка временного интервала между функциональным вызовом и вычислением выражения.



SetTimeout



Установка однократного временного интервала до функционального вызова или вычисления выражения.



Объект Window Глава 15 Однако, для вызова этих методов нет необходимости использовать ссылку непосредственно на окно; такая ссылка будет неявной. Работа с объектами Window — сложная часть программирования на JavaScript из-за способов, по которым пользователи применяют окна браузера. Хотя большинство пользователей обычно имеют дело только с одним окном, иногда бывает полезно открыть сразу два и больше окон. Так можно сравнивать страницы различных сайтов, вводить информацию в форму, используя данные с другой Web-страницы, а также проводить поиск элементов списка одной страницы, просматривая ссылки с помощью еще одного экземпляра браузера. Термин окно браузера часто сокращается до просто окна, хотя нужно быть внимательнее и не путать разные копии браузера с фреймами, которые также называют окнами (подокнами окна браузера). Окно браузера также называют верхним (top) окном, потому что фреймы — это подокна браузера. Браузеры, поддерживающие JavaScript, позволяют программно открывать и закрывать окна браузера, а также перемещаться по этим окнам. Сайт с отдельными окнами сможет обеспечить сразу несколько версий содержимого, увеличив тем самым доступ к информации и возможностям и предложить новые пути более полного взаимодействия с сайтом. ПРИМЕЧАНИЕ В JavaScript 1.2 в Window было добавлено несколько новых методов: atob, back, btoa, captureEvents, clearlnterval, crypto.random, crypto.signText, disableExternalCapture, enableExternalCapture, find, forward, handleEvent, home, moveBy, moveTo, releaseEvents, resizeBy, resizeTo, routeEvent, scrollBy, scrollTo, setHotKeys, setlnterval, setResizable и setZOptions. Кроме того, добавилось несколько новых свойств: crypto, innerHeight, innerWidth, locationbar, menubar, offscreenBuffering, outerHeight, outerWidfh, pageXOffset, pageYOffset, personalbar, screenX, screenY, scrollbars, statusbar и toolbar. Для JavaScript 1.2 требуется Navigator 4.0-4.05, в то время как для JavaScript 1.3 — Navigator 4.06-4.5. Во многих случаях для одновременного просмотра страниц удобнее использовать фреймы (см. главу 18). Однако, у пользователей есть возможность изменять размеры и положение множества отдельных окон браузера. Пользователи могут также сворачивать и разворачивать окно, при необходимости перемещать окно поверх или вниз всех окон и сохранять все инструментальные средства и другие особенности (строку меню, поле адреса, строку состояния, закладки и т.д.) в каждом экземпляре браузера.



СОВЕТ Многие пользователи считают отвлекающим и раздражающим неожиданное открытие новых окон браузера, в особенности, если они потом должны сами закрывать их. Уведомьте посетителя о том, что данное действие откроет новое окно — например, с помощью короткого примечания рядом со ссылкой. В следующем примере Spike — это ссылка, которая открывает новое окно: See a picture of my dog Spike, (new window)



Открытие и закрытие окон ПРИМЕЧАНИЕ Пользователь в любой момент может открыть новое окно, выбрав File, New Browser (или что-то подобное). Однако, сослаться на такое окно из JavaScript не удастся. При помощи JavaScript можно открывать и закрывать окна браузера. Разработчик может создать новое окно с определенным документом, загружающимся в него при выполнении некоторых условий. Можно также указать, например, размер нового окна и параметры, доступные в окне, а также присвоить окну имя (для ссылок на него). Хотя открытие окна подобно созданию нового объекта Window, в данном случае конструктор new не используется. Вместо этого применяется следующий синтаксис: WindowVar = window.open [ , windowFeatures])



(URL, windowName,



Параметры метода openQ: •



URL. URL целевого окна. Этот параметр не обязателен. Если URL — пустая строка (""), браузер открывает пустое окно, позволяя использовать метод write() для создания динамического HTML.







windowName. Имя объекта Window. Имя также не обязательно; однако для обращения к окну с помощью ссылок или форм имя необходимо. Можно присвоить имя позже, через свойство window.name.



• windowFeatures. Список атрибутов отображения для окна браузера. Если окно открылось, метод ореп() возвращает метку объекту Window. Если окно почему-либо не было открыто, данный метод возвращает значение Null. ПРИМЕЧАНИЕ В9ННВ" Два имени, относящихся к окну, функционально — не одно и то же. Рассмотрим следующий код: myWindow=window. open (" " , " newWindow ") ; myWindow — переменная объекта, который открыл newWindow. newWindow — имя нового окна. На свойства нового окна можно ссылаться с помощью переменной myWindow. Ссылки и формы могут об-



Использование DOM



Часть III ращаться к новому окну с использованием его имени new Window.



Ссылки на окна При работе с одиночными и множественными фреймами в JavaScript-приложениях, возможно, потребуется использовать и другие способы ссылок на окна. JavaScript обеспечивает четыре вида ссылок на окна, и каждый из них реализуется как свойство объекта Window. Более подробная информация относительно ссылок на окна и фреймы будет дана в главе 18.



Отдельные окна браузера не имеют иерархической структуры; однако, окно, содержащее код, который открывает другое окно, часто называется родительским окном. Соответственно, новое окно называется дочерним. Любое новое окно можно присвоить переменной из других окон так, чтобы другие окна могли ссылаться на нее и ее свойства. Для ссылки на свойство в новом окне используйте windowName.property. Рассмотрим следующий код: newWinciow = window. open () ; newWindow. location, href = "http://www.mcp.com/"; Хотя этот фрагмент — не самый эффективный способ записи кода, он демонстрирует способ ссылки на свойство дочернего окна. Новое окно открывается и получает имя (в данном случае, newWindow). Затем устанавливается location.href нового окна.



Текущее окно В главе 9 обсуждалось использование окон для ссылок на текущее окно. Однако, не было упомянуто, что объект Window содержит свойство под названием window, которое может использоваться как инструмент ссылки на самого себя. Кроме того, свойство self объекта Window — еще одно средство сделать окно текущим или активным. Например, следующие две строки кода — функционально идентичны: window. defaultStatus = "Welcome to the Goat '•* Farm Home Page" self. defaultStatus = "Welcome to the Goat Farm w Home Page" Поскольку window и self — синонимы текущего окна, может показаться странным, что оба они включены в язык JavaScript. Как показано в предыдущем примере, это объясняется необходимостью увеличения гибкости, т.е., по желанию, возможно использовать либо window, либо self. Однако, насколько полезными могут быть window и self, настолько же они могут стать запутанными, если подойти к этому логически. В конце концов, свойство объекта, которое используется как эквивалентный тер-



мин для самого объекта, довольно необычно. Следовательно, window и self будет удобнее считать зарезервированными словами для объекта Window, а не его свойствами. Поскольку window и self — свойства объекта Window, нельзя использовать и window, и self в одном и том же контексте. Например, следующий код не будет работать: window.self-document.write("Test.") Наконец, в мультифреймовых средах window и self всегда относятся к окну, в котором выполняется JavaScriptкод. ПРИМЕЧАНИЕ В некоторых объектно-ориентированных или основанных на объектах языках self может относиться к активному объекту, независимо от его типа. В JavaScript self относится только к активным объектам Window или Frame — и ни к чему больше.



Определение содержимого окна Параметр URL определяет, какое содержимое появится в новом окне. Если задается какое-то значение, браузер пытается найти и отобразить указанный документ: NewWindow = window.open("http:// www.acadians.com", "AcadiaPage", LO:WRONG) С другой стороны, можно отобразить пустую страницу, указав в качестве параметра URL пустую строку (""). Используйте эту методику при необходимости динамического создания HTML-страницы с использованием JavaScript: newWindow = window.open("", "DynamicPage" " " ) newWindow.document.write("Document created Busing JavaScript.") newWindow.document.close() В главе 16 подробно рассматривается использование метода write() объекта Document для создания динамического HTML.



Определение атрибутов окна Параметр windowFeatures необходим при отображении окна, т.к. с его помощью настраивается внешний вид открытого окна. Параметр windowFeatures не обязателен; если он не используется, отобразится окно с такими же атрибутами, как у текущего окна. Таблица 15.2 содержит список атрибутов внешнего вида окна. ПРИМЕЧАНИЕ Атрибуты alwaysRaised и z-lock, добавленные в JavaScript 1 .2, работают только на платформах Windows и Macintosh.



Объект Window



Глава 15 Таблица 15.2 . Атрибуты метода openQ для отображения окна. Атрибут



Описание



width



Ширина клиентской области Navigator в пикселах. См. innerWidth, который появился в JavaScript 1.2.



height



Высота клиентской области Navigator в пикселах. См. innerHeight, который появился в JavaScript 1.2.



dependent



Если значение равно yes, создает дочернее окно из текущего окна; в Windows дочернее окно в панели задач не появляется. Дочернее окно закрывается одновременно со своим родительским окном. Появился в JavaScript 1.2.



toolbar



Отображает/скрывает инструментальную панель браузера.



menubar



Отображает/скрывает меню браузера.



scrollbars



Отображает/скрывает горизонтальную и вертикальную полосы прокрутки браузера.



innerWidth



Определяет ширину области содержания окна. Окна размером меньше, чем 100x100 пикселов, требуют подписанного сценария. Атрибут появился в JavaScript 1.2. Заменяет width, который также может использоваться для совместимости сверху вниз.



innerHeight



Определяет высоту области содержания окна. Окна размером меньше, чем 100x100 пикселов, требуют подписанного сценария. Атрибут представлен JavaScript 1.2. Заменяет height, который также может использоваться для совместимости сверху вниз.



resizable



Разрешает/запрещает изменение размеров окна браузера.



screenX



Определяет расстояние от левой стороны экрана до нового окна. Окно может быть помещено за пределами экрана с помощью атрибута в подписанных сценариях. Появился в JavaScript 1.2.



screenY



Определяет расстояние от вершины экрана до нового окна. Окно может быть помещено за пределами экрана с помощью этого атрибута в подписанных сценариях. Появился в JavaScript 1.2.



status



Отображает/скрывает строку состояния браузера,



location



Отображает/скрывает окно URL-адреса.



directcries



Если значение равно yes, отображает вторичную инструментальную панель (Netscape) с кнопками наподобие "What's New" и "What's Cool".



copyhistory



Копирует список посещений текущего окна в новое окно.



outerWidth



Ширина окна Navigator в пикселах (JavaScript 1.2).



outerHeight



Высота окна в пикселах (JavaScript 1.2).



left



Расстояние в пикселах от левой стороны экрана (JavaScript 1.2).



top



Расстояние в пикселах от верха экрана (JavaScript 1.2).



alwaysLowered



Создает окно браузера, которое всегда помещается ниже других окон, независимо от того, является ли оно активным (появился в JavaScript 1.2). Безопасная возможность, требующая подписанного сценария.



alwaysRaised



Если значение равно yes, создает окно браузера, которое помещается выше других окон, независимо от того, является ли оно активным. Появился в JavaScript 1.2. Безопасная возможность, требующая подписанного сценария.



z-lock



Создает новое окно браузера, которое не всплывает поверх других окон при помещении в фокус (JavaScript 1.2).



Атрибуты height и width определяют размеры окна в пикселах и совместимы сверху вниз с JavaScript 1.0 и 1.1, хотя предпочтительнее использовать вместо них соответствующие ключевые слова — innerWidth и innerHeight. Остальные атрибуты устанавливаются с помощью логически* значений: значение true — 1, yes или атрибут alone; значение false — 0, по или отсутствие атрибута вообще. Например, если необходимо отобразить новое окно только с инструментальной панелью и меню, используют следующий синтаксис: NewWindow = window.open (LO:WRONG, " toolbar=l, menubar=l")



"myWindow",



Следующий синтаксис также допустим: NewWindow = window, open ("", "myWindow", "toolbar=yes, menubar=yes") NewWindow = window.open (" " , "myWindow", "toolbar, menubar") Таким образом, можно просто не учитывать те атрибуты, которые не определены. Эти атрибуты имеют значения false. ПРИМЕЧАНИЕ Атрибуты outerWidth, outerHeight, left и top, добавленные в JavaScript 1.2, обеспечивают абсолютное пози-



Использование DOM Часть III ционирование окон браузера на рабочем столе. InnerWidth и innerHeight обеспечивают контроль над точными размерами окон браузера, хотя при использовании JavaScript 1.0 или 1.1 вместо них необходимо применять ключевые слова width и height. СОВЕТ Ошибка в некоторых версиях браузера Netscape Navigator не позволяет использовать метод window.openl) для отображения документов. Для обхода этой ошибки нужно повторить команду открытия окна: myWindow = window, open ("new.html" , "newWindow"); myWindow = window.open("new.html", "newWindow"); При таком повторении newWindow и его документ отобразится во всех версиях браузеров Netscape Navigator. ПРИМЕЧАНИЕ В дополнение к методу window.openl), для открытия нового окна можно также применять атрибут ссылки TARGET = "_blank" или даже целевой атрибут со значением любого имени (окна или фрейма), не используемого в данный момент. Ссылка foo открывает окно браузера, именует заголовок окна и загружает в окно документ foo.html, пока одно из текущих окон или фреймов не получит имя bar (имена окон и фреймов зависят от регистра). Кроме того, ссылка TARGET = "_blank" создает непоименованное окно, которое в дальнейшем тяжело поддается модификациям. С помощью _blank ссылка (та же самая ссылка или другая) просто создает еще одно новое окно вместо обновления открытого ранее.



Закрытие окон Для закрытия окна используют метод close() объекта Window. Если требуется закрыть текущее окно, вызов метода будет выглядеть просто как window.close(). В отличие от других методов объекта Window, таких как alert() или setTimer(), метод closeQ должен всегда сопровождаться объектной ссылкой. Если метод close() использовать без объектной ссылки, может закрыться текущий документ, а не окно, в зависимости от контекста вызова метода. Причина в том, что объект Document



также имеет метод close(). Таблица 15.3 содержит некоторые типичные коды сценария, в которых можно применять метод close (). ПРИМЕЧАНИЕ Более поздние версии Netscape не допускают, чтобы метод window.closel) закрывал окна, которые были созданы не JavaScript. Эта мера защиты не позволяет шутникам вставлять нежелательный код в гостевые книги и т.п. Данная мера не затрагивает любое законное использование метода window.close!). Функция или обработчик событий с window.close() закрывают окно, содержащее их:



ПРИМЕЧАНИЕ Для обработчика событий типа onClick необходимо определять имя окна, например, window, parent, top, self либо имя установленной переменной, например, myWindow, как в window.closel) или в myWindow.closel). Простое использование closed в обработчике событий подразумевает document, close!). Можно закрывать окно с помощью ссылки на то же самое окно, из которого данное окно было открыто, используя переменную, установленную равной новому окну: myWindow = window.open("new.html", "newWindow");



ПРИМЕЧАНИЕ new Window.closel); работать не будет. Имя newWindow можно использовать в предыдущем примере для идентификации окна (свойство window.name) и для адресации окна в ссылках и формах. Однако, нельзя использовать newWindow для ссылки на новое окно и его свойства.



Таблица 15.3. Метод close() и открывающие окна. Close()/Opener



Описание



window.opener.close()



Закрывает окно, из которого было открыто текущее окно.



document.write("
opener property is " + window.opener.name)



Определяет имя окна, из которого было открыто текущее окно.



top.opener.close()



Закрывает главное окно браузера.



window.opener.document.bgColor='bisque'



Изменяет цвет фона окна, определенного свойством opener.



window.opener=null



Устанавливает значение свойства opener равным Null, предотвращая закрытие открывающего окна.



Объект Window



Глава 15 СОВЕТ



:



При использовании метода window.closel) хорошо было бы обеспечить кнопку или ссылку для пользователей, чтобы они могли закрыть новое окно по завершении работы с ним. (Некоторые пользователи, в особенности новички, могут не знать, как закрыть окно, или могут по ошибке выйти из браузера вместо закрытия окна.) Можно использовать условный оператор для создания закрывающей кнопки или ссылки, если документ загружен в названном явно окне (новое окно):



Форма на рис. 15.1 демонстрирует различные аспекты открытия и закрытия окон. Заполняя форму, можно по желанию определить просмотр нового окна.



Г status



Г Location



Г Э|ГГ-с1Шага



Г кезгсаы



Г Directories



Г copy Hio



В первом поле определяют параметр URL — используя существующий URL или создавая страницу "на лету". Второе поле позволяет определять каждый из доступных атрибутов окна. По умолчанию все поля не заполнены. Можно заполнить требуемые из них. За счет заполнения полей "Custom Size" можно определить размеры нового окна. При нажатии кнопки "Open Window" всплывает новое окно, показанное на рис. 15.2. Листинг 15.1 содержит исходный код этого примера.



Листинг 15.1. OpenWindow.htm.



Window Open



Window Open Example Please select the following display options and then click the Open Window button.



Would you like an existing page or one created on the fly?

Existing Page



Dynamic Page





Window Attributes :

Toolbar Menubar Scrollbars Resizable Status Location Directories Copy History Custom Size



Объект Window Глава 15 Width : type=text size=5 maxlength=5



Height: type="button" name= " OpenBu tton " value="Open Window" onClick="openWindow() "> type="button"



. .'.'.< .-„^ :,r.--K-w»,) ..'fi~!.-4'..4.- tro,: :.vr,^,,! WL-ifeWLi . • l



l







  • What other magazines do you currently subscribe to? PC Week DBMS Wired Yahoo InfoWorld Databased Advisor Web Publisher



    • .



    .



    РИСУНОК 15.5. Диалоговое окно подтверждения возвращает ответ пользователя.



    Пользовательский ввод Третье диалоговое окно, которое можно использовать для получения пользовательского ввода, вызывается с помощью метода Prompt() объекта Window. Воспользуйтесь диалоговым окном подсказки, когда требуется получить значение от пользователя. Это диалоговое окно



    Объект Window Глава 15



    состоит из сообщения, поля пользовательского ввода и кнопок "ОК" и "Cancel". Метод Prompt() имеет следующий синтаксис: returnValue = defaultReply)



    [window.]prompt(message,



    Как видно из этого примера, в дополнение к указанию сообщения диалогового окна необходимо определить параметр defaultReply. Это значение будет заданным по умолчанию текстом, вставляемым в поле пользовательского ввода окна. Данный параметр нужно определять даже в том случае, когда он не имеет никакого значения по умолчанию. ПРИМЕЧАНИЕ Будьте уверены, что для диалогового окна подсказки определен заданный по умолчанию ответ. Если не добавлять этот параметр, JavaScript поместит в поле ввода Undefined, которое может запутать пользователей. Если значений по умолчанию нет, используйте для этого параметра пустую строку ("").



    New Frameset











    Листинг 16.7. Исходный код нижнего фрейма.



    Links



    Launching Pad




  • Software







    Magazines







    Search







    JavaScript



    Borland



    Использование DOM



    Часть III Web Informant
    Excite



    Gamelan
    Microsoft



    JavaWorld



    Yahoo



    JavaScript Index
    Netscape



    £"CWeeJc







    Alta Vista
    JavaScript Res. Center




    finbsp;
    InfeWorld



    developer /conference/proceedings "> Netscape Conference




    Листинг 16.8. Исходный код верхнего фрейма.



















    Выполнение JavaScript-кода для ссылок Используя javascript в качестве элемента протокола href ссылки, можно выполнять выражение JavaScript вместо обычного действия ссылки (вместо перехода на новую Web-страницу или отправки сообщения по почте). Однако, выполняемый код должен быть самодостаточным. Нельзя ссылаться на другой объект вне его контекста, например, на другое окно. Ссылку можно использовать для определения типа пользовательского браузера, как показано в следующем коде:



    All Netscape users, click me В качестве второго примера приведем оглавление первого издания этой книги в HTML-документе со ссылками на каждую ее часть. Для атрибута href этих ссылок описание каждой части помещается в окно сигнального сообщения. Листинг 16.9 показывает HTMLкод для данного примера, а рис. 16.7 — результат после щелчка на ссылке "Part Ш".



    Объект Document



    Глава 16 Листинг



    16.9.



    Создание



    оглавления



    со



    ссылками



    document.alertQ.



    _



    JavaScript Unleashed Table of Contents



    . Помимо off (опции по умолчанию), существуют еще две дополнительных опции: •



    virtual. Если параметр WRAP= установлен в virtual, строки переносятся на экране на границе области объекта Textarea, однако новая строка определяется только через нажатие клавиши "ENTER".







    physical. Если параметр WRAP= установлен в physical, строки переносятся на экране, а при отправке данных на сервер в конце каждой экранной строки устанавливается символ возврата каретки.



    Объекты Button: Submit, Reset и Button



    [onSelect="jnethoc£Name"] > displayText



    •Ctextarea name=" Comments"



    Перенос текста в объекте Textarea



    cols=78>



    На рис. 17.4 показана результирующая форма.



    Ввиду того что графические среды в течение прошлого десятилетия стали доминирующими, кнопка представляет собой, возможно, наиболее распространенный из всех компонентов пользовательского интерфейса. В HTML существует три типа кнопок, которые можно использовать в формах: Button, Submit и Reset. Как видите, два из них являются специализированными формами универсального объекта Button. С помощью обычного HTML-синтаксиса кнопка определяется так:




    Comments Enter your commerti In the space provided below: ueac Editor:



    jgl



    я aw«:ed to see tbnt you did run • itory on "Нои со Develop J*va Apple» in 20 ainutia". 1 did cot think It could be dene, but you proved : wrong, llcer reaalng the article, I sat down and wrote m? 21ГЭС Java ЛС 19 uore anazing 13 tbal I never progtaMMd aunblna in my lire before



    ^wwBWit*»«.jM



    .



    .



    Эти три типа кнопок предназначены для различных целей: •



    Кнопка Submit отправляет форму, в которой она содержится, на сервер, основываясь на параметрах формы. Для такого действия не нужен JavaScriptкод, поскольку все поведение встроено непосредственно в объект.







    Кнопка Reset сбрасывает значения полей в текущей форме, восстанавливая ранее установленные значения по умолчанию. Как и для кнопки Submit, JavaScript-код здесь не используется.







    Объект Button — это универсальный объект без предварительно определенного встроенного поведения. При работе с этим объектом необходимо добавлять к кнопке обработчик событий onClick.



    _



    РИСУНОК 17.4. Объект Textarea. ПРИМЕЧАНИЕ



    Дополнительная информация о событиях Textarea (таких ка < onBlur, onChange, onFocus и onSelect) может быть найдена в главе 14.



    Использование DOM Часть III



    При недостаточном знакомстве с HTML может возникнуть вопрос о целесообразности существования кнопок Submit и Reset, т.к. объект Button можно использовать для выполнения тех же самых задач. Они возникли до появления JavaScript, когда нельзя было использовать универсальную кнопку, потому что не существовало соответствующих способов. Кроме того, несмотря на то, что не все браузеры поддерживают JavaScript (a, значит, и объект Button), все современные браузеры поддерживают кнопки Submit и Reset. Преследуя цели совместимости, обычно лучше всего использовать кнопки Submit и Reset, если поддержка JavaScript не является требованием для доступа к данной странице. При наличии таких требований выбор кнопок роли не играет. ПРИМЕЧАНИЕ



    Для получения дополнительной информации о событии onClick для объектов типа Button стоит обратиться в главу 14.



    Листинг 17.6 демонстрирует пример использования всех трех кнопок. Как и следовало ожидать, кнопки Submit и Reset используются для отправки и очистки формы, хотя их параметры VALUE= были изменены для отображения более дружественных к пользователю формулировок. Объект Button используется для вывода на экран справочного окна, которое подсказывает пользователю, как заполнять регистрационную форму. Вдобавок, в справочном окне (которое было сгенерировано методом showHelp()) объект Button определяется с помощью метода write() документа. Обратите внимание на две вещи, связанные с этой кнопкой. Во-первых, для центрирования кнопки на странице используется дескриптор . Во вторых, для увеличения ширины кнопки добавлено несколько пробелов до и после ОК в параметре VALUE=. На рис. 17.5 показана форма, сгенерированная в HTML.



    Листинг 17.6. buttons.htm.



    Online Registration



    Online Registration



    Please provide the following product information:





    Product name



    Model



    Version number Operating system



    Serial number















    Online Registration



    Использование DOM Часть III

    Username:




    Browser used:

    Email address:




    Activate field selection.







    Online Registration



    (7 Activate field selection



    РИСУНОК 17.6. Использование флажка. ПРИМЕЧАНИЕ Пример, показанный в листинге 17.7, демонстрирует порядок вычисления отмеченного свойства. Однако, необходимо учитывать, что этот код не обязательно работает так, как ожидается. Как только выставлен флажок, текст будет выделяется от текущего пункта, независимо от того, снимет ли пользователь флажок. Так происходит потому, что при вызове метода select!) для объекта Text состояние выделения текста будет оставаться в силе, пока страница не перезагрузится. Стоит заметить также, что при перегрузке страницы командой инструментальной панели "Reload" в Netscape Navigator содержимое формы сохраняется. В то же время, при использовании метода reload!) в Netscape Navigator 3.0 текущие значения в форме сбрасывают-



    Объект Radio Объект Radio используется для предоставления пользователям возможностей выбора одиночной опции из группы параметров. Если выбирается одна опция в пре-



    делах набора, другие в тот же момент выбраны быть не могут. Щелчок на переключателе снимает выделение с любого другого выбранного ранее переключателя. Объект Radio отличается от других изученных ранее объектов Form. Заметим, что другие объекты Form имеют взаимно-однозначное соответствие HTML-дескриптору, тогда как объекту Radio в пределах исходного HTML-кода соответствует целый набор элементов . Каждый элемент объекта Radio определяется таким образом:



    [displayText] Элементы здесь не группируются таким способом, как это делается с элементами в объекте Select (который обсуждается ниже в главе). Способ их группировки основан на параметре NAME= переключателя. Каждый элемент в объекте Radio должен использовать в этом параметре одно и то же значение. Например, следующий набор переключателей работает с одним объектом Radio — weekdays: Monday Tuesday Wednesday Thursday Friday Saturday Sunday ПРИМЕЧАНИЕ; За дополнительной информацией о событии onClick для объекта Radio обращайтесь в главу 14.



    Определение значения выбранного переключателя Одной из наиболее распространенных задач, которые должны решаться при использовании объекта Radio, является проблема получения значения выбранного в данный момент переключателя. Для этого потребуется определить, какой из переключателей выбран и затем вернуть его значение. Вместо написания оригинального кода каждый раз, проще воспользоваться универсальной функцией, называемой getRadioValueQ, которая может возвращать значение объекта Radio, передаваемого в метод в качестве параметра.



    Объекты Form Глава 17



    Рассмотрим код, показанный в листинге 17.8. Объект SongsRadio содержит список из трех песен. Объект Button "Show Selected" отображает выбранный в данный момент объект, вызывая метод getRadioValue() с передачей объекта Songs в качестве параметра функции. Метод GetRadioValue() выполняет цикл for, предназначенный для проверки, какой из переключателей выбран. Для определения количества итераций используется свойство length объекта Radio. Когда цикл for сталкивается с выбранным значением, он присваивает переменной значение переключателя, прерывает выполнение цикла, а затем возвращает значение в обработчик событий Button. Листинг



    17.8.



    radio.htm.



    ство под каждый переключатель. Базовый синтаксис HTML для объекта Select выглядит так:



    displayText [d±splayText ]



    _











    Liquid

    Flood

    World's Apart









    На рис. 17.7 показан результат нажатия кнопки "Show Selected". ПРИМЕЧАНИЕ Листинги 17.12 и 17.17, приведенные ниже в главе, демонстрируют способ автоматической проверки переключателя.



    Объект Select Объект Select — один из наиболее полезных и гибких объектов Form. Его можно использовать в тех же случаях, что и объект Radio. Объект Select нуждается в меньшем количестве реального пространства по сравнению с объектом Radio, которому необходимо простран-



    РИСУНОК 17.7. Определение значения объекта Radio.



    Благодаря своей гибкости, объект Select может принимать три различных формы: список выбора, прокручиваемый список и прокручиваемый список с мультивыбором. ПРИМЕЧАНИЕ Щ| Дополнительная информация о событиях объекта Select может быть найдена в главе 14.



    Создание списка выбора Список выбора — это выпадающий список опций, в котором пользователь может выбрать только одну опцию. Список выбора обычно отображает одно значение на экране (см. рис. 17.8), но при нажатии на стрелку список расширяется и отображает все элементы выбора (см. рис. 17.9). В отличие от комбинированных списков Windows, вводить значение в список выбора не допускается; можно только выбирать элемент из существующего массива элементов. Список выбора, показанный на рис. 17.8 и 17.9, можно определить так:



    Liquid



    Использование DOM Часть III World's Apart



    Ironic •Coption VALUE="1979">1979 Wonderwall Coption VALUE="Standing Outside a Broken Phone w Booth">Standing Outside a Broken Phone Booth



    крутки, при этом пользователь может прокручивать список элементов вверх или вниз, чтобы просматривать и те элементы, которые не уместились в окне. Для создания прокручиваемого списка единственное изменение в HTML-определении необходимо проделать в параметре SIZE=. Если его значение больше 1, объект Select преобразуется в прокручиваемый список. Например, если изменить параметр SIZE= определенного ранее объекта Songs с 1 на 5, список примет новый вид, показанный на рис. 17.10. Как и список выбора, прокручиваемый список позволяет выбирать только одно значение.



    Создание прокручиваемого списка с мультивыбором



    РИСУНОК 17.8. Список выбора в начальном состоянии.



    Последняя форма, в которой может быть представлен объект Select, — это прокручиваемый список с мультивыбором. Он выглядит так же, как обычный прокручиваемый список, но ведет себя по-другому. Из этой формы объекта Select можно выбирать один и более элементов. Решение задачи выбора множества элементов зависит от среды. В большинстве случаев можно либо перемешать мышь с нажатой кнопкой поверх требуемых элементов, либо удерживать в нажатом состоянии клавишу Shift или Ctrl во время щелчков на элементах списка.



    РИСУНОК 17.9. Список выбора в развернутом состоянии.



    Ключ к определению списка выбора заключается в присвоении параметру SIZE значения 1 (либо вообще никакого значения). Это даст гарантию того, что список будет отображать только одну строку.



    Создание прокручиваемого списка Второй формой объекта Select является прокручиваемый список, во многих средах называемый окном списка. Он отображает указанное число элементов одновременно в формате списка, вместо того чтобы прятать все элементы кроме одного, как это делает выпадающий список. Прокручиваемый список включает полосу про-



    РИСУНОК 17.10. Прокручиваемый список.



    Для определения прокручиваемого списка с мультивыбором необходимо в определение объекта Select добавить параметр MULTIPLE:



    Liquid World's Apart



    Ironic 1979 Wonderwall



    Объекты Form



    Глава 17



    Standing Outside a. Broken Phone Booth



    Определение значения или текста выбранной опции В списке выбора или прокручиваемом списке можно определять значение выбранной опции с помощью комбинации свойств options и selectedlndex объекта Select. Например, если требуется определить песню, которая была выбрана в приведенном выше примере объекта Songs, используют следующий код: favorite = document.forml.songs.options [document.forml.songs.selectedlndex].value



    Свойство options — это массив, содержащий каждую опцию, определенную внутри объекта Select. Используя это свойство, можно обращаться к свойствам каждой опции. С помощью свойства Selectedlndex возвращается индекс выбранной опции. Когда options и Selectedlndex используются в комбинации, возвращается значение выбранной в данный момент опции. С учетом требований точечной нотации JavaScript, выбранное в данный момент значение может включать длинные строки текста программы. Этого можно избежать с помощью универсального метода getSelectValue(). Листинг 17.9 показывает способ применения такого метода. Как видно из листинга, объект Select переходит к параметру метода getSe!ectValue(), как только пользователь нажимает на кнопку "Show Current". Переменная SelectObject обрабатывается как переменная объектного типа и принимает значение выбранной в данный момент опции. Это значение переходит в обработчик событий объекта Button и отображается в сигнальном окне сообщения. Листинг 17.9. select.htm.







    Songs: Liquid World's Apart



    Ironic 1979 Wonderwall



    Standing Outside a Broken Phone Booth







    Одно важное различие между объектами Select и Radio связано с тем, что объект Select, в дополнение к свойству value, имеет свойство text. Если определяемое значение аналогично тому, которое отображается для пользователя (как в листинге 17.9), то можно вместо свойства value возвращать значение text выбранного в данный момент объекта. Предположим, что объект Select был определен так:



    Liquid World's Apart Ironic 1979 Wonderwall Standing Outside a Broken Phone Booth



    Тогда для возврата названия песни вместо свойства value можно воспользоваться свойством text: function getSelectValue(selectObject) { return selectObject.options[selectObject. selectedlndex].text !



    Определение значений в прокручиваемых списках с мультивыбором В списках, где в каждый момент времени может быть выбрана только один вариант, свойство selectedlndex работает эффективно и возвращает необходимую информацию из выбранной опции. Однако, в прокручиваемом списке с мультивыбором selectedlndex возвращает только первую выделенную опцию, а не все сразу. При использовании списка с мультивыбором необходимо применять свойство selected массива опций для определения состояния каждой опции в списке. Листинг 17.10 демонстрирует пример этого в методе showSelection(). Цикл for выполняет итерации по каждой опции объекта Select и проверяет, равно ли свойство selected значению true. Если да, то значение свойства text элемента добавляется в переменную списка. Результат отображается во втором окне, показанном на рис. 17.11. Листинг 17.10. selectMultiple.htm.







    Pick Your Favorite Songs From the List:





    Fortress Around Your Heart Breakfast at Tiffany's Flood The Chess Game Liquid World's Apart Ironic 1979 Wonderwall Standing Outside a Broken Phone Booth











    Выбор опции с помощью JavaScript Можно программно выбирать опцию, устанавливая свойство selected массива параметров объекта Select. Предположим, что имеется поле "Favorite Band" и список песен. Пусть значение поля "Favorite Band" — Oasis, и требуется расположить песню, исполняемую этой группой, в поле "Songs". В листинге 17.11 показан код этого примера. Листинг 17.11. selectSelected.htm.











    Favorite Band: Songs: Liquid World's Apart



    Ironi c 1979 Wonderwall



    Standing Outside a Broken Phone Booth







    РИСУНОК 17.11. Отображение множественного выбора.



    Объект Password Как можно понять по его имени, объект Password преследует одну цель: захватывать значения пароля, введенного пользователем. Объект Password аналогичен объекту Text, но отображает любой символ, напечатанный пользователем в поле, в виде звездочки (*). Этот объект определяется в синтаксисе HTML следующим образом: •CINPUT TYPE="password" [NAME="objectName" ] [VALUE="defaultPassword"] [SIZE=integer]> Ниже приведен пример:



    JavaScript не предоставляет большой степени управления объектом Password. Например, нет возможности



    Объекты Form Глава 17



    получать значение текста, введенного пользователем; можно только получить заданный по умолчанию текст, который был определен в параметре VALUE= дескриптора . Одна из причин, почему JavaScript не может получить доступ к объекту Password, связана с тем, что JavaScript-код в настоящее время встраивается в HTML-документ так, чтобы пользователь мог обращаться к нему. Когда язык JavaScript будет разработан до конца, вероятно, появится большая степень управления этим объектом.



    Объект Hidden Как можно понять по его имени, объект Hidden невидим для пользователя. Объект Hidden — это поле скрытого текста, использующееся для хранения значений, которые не требуется представлять пользователю в обычных текстовых полях. Затем можно передавать эту информацию на сервер для обработки. Объект Hidden в HTML определяется с помощью следующего синтаксиса:



    Ниже приведен пример:



    В HTML-мире скрытые поля играли важную роль в получении определенной информации со стороны пользователя, которая затем использовалась сервером. С появлением JavaScript, применение объекта Hidden в комбинации с JavaScript становится менее эффективным. Причина связана с тем, что глобальные переменные JavaScript служат тем же целям, что и объекты Hidden, однако ими намного проще управлять. Следующие два примера демонстрируют это. На рис. 17.12 показан набор переключателей, на которых можно совершать щелчки. Необходимо добавить код к кнопке "Undo Last", чтобы пользователь мог отменять последний сделанный выбор. Использовать кнопку Reset для этого нельзя, т.к. она или сбросит все переключатели, или вернет значение по умолчанию. Вместо этого для выполнения упомянутой задачи придется добавить JavaScript-код. Код, приведенный в листингах 17.12 и 17.13, демонстрирует решение такой задачи. Листинг 17.12 использует для этого набор скрытых полей, в то время как листинг 17.13 выполняет данную задачу с помощью глобальных переменных. Заметим, что оба эти метода — вполне допустимы.



    Листинг 17.12. hidden.htm.



    Hidden Test



    I remember



    Argentina

    Burkina Faso

    Pakistan

    Switzerland





    Netscape и Microsoft предоставляют расширенные возможности в браузерах последних версий. Посетите web-сайты этих компаний, на которых находится более подробная информация (соответственно http:// home.netscape.com/ и http://www.microsoft.com/). При использовании фреймов дополнительно необходимо рассмотреть обработку событий, отлаживая JavaScript-код или подстраивая его под целевой браузер. JavaScript-события, наиболее часто встречаемые как в Microsoft Explorer, так и в Netscape Navigator, сведены в табл. 18.1.



    Размещение дескрипторов Дескрипторы и обычно размещают в теле документа. Однако, в некоторых версиях Netscape Navigator помещение их между дескрипторами и не позволяет браузеру прочесть дескрипторы . Поскольку дескрипторы необязательны, дескрипторы размещают после раздела документа, а дескрипторы опускают, как показано ниже:



    Frame Demo " (для "больше"), то в старых браузерах он может быть ошибочно интерпретирован как завершающий символ HTML-комментария, поэтому предпочтительнее использовать символы "!=" ("не равно"). Применение короткого цикла с оператором if поможет избежать ошибок, если документ, не находящийся во фрейме, попытается сослаться на переменную из другого фрейма или мультифреймового окна. Если верхнее мультифреймовое окно содержит переменную al, которая используется в операторе if в соответствие с созданным документом, ошибка возникнет при просмотре данного документа в автономном нефреймовом виде. Однако, если свойство length, заранее проверенное в условном выражении, равно false, то оператор if завершает работу, предотвращая возникновение ошибки изза попытки обращения к несуществующей переменной. Первая часть следующего оператора, parent.length != О, равна false, когда фреймы не используются, так что дальнейшее выполнение останавливается и ошибка не возникает: if( (parent.length != 0) && (top.al = x ) )



    Проверка правильности загрузки документов Для синхронизации фреймов были разработаны различные методы, некоторые из них довольно просты, в то время как другие — гораздо сложнее. Один из самых простых методов использует JavaScript для проверки наличия необходимого документа в данном фрейме перед продолжением выполнения остальной части кода. Массив frames позволяет определять фрейм как элемент массива. (В разделе "Ссылки на окна и фреймы" далее в этой главе можно найти дополнительную информацию относительно массива frames.) Рассмотрим следующую строку кода: if( (parent.length == 3) SS(parent.frames [1] .title == "My Page") )



    Оператор if проверяет правильность структуры фрейма (в данном случае — наличие трех фреймов), а также правильность документа во втором фрейме (на



    который в данном случае ссылаются). Если структура фрейма неправильна, вычисление условия останавливается, и никаких дальнейших действий не предпринимается либо же предпринимаются альтернативные действия. Если структура фрейма корректна, но неправилен документ, сценарий не инициирует никаких действий либо реализует альтернативные действия. Если никакие дальнейшие действия не предпринимаются, программа просто остается в текущей позиции, разрешая пользователю продолжать выполнение других действий или повторить неудавшееся действие. (Возможно, страница не была до конца загружена, и следующая попытка загрузки окажется успешной.) Альтернативные действия могут включать обеспечение сигнала для пользователя, загрузку правильной страницы и продолжение работы или же продолжение действия с пропуском шагов, требующих обращений к отсутствующему документу. Предыдущий пример проверял простую фреймовую структуру (три фрейма). Можно проверять корректность и более сложных структур, используя массив frames различных окон в составном операторе if. Составной оператор if проверяет структуру сверху вниз, в противном случае ссылка на отсутствующий фрейм вызовет ошибку. Рассмотрим следующую строку программы: if (top.length==3) ss(top.frames [1] .length=2) && (top.frames[l] .frames [1]=3) . . .



    Если часть фреймовой структуры не существует, оператор if останавливает работу в этой точке и сценарий выполняет альтернативное действие либо не выполняет никаких действий вообще. В ходе проверки наличия правильного документа код может проверять помимо заголовка и другие свойства, например, location.href фрейма. Вместо проверки заголовка документа или другого свойства можно присваивать общей переменной в каждом документе уникальное имя или номер и затем проверять эту идентифицирующую документ переменную.



    Регистрация документов Простая проверка присутствия требуемого документа в случае больших сайтов может стать слишком сложной, в этом случае проверку полной зафузки документа можно не проводить. Другой выход из ситуации состоит в том, чтобы сами документы уведомляли, загружены ли они. Используя события onLoad() и onUnload(). документы регистрируют свое присутствие в переменной topWindow или в cookie-набора. Следующий код показывает, что нет необходимости использовать заголовок для идентификации документа; можно использовать другое свойство или идентифицирующую переменную:



    Объекты Frame Глава 18



    Приведенный ниже пример демонстрирует простую схему регистрации документа. Первый фрагмент кода содержит файл для установки верхнего фреймового окна:



    Следующий фрагмент кода показывает файл документа:



    The Harley FXSTC



    Код, показанный ниже, проверяет, зарегистрирован ли документ: i f ( funCheck("The Softtail Series") ) top. frames [2] . fxnames () ; // документ // зарегистрирован, продолжить выполнение else // документ не зарегистрирован, // выполнить альтернативные действия top . location .href = "http: //www. foo. com/ f x . html" ;



    Использование расширенных схем регистрации Более сложные схемы регистрируют не только документ, но также и позицию документа в иерархической структуре фреймов. Если позиция документа изменяется из-за различных возможных сценариев загрузки или модификации сайта, код, содержащий ссылки на документ, может находить документ с использованием информации о регистрации документа. Вместо применения одной переменной или cookie-набора для получения информации по регистрации, некоторые схемы используют массив переменных, в котором каждый элемент (переменная) содержит идентификационную и позиционную информацию для зарегистрированного документа. Эти схемы сложны для установки, однако, их гораздо выгоднее использовать при проектировании очень больших сайтов, где маленькая ошибка в структуре может вывести из строя коды ссылок во многих документах. Набор фреймов hldaho (http://hidaho.com/frameset/) — это схема регистрации, эффективная для больших, сложных фреймовых структур. Она регистрирует функции и расположения функций во фреймовой структуре. Она определяет расположение фрейма, передавая его имя (self.name) родительскому фрейму, который присоединяет к этому имени свое собственное имя и передает далее эту информацию родительскому фрейму. Процесс продолжается все выше по родительским окнам, вплоть до самого верхнего окна. Также имеется возможность снятия регистрации заданной функции (все функции должны иметь уникальное имя) и регистрации имени фрейма (всех функций, расположенных в этом фрейме) при закрытии документа. В набор фреймов hldaho включена функция для проверки, зарегистрирована ли указанная функция (она возвращает false, если указанная функция не зарегистрирована), а также функция Ехес(), которая вызывает другие функции и передает им параметры. Поскольку все имена функции должны быть уникальны, разработчик получает возможность вызова требуемой функции, не зная ее расположения, и передачи параметров в нее через Exec(function, parameterl, parameter!,...).



    Обновления фреймов Существенная выгода, которую дают фреймы, заключается в возможности модификации документа во фрейме, не затрагивая при этом другой фрейм. Независимо от того, обновляется ли фрейм с помощью ввода пользователя в другом фрейме или модифицируется программно, существует несколько методов для внесения изменений в соответствующие фреймы. Эти методы могут использовать HTML (с некоторыми расширениями Netscape), JavaScript или комбинацию их обоих.



    Использование DOM Часть III



    Ссылки Возможно, самой простой методикой обновления следует считать использование ссылок для изменения текущего фрейма (загружая новый документ). Для того чтобы направить новый документ в другой фрейм, используют дескриптор якоря, имеющий атрибут target, для которого можно определить значение имени фрейма или относительное имя. Относительные слова (в Netscape они называются magic target names) соответствуют относительным свойствам окна, обсуждавшимся ранее. Относительные имена, применяющиеся для целевых ссылок, всегда начинаются с символа "_" и всегда записываются в нижнем регистре. Эти имена — _top, _parent и _self — соответствуют свойствам окна top, parent и self. Однако, не существует имени _window. Следующий код представляет фреймы, в которых ссылка в одном фрейме должна обновить другой фрейм:











    Файл frame2.html содержит дополнительную информацию для установки фреймов в окне:







    Для загрузки нового документа в frame2 с помощью ссылки в doc4.html (в frame4) эту ссылку записывают следующим образом:



    Для загрузки документа в верхнее окно и очистки всех фреймов используют такую строку:



    Динамические ссылки Поскольку ссылки в JavaScript являются объектами, а href и target — свойствами ссылок, можно создать динамическую ссылку, присваивая другие значения href и target:



    Для поддерживающих JavaScript браузеров документ ncw.html загрузится в текущий фрейм; если же JavaScript не поддерживается, то текущий документ загружается в



    верхнее окно. (Спецификатор фрагмента, #, без URL и якорного имени, или идентификатор фрагмента, ссылается на текущий документ.) Переназначение свойств ссылки href и target можно сделать более динамическим путем объединения операторов присваивания с условным и другими операторами. В следующем примере при использовании фреймов файл, устанавливающий фреймы, загружается в родительское окно; если же фреймы не используются, в окно загружается главный документ:



    Обратите внимание на кавычки; обработчик событий должен быть заключен в кавычки (двойные или одиночные). Нет необходимости переназначать свойства href и target для каждой динамической ссылки. В предыдущем примере атрибут target можно установить в _parent. Для нефреймовой версии _parent и _top эквивалентны. Если пользователь имеет неподдерживающий фреймы браузер, то атрибут target игнорируется. Пример мог быть написан этот путь:



    отменяет целевой фрейм и загружает документ в собственный фрейм. ПРИМЕЧАНИЕ Дескриптор , , необходимо помещать в раздел документа. Для дескриптора не предусматривается какое-либо содержимое и не существует закрывающего дескриптора . Этот дескриптор с атрибутами HREF и TARGET показан в следующем примере:



    Base Demo







    Дополнительную информацию относительно использования URL в фреймах можно найти в этой главе, в основном, в следующем разделе и в разделе "Обновление фреймов".



    Ссылки на фреймы При работе с фреймовыми окнами в прикладных программах JavaScript, вероятно, потребуются другие способы ссылок на окна. JavaScript обеспечивает четыре



    Объекты Frame Глава 18 вида ссылок на окна. Каждый вид реализован как свойство объекта Window. ПРИМЕЧАНИЕ Отдельные окна браузера не имеют иерархической структуры; однако при ссылках на окно, содержащее код, который открывает другое окно, его зачастую называют родительским элементом. Новое открытое окно при этом называют дочерним. Любое новое окно может назначать переменную в других окнах, чтобы другие окна могли ссылаться на данное окно и его свойства. Для ссылки на свойство в новом окне просто используют windowName.property. Рассмотрим следующий код: newWindow = window.open(); newWindow.location.href = "http://www.mcp.com/"; Хотя этот фрагмент и не обеспечивает наиболее эффективный способ записи кода, он демонстрирует способ ссылки на свойство дочернего окна. Новое окно было открыто и получило имя (в данном случае, newV/indow). Затем было присвоено значение location.href нового окна.



    Ссылки на текущее окно В главе 9 обсуждалось использование window для ссылок на текущее окно. Однако, тогда не было сказано, что объект Window также содержит свойство под названием window, которое может служить инструментом для ссылки на само себя. Кроме того, свойство self объекта Window — это еще одно средство для ссылок на текущее или активное окно. Например, следующих две строки кода программы функционально эквивалентны: window.defaultStatus = "Welcome to the Goat Farm Home Page" self.defaultStatus = "Welcome to the Goat Farm Home Page" Поскольку как window, так и self — синонимы текущего окна, может показаться странным, что оба они включены в язык JavaScript. Как было показано в предыдущем примере, объяснение этому — гибкость; по желанию можно использовать как window, так и self. Однако, насколько полезными могут быть window и self, настолько же они могут привести к путанице, если подойти к этому логически. В конце концов, свойство объекта, которое используется как эквивалентный термин для самого объекта, довольно необычно. Следовательно, будет удобнее считать window и self для объекта Window зарезервированными словами, а не свойствами. Поскольку window и self — свойства объекта Window, нельзя использовать и window, и self в одном и том же контексте. Например, следующий код работать не будет: window.self.document.write("Test.") Наконец, в мультифреймовых средах window и self всегда относятся к окну, в котором выполняется JavaScriptкод.



    ПРИМЕЧАНИЕ ; В некоторых объектно-ориентированных или основанных на объектах языках self может относиться к активному объекту, независимо от его типа. В JavaScript self относится только к активным объектам Window или Frame — и ни к чему больше.



    Ссылки из родительского фрейма на дочерний Родительский фрейм может ссылаться на свой дочерний фрейм одним из двух способов. Во-первых, можно использовать имя фрейма, которое определяется в параметре NAME дескриптора . Например, в следующем коде переменная myFrameFlicka ссылается на имя фрейма frameA:



    Parent to Child Demo











    Во-вторых, можно ссылаться на дочерний фрейм, используя массив frames. Каждый фрейм в окне, или родительский фрейм, является элементом массива. На элементы массива frames ссылаются помощью frames [i], где i — число, соответствующее порядковому номеру фрейма в родительском окне. Фреймы пронумерованы от нуля до числа, на единицу меньшего общего количества фреймов. Следующий код определяет четыре фрейма:







    Следовательно, массив frames данного окна будет содержать четыре элемента: frames[0] для фрейма frameA frames[1] для фрейма frameB frames[2] для фрейма frameC frames[3] для фрейма frameD Обратите внимание, что при ссылках на элемент массива frames в конце слова frames[i] присутствует "s", что указывает на множественное число.



    Использование DOM



    Часть III



    Ссылки из дочернего фрейма на родительский Как было показано в данной главе, фреймы — это те же самые объекты Window, но внутри содержащего фреймы окна. Внутри мультифреймового окна возникает необходимость различать между собой фреймы, отображаемые в браузере. Свойство parent объекта Window помогает это делать, ссылаясь на родительское окно — окно, содержащее определение . Например, если требуется получить некоторую информацию о текущем родительском окне, используйте пример из листинга 18.1. Листинг



    18.1.



    childWindow.htm. _



    Child Window











    СОВЕТ



    Для определения пустого фрейма следует престо опустить атрибут SRC в конструкции . Листинг



    18.3.



    anotherChildWindow.htm. _



    Child Window







    0, загружает документ, который находится на л пунктов дальше в списке посещений. Загружает документ из списка посещений, URL которого содержит указанную строку.



    Go() Go(n)



    Go(string)



    Определение размеров списка Для определения количества посещений в списке можно использовать свойство length объекта History. Предположим, что требуется отследить число посещений правого фрейма мультифреймового окна. Левый фрейм содержит следующий код:











    Пользователь может применять текстовый объект Editl для ввода целевого URL. Когда пользователь щелкает на кнопке "Move" для перехода на указанный URL, текстовый объект EditZ изменяется и отображает длину списка посещений правого фрейма.



    Навигация по списку посещений



    Свойство



    Forward ()











    Одно знание длины списка посещений редко оказывается особо полезным, однако оно может принести больше пользы, если требуется перемещаться по списку с использованием объекта History. Перемещение на одну страницу назад Метод back() функционально эквивалентен щелчку на кнопке "Back" (стрелка влево) в инструментальной панели браузера. Например, следующий код перемещает окно в его предыдущую позицию: window.history.back() Перемещение на одну страницу вперед Как и следовало ожидать, метод forward() — то же, что и щелчок на кнопке со стрелкой вправо в инструментальной панели браузера. Этот метод используется аналогично: window. history. forward () Переход к указанной странице по номеру в списке Метод go() используется для перехода к определенному месту в списке посещений. Его синтаксис таков: [window. ] hi story .go (delta



    |



    "location")



    Параметр delta — положительное или отрицательное целое число, которое определяет количество шагов перехода. Например, следующая строка — это переход к следующему документу в списке посещений (эквивалент использования метода forward()): window.history.до(1) Таблица 18.7 содержит возможные значения delta. Таблица 18.7. Значения delta. Метод



    Описание



    delta < 0 delta > 0 delta = 0



    Перемещает назад на delta пунктов. Перемещает вперед на delta пунктов. Перегружает текущий документ.



    Объекты Frame



    Глава 18 Переход к указанной странице по строке в списке В качестве альтернативы можно использовать параметр location для определения заданного URL в списке. Обратите внимание, что здесь не нужен точный URL, a только подстрока. Следующий пример позволяет перемещаться к URL в списке посещений, который содержит www.acadians.com/filenew: window.history.go("www.acadians.com/filenew")



    В приведенный выше пример можно добавить back(), forwardO и go() для обеспечения более полной функциональности мультифреймовой системы навигации. На рис. 18.12 показано мультифреймовое окно. Листинг 18.9 содержит исходный код HTML для родительской страницы мультифреймового окна, а листинг 18.10 — код для списка посещений. Правая область окна не содержит никакого JavaScript-кода.



    Ways to narbatt • use the location a



    JavaScript Chronicles — Free Subscription Form i. WhstotnermagazinesdoyoijcurrenHysutMWbetD?



    Г к ,«« Ги«5



    parent . frames [ 1 ] . history. back()



    i function goNext ( ) { parent . frames [ 1] . history . forward ( ) } function moveOn ( ) { var urlAddress = "" urlAddress = document . forms [ 0 ] . LocationBox . value if (urlAddress != "") { parent. f rames [1] .location = urlAddress document, forms [0] . ListLen. value = parent. f rames [1] .history. length ) else { alert ("Please enter a DRL before ^•clicking the Go button.") } 1 function jump() ( if (document. forms[0] .goParam[l] .checked) ( var goVal = 0 goVal = parselnt (document. f orms [0] .GoBox. value) ) else { var goVal = "" goVal = document . forms [ 0 ] . GoBox . value I parent. frames [1] .history .go (goVal)



    Г" InfoVotld



    Г iminbaseil LdviaoE



    ** By £oum ".



    Text



    Объект, содержащий текст.



    ПРИМЕЧАНИЕ



    document.all[id].innerHrML = newtext



    DOM-модель WWW-консорциума (W3C) поддерживается в Netscape Navigator 5 и в Microsoft Internet Explorer 5. В Navigator 4 написан новый HTML для объекта Layer. Для изменения текстового элемента с заданным ID и значением newtext форма приобретет следующий вид:



    Explorer 5 использует ключевое слово ALL для достижения совместимости сверху вниз. A Navigator 5.0 для обеспечения совместимости сверху вниз сохраняет модель Layers для объектов.



    var lyr = document.layers[id].document lyr.open() lyr.write(newtext) lyr .closed Internet Explorer 4.0 реализует другой способ и предоставляет HTML-элементы документа, использующие ключевое слово ALL. Для изменения текстового элемента с заданным ID и значением newtext форма получает следующий вид:



    СОВЕТ



    . "; -Р



    В DHTML версии 4 для всех браузеров потребуется создать разветвление кода, с помощью которого выясняется тип браузера и выполняются соответствующие корректировки: ns4 = (document.layers)? t r u e : f a l s e ie4 = (document.all)? true:false function simpleLayerWrite(id,newtext)



    {



    Использование DOM



    Часть III if



















    •ME-MGD : '



    E



    обходимо определить ссылку и изначально скрытый слой. Результирующий документ предельно прост.



    Rollover to show and hide the layer.



    He беспокойтесь, что сейчас слоям уделяется мало внимания, поскольку эта тема рассматривается позже, в главе 23. В настоящий момент лучше сфокусировать внимание на коде JavaScript. Так же, как и в примере с rollover-изображениями, для захвата событий onMouseOver и onMouseOut будет использоваться дескриптор . В дескрипторе можно заметить три фрагмента кода. Первый фрагмент находится в атрибуте href. Этот вызов (javascript:) сообщает браузеру о том, что при условии выполнения щелчка кнопкой мыши на ссылке ничего больше не произойдет (void(O)). Второй и третий фрагменты вызывают функцию changeState() и передают ей две переменные. Первая, name (для браузеров Navigator) и id (для браузеров Internet Explorer) — это экземпляр слоя, а вторая — индикатор, который скрывает или отображает слой. СОВЕТ В атрибуте href допускается применение такого синтаксиса, на который ссылаются как на "JavaScript URL", для вызова функции либо для любого другого кода на JavaScript.



    РИСУНОК 20.2. Динамическая замена одного из изображений



    ПРИМЕЧАНИЕ В главе 24 приводятся более конкретные примеры rollover-изображений и подробно рассматривается их использование.



    Rollover-эффекты для слоев Следующий рассматриваемый нами вопрос — это реализация rollover-эффектов для слоев. Они генерируются за счет сокрытия и отображения слоев внутри документа. Эта тема также затрагивается и в главе 23. Сейчас стоит кратко рассмотреть вопрос реализации доступа к свойству visibility таблиц стилей (CSS) в JavaScript. Первое, что потребуется сделать — создать HTMLдокумент, который станет основой примера. Здесь не-



    Следующий шаг заключается в установке таблицы стилей для слоя, которая обеспечит его сокрытие. Несмотря на то что в CSS присутствует несколько свойств, которые будут рассматриваться в главах 22 и 23, сейчас примем во внимание только одно свойство visibility. Несложно заметить, что ему присваивается значение hidden.







    Следующая часть кода необходима лишь для того, чтобы учесть отличия реализации слоев в браузерах Navigator и Internet Explorer. Вначале потребуется оп-



    Динамическая подмена



    Глава 20 ределить, какой из браузеров получает доступ к странице, и установить переменные, которые позволят использовать одну функцию для обработки rollover-эффектов. Детали реализации обсуждаются в главе 23. Сейчас рассмотрим только код: // // var var var var



    Создание глобальных переменных для хранения типа браузера. isIE = new Boolean (false) ; isNav = new Boolean (false) ; layer = new String () ; style = new String () ;



    // Определение, является ли браузер Internet // Explorer, Navigator и др. Кроме того, // установка переменной слоя в зависимости от // необходимого способа доступа. function checkBrowser () { if (navigator .userAgent.indexOf ("MSIE") != -1) { is IE = true; layer = ".all"; style = " . style" ; )else if (navigator .userAgent.indexOf ("Nav") != -D( isNav = true; layer = ".layers"; style = " " ; I }



    Последняя функция в данном примере отображает и скрывает слой. Так же, как и в HTML-документе, она принимает два параметра: имя слоя и состояние, на которое требуется переключить слой. Благодаря проделанной ранее работе, функция содержит только одну строку кода: function changeState(layerRef, state)( eval("document" + layer + "[t" + layerRef + "']" + style + ".visibility = '" + state + I



    В функции используется верхнеуровневый метод eval(), который принимает объект String и выполняет его как код JavaScript. В нашем примере строка "document" + layer + "['" + layerRef + "']" + style + ".visibility = '" + state + "'");



    получает значение



    браузере. Рисунок 20.4 демонстрирует rollover-эффекты для слоя. Листинг 20.2. Пример реализации rollover-эффектов для слоев



    JavaScript Unleashed







    Hello World !



    Технологии программирования на динамическом HTML



    Часть IV



    Rollover to show and hide the layer.



    РИСУНОК 20.4. Rollover-эффект в действии



    Резюме



    РИСУНОК 20.3. Ссылка без воздействия rollover-эффекта ПРИМЕЧАНИЕ И в Internet Explorer, и в Navigator предусмотрены собственные реализации CSS, поэтому не удивляйтесь, если результаты запуска некоторых сценариев будут отличаться. Например, при загрузке кода из листинга 20.2 Navigator 4 окрашивает только фон текста, а не весь слой.



    Несмотря на небольшой объем главы, были описаны важные характеристики приложений JavaScript. Реализация rollover-эффектов на собственном сайте — одно из простейших и безопасных задач в JavaScript Но не стоит ограничиваться только информацией, полученной из книги. Rollover-эффекты могут лежать в основе многих задач, решаемых с использованием JavaScript. Они позволяют глубже понять события и доступ к элементам страницы, а также знакомят с дизайном интерфейсов. Остальная часть книги посвящена вопросам создания визуальных эффектов, CSS и слоев. Будут рассматриваться особенности создания на DHTML инструментальных панелей и меню. Также будут исследоваться способы взаимодействия компонентов на странице с использованием JavaScript.



    Визуальные эффекты В ЭТОЙ ГЛАВЕ Бегущие



    строки



    Баннеры Постепенное



    изменение



    цветов



    Анимированные командные кнопки



    На сегодняшний день такие технологии, как JavaScript и Java, широко применяются в сфере разработки Webприложений. Они популярны также благодаря изящным операциям, которые можно проделывать с их помощью на Web-сайте. Вспомните, сколько бесполезных Java-аплетов блуждали по Web во времена, когда возросла популярность Java. Однако с появлением JavaScript горизонты применения различных операций существенно расширились.



    Бегущие строки Эффект бегущей строки относится к числу наиболее распространенных в среде разработчиков Web-сайтов. Цель данного эффекта — передать посетителям сайта последние новости или пикантные сообщения. Бегущая строка впервые получила популярность после применения в Java-аплетах. Создание бегущей строки в JavaScript тоже предусматривается, хотя при этом внешний вид ее будет не столь эффективным, как в Java-аплете. Все это объясняется использованием объекта Text в роли контейнера для прокручиваемого текста, а ни один из объектов HTML-формы не сможет поразить пользователя своим великолепием. У разработчиков не будет проблем с созданием бегущих строк JavaScript, поскольку они не нуждаются в отдельном аплете. Необходимость в таких строках возникает очень часто. Для создания бегущей строки в JavaScript необходимо: •



    Создать HTML-форму с внедренным объектом Text.







    Записать функцию, прокручивающую текст внутри объекта Text.







    Ассоциировать функцию с обработчиком событий окна on Load для запуска процесса.



    Для начала создайте объект Form и внутри него объект Text. При этом рекомендуется соответствующим образом назвать эти объекты, поскольку они создаются исключительно для реализации бегущей строки и ни для чего более. Например, форму стоит назвать "marqueeForm", а объект Text — "marqueeText" или както по-другому, однако максимально близко по смыслу. После этого необходимо ввести сообщение как атрибут value дескриптора . Ниже приводится код :







    После определения контейнера для бегущей строки можно приступить к основной части. Для начала определяются две глобальные константы, используемые в бегущей строке: скорость прокручивания (в миллисекундах) и количество знаков, прокручиваемых за определенный временной промежуток. Затем потребуется создать объект String с именем marqueeMessage: var SCROLL_RATE = 100; var SCROLL_CHARS = 1; var marqueeMessage = new String();



    Следующий шаг — создание функции JSMarquee(), придающей обыкновенному объекту Text вид бегущей строки. Поскольку бегущая строка должна постоянно обновляться, не удастся обойтись без рекурсии JSMarquee() за счет вызова setTimeout() в начале функции. Метод setTimeout() подробно описывается в главе 14. Глобальная переменная SCROLL_RATE исполь-



    Технологии программирования на динамическом HTML Часть IV зуется как параметр метода, определяющий частоту вызова функции. Основная задача функции JSMarquee() заключается в получении значения объекта Text и присвоению его строке marqueeMessage. Затем можно смоделировать перенос слов, отделяя порцию данных сообщения спереди и переписывая эту порцию в конец строки. Для этого используется метод substring() объекта String: function JSMarquee(){ setTimeout (' JSMarquee () ' , SCROLL_RATE) ; marqueeMessage = document.marqueeForm.marqueeText.value; document.marqueeForm.marqueeText.value = marqueeMessage. substring ( SCROLL_CHARS ) + marqueeMessage.substring( 0, SCROLL_CHARS ) ; I



    На рис. 21.1 показан эффект бегущей строки в момент, когда пользователь находится на странице. Полный исходный код для этого примера приводится в листинге 21.1. ПРИМЕЧАНИЕ Помимо исходного кода, в листинге 21.1 имеется также и дополнительный код JavaScript, поэтому текст сообщения можно определить как глобальную переменную. Так его проще поддерживать при условии частого изменения текста объявления.



    Баннеры Баннеры — еще один компонент, который часто присутствует на Web-страницах. Они привлекают к себе внимание и применяются, в основном, для рекламных целей. Обычно их миссия состоит в том, чтобы заинтриговать пользователя и заставить его щелкнуть мышью именно в этом месте. Используя объекты Image, можно создавать профессиональные баннеры, обходясь без анимированных GIF-изображений или Java-аплетов. ПРИМЕЧАНИЕ Перед созданием самого сценария потребуются два набора GIF-файлов одинаковых размеров. Необходимы два или три изображения, которые после будут служить как главные изображения баннера. Для достижения эффекта перехода потребуется серия переходных изображений. Изображения, в случае их последовательной отрисовки, будут выглядеть подобно анимации. Для создания удобоваримого эффекта достаточно будет и пяти-шести переходных изображений. Следите за общим размером GIF-файлов. Некоторые пользователи, загружая страницу с 15 6!Р-изо6|ражениями на скорости соединения 28,8 Кбайт/с могут и не оценить ее. Как только GIF-файлы готовы, можно приступить к созданию баннера в JavaScript:



    Листинг 21.1. Реализация бегущей строки с использованием JavaScript



    JavaScript Unleashed















    MESSAGE;



    Визуальные эффекты



    Глава 21



    1. Создайте заглушку для изображения на Web-странице.



    отображения основного и переходного изображений. Две дополнительные переменные определяются позже:



    2. Определите массив для хранения исходных изображений и для хранения переходных изображений.



    // Глобальные константы var DISPLAYJTIME = 3500; var TRANSITIONJTIME = 50;



    3. Создайте программу для управления презентацией изображений. 4. Определите эту функцию в качестве обработчика событий onLoad.



    // Глобальные переменные var primaryldx = О ; var transldx = 0 ;



    Потребуется определить два массива для хранения информации о наборах начальных и переходных изображений. Для каждого элемента массива объявляется свойство изображения scr. // Первый массив содержит начальные изображения JSBillboardArray = new Array( 3 ) ; JSBillboardArray[0] = new Image ( 49, 333 ); JSBillboardArray[0].src = "./visjs.gif"; JSBillboardArray[l] = new Image ( 49, 333 ) ; JSBillboardArray[1].src = "./url.gif"; JSBillboardArray [2] = new Image ( 49, 333 ) ; JSBillboardArray[2].src = "./bltwith.gif";



    РИСУНОК 21.1. Пример бегущей строки



    Для начала создайте на Web-странице объект Image, который послужит заглушкой для всех действий. Поскольку баннер переносит куда-то в другое место, как только на нем совершается щелчок, очевидно, дескриптор потребуется поместить внутрь ссылки:



    ПРИМЕЧАНИЕ Обратите внимание на обработчики событий onMouseOver и onMouseOut, определенные в объекте Link. Без них можно обойтись, если URL закодирован жестко. Эти обработчики необходимы в случае, если с каждым исходным изображением в баннере связаны различные адреса URL. В таком случае потребуется предусмотреть массив URL и текст mouseOver, зависящий от активного изображения. Внутри раздела поместите дескриптор







    Визуальные эффекты Глава 21



    Для создания анимированных кнопок потребуется проделать следующее: •



    Создать заглушки для изображений на Web-странице под каждую кнопку. • Определить объекты Image и поставить им в соответствие GIF- и JPG-файлы. • Создать программу для вывода изображений на экран по запросу. •



    Добавить код обработчика событий click для объекта Link.



    Для использования объектов Image в качестве заменителей кнопок потребуется определить дескрипторы . Однако, поскольку объекты Image не способны реагировать на события, каждое изображение следует поместить в объекте Link:







    Внутри дескриптора











    - • : < t..



    v-v



    •,» •....- .,.. !• -



    '-.-• 0 ) ) { if «ball, top < 200) SS (ball, top > 0 ) ) ( ball.offset(offsetX, offsetY); return ' ok' ; }else{ return 'topBoundary';



    }else{ return 'leftBoundary' ;



    Теперь рассмотрим функцию, которая обращается к moveBalI(). Для каждого из трех шариков StartTheBallRoIlingO вызывает moveBallO и затем анализирует результаты выполнения. Для зеленого шарика код выглядит так: if



    (moveBall(green, grnX, grnY) == 1 topBoundary'){ grnY = 0-grnY; green.offset(grnX, grnY),: }else{ if(moveBall(green, grnX, grnY) = ' leftBoundary'){ grnX = 0-grnX; green.offset(grnX, grnY); l I



    Если moveBall() завершилась успешно и вернула значение 'ok', сценарий переходит на следующий шаг. Однако, если возвращается 'topBoundary' (или 'leftBoundary'), это означает, что необходимо подкорректировать значение смещения по у (либо по х). Для этого неудовлетворительное значение смещения заменяется на новое, делая его равным нулю минус его текущее значение. Затем выполняется действие offsetO, которое смещает шарик в обратном направлении. Код совершенно аналогичен для красного и разноцветного шариков: if(moveBall(red, redX, redY) == 'topBoundary')( redY = 0-redY; red.offset(redX, redY); )else{ if(moveBall(red, redX, redY) == 'leftBoundary')( redX = 0-redX; red.offset(redX, redY), ) : if(moveBall(color, colorX, colorY) == 1 topBoundary')( colorY = 0-colorY; color.offset( colorX, colorY ) ; )else{ if(moveBall( color, colorX, colorY) == 'leftBoundary')( colorX = 0-colorX; color.offset( colorX, colorY);



    Наконец, вызывается setTimeout(), чтобы сделать этот полный процесс рекурсивным: setTimeout("startTheBallRolling()",



    2) ;



    Заключительный шаг связан с фактическим запуском шарика за счет установки StartTheBallRoIlingO в качестве обработчика для события on Load окна:



    Слои



    Глава 23 После определения функций мультипликации код следует протестировать. На рис. 23.13 и 23.14 показан результирующий мультипликационный эффект. Листинг 23.13 содержит полный исходный код демонстрационной версии BallsGoneWild.



    grnY = 0 - grnY; green.offset(grnX, grnY); }else{ if(moveBall(green, grnX, grnY) == 1 leftBoundary'){ grnX = 0 - grnX; green.offset(grnX, grnY);



    i



    I •



    if (moveBall (red, redX, redY) == ' topBoundary ' ) ( redY = 0 - redY; red.offset(redX, redY) ; )else{ if (moveBall (red, redX, redY) == ' lef tBoundary ' ) { redX = 0 - redX; red.offset(redX, redY) ; t



    if (moveBall (color, colorX, colorY) == 1 topBoundary' ) ( colorY = 0 - colorY; color. off set ( colorX, colorY ) ; )else{ if (moveBall ( color, colorX, colorY) ' lef tBoundary ' ) ( colorX = 0 - colorX; color. off set ( colorX, colorY); } I setTimeout ("startTheBallRolling () " , 2) ;



    РИСУНОК 23.13. Шарики в движении.



    Листинг 23.13. Мультипликационные эффекты на Web-странице.



    _



    JavaScript Unleashed























    Технологии программирования на динамическом HTML Часть IV



    Резюме Слои представляют собой одно из наиболее значительных достижений в HTML за последние несколько лет. Они позволяют выйти за рамки последовательного текстового процессора и погрузиться в мир HTML, графики и дизайна. JavaScript эффективно работает со слоями, обеспечивая разработчикам полный контроль их поведения. Результаты получаются великолепными.



    1



    РИСУНОК 23.14. Шарики в действии.



    Меню и панели инструментов DHTML В ЭТОЙ ГЛАВЕ Начальные предположения Проектирование меню Создание



    инструментальных



    панелей



    Знание языка JavaScript и способов его практического применения — две совершенно разные вещи. Многие способны выучить язык программирования, понять его синтаксис и семантику. Однако очень немногие достигают действительного мастерства в применении своих знаний для решения практических задач, т.е. при создании реальных приложений. Динамический HTML (DHTML) впервые появился в четвертых версиях браузеров Internet Explorer и Netscape Navigator. Оба эти браузера поддерживали JavaScript, слои и таблицы стилей, необходимые для проектирования страниц, у которых полный набор динамических свойств постоянно находился на исходной Web-странице. Именно это способствовало возникновению DHTML, и с тех пор такие технологии применяются на многих сайтах, придавая им яркость и усиливая функциональные возможности. В этой главе рассматриваются два примера DHTMLприложений. Первый пример — меню, а второй — инструментальная панель. Как и в повседневной практике, придется решить, какие браузеры поддерживать и выяснить все отличительные особенности работы браузеров в рамках реализации примеров.



    Начальные предположения Перед началом создания проекта DHTML возникает несколько вопросов, которые задает себе каждый разработчик. Некоторые из них обсуждались в главе 23, тем не мгнее, имеет смысл еще раз напомнить о них: •



    Какие браузеры требуется поддерживать? Помните, что в настоящее время только Navigator 4+ и Internet Explorer 4+ обладают всеми функциональными возможностями, необходимыми для создания DHTMLприложений.







    Требуется ли адаптировать код под неподдерживающие браузеры?







    Насколь изящно требуется обходить возникающие проблемы в неподдерживающих браузерах?



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



    Возможно ли сделать это?







    Как выглядят планы на будущее?







    Существует ли лучший путь для реализации проекта?



    Выяснение возможностей Этот вопрос зачастую игнорируется. JavaScript воспринимается как простой язык, которому может кто угодно научиться. Это могло бы быть верным для версии 1.0 или 1.1, но 1.2 преподносит нечто совершенно новое. Начиная с этой версии, возможности JavaScript существенно возросли, обеспечивая большее количество объектов для поддержки DOM-модели, а также соответствующие XML-технологии. Создание DHTML-приложения не настоль просто, может показаться на первый взгляд, а различия в версиях браузеров превращают этот процесс в весьма утомительную задачу.



    Планы на будущее Еще одно соображение, которое необходимо учесть, — это планы на будущее. Netscape и Microsoft выпускают



    Технологии программирования на динамическом HTML



    Часть IV



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



    Учет API В заключение стоит обсудить тему использования в JavaScript интерфейса программирования приложений (Application Programming Interfaces, API). При создании DHTML в определенный момент может возникнуть мысль: "Должен же существовать более простой способ решения данной задачи; кто-то наверняка уже должен был делать это ранее". Скорее всего, мысль верна. Выгодная сторона JavaScript, который ни что иное как язык программирования для Internet, состоит в том, что можно обнаружить (если немножечко поискать), что другие разработчики уже создали требуемые функции, например, реализующие перемещение слоев. Кроме того, можно обнаружить, что многие разработчики уже создали объекты наподобие каскадного меню или объекты графического редактора. Не стоит в очередной раз изобретать велосипед, если обнаруживается, что кто-то уже написал нужный вам код; просто изучите этот код и воспользуйтесь им при создании своего сайта. СОВЕТ Приложение А содержит ссылки на хорошие сайты, которые содержат полезную информацию по JavaScript API.



    Проектирование меню При проектировании DHTML-меню возникают достаточно очевидные вопросы, например, какие меню и пункты в нем необходимы, и какие должны обеспечиваться функциональные возможности. К тому же, потребуется решить вопрос по поводу оформления меню. Какие планируются цвета и размеры? Насколь длинной должна быть строка меню, и вообще, где меню будет отображаться? Все это вопросы, на которые придется ответить, чтобы потом применять соответствующее форматирование и стили для создания желаемого вида сайта. Для нашего примера меню поставим перед собой следующие цели:







    Работа только с Internet Explorer.







    Серая строка меню в верхней части окна браузера.







    Две опции меню: "Go" и "Help".







    Меню "Go" будет содержать три ссылки на популярные сайты для разработчиков под браузеры Netscape и Microsoft.







    Меню "Help" будет содержать один пункт "About", после выбора которого должно отображаться диалоговое окно с информацией о меню.







    Диалоговое окно "About" будет содержать изображение и кнопку, закрывающую окно.



    Определение слоев Первая вещь, которая будет сделана в плане создания нашего меню — это определение слоев и самой строки меню. Для этого можно использовать комбинацию HTML и CSS. В HTML будут применяться дескрипторы для задания слоев и дескрипторы для определения диалогового окна. Будут также использоваться дескрипторы для работы с событиями щелчков на пунктах меню. Код раздела , реализующий меню, содержится в листинге 24.1. . Одним из важных моментов при создании любого JavaScript-приложения является повторное использование кода; в этом примере повторно используется часть кода из главы 23. Читатель увидит несколько знакомых имен функций и функциональных возможностей. Поскольку планируется, что меню будет поддерживаться только в Internet Explorer, код выяснения типа браузера здесь отсутствует, однако если требуется поддержка Navigator, требуется заменить функцию на ту, которая использовалась в листинге 23.9 главы 23. Как видно из листинга 24.1, для каждого из слоев определяются id и name. Это позволяет применять стили так, чтобы можно было управлять видом и представлением этих слоев. Для установки стилей требуется несколько определений. Ниже приведен соответствующий список: •



    Запрещение подчеркивания дескрипторов ,







    Определение цвета и расположения строки меню.







    Определение цвета и расположения пунктов "Go" и "Help" в меню.







    Определение цвета, расположения и сокрытия "Go" и "Help" в меню.



    • Определение цвета, расположения и сокрытия диалогового окна "About". Листинг 24.2 содержит определения таблиц стилей, которые потребуются для форматирования.



    Меню и панели инструментов DHTML



    Глава 24 Листинг 24.1. Определение слоев в HTML. .r



    , .



    ^ШШ;.^'."";:^.



    РИСУНОК 24.5. Прохождение мышки над кнопкой.



    !•'..



    g|



    Ц -.•.„i,.,. №j>



    .»" ' i..-»./; Ц :



    4 i...r-i!,4! j



    Что должно происходить? Первое, что необходимо, — это задокументировать, что должно происходить в инструментальной панели. Откройте окно браузера и понаблюдайте, как изменяется состояние кнопок при проходе по ним мышкой и при нажатии на них. На рис. 24.4—24.6 показано, изменение состояний кнопок в браузере Navigator 4.



    '



    ,.:



    •: .;.>г.г,-ЬЮ ЙЙ-,159 r V i ^ . / . n ^ i . A'Jr. --



    ~. ,, ..... . ,,„1:г [t;iO-"uiuae;.-tlD >ll U-^ , b.-i'r.i', .,



    i\



    * Л



    l



    f



    Met-, щ-к BI:;' Helsi'ipe N .v/i;'f &t m " -"i C;.nruwr,K,v.;.ir)iC'-'ii,;.i,,{l. i»d if r^.C!; nuitlr* Mt: t"J.4' trU'itei^-S ч'Г t ' i b r v ;



    .. }



    РИСУНОК 24.6. Нажатие на кнопку инструментальной панели.



    Что может происходить?



    ,,



    L



    ;• '



    ;



    !-j



    ' Netscape® .Navioator^Os *



    N



    .



    c 1



    - / : --







    ' •"•....'.



    19Й«В98^ёЙеаг.(-Сс



    1 TW Т



    \ This eof*,v/3if ii£\itJ5ctlotin'lk»r. :.• |*ай and agree to



    РИСУНОК 24.4. Обычная инструментальная панель.



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



    В перспективе совершенствования разработки под Web могут быть созданы все необходимые функциональные возможности для инструментальной панели. Существуют события для перемещения курсора мыши на элемент и с этого элемента, а также для нажатия и отпускания кнопки. С помощью свойства Image.src, которое может заменять одно изображение на странице на другое, можно смоделировать перемещение курсора мыши и нажатие кнопок. Это свойство обеспечит визуальные эффекты. Для кнопок потребуется также выполнять определенные задачи. Для этого будет использоваться событие onClick в дескрипторе . Если пользователь нажимает на кнопку, щелчок захватывается и обрабатывается. Ниже приведен список используемых кнопок вместе с их функциями.



    Технологии программирования на динамическом HTML



    Часть IV











    Back. Эта кнопка моделирует кнопку "Back" или "Previous" браузера. Будут использоваться разные методы для работы в Internet Explorer и Navigator с целью демонстрации того, как можно создавать нужные программы с учетом разных браузеров. Forward. Эта кнопка моделирует кнопку "Forward" или "Next". Будут использоваться разные методы для работы в Internet Explorer и Navigator с целью демонстрации того, как можно создавать нужные программы с учетом разных браузеров.



    Модульное программирование Спланируем это приложение как можно более модульным, чтобы код при необходимости мог использоваться в другом месте. Для этого придется создать множество функций, обрабатывающих информацию. Для приложения можно выделить три различных набора функциональных возможностей: •



    • Ноте. Эта кнопка моделирует кнопку "Ноте" в браузерах Navigator. Internet Explorer данный метод не поддерживает.



    Image State Change (Изменение состояния изображения). Эта функция, вызываемая в методе rolllmage(), будет отвечать за изменение изображения при перемещении на него курсора мыши либо при нажатии кнопки.







    Reload/Refresh. Эта кнопка моделирует кнопку "Reload" или "Refresh" браузера, которая приводит к повторной обработке и визуализации текущей страницы. При помощи метода Date.getTime() будет отображаться загрузка страницы.



    • Button Processing (Обработка кнопки). Эта функция, вызываемая в методе process(), будет выполнять задачи, возложенные на кнопку. Когда пользователь нажимает на кнопку, эта функция реагирует соответствующим образом.







    Find. Эта кнопка моделирует опцию меню Edit -> Find, которая обеспечивает поиск текста в окне браузера. Internet Explorer этот метод не поддерживает.







    Print. Эта кнопка моделирует кнопку "Print" браузера — вызов диалогового окна Print для печати текущей страницы.



    • URL Handling (Обработка адресов URL). Эта функция, вызываемая в методе takeBrowser(), будет брать данные, введенные в форму, и направлять браузер в указанное расположение.



    В дополнение к перечисленным шести кнопкам, будет также использоваться форма с текстовым полем, которое позволяет вводить URL и щелкать на кнопке "Go" для загрузки URL в окно браузера. Теперь, когда выяснены все требования, приступим к реализации приложения. Будет рассматриваться как создание изображений, так и написание кода.



    Описание проблем проектирования Прежде чем приступать к написанию какого-либо кода, следует принять несколько решений относительно способов записи и хранения кода. Большинство функциональных возможностей меню можно включить в HTMLдескрипторы — не такое существенное увеличение объема кода. Однако, функциональные возможности, которые предоставляет пример, могут быть задействованы и в другом месте, потому стоит прибегнуть к более модульному подходу. Хранение кода До начала создания приложения необходимо решить, где будет храниться код. Здесь следует опираться на то, что именно конструируется. Для текущего приложения весь код будет храниться в рамках HTML-документа. Если сайт располагается во множестве мест, тогда код лучше хранить во внешнем JavaScript-файле (с расширением .js).



    Создание изображений В отличие от других приложений, для Web-приложения потребуется обеспечить максимум компонентов, которые могли бы погрузиться в любой интерфейс. Помимо подобъектов объекта Form, необходимо создать все собственные изображения и интерфейсные компоненты. Из-за характера задачи также потребуется обеспечить версии изображений для событий прохождения курсора мыши по изображению и нажатых состояний кнопок. Ранее упоминалось, что кнопка на инструментальной панели должна изменить свое состояние, при перемещении по ней курсора мыши, а также в ситуации, когда она нажата. Для работы примера возникает необходимость в следующих изображениях: • Normal. Изображение по умолчанию. • Rollover. Значение по умолчанию, отображаемое с белой рамкой толщиной в 1 пиксел слева и сверху и серой рамкой толщиной в 1 пиксел справа и снизу. •



    Pressed. Значение по умолчанию, отображаемое с серой рамкой в 1 пиксел слева и сверху, и с белой рамкой в 1 пиксел справа и снизу.



    Написание HTML-кода Первое, что будет создаваться — это HTML-код, который содержит макет инструментальной панели. Существует несколько компонентов для интерфейса проектируемой инструментальной панели (см. рис. 24.7).



    Меню и панели инструментов DHTML Глава 24 Во второй строке инструментальной панели содержится текстовое поле, в котором пользователь будет вводить URL. Когда пользователь нажимает кнопку "Go", браузер начинает загружать URL. HTML-код для этого — простой дескриптор . Кнопка использует обработчик событий onClick(), чтобы вызвать функцию, которая перенаправляет браузер на соответствующий URL. Атрибут colspan применяется для корректного размещения ячейки по ширине всей таблицы. HTML-код выглядит так:



    Location:











    Последняя строка всего лишь содержит результаты вызова метода getTime() экземпляра объекта Date. Это делается для того, чтобы пользователь мог видеть работу кнопки "Reload". Когда пользователь нажимает "Reload", числовое значение, отображаемое в этой ячейке, изменяется, подтверждая фактическую перегрузку страницы. HTML-код для этой строки следующий: Result of Date.getTimeO (reload verification) :



    Три строки в комбинации с дескриптором составляют всю интерфейсную часть инструментальной панели. Листинг 24.5 показывает, что у нас уже имеется к настоящему моменту.



    Листинг 24.5. HTML-часть панели инструментов.











    Технологии программирования на динамическом HTML Часть IV




















    Location :



    Result of Date . getTime ( ) (reload verification):







    Реализация rollover-эффектов для изображений Для реализации rollover-эффектов для изображений



    жение. Как видно в HTML-коде из листинга 24.5, каждый из дескрипторов , обрамляющих изображение, вызывает функцию rollImageQ, которая будет определена в данном разделе.



    используется объект Image, который, надо признать,



    Вначале потребуется объявить все используемые



    ограничивает применимость приложений до браузеров,



    изображения. Поскольку планируется использовать раз-



    поддерживающих JavaScript 1.1. Прежде всего рассмот-



    личные состояния, лучше всего сохранить их в масси-



    рим свойство src, которое позволяет изменять изобра-



    ве. Это позволит обращаться к изображениям в массиве



    Меню и панели инструментов DHTML Глава 24 и в документе с помощью тех же самых индексных значений. Например, на первое изображение в документе можно ссылаться через массив document.images таким образом: document.images [ 0 ] Если хранить изображения версий "нажатия" и "курсор понерх изображения" в двух разных массивах с одной и той же индексацией [0], то для выполнения подмены изображений в функцию можно передавать только одну переменную позиции. Ввиду того что требуется также восстановить предыдущее состояние изображение (значение по умолчанию), возникает необходимость в объявлении трех массивов. Ниже показан код для создания этих массивов и для записи изображений в них: // Массив для хранения изображений версий // "нажатия" var overling = new Array () ; overImg[0] = new Image(24,24) overling [1] = new Image(24,24) overling [2] = new Image(24,24) overImg[3] = new Image (24,24) overling [ 4 ] = new Image(24,24) overling [ 5 ] = new Image(24,24) // Массив для хранения изображений версий // "курсор поверх изображения var downlmg = new Array () ; downlmg[0] new Image(24,24) downlmg[1] new Image (24,24) downlmg[2] new Inage(24,24) downlmg[3] new Image(24,24) downlmg[4] new Image(24,24) down Img [5] new Image (24,24) // Массив для хранения изображений по ,'/ умолчанию var defaulting = new Array () ; defaultlmg[0] : new Image(24,24) ; defaulting[1] : new Image(24,24); defaultlmg[2] = new Image(24,24) ; defaulting[3] • new Image(24,24) ; defaulting[4] • new Image(24,24); def aultlmg [5] • new Image(24,24) ; 11 Загрузка over • изображений overImg[0].src = "back-over.gif"; overling[1] .src = "forward-over.gif" overling [2 ]. src = "home-over.gif" ; overling[3] .src = "reload-over.gif"; overImg[4].src = "search-over.gif"; overlng[5].src = "print-over.gif"; // Загрузка down- изображений downlmg[0].src = "back-down.gif"; downlmg[l].src = "forward-down.gif" downing[2].src = "home-down.gif"; downlmg[3].srс = "reload-down.gif"; downlmg[4].src — "search-down.gif"; downing[5].src = "print-down.gif"; // Загрузка изображений по умолчанию defaultlmg[0].src = "back.gif"; defaultlmg[1].src = "forward.gif"; defaultlmg[2].src = "home.gif"; 1-15!



    defaulting[3].src = "reload.gif"; defaultlng[4].src = "search.gif"; defaultlmg[5].src = "print.gif"; Сейчас необходимо определить функцию. Это гораздо проще, чем можно было ожидать. Функция будет принимать два параметра. Первый параметр — индекс обрабатываемого изображения. Вызов функции, содержащийся в дескрипторе , передает числовое значение, которое представляет его расположение в документе. Например, для первого изображения потребуется передать 0, для второго — 1 и т.д. Помните, что нумерация этого списка начинается с нуля, поэтому первому изображению соответствует индекс 0. Второй параметр — это тип rollover-эффекта. Для нашего примера возможны четыре типа: over, out, up и down. Переданное значение анализируется в операторе switch и выполняется соответствующая подмена изображения с использованием свойства src экземпляров объекта Image — как в документе, так и в массивах. Полное определение функции выглядит следующим образом: function roilImage(img,type){ switch(type){ case "over": document.images[ img].src = overlmg[img].src; break; case "out": document.images[img].src = defaultlmg[img].src; break; case "up": document.images[img].src = defaulting[img].src; break; case "down": document, images[img] .src = downing[img].src; break; I I



    Приведенный код обеспечивает необходимую реализацию rollover-эффектов для изображений.



    Реализация поля адреса Во второй строке примера для инструментальной панели находится текстовое поле, которое позволяет пользователю вводить URL, после чего нажимать "Go" для переадресации браузера. Как было показано в HTMLкоде, эта кнопка обращается к функции takeBrowser() и передает ей объект this.form. Как только функция вызвана, она будет использовать переданную ей ссылку на объект Form, присвоит ее переменной и обратится к значению текстового поля. Затем для изменения страницы, загруженной в настоящий момент в браузер, задействуется свойство location.href, и, таким образом, браузер переадресуется на введенный пользователем новый адрес URL.



    Технологии программирования на динамическом HTML Часть IV



    Эта функция не выполняет проверку ошибок, поэтому, если пользователь вводит некорректное значение, браузер просто сообщает о невозможности загрузки страницы. Из показанного ниже кода видно, что к значению текстового поля обращаются через имя поля, определенное в атрибуте name. function takeBrowser(ref){ var form = ref; location.href = form.where.value;



    >



    Обработка событий, связанных с кнопками Последняя необходимая функция будет отвечать за собственно обработку. Эта функция имя которой processQ, принимает один параметр. Параметр будет вычисляться в операторе switch для шести возможных кнопок. Кнопки "Find" и "Ноте" в Internet Explorer не работают, поэтому необходимо возвращать сигнальное диалоговое окно, сообщающее об этом факте. Существует также ряд других функций, которые реализуются поразному в браузерах Navigator и Internet Explorer; им также потребуется уделить внимание. Введем переменную, которая будет сообщать о том, является ли данный браузер браузером Internet Explorer. Это логическое значение будет храниться в переменной isIE, которая будет проверяться в первой строке кода функции. Код для данной функции выглядит следующим образом: function process(item){ var isIE = new Boolean(navigator.userAgent. indexOf("MSIE") != -1) ; switch(item){ case "find": if(isIE){ alert("Internet Explorer does not w support this method"); )else{ window. find() ; I break; case "print":



    window.print() ,° break; case "home": if (isIE) { alert("Internet Explorer does not "••support this method") ; }else{ window.home(); i break; case "reload": document.location.reload(); break; case "forward": if(isIE){ history.forward(); )else{ window.forward(); I break; case "back": if(isIE){ history.back(); )else{ window. back () ; ) break;



    Проверка результатов На данный момент рассмотрены все HTML- и JavaScriptкоды, поэтому теперь можно протестировать полученное приложение. Окончательный код содержится в листинге 24.6, а рис. 24.8 и 24.9 демонстрируют rolloverэффекты для кнопок. При тестировании программы наблюдайте за изменениями строки, содержащей текущее время, она должна изменяться после щелчка на кнопке "Reload". Результат нажатия на кнопки "Find" и "Print" очевидны, поскольку при этом всплывают диалоговые окна. Если требуется проверить кнопки "Forward" и "Back", загрузите несколько страниц в браузер, тем самым обеспечив переходы браузера вперед и назад.



    Листинг 24.6. Полный исходный код для инструментальной панели.



    JavaScript Unleashed































    Location :



    Result of Date . getTime ( ) (reload verification) :







    РИСУ НОК 24.8. Курсор мыши над кнопкой.



    Резюме В главе уделялось внимание подробностям, связанным с реализацией DHTML на сайте. Полученные знания



    РИСУНОК 24.9. Нажатие кнопки инструментальной панели. помогут приступить к созданию динамических страниц с использованием не только JavaScript, но также и других HTML-элементов и CSS.



    Взаимодействие с другими технологиями В ЭТОЙ ГЛАВЕ Подключаемые модули браузера Элементы управления ActiveX Java-аплеты LiveAudio



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



    Подключаемые модули браузера Современные браузеры собственными средствами могут поддерживать содержимое всего лишь нескольких видов файловых форматов, к которым относятся тексты (включая HTML) и изображения. Однако для работы вне Web-браузеров люди для решения различных задач постоянно используют множество других файловых форматов. Например, большинство прикладных программ обработки текстов имеют собственные файловые форматы (например, формат .doc файла Microsoft Word), так же дело обстоит и с приложениями электронных таблиц, презентаций, мультимедиа и т.д. Если Web-браузер поддерживает различные файловые форматы, появляется возможность построения различного содержимого, в любой момент доступного через Web, не говоря уже о применении Internet для новых и увлекательных способов представления информации. Однако, для Netscape (или любой другой компании) создание в браузере собственной поддержки всех ис-



    пользуемых файловых форматов было бы непрактичным из-за слишком больших затрат денежных и временных ресурсов. Так что для большинства браузеров решение отдается в пользу технологии подключаемых модулей. ПРИМЕЧАНИЕ



    Хотя в главе обсуждаются различные технологии, с которыми JavaScript может взаимодействовать, здесь не будет говориться о применении этих технологий на Web-страницах. Например, не будет детально рассматриваться использование дескрипторов , и , а также их атрибутов. Для получения дополнительной информации по этой теме посетите сайты Microsoft Developer Network (http:// msdn.microsoft.com) либо Netscape DevEdge (http:// developer.netscape.com), а также сайт W3C-«oHcopциума (http://www.w3.org).



    Подключаемые модули и MIME-типы Подключаемые модули идентифицируют тип передаваемых им данных в зависимости от MIME-типов. Идентифицируя тип данных, подключаемый модуль может выбирать соответствующий способ их обработки. MIME является стандартом Internet, который определяет способы передачи файловых форматов (не текстовых) в почтовых сообщениях Internet. (Более подробная информация может быть найдена в Internet Requests For Comment (RFCs) 1521 и 1522.) Толчком для создания упомянутого стандарта послужила необходимость передачи через электронную почту не только документов, содержащих простой текст. MIME теперь позволяет прикладным программам электронной почты работать с отформатированным текстом, файлами приложений и другими типами файлов, расширяющих сообщения. Стандарт MIME может обрабатывать любой файловый



    Взаимодействие с другими технологиями



    Глава 25



    формат, включая текст, PostScript, файлы изображений, звуковые, видео- и сжатые файлы. MIME-типы определяют тип содержимого и специфический подтип различных файловых форматов. Это стоит пояснить на примере. М1МЕ-тип для файлов с расширением .wav (Microsoft audio) определяется как audio/x-wav. audio описывает звуковой тип или категорию поддерживаемых файлов, a x-wav — определенный тип файла (или подтип), поддерживаемый с учетом требований браузера, для интерпретации файлов .wav. После начала работы браузер начинает просматривать все установленные подключаемые модули и присваивает MIME-типы соответствующим подключаемым модулям, которые могут прочитать их. При выявлении в процессе просмотра MIME-типа браузер загружает присвоенный (или зарегистрированный) подключаемый модуль в память, и MIME-тип обрабатывается этим подключаемым модулем. MIME-тип может отображаться одним их трех способов: •







    navigator.plugins. Этот объект, представляющий собой свойство объекта Navigator, — массив всех подключаемых модулей, в настоящий момент установленных в браузере клиента. Поскольку такой массив фактически является подобъектом объекта Navigator, он имеет следующие свойства: •



    name. Имя подключаемого модуля (например, Shockwave).







    filename. Имя файла подключаемого модуля.







    description. Описание подключаемого модуля (обеспечивается поставщиком модуля).







    length. Количество элементов в массиве.







    [...]. Массив объектов mimeTypes, которые может прочесть подключаемый модуль.



    • navigator.mimeTypes. Это свойство, представляющее собой подобъект объекта Navigator, — массив всех mimeTypes, поддерживаемых в браузере клиента. Подобъект имеет следующие свойства:



    Встроенный (inline). Появляется на странице вместе с другим содержимым. Размер области подключаемого модуля определяется предварительно установленными значениями параметров height и width дескриптора, используемого для загрузки этого подключаемого модуля.











    enabledPlugin. Подключаемые модули, которые могут прочесть данный MIME-тип.







    Полный (full). Подключаемый модуль занимает все окно браузера за исключением инструментальных панелей.











    Скрытый (hidden). Подключаемый модуль выполняется в фоновом режиме (подобно некоторым аудиомодулям).



    suffixes. Расширения имен файлов, с помощью которых идентифицируются MIME-типы (например, .wav для MIME-типа audio/x-wav). Расширения отделяются друг от друга запятыми.



    Определение устанавливаемых подключаемых модулей Определение того, какие в клиентском браузере установлены подключаемые модули и какие поддерживаются MIME-типы, дает разработчику Web-страницы множество возможностей по управлению содержимым, предназначенным для отображения пользователям. Например!, один из сценариев разработки мог бы выглядеть так: "Если пользователь имеет подключаемый модуль, отображается страница со всеми соответствующими MIME -типами, а иначе — альтернативное содержимое". В большинстве браузеров (но только не в Internet Explorer) JavaScript помогает выполнить это. JavaScript-браузеры содержат два встроенных объекта, которые дают весьма полезную информацию о подключаемых модулях и MIME-типах, поддерживаемых браузером клиента:



    type. Имя MIME-типа (например, audio/x-wav).



    • description. Описание MIME-типа (обеспечивается поставщиком модуля).



    Объект Plugins Используя эти объекты в сочетании с JavaScript, можно довольно быстро определить, установлен ли подключаемый модуль. Ниже приведен пример, в котором выясняется наличие подключаемого модуля Macromedia Shockwave. Если данный подключаемый модуль присутствует, файл загружается и отображается. Если нет, отображается альтернативная информация: var



    DesiredPlugin = navigator.plugins["Shockwave"];



    // if



    ссылка на имя объекта подключаемого модуля (DesiredPlugin) { document. write ( ' viewing is lecue. hlamatior. about it! privacy certificate wil be thown beta»



    Certificate Hoflnferr. L-Pittsbugh 0-GAlTTecbnologiei.lnc. :N-netwixlh gaK.com vcuec C-US 0-RSA Data Secujty. Ire. E«pralionDa(B: Sioaiiy Ptntocot Е:кгур|юп Type: Plivacy Stiength-



    7/гЭ/Ж1гОО:ООДМ 1 /36У97 1 1 £333 FW



    SSL го



    HSfcMDS RC4 Low (40 Ыгг)



    РИСУНОК 35.7. Информационное диалоговое окно Internet Explorer, сообщающее о защищенности документа.



    lietrite: fctip^'totwonh Mdt coi.i' File MIME Type: leatfhbd Source: Currency in diik cache Local cache rae: MOOWJVH Lut Modified: Моп