Глава 2. Основы сценариев HTML



Объектная модель динамического HTML (Dynamic HTML object model) была разработана на основе объектных моделей, включенных в Microsoft Internet Explorer 3.0 и Netscape Navigator 3.0. В данной главе приведен исторический обзор со сравнением старых объектных моделей и модели динамического HMTL и показан уровень поддержки данной модели различными версиями браузеров.

Языки написания сценариев развивались наряду с объектными моделями HTML. Путем внедрения сценариев в документы вы можете обращаться к объектам HTML для манипулирования элементами Web-страниц. Здесь приведено описание этого мощного метода программирования.

В главе рассмотрены следующие темы:

  • Объектная иерархия динамического HTML. Объектная иерархия представляет собой интерфейс прикладного программирования (application programming interface, API) для создания живых интерактивных страниц. Объекты в иерархии представляют браузер и элементы страницы HTML. В данном разделе обсуждаются объектные модели, поддерживаемые Internet Explorer 3.0 и Netscape Navigator 3.0 и 4.0 и дается сравнение этих моделей с объектной моделью динамического HTML, поддерживаемой Internet Explorer 4.0.

  • Написание сценариев. Доступ к объектной модели динамического HTML осуществляется посредством написания сценариев и связывания их с документом HTML. Сценарий присоединяется к документу HTML с помощью элемента Script, который содержит выполняемую программу на определенном языке. Элемент Script может быть также использован для связывания с документом внешних библиотек сценариев.

  • Выбор языка написания сценариев: JavaScript или VBScript. На Web используются два главных языка программирования: JavaScript и VBScript. Оба языка могут манипулировать объектами динамического HTML. В этом разделе дано описание выбора языка в определенных ситуациях.

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

  • Использование сценариев и безопасность в Web. Безопасность является общей заботой всех участников Web. Языки программирования накладывают определенные ограничения для обеспечения безопасности клиента, которые должны быть известны программисту. В данном разделе вводится модель безопасности для динамического HTML. Дополнительные вопросы безопасности обсуждаются на протяжении всей книги.

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



Иерархия объектов динамического HTML

Минимальная модель объектов HTML была впервые введена как часть реализации JavaScript в Netscape Navigator 2.0. Исходная модель предоставляла возможность манипулирования только малым количеством параметров документа с помощью языка написания сценариев. Однако эта модель заложила основу для последующих версий объектных моделей.

Internet Explorer 3.0 отделял исходную объектную модель для описания документа от реализации языка. Это положило основу для требования независимости от языка динамического HTML. Internet Explorer 4.0 построен на данной модели для полного представления всех параметров документа.

На рис. 2.1 показана объектная модель, поддерживаемая Internet Explorer 4.0.

Рис. 2.1. Объектная модель Internet Explorer 4.0



Эволюция иерархии динамического HTML

В приведенных ниже списках представлена эволюция поддержки объектов в различных браузерах.

Intemet Explorer 3.0 поддерживает следующие объекты:

  • anchors
  • document
  • document.frames
  • elements
  • forms
  • history
  • links
  • location
  • navigator
  • window
  • window.frames

Netscape Navigator 3.0 поддерживал тот же набор объектов, что и Internet Explorer 3.0 за исключением объекта document.frames и двух дополнительных объектов:

  • applets
  • images

Internet Explorer 4.0 поддерживает те же объекты, что и Internet Explorer 3.0 и Netscape Navigator 3.0, а также добавляет поддержку для следующих элементов:

  • all
  • body
  • clientInformation
  • event
  • screen
  • scripts
  • selection
  • styleSheets

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

Объект window (окно) представляет собой объект высшего уровня в объектной модели HTML и является фреймом для объекта document (документ). Все взаимосвязи с документом поддерживаются посредством окна. Объект window также представляет информацию об URL текущего документа, об URL, которые были просмотрены клиентом ранее, и информацию о типе текущего документа.

Окно может содержать различные типы документов в зависимости от типа MIME. Существует два типа документов HTML: традиционный документ HTML и набор фреймов (frameset) HTML. Для обоих типов содержание документа выводится посредством объекта document. Поскольку наборы фреймов разделяют экран на многочисленные фреймы, каждый индивидуальный фрейм также выводится посредством семейства окна frames. Каждый фрейм в этом семействе в действительности представляет другой объект window и потенциально другой документ или другое семейство frames и так далее.

Наборы фреймов подробно обсуждаются в главе 5.



Эволюционное (революционное) развитие динамического HTML

Netscape Navigator 2.0 и Internet Explorer 3.0 ввели базовые объектные модели для HTML-документов. Однако уровень поддержки был преимущественно ограничен условной логикой в ходе загрузки страниц и проверки форм. Небыли разрешены изменения, которые могли бы изменить форму или воспроизведение документа. Internet Explorer 4.0 преодолел данное ограничение путем использования объектной модели, которая выводит весь документ целиком.

Вместо определения совершенно новой объектной модели разработчики создали объектную модель динамического HTML, которая содержит в своем составе текущую модель. Кроме того, объектная модель динамического HTML согласуется с текущими парадигмами программирования, что позволяет разработчикам использовать накопленные знания. Если вы знакомы с написанием сценариев для Internet Explorer 3.0 или Netscape Navigator 3.0, то у вас уже есть базовые сведения для изучения динамического HTML.



Поддержка старых версий браузеров

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

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

В некоторых случаях программа выдает визуальный сигнал и деградация обычно примитивна. В других случаях, в зависимости от цели сценария единственным решением является создание отдельных страниц, которые предоставляют те же возможности отличным образом. В целом, чем более динамична страница, тем тщательнее следует продумывать режимы воспроизведения страницы в примитивных браузерах (браузерах с меньшими возможностями). На рис. 2.2 показана страница, разработанная с использованием динамического HTML, которая запущена в двух браузерах: Internet Explorer 3.0 (сверху) и Internet Explorer 4.0 (снизу). Версия Internet Explorer 3.0 отображает расширенную примитивную таблицу, тогда как Internet Explorer 4.0 выводит красиво оформленное оглавление.

Рис. 2.2. Страница динамического HTML в Internet Explorer 3.0 (сверху) и Internet Explorer 4.0 (снизу)

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



Динамическое переформатирование

Возможность доступа к любому параметру страницы и его изменения демонстрирует одно из ключевых нововведений, доступное в динамическом HTML. Старые браузеры, хотя и позволяли осуществлять некоторые изменения в документе, были не способны выполнять переформатирование (reflow) документа без сложных сценариев, которые создавали совершенно новые документы. Динамический HTML свободен от этих ограничений. Когда сценарий манипулирует и изменяет атрибуты элемента или таблицы стилей, или модифицирует содержание, то документ соответствующим образом изменяет представление страницы на основе новой информации.

Динамический HTML был разработан для использования преимуществ существующих рекомендаций и рабочих проектов HTML и CSS (Cascading Style Sheets). Разработчикам не надо изучать новую модель представления страницы - объектная модель динамического HTML представляет отражение документа в языке написания сценариев. Например, сценарий может изменить атрибут CLASS любого элемента HTML. В языке написания сценариев атрибут CLASS, подобно другим атрибутам, представляется как свойство элемента - в данном случае свойство className. Изменение атрибута внутренне совместимо с открытием файла пользователем в текстовом редакторе и изменением атрибута в исходном файле. Данная модель гарантирует, что по мере развития HTML и CSS будет соответствующим образом изменяться и объектная модель.



Создание сценариев

Сценарии не являются единственным способом доступа к объектной модели динамического HTML. Доступ к объектной модели динамического HTML может осуществляться тремя способами:

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

  • Посредством внедренных апплетов или элементов управления, которые находятся на странице.

  • Посредством хостов, которые находятся за пределами или рядом с браузером. Например, диалоговое окно Find в Internet Explorer 4.0 было создано с помощью динамического HTML.

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



Элемент Script

Сценарии на странице могут быть связаны с документом с использованием одного из трех методов. Наиболее общий метод заключается в помещении программы в элемент Script. (Два остальных метода помещают программу в отдельный файл и ссылаются на него при помощи тега <SCRIPT> или помещают программу в атрибут события в другом теге). Элемент Script представляет собой контейнер для программы, написанной на определенном языке программирования. Элемент Script может содержать программу, находящуюся в документе, или ссылаться на внешний файл. Сценарии, содержащиеся внутри элемента Script, могут быть связаны с элементом при помощи программы, специальных атрибутов элемента Script или посредством зависимого от языка механизма. Индивидуальные элементы могут иметь сценарии, которые связаны с ними непосредственно атрибутами событий, представленных в самом элементе.

Ниже приведен синтаксис элемента Script:

<SCRIPT LANGUAGE="languageName" [TYPE="MIMEtype"]
[SRC="optionalFile"] [DEFER]>
Script statements
</SCRIPT>

Язык написания сценариев определяется с помощью атрибута LANGUAGE. Приведенная ниже программа демонстрирует определение сценария для языков JavaScript и VBScript:

<SCRIPT LANGUAGE="VBScript">
' VBScript code
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
// JavaScript code
</SCRIPT>

Примечание: В VBScript комментарии предваряются символом апострофа ('). В языке JavaScript перед комментариями ставятся символы // (это значит, что вся остальная часть строки является комментарием), или комментарий заключается между символами /* и */. Поисковые машины игнорируют текст комментариев.

Исторически сложилось так, что пропуск атрибута LANGUAGE приводит к интерпретации сценария как программы на JavaScript. Рекомендуется всегда указывать атрибут LANGUAGE, в соответствии с контекстом сценария документа.

Примечание: В HTML 4.0 атрибут LANGUAGE элемента Script использовать не рекомендуется. Вместо него следует использовать атрибут TYPE. Атрибут TYPE использует тип MIME для определенного языка: для JavaScript используется параметр text/JavaScript, а для VBScript - параметр text/VBScript. Однако поскольку примитивные браузеры не распознают атрибут TYPE, то рекомендуется использовать тег LANGUAGE или оба тега: LANGUAGE и TYPE. Обратите внимание, что если распознается атрибут TYPE, то установка атрибута LANGUAGE отменяется.

С введением Netscape Navigator 3.0 компания Netscape начала присоединять номер версии к строке определения языка JavaScript. Поэтому для написания программы, которая выполняется только в Netscape 3.0 и Microsoft Internet Explorer 4.0 или более поздней версии, установите значение атрибута LANGUAGE равным JavaScript 1.1. Данный метод работает, поскольку если браузер не распознает указанный язык, то программа не выполняется и блок сценария пропускается.

В разделе данной главы "Языки написания сценариев" можно найти программу, которая демонстрирует, как определить поддерживаемые клиентом языки написания сценариев без проверки типа и версии браузера.

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

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

Модель событий подробно описана в главе 3.

<HTML>
<HEAD>
<TITLE>Execution of Code</TITLE>
<SCRIPT LANGUAGE="JavaScript">
// Приведенное ниже сообщение появляется во время загрузки страницы. alert('Hello, World!');
function helloWorld() {
// Данная программа выполняется только при вызове функции // helloWorld.
alert('Hello, World Too!');
}
</SCRIPT>
</HEAD>
</HTML>



Библиотеки сценариев

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

Ссылка на внешний сценарий осуществляется с помощью атрибута SRC, как показано в приведенном ниже примере:

<SCRIPT LANGUAGE="JavaScript" SRC="genericFile.js">
/* Здесь можно поместить текст программы для браузеров, которые не
поддерживают атрибут SRC.*/
// Всегда указывайте закрывающий тег SCRIPT.
</SCRIPT>

Даже при указании атрибута SRC тег <SCRIPT> должен иметь закрывающий тег. Браузеры, не поддерживающие атрибут SRC, игнорируют содержание элемента Script. Браузеры, которые распознают атрибут SRC, интерпретируют содержание элемента Script как программу.

Поддержка внешнего файла сценария доступна только в Netscape Navigator 3.0 и Internet Explorer 4.0 или более поздней версии. Поэтому при использовании внешних файлов сценариев учтите ограниченные возможности более ранних версий данных браузеров.



Немедленное выполнение программы

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

  • Добавлению свойств в объект window и инициализации его состояния

  • Выводу содержимого в поток документа

Первая цель сходна с описанием того, что можно считать глобальными переменными. Во всех языках написания сценариев переменные, которые ограничены объектом window, добавляются непосредственно в объект window как свойства. В приведенном ниже примере переменная х добавляется как свойство в окно:

<SCRIPT LANGUAGE="JavaScript">
var x = 0; // Создает свойство и присваивает ему значение, равное 0.
alert(window.x); // Выводит 0, значение переменной х.
</SCRIPT>

Чтобы лучше разобраться в приведенной выше программе, рассмотрим более подробный пример:

<SCRIPT LANGUAGE="JavaScript">
// Создает свойство х и присваивает ему значение, равное 10.
var x = 10;
function foo() {
Данная программа выполняется только после явного вызова.
/* Создает экземпляр переменной у, который существует только во время выполнения функции.*/
var y = 0; alert(x); // Выводит 10; х является свойством окна.
}
// Вызывает foo при загрузке страницы. foo();
window.foo(); // Вызывает функцию foo снова, поскольку данная // функция добавляется в окно.
</SCRIPT>

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

Второй целью программы, которая выполняется при загрузке страницы, является запись содержимого в документ. Это выполняется с помощью метода write объекта document. Ниже приведена простая программа, которая записывает строку "Hello, World!" в HTML-документ:

<HTML>
<HEAD>
<TITLE>Hello, World!</TITLE> </HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
// Запись строки "Hello, World!" в документ.
document.write("<H1>Hello, World!</H1>")
</SCRIPT>
</BODY>
</HTML>

Метод write может быть вызван в ходе загрузки страницы для вставки содержимого для манипулирования. Чтобы изменить содержание после загрузки страницы, следует использовать другой метод.

Динамическое добавление содержания в документ в ходе процесса загрузки обсуждается в главе 6, а манипулирование содержанием обсуждается в главе 13.



Местоположение сценариев в документе

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

Местоположение элемента Script более важно, если элемент действительно записывает содержание в поток документа или ссылается на элемент в документе. Запись в поток осуществляется с помощью методов write или writeln в объекте document, как показано в приведенном ниже примере:

<HTML>
<SCRIPT LANGUAGE="JavaScript">
// Генерирует весь документ на основе данного сценария.
document.write("<HEAD><TITLE>My Document</TITLE></HEAD>");
document.write("<BODY><H1>This is my page.</H1></BODY>");
</SCRIPT>
</HTML>

Данный код создает и воспроизводит следующий HTML:

<HTML>
<HEAD>
<TITLE>Мой документ</TITLE>
</HEAD>
<BODY>
<H1>Это моя страница.</H1>
</BODY>
</HTML>

Если вы записываете содержание заголовка, то важно поместить сценарий в заголовке. Например, сценарий, помещенный в середине страницы, не будет выводить текст HTML, который устанавливает заголовок документа. При вызове методов write или writeln содержание документа помещается в поток в текущем месте. Например, вставка тега TITLE в неверном месте может изменить определение типа документа (DTD) HTML и привести к непредсказуемым последствиям.

Использование методов write подробно обсуждается в главе 6.

Генерация страниц с помощью метода document.write не всегда является идеальным способом, поскольку препятствует работе инструментов редактирования и индексирования, которые не смогут интерпретировать сценарии. Без выполнения сценария в фоновом режиме действительное содержание останется неизвестным.



Доступность объектов

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

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

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

<SCRIPT FOR="document" EVENT="onclick()" LANGUAGE="JavaScript">
// Данная программа выполняется только когда пользователь щелкает
// мышью в документе.
// Проверка наличия элемента.
if (null != document.all.myElement) {
// Некоторые действия.
}
else
alert("Документ загружен не полностью!");
</SCRIPT>

Связывание событий обсуждается в главе 3.



Отложенное выполнение сценария

Internet Explorer 4.0 может повысить производительность выполнения сценариев, которые не содержат немедленно выполняемого кода. Если элемент Script содержит только описания функций, то помещение атрибута DEFER в тег <SCRIPT> уведомляет браузер, что не требуется ожидать окончания анализа и интерпретации всего сценария. Вместо этого браузер может продолжать загрузку и отображение страницы. Данный атрибут должен быть использован только в том случае, если элемент Script не содержит ничего, кроме описаний функции и когда все последующие сценарии, которые выполняются немедленно, не вызывают данные функции. Немедленно выполняемый код в элементе Script может отреагировать непредсказуемо. При правильном использовании атрибут DEFER не вызывает отрицательного влияния на браузеры, которые не распознают данный атрибут. Примитивные браузеры игнорируют его и выполняют традиционное блокирование до тех пор, пока не закончен анализ сценария.



Языки написания сценариев

Подобно возможности определения многочисленных элементов Script одиночный документ может также содержать и выполнять программы на различных языках написания сценариев. Все доступные в настоящее время языки написания сценариев будут выполняться на странице, если браузер поддерживает их. Например, при использовании Internet Explorer страница может быть создана с помощью программ на JavaScript и VBScript. Более того, допускается вызов функций из программы на одном языке программой, написанной на другом языке, как продемонстрировано в приведенном ниже коде. Вызов функции в сценарии на другом языке возможен, поскольку все функции и переменные добавляются как методы и свойства объекта window.

<SCRIPT LANGUAGE="VBScript">
' Простая процедура, которая выводит всплывающее окно сообщения.
sub MyAlert(str)
msgBox(str)
end sub
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
// Вызов процедуры VBScript по имени MyAlert, определенной выше.
MyAlert("Hello, World!");
window.MyAlert("MyAlert является методом объекта окна.");
</SCRIPT>

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

<SCRIPT LANGUAGE="JavaScript1.1">
<!--
window.js11 = true; // Установка флага для JavaScript 1.1.
// -->
</SCRIPT>
<SCRIPT LANGUAGE="VBScript">
<!--
vbSupport = True ' Установка флага для VBScript.
' -->
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
<!-- --><H1>Ваш браузер не поддерживает сценарии.</H1>
<!--
/* В данном примере JavaScript считается самым низким общим знаменателем. Данный пример может быть модифицирован для использования другого языка для окончательного тестирования.*/
document.write("Поддерживается язык JavaScript.<BR>");
if (null != window.js11)
document.write("Поддерживается язык JavaScript 1.1.<BR>");
if (null != window.vbSupport)
document.write("Поддерживается язык VBScript.<BR>");
// -->
</SCRIPT>



Скрытие сценариев от браузеров низкого уровня

Если вы не предпримете меры предосторожности, то браузеры, которые не поддерживают сценарии, будут воспроизводить код сценариев как часть содержания документа. Это происходит по причине того, что браузеры низкого уровня будут игнорировать тег <SCRIPT> и обрабатывать содержание как текст HTML. Такое поведение согласуется с методом обработки нераспознаваемых тегов в HTML и необходимо в эволюции HTML. Для скрытия сценариев от браузеров низкого уровня создайте комментарий HTML, который охватывает код:

<SCRIPT LANGUAGE="VBScript">
<!--
' Код VBScript
' На следующей строке заканчивается комментарий HTML.
' -->
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
<!--
// Код JavaScript
// -->
</SCRIPT>

Оба языка интерпретируют строку HTML, которая начинается с <! --, как комментарий на одной строке, так что строка игнорируется анализатором языка. Закрывающему комментарию должен предшествовать определенный указатель комментария ('в VBScript, //в JavaScript). Это приведет к тому, что код внутри элемента Script будет обрабатываться как комментарий и не будет воспроизводиться браузерами низкого уровня.

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

<SCRIPT LANGUAGE="JavaScript">
<!--
/* Тег закрытия комментария, который записан в документе, разделен на две строки. */
document.write("<" + "!--
Это комментарий, который должен быть записан в" + "потоке. - " + ">");
// -->
</SCRIPT>

Использование тегов комментариев HTML внутри сценария скрывает сценарий от браузеров низкого уровня, но не предупреждает пользователя о том, что в странице используются сценарии. Поэтому для указания текста браузеру, который не поддерживает сценарии, используется специальный тег <NOSCRIPT>. Содержание элемента NoScript игнорируется браузерами, которые поддерживают сценарии:

<!-- Текст для браузеров, которые не поддерживают сценарии -->
<NOSCRIPT>
<H1>Данная страница требует поддержки сценариев.</H1>
<H2>Пожалуйста, загрузите последнюю версию Internet Explorer
для правильного отображения данной страницы.</H2>
</NOSCRIPT>

Этот метод работает в браузерах низкого уровня, поскольку они игнорируют тег <NOSCRIPT> так же, как тег <SCRIPT> за пределами документа. Поддерживающий сценарии браузер знает, что не следует воспроизводить содержание между тегами <NOSCRIPT> и </NOSCRIPT>.

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

Internet Explorer 4.0 позволяет отключать сценарии посредством установок безопасности. Internet Explorer 4.0 использует мощную модель безопасности, которая может быть настроена для различных "зон" содержания Web. Зона представляет весь Web, корпоративную сеть (intranet) или определенный набор страниц. Перечисленные ниже действия позволяют отключить поддержку сценариев для определенной зоны:

  1. В меню View выберите пункт Internet Options для отображения диалогового окна Internet Options.

  2. Выберите вкладку Security из списка страниц.

  3. Выберите зону для настройки. Установите переключатель Custom и нажмите кнопку Settings.

  4. В категории Scripting, подкатегория Active Scripting установите опцию Disable.

  5. Нажмите кнопку ОК или Apply для сохранения данных установок.

Netscape Navigator 2.0 не поддерживает тег <NOSCRIPT>. Следует использовать другой метод для предупреждения пользователя, что на странице используются сценарии. Данный метод включает в себя написание примитивного сценария в документе, который использует возможности схемы комментариев для вывода содержания на клиентах низкого уровня:

<!-- Другой метод для вывода содержания низкого уровня -->
<SCRIPT LANGUAGE="JavaScript">
<!-- -->Ваш браузер не распознает сценарии. <!--
// Текст вашей программы.
-->
</SCRIPT>

Метод комментариев имеет следующий недостаток: когда вы отключаете поддержку сценариев, содержание элемента Script игнорируется, и отображается содержание элемента NoScript. Поэтому текст комментариев не отображается при отключении сценариев.

Хотя метод NoScript используется для браузеров, которые не поддерживают сценарии, данный метод не различает реализации поставщиков. Разные поставщики по мере развития динамического HTML будут реализовывать его различные версии. Сценарий может не запускаться в некоторых браузерах. К сожалению, отсутствует простое решение этой проблемы. Некоторые разработчики предпочитают создавать многочисленные экземпляры страниц и отправлять разные страницы разным браузерам. Данная переадресация может быть выполнена на клиенте. Пример подобной переадресации представлен в следующем разделе.

Примечание: Чтобы подчеркнуть возможности динамического HTML, в данной книге большинство примеров кода не содержат меры для браузеров низкого уровня.



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

Одним из методов обработки различных версий программного обеспечения является переадресация пользователя на другие страницы, в соответствии с типом клиентского браузера, как показано в приведенном ниже коде. Переадресация на клиентской стороне (client-side redirection) возникает, когда сценарий страницы переключает браузер на другой документ. Путем необязательной проверки версии браузера может быть загружена другая версия страницы. При использовании данного метода базовой будет та страница, которая предназначена для более важной аудитории, поскольку переадресация снижает производительность. При переадресации будут загружены две страницы.

<SCRIPT LANGUAGE="JavaScript">
var MS = navigator.appVersion.indexOf("MSIE");
// Проверка того, что браузером является IE4.
window.isIE4 = (MS > 0) &&
(parseInt(navigator.appVersion.substring
(MS + 5, MS + 6)) >= 4);
if (!isIE4) // Если браузер - не IE4, то загружается не динамическая // страница.
If not IE4, get non-dynamic page.
window.location="downlevelpage.htm";
</SCRIPT>

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



Выбор языка: JavaScript или VBScript

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

На данный момент существует два основных языка написания сценариев на Web: JavaScript и VBScript. Комитет ЕСМА (European Computer Manufactures Association - европейская ассоциация производителей компьютеров), в состав которой входят представители компаний Netscape, Microsoft и других поставщиков, утвердил стандартный вариант языка JavaScript. Реализация JScript компании Microsoft в Internet Explorer 4.0 полностью совместима с новым стандартом.

Для создания Web-страниц в Internet, которые должны быть выставлены на всеобщее обозрение, JavaScript предоставляет наибольшие возможности, и поддерживается в настоящее время браузерами Netscape и Microsoft. (При этом также предполагается, что ваша программа использует набор элементов, совместно используемых в различных реализациях).

Кроме того, синтаксис для управления программным потоком в JavaScript очень сходен с синтаксисом в таких языках, как Java, C++, которые знакомы многим авторам Web-страниц.

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

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



JavaScript

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

Некоторые объекты JavaScript не являются частью объектной модели динамического HTML и являются специфическими для языка. Например, тип данных даты, математический, числовой и другие типы данных являются специфическими для языка. В зависимости от языка могут быть использованы различные типы данных. Например, VBScript использует тип данных String (строка), но в VBScript строка не является объектом со своим собст-венным интерфейсом. Напротив, манипуляции со строкой выполняются отдельно, при помощи функций. Приведенный ниже код сравнивает манипуляции со строкой свойства title в VBScript и JavaScript:

<!-- Простое сравнение функций строки в VBScript и JavaScript -->
<SCRIPT LANGUAGE="VBScript">
dim s ' Описывает строковую переменную.
s = document.title ' Инициализирует переменную.
msgBox(len(s)) ' Выводит длину s.
msgBox(left(s, 1)) ' Выводит первый символ s.
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
var s = document.title; // Инициализация переменной во время описания.
alert(s.length); // Выводит длину s.
alert(s.charAt(0)); // Выводит первый символ s.
</SCRIPT>



Передовые методы JavaScript

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



Добавление свойств в объекты

Массивы и объекты в JavaScript предоставляют два метода доступа к их содержанию: прямая ссылка на содержание как свойство с помощью точечной (.) нотации или ссылка на индекс в массиве с помощью скобок ([index]). Индекс в массиве JavaScript может быть значением типа String, которое представляет имя свойства. Точечная нотация позволяет осуществлять прямой доступ к свойству, когда имя свойства известно заранее. Когда вызываемое свойство должно быть переменной, то к нему можно обратиться посредством позднего связывания, используя идентификатор строки:

<SCRIPT LANGUAGE="JavaScript">
var prop = "title";
alert(document.title); // Доступ к названию посредством точечной нотации.
alert(document[prop]); // Доступ к свойству, на которое ссылается
// переменная prop.
// Массивы и встроенные объекты работают одинаково.
var ar = new Array;
ar.myProperty = "Demo";
alert(ar.myProperty);
alert(ar["myProperty"]);
</SCRIPT>

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

JavaScript является чувствительным к регистру. Например:

<SCRIPT LANGUAGE="JavaScript">
alert(document.title); // Вывод заголовка документа.
document.Title = "He является настоящим заголовком"; // Добавление свойства Title.
alert(document.Title); // Вывод нового свойства Title.
</SCRIPT>

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

Примечание: Internet Explorer 4.0 не чувствителен к регистру. Internet Explorer 3.0 и все выпуски Netscape Navigator требуют четкого выполнения правил чувствительности к регистру.

Для решения проблем отладки Internet Explorer 4.0 предлагает свойство документа expando, которое может быть использовано для отключения возможности неявного добавления свойства в JavaScript, как показано в приведенном ниже коде:

<SCRIPT LANGUAGE="JavaScript">
/* Internet Explorer 4.О позволяет отключать возможность неявного добавления свойств.*/
document.expando = false;
document.Title = "He является действительным заголовком"; // Ошибка - // отсутствует данное свойство
Error--no such property
</SCRIPT>

Свойство expando не отключает явное добавление свойств в окно путем описания переменных, но отключает неявное добавление, как показано в приведенном ниже примере:

<SCRIPT LANGUAGE="JavaScript">
document.expando = false;
var x = 0; // Нет ошибки
alert(window.x); // Явно добавляется х
window.y = 10; // Ошибка - отсутствует свойство у
</SCRIPT>

Примечание: Internet Explorer 4.0 является первым браузером, который поддерживает свойство expando для управления связанной характеристикой массивов объектов. Netscape Navigator 4.0 и ранние версии Internet Explorer не распознают данное свойство. Когда свойство expando не распознается, то ссылка на него автоматически приводит к его добавлению в объект document.

Поскольку любой объект может содержать любое число свойств, то Java-Script использует оператор совместимости для доступа к ним. С помощью цикла for...in вы можете выполнить инструкцию для каждого используемого свойства в объекте, без выяснения конкретных свойств. Приведенный ниже код выводит все свойства, используемые в объекте window:

<SCRIPT LANGUAGE="JavaScript">
// Отображает сообщение со всеми свойствами окна и их значениями. var sProps = "Window Properties\n";
for (props in window)
sProps += props + ": " + window[props] + "\n";
alert(sProps);
</SCRIPT>



Указатели функций

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

Указатели функций (function pointers) являются очень мощными в том смысле, что они позволяют повторно использовать функции как методы объекта, как показано в приведенном ниже примере:

<SCRIPT LANGUAGE="JavaScript">
// Определение функции test.
function test() {
alert("Функция была вызвана.");
}
// Функция test как обработчик нажатия кнопки.
// Это приводит к тому, что при щелчке мышью в документе // вызывается функция test.
document.onclick = test; </SCRIPT>

Кроме того, при вызове функция имеет доступ к массиву arguments, который содержит все параметры, передаваемые функции. JavaScript автоматически заполняет массив arguments в момент вызова функции. Приведенный ниже код демонстрирует, как функция может вызвать массив arguments:

<SCRIPT LANGUAGE="JavaScript">
function testArgs() {
/* Функция в JavaScript может обращаться к массиву, аргументов. Данный массив содержит все параметры, которые передаются функции. */
alert(arguments.length + " arguments"); // Вывод числа аргументов.
// Вывод каждого аргумента.
for (var i = 0; i < arguments.length; i++)
alert("argument " + i + " - " + arguments[i]);
}
testArgs(1, 2, 3, 4); // Вызов функции testArgs с четырьмя аргументами.
</SCRIPT>

Массив arguments позволяет написать функцию, которой может быть передан ряд переменных аргументов. На основе передаваемых аргументов могут выполняться различные действия. Простой демонстрацией использования данной возможности является процедура суммирования:

<SCRIPT LANGUAGE="JavaScript">
function Sum() {
// Суммирует все передаваемые аргументы и возвращает результат.
var intSum = 0;
for (var intLoop = 0; intLoop < arguments.length; intLoop++)
intSum += arguments[intLoop];
return intSum;
}
alert(Sum(1, 1, 1, 2)); // Добавляет четыре значения.
</SCRIPT>

Функции могут быть также созданы динамически с помощью оператора new. Функция создается следующим образом:


var functionname = new Function(args1, …, argsn, body);

Может быть указано любое число аргументов args, включая 0. Последним аргументом конструктора Function всегда является выполняемый код. Например, приведенный ниже код создает простую функцию, которая возвращает разницу между двумя числами:


var Difference = new Function("x","y","return x - y;");

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



Проверка поддержки

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

<SCRIPT LANGUAGE="JavaScript">
if (null == document.all) {
// Семейство all не поддерживается, запускается
альтернативный код.
}
else {
// Операции с семейством all. }
</SCRIPT>



Соглашения об именовании свойств и функций

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

  • Начинайте имена переменных с заглавной буквы, указав перед ней префикс с типом данных или в виде знака подчеркивания (например, Counter, intCounter или _counter).

  • Не используйте имя тега в качестве имени переменной, независимо от регистра. Это позволит предотвратить конфликт с элементами, которые используют или могут использовать конструкцию new (например, new Image).

  • Не следует использовать в качестве префикса в имени переменной или функции слова html, css или style. Данные префиксы могут иметь более широкое использование в будущем.

Возможно, лучшим методом предотвращения конфликтов является добавление только объектов с одним членом во встроенные объекты и затем добавление всех новых индивидуальных членов в данный объект. Такой метод изолирует потенциальный конфликт с одним свойством, но требует некоторых мер предосторожности: необходимо определить одиночное свойство для того, чтобы в коде не возникали синтаксические ошибки. Ниже приведен пример использования данного метода с объектом window, в котором все индивидуальные члены добавляются в свойство _Сustom:

<SCRIPT LANGUAGE="JavaScript">
// До использования объекта Custom инициализируйте его // как свойство объекта window.
if (null == window._Custom)
window._Custom = new Object;
// Добавление свойств в _Custom. window._Custom.special = true;
window._Custom.top = self;
</SCRIPT>

Инструкция инициализации должна предшествовать добавлению свойств в объект _Сustom, поскольку JavaScript может добавлять в объект только один элемент одновременно. Если объект _Сustom не был сначала инициализирован, то при обращении к свойству special возникнет ошибка.



Сценарии и безопасность в Web

С введением сценариев осложнился вопрос с безопасностью в Internet. В настоящее время браузеры могут создавать sandbox (песочницу) вокруг страницы со сценарием, так что доступ возможен только к правильно определенному набору информации. В динамическом HTML для доступа к машине и жесткому диску клиента используется хорошо управляемый механизм cookies. Механизм cookies будет рассмотрен в главе 6.

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

Для большей гарантии безопасности объектная модель ограничена в ряде случаев. Например, объект загрузки файлов позволяет пользователю загружать файлы на сервер. Чтобы исключить доступ страницы к файловой системе пользователя, значение свойства value, представляющее загружаемый файл, должно быть установлено равным read-only (только чтение). Объект history, который позволяет создавать кнопки Forward (Вперед) и Back (Назад), не использует информацию об отображаемой ссылке URL. Дополнительные ограничения безопасности описываются ниже.

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