Глава 11. Динамические стили



Динамические стили являются интегральным компонентом интерактивных Web-страниц. Вид документа определяется с помощью таблиц стилей и HTML. Динамические стили используют объектную модель для модификации каскадных таблиц стилей документа (CSS) с целью внесения изменений во внешний вид документа.

Синтаксис описания CSS был введен в главе 1. В данной главе внимание сосредоточено на вопросах изменения таблиц стилей с помощью сценариев для изменения внешнего вида документа.

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

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

В разделе "Адаптивные методы размещения" разъясняется, как обеспечить изменение документа в соответствии с определенной средой. В разделе "Методы отображения данных" рассматривается скрытие и отображение данных в ответ на действия пользователя. В разделе "Методы анимации текста" описаны методы изменения стиля в зависимости от таймера.

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



Динамические стили и CSS

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

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

В Microsoft Internet Explorer 4.0 динамические стили не являются процедурным языком таблиц стилей, но они могут реализовать все аспекты JASS и предоставляют дополнительные возможности. Вместо определения альтернативного языка таблиц стилей, динамические стили в Internet Explorer 4.0 модифицируют таблицу стилей документа, определенную CSS, путем предоставления возможности определения внутренних свойств style для всех элементов, включения и отключения таблиц внутренних и глобальных стилей, добавления и изменения правил для существующей таблицы стилей.



Свойства таблиц стилей

Таблицы стилей (style sheets) представляют ряд свойств, которые управляют внешним видом содержания элемента. В объектной модели данные свойства представлены с использованием соглашения об именовании. Большинство свойств в CSS разделяют ключевые слова при помощи дефиса (-). Поскольку дефис интерпретируется как оператор в большинстве языковых конструкций, он не может быть частью имени свойства CSS, которое представлено в объектной модели. Более того, для чувствительных к регистру языков, таких как JavaScript, все представленные свойства CSS согласованы с другими свойствами - то есть, первый символ набран в нижнем регистре, а все последующие ключевые слова выделены прописными буквами. Например, свойство каскадных таблиц стилей margin-top представлено в объектной модели как marginTop.

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



Составные свойства

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


body {background:red URL(cool.gif)}

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

Таблица 11.1. Компоненты составного свойства background


Свойство Описание

backgroundColor Название цвета или значение RGB
backgroundImage Адрес URL фонового изображения
backgroundPosition Положение фонового изображения
backgroundRepeat Определяет повторение фонового изображения по горизонтали, вертикали или по обоим направлениям
backgroundScroll Определяет, прокручивается ли фоновое изображение вместе с документом или представляет статический водяной знак



Свойство cssText

Свойство cssText содержит стиль элемента в форме или строке. Используя данное свойство можете установить стиль элемента или скопировать стиль из одного документа в другой. Приведенный ниже код назначает параграфу р2 стиль, который был установлен в параграфе p1.

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


<HTML>
<HEAD>
<TITLE> Совместное использование свойства cssText </TITLE>
</HEAD>
<BODY>
<P ID="p1" STYLE="text-indent:.5in; color:red">
Параграф красного цвета с отступом в полдюйма.
</P>
<P ID="p2">
Данный параграф имеет внешний вид по умолчанию. Нажмите <INPUT TYPE=BUTTON VALUE="here"
ONCLICK="document.all.p2.style.cssText =
document.all.p1.style.cssText;">
для того чтобы данный параграф выглядел как первый параграф.
</P>
</BODY>
</HTML>



Изменение свойств

Большая часть свойств таблиц стилей, поддерживаемых браузером Internet Explorer 4.0, может быть изменена динамически, но некоторые свойства нельзя изменить в динамическом режиме:



Внутренние стили

Внутренний стиль (inline style) назначается элементу с помощью атрибута STYLE. Атрибут STYLE позволяет назначать свойства CSS непосредственно экземпляру элемента. Например, используя элемент STYLE можно установить цвет параграфа:


<P STYLE="color:blue">Это параграф голубого цвета.</P>

До таблиц стилей цвет параграфа можно было установить, используя элемент Font:


<P><FONT COLOR="Blue">Это параграф голубого цвета.</FONT></P>

Преимущества использования внутреннего стиля по сравнению со стилевыми элементами и атрибутами HTML перечислены ниже:

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

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


<H1 ONMOUSEOVER="this.style.backgroundColor = 'yellow';"
ONMOUSEOUT="this.style.backgroundColor = '';">
Элемент становится желтым, когда над ним проходит указатель мыши.
</H1>

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



Изменение атрибута class

Изменение внутреннего стиля полезно, но это может оказаться тяжелой задачей, если необходимо модифицировать значения сразу нескольких свойств. Более эффективным способом является изменение стилей для одного или большего количества классов в таблице глобальных стилей и динамическое изменение атрибута class элемента. Атрибут class элемента представлен свойством className. Данное свойство может быть изменено с помощью сценария для связи другого правила стиля с элементом. Например, приведенный ниже код перезаписывает метод изменения цвета onmouseover из предыдущего раздела с учетом преимуществ таблиц глобальных стилей:


<HTML>
<HEAD>
<TITLE> Изменение атрибута class </TITLE>
<!-- Создание таблицы глобальных стилей. -->
<STYLE TYPE="text/css">
.yellow {background:yellow; font-weight:bolder}
</STYLE>
</HEAD>
<BODY>
<H1 ONMOUSEOVER="this.className = 'yellow';" ONMOUSEOUT="this.className = '';">
Атрибуты класса данного элемента изменяются при перемещении над ним указателя мыши.
</H1>
</BODY>
</HTML>

В данном примере значение атрибута CLASS изменяется на yellow (желтый), когда указатель мыши перемещается через элемент H1. Это приводит к немедленному применению стиля, определенного для значения yellow. В этом случае фон становится желтым, а текст выделяется полужирным начертанием. Метод изменения имен класса имеет два преимущества:

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

Можно установить динамические элементы управления, используя тот же метод. Код в приведенном ниже примере изменяет таблицу стилей, связанных с кнопкой, в ответ на четыре события мыши: перемещение указателя мыши через элемент и снятие указателя мыши с элемента, нажатие и отпускание левой кнопки мыши.


<HTML>
<HEAD>
<TITLE> Анимированные кнопки </TITLE>
<STYLE TYPE="text/css">
.over {color:yellow; background:navy}
.down {color:yellow; background:navy; font-style:italic}
</STYLE>
</HEAD>
<BODY>
<INPUT TYPE=BUTTON VALUE="Demo Button"
ONMOUSEOVER="this.className = 'over';" ONMOUSEOUT="this.className = '';" ONMOUSEDOWN="this.className = 'down';" ONMOUSEUP="this.className = 'over';">
</BODY>
</HTML>

Данный пример может быть также применен к другим событиям и другим элементам и переписан в общем виде путем помещения обработчиков событий в элемент Body.

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


<HTML>
<HEAD>
<TITLE> Эффекты "взрыва" </TITLE>
<STYLE TYPE="text/css">
.explode {color:red; letter-spacing:5px}
.header {color:green}
/* Для установки эффекта просто определите новые правила и свяжите их с элементами документа. */
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
function walkStyles(src) {
/* Просмотр дерева; для каждого элемента со свойством эффекта заменяет значения его свойств эффекта и className. Просмотр дерева необходим, чтобы гарантировать обработку всех вложенных эффектов. */
while ("HTML" != src.tagName) {
if (null != src.getAttribute("effect", false)) {
var tempClass = src.className;
src.className = src.getAttribute("effect", false);
src.setAttribute("effect", tempClass, false);
}
src = src.parentElement;
}
}
function setupEffect() {
// Обращение к элементу
walkStyles(event.toElement);
}
function cleanupEffect() {
// Выход из элемента
walkStyles(event.fromElement);
}
// Связывает обработчики событий.
document.onmouseover = setupEffect;
document.onmouseout = cleanupEffect;
</SCRIPT>
</HEAD>
<BODY>
<H1 CLASS="header" effect="explode">
Данный элемент "взрывается" при проведении над ним.указателя мыши.
</H1>
</BODY>
</HTML>

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

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

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



Таблицы глобальных стилей

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

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



Семейство styleSheets

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

Семейство styleSheets содержит объекты styleSheets, а не объекты элементов. Имеется связь между объектами styleSheets в семействе styleSheets и объектами style и link в семействе all. Каждый объект styleSheets представляет свойство owningElement, возвращающее объект style или link, который определяет таблицу стилей. Каждый стиль и элемент Link, который связывает стиль, представляет свойство styleSheet, возвращающее объект styleSheet.



Ссылка на таблицу стилей

Все элементы в документе поддерживают атрибут ID. Атрибут ID в элементах Style и Link служит двум целям: обеспечивает значение индекса для прямого доступа к элементу посредством семейства all и обеспечивает значение индекса для прямого доступа к объекту styleSheet в семействе styleSheets. Важно понимать, что в семействе all определенный атрибут ID ссылается на действительный объект style или link, тогда как в семействе styleSheets атрибут ссылается на связанный объект styleSheet. Приведенный ниже пример показывает установку ссылки на объект style и его связанный объект styleSheet с использованием ID и обращение к каждому из данных объектов из другого объекта:


<HTML>
<HEAD>
<TITLE> Объект styleSheet и элемент Style </TITLE>
<STYLE ID="demo" TYPE="text/css">
BODY {color:red}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
// Возвращение объекта style.
var styleElement = document.all["demo"];
// Возвращение объекта styleSheet.
var styleSheetObject = document.styleSheets["demo"];
// Обращение к каждому из данных объектов из другого объекта.
// Оба окна сообщения отображают true.
alert(styleSheetObject.owningElement == styleElement);
alert(styleElement.styleSheet == styleSheetObject);
</SCRIPT>
</HEAD>
<BODY>
Содержание
</BODY>
</HTML>



Список альтернативных таблиц стилей

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

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


Атрибут DISABLED

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


Предоставление выбора средств просмотра

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


<HTML>
<HEAD>
<TITLE> Различные режимы просмотра </TITLE>
<STYLE ID="all" TYPE="text/css">
#headOnly {display:none}
#allText {color:red; cursor:default}
</STYLE>
<STYLE ID="headers" TYPE="text/css" DISABLED>
#allText {display:none}
#headOnly {color:navy; cursor:default}
DIV {display:none}
</STYLE>
</HEAD>
<BODY>
<H1> Demonstration of Multiple Views</H1>
<P ID="allText" ONCLICK="document.styleSheets['headers'].disabled = false;
document.styleSheets['all'].disabled = true;">
YoВы просматриваете полностью развернутую версию документа. Щелкните по данному параграфу для переключения режима просмотра. </P>
<P ID="headOnly" ONCLICK="document.styleSheets['headers'].disabled = true;
document.styleSheets['all'].disabled = false;">
Вы просматриваете только заголовки документа. Щелкните по параграфу для переключения режима просмотра. </P>
<H2>Multiple Views</H2>
<DIV>Используя объектную модель CSS, вы можете установить несколько режимов просмотра данных.
</DIV>
<H2>Swapping Data</H2>
<DIV>> Вы можете также заменить режим просмотра данных. В документ можно включить стандартные данные и выборочно скрывать и просматривать их.
</DIV>
</BODY>
</HTML>

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

Рис. 11.1. Два типа отображения документа


Выбор таблиц стилей

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


<HTML>
<HEAD>
<TITLE> Перечисление таблиц стилей </TITLE>
<STYLE ID="all" TITLE="Entire Document" TYPE="text/css">
#headOnly {display:none}
#allText {color:red; cursor:default}
</STYLE>
<STYLE ID="headers" TITLE="Headers Only" TYPE="text/css"
DISABLED>
#allText {display:none}
#headOnly {color:navy; cursor:default}
DIV {display:none}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
function selectSheet(s) {
for (var intLoop = 0;
intLoop < document.styleSheets.length; intLoop++)
document.styleSheets[intLoop].disabled =
(s.selectedIndex != intLoop);
}
</SCRIPT>
</HEAD>
<BODY>
<H1>Listing Alternative Style Sheets</H1>
<P>Select a View:
<SELECT ONCHANGE="selectSheet(this);">
<SCRIPT LANGUAGE="JavaScript">
// Динамическое построение списка вариантов. for (var intLoop = 0;
intLoop < document.styleSheets.length;
intLoop++)
document.write("<OPTION>" +
document.styleSheets[intLoop].title);
</SCRIPT>
</SELECT>
<P ID="allText">
Вы просматриваете полностью развернутую версию документа.
</P>
<P ID="headOnly">
Вы просматриваете только заголовки документа.
</P>
<H2>Multiple Views</H2>
<DIV>Используя объектную модель CSS, вы можете установить несколько режимов просмотра данных.
</DIV>
<H2>Swapping Data</H2>
<DIV>Вы можете также заменить режим просмотра данных. В документ можно включить стандартные данные и выборочно скрывать и просматривать их.
</BODY>
</HTML>

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

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

Рис. 11.2. Сравнение двух различных средств просмотра


Случайные таблицы стилей

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

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



Таблицы стилей, зависящие от среды

HTML 4.0 определяет механизм связи различных таблиц стилей с различными типами средств передачи информации. Браузер Internet Explorer 4.0 поддерживает два типа средств передачи информации: screen (экран) и print (печать). Вы можете определить различные таблицы стилей, которые применяются к документу при отображении на экране или выводе на печать. Приведенный ниже код демонстрирует определение трех таблиц стилей, из которых первая служит для печати, вторая - для просмотра на экране и третья - для всех режимов просмотра документа:


<STYLE TYPE="text/css" MEDIA="screen">
/* Применяется, если документ просматривается на экране */
H1 {color:navy; text-align:center}
P {margin-left:10pt}
</STYLE>
<STYLE TYPE="text/css" MEDIA="print">
/* Применяется при печати документа. */
H1 {color:black}
P {margin-left:5pt}
</STYLE>
<STYLE TYPE="text/css" MEDIA="screen, print">
/* Применяется при печати или отображении документа */
H2 {font-size:12pt}
</STYLE>

Если атрибут media опущен, то таблица стилей применяется ко всем типам отображения документа. Атрибут media является свойством объекта styleSheet и элементов Style и Link. Вы можете динамически изменить данное свойство для переключения средства воспроизведения, к которому применяется таблица стилей. В следующем разделе содержится пример кода, определяющий таблицы стилей, применяемые на данный момент к отображению документа на экране.



Свойство cssText объекта styleSheet

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


<SCRIPT LANGUAGE="JavaScript">
var ss = document.styleSheets;
document.write("<PRE>");
for (var intLoop = 0; intLoop < ss.length; intLoop++)
// Таблица стилей применена к экрану и не отключена.
if ((("" == ss[intLoop].media) ||
(-1 != ss[intLoop].media.indexOf("screen"))) &&
(!ss[intLoop].disabled))
document.write(ss[intLoop].cssText);
document.write("</PRE>");
</SCRIPT>



Семейство rules

Каждая таблица стилей содержит собственное семейство правил. Правило представляет собой комбинацию описания стиля (например, color: red) и его селектора (например, H1). Используя данное семейство, вы можете динамически изменить описание. Селектор предназначен только для чтения. Если необходим новый селектор, то следует удалить данное правило и добавить новое в таблицу стилей. Правила добавляются и удаляются с помощью методов addRule и removeRule объекта styleSheet.

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


<STYLE TYPE="text/css">
H1, H2, P EM {color:green}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
var rules = document.styleSheets[0].rules;
for (var intLoop = 0; intLoop < rules.length; intLoop++)
document.write("Rule: " + rules[intLoop].selectorText +
", Style: " + rules[intLoop].style.cssText + "<BR>");
</SCRIPT>

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


Добавление и удаление правил

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


var intSS = document.styleSheets.length;
if (0 < intSS) // Убедитесь в наличии таблицы стилей, в которую будет // добавлено правило.
document.styleSheets[intSS - 1].addRule("H1",
"color:red; font-size:18pt");

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


var intSS = document.styleSheets.length;
if (0 < intSS) // Убедитесь в наличии таблицы стилей, в которую будет // добавлено правило.
document.styleSheets[intSS - 1].addRule("H1",
"color:red; font-size:18pt", 0); // Добавляет правило в первую позицию

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

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


var intSS = document.styleSheets.length;
if (0 < intSS) // Убедитесь в наличии таблицы стилей, из которой будет // удалено правило.
document.styleSheets[intSS - 1].removeRule(0);


Таблицы связанных стилей и правила

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



Импортированные таблицы стилей

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

Импортированные элементы таблицы стилей представлены семейством imports, каждый элемент которого является объектом styleSheet. Импортированная таблица стилей может импортировать другую таблицу стилей. Поэтому для определения таблицы стилей, в которой находится импортированная таблица, объект styleSheet Представляет свойство parentStyleSheet, которое возвращает объект styleSheet, определяющий импорт. Для таблиц стилей высшего уровня данное свойство возвращает null.

Метод addImport объекта styleSheet использует в качестве аргумента строку адреса URL. В соответствии со спецификацией CSS импортированные правила стилей всегда находятся в начале таблицы стилей и, следовательно, в начале последовательности каскадирования. Таким образом, все правила в импортированных таблицах стилей имеют более низкий приоритет по сравнению с правилами, которые уже находятся в таблице стилей. Приведенный ниже код импортирует таблицу стилей cool.css в первую таблицу стилей в семействе styleSheets:


document.styleSheets[0].addImport("URL('cool.css');");

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


document.styleSheets[0].removeImport(0);



Добавление новых таблиц стилей

Таблицы стилей можно добавить в документ, используя метод sreateStyleSheet. По умолчанию метод createStyleSheet добавляет новую таблицу стилей последней в семейство styleSheets. Для добавления новой таблицы связанных стилей укажите адрес URL в качестве первого аргумента. В качестве второго аргумента задайте индекс для определения места Ставки таблицы стилей. Если требуется создать таблицу несвязанных стилей, вставьте ее в определенную позицию в семействе styleSheets, и укажите null в качестве первого аргумента.


Создатель таблиц стилей

Приведенный ниже пример демонстрирует динамическое изменение таблицы глобальных стилей документа для быстрого изменения внешнего вида всех элементов одного типа. При этом используется набор фреймов, в котором левый фрейм содержит набор стилей, а в правом фрейме находится содержание, к которому должны быть применены стили. Пользователь выбирает стиль из левого фрейма, а затем щелкает по элементу в правом фрейме. Все элементы данного типа будут немедленно обновлены. Имя тега элемента, к которому будет применен стиль, отображается в строке состояния. Данный пример использует три файла. Файл stylizer.htm содержит набор фреймов и большую часть основного кода для передачи стиля из фрейма стилей во фрейм содержания. Файл styles.htm содержит таблицу предлагаемых стилей. В файле contents.htm находится содержание, к которому должны быть применены стили.

В данном примере соблюдаются следующие правила:

На рис. 11.3 показано окно приложения создателя стилей.

Рис.11.3. Окно приложения создателя стилей

Файл stylizer.htm. Приведенный ниже документ с набором фреймов разделяет экран на два фрейма: левая половина отображает список параметров стиля, а правая - отображает документ, к которому должны быть применены стили. Код, обрабатывающий связи между двумя другими документами, находится внутри данного документа.


<HTML>
<HEAD>
<TITLE>The Stylizer</TITLE>
<SCRIPT LANGUAGE="JavaScript">
window.curStyle = null;
function selectStyle() {
// Выделение выбранной ячейки стиля.
var el = this.parentWindow.event.srcElement;
if ("TD" == el.tagName) {
if (null != curStyle)
curStyle.className = "";
curStyle = el;
curStyle.className = "selected";
}
}
function addStyle() {
// Добавление в документ нового правила для выбранного стиля.
if (null != curStyle) { var srcWin = this.parentWindow;
var tag = srcWin.event.srcElement.tagName;
srcWin.document.styleSheets[0].addRule(tag,
curStyle.style.cssText);
}
}
function hookupEvents() {
/* Связывает все события нажатия фрейма с соответствующей
функцией в данном документе. */
window.styles.document.onclick = selectStyle;
window.content.document.onclick = addStyle;
}
</SCRIPT>
</HEAD>
<FRAMESET ONLOAD="hookupEvents();" COLS="170, *">
<FRAME SRC="styles.htm" NAME="styles">
<FRAME SRC="content.htm" NAME="content">
</FRAMESET>
</HTML>

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


<HTML>
<HEAD>
<TITLE>Style List</TITLE>
<STYLE TYPE="text/css">
/* Данный стиль используется для выделения выбора пользователя. */
.selected {border:2px black solid}
</STYLE>
</HEAD>
<BODY>
<P>Select a style and click on the document to apply it.</P>
<!-- Внутренний стиль ячейки определяет стиль, который может быть применен к документу при выборе ячейки. Данный стиль просто копируется вместо старого стиля. -->
<TABLE>
<TR>
<TD STYLE="background:white; color:black; font-size:12pt">
Small White and Black
</TD>
</TR><TR>
<TD STYLE="background:red; color:white; font-size:18pt">
Big Red and White
</TD>
</TR><TR>
<TD STYLE="background:navy; color:yellow; font-size:14pt">
Medium Navy and Yellow
</TD>
</TR>
</TABLE>
</BODY>
</HTML>

Файл content.htm. К содержанию приведенного ниже документа применены выбранные стили. Небольшой сценарий в данном документе используется для отображения имени тега элемента, к которому должен быть применен стиль в строке состояния.


<HTML>
<HEAD>
<TITLE> Демонстрационное содержание </TITLE>
<SCRIPT LANGUAGE="JavaScript">
function updateStatus() {
/* Отображает имя элемента, над которым находится указатель мыши. К данному типу элемента будет применен новый стиль. */
window.defaultStatus = event.srcElement.tagName;
}
</SCRIPT>
<STYLE TYPE="text/css">
/* Блок стиля, в который будет добавлено новое правило. */
</STYLE>
</HEAD>
<BODY ONMOUSEOVER="updateStatus();">
<H1>Demo Contents</H1>
<P>Here are some demo <EM>contents</EM> to test the
<EM>stylizer</EM> on.</P>
<P>Select a style from the left pane, and click on
<STRONG>text</STRONG> in this pane. The element you click
and all elements of the same type will
<STRONG>change</STRONG> to match that style.
<P>This technique adds new rules to the style sheet for
this document.
</BODY>
</HTML>



События таблицы стилей

Объект styleSheet не создается и не добавляется в семейство styleSheet, пока не будет загружена вся таблица стилей, включая полную загрузку всех таблиц связанных или импортированных стилей. Для отслеживания состояния таблицы стилей элементы Style и Link представляют события onreadystatechange и onload. Свойство readyState возвращает строку, которая представляет текущее состояние элемента. Данные события и свойство readyState аналогичны членам с такими же именами документа и окна.

Во время анализа таблицы стилей значение readyState равно loading. После загрузки всей таблицы стилей значение readyState изменяется на complete. Непосредственно перед переходом в состояние complete создается объект styleSheet, который добавляется в семейство styleSheet. События onreadystatechange или onload могут быть использованы для отслеживания момента, когда таблица стилей становится доступной. Событие onload всегда возникает сразу же после события onreadystatechange в момент, когда таблица стилей переходит в состояние complete. Приведенный ниже документ демонстрирует последовательность событий.


<HTML>
<HEAD>
<TITLE> События таблицы стилей </TITLE>
<STYLE TYPE="text/css"
ONREADYSTATECHANGE=
"alert('readyState: ' + this.readyState);"
ONLOAD="alert('load event');">
H1 {color:red}
</STYLE>
</HEAD>
<BODY>
<H1>Heading</H1>
</BODY>
</HTML>

Все окна отображают приведенные ниже сообщения в указанном порядке:

  1. readyState: loading

  2. readyState: complete

  3. load event

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


<HTML>
<HEAD>
<TITLE> Состояние readyState документа </TITLE>
<SCRIPT LANGUAGE="JavaScript">
function updateStatus(msg) {
window.defaultStatus = msg;
}
</SCRIPT>
<!-- Обеспечивает обновление загружаемой таблицы стилей. -->
<LINK REL="styleSheet" TYPE="text/css"
HREF="dhtml.css" TITLE="Default Sheet"
ONREADYSTATECHANGE="updateStatus('StyleSheet[' +
this.title + ']: ' + this.readyState);">
<SCRIPT LANGUAGE="JavaScript">
// Позволяет пользователю узнать, что документ еще находится // в состоянии анализа.
updateStatus("Parsing: " + document.title);
</SCRIPT>
</HEAD>
<BODY ONLOAD="updateStatus('');">
<H1>Status Tracking</H1>
</BODY>
</HTML>

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


<HTML>
<HEAD>
<TITLE> Отслеживание ошибки загрузки </TITLE>
<LINK REL="styleSheet" TYPE="text/css" HREF="dhtml.css"
TITLE="Default Styles" ID="ss1"
ONLOAD="this.downloaded = true; // Success!">
<SCRIPT LANGUAGE="JavaScript">
/* Если данное свойство не существует, то возникает ошибка.
Свойство будет добавлено в элемент, а не в объект StyleSheet. */
if (null == document.all.ss1.downloaded) alert("Error downloading style sheet.");
</SCRIPT>
</HEAD>
<BODY>
<H1>Error Tracking</H1>
</BODY>
</HTML>



Адаптивные методы размещения

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

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

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

На рис. 11.4 показаны две альтернативные схемы размещения содержания документа.

Рис. 11.4. Схемы размещения адаптивного документа в окнах с различной шириной

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

Ниже приведен полный листинг данного примера:


<HTML>
<HEAD>
<TITLE> Пример адаптивной схемы размещения </TITLE>
<STYLE TYPE="text/css" ID="default">
/* Таблица стилей по умолчанию всегда применяется к документу. */
/* Определение строки меню для соответствия встроенным меню пользовательской системы. */
.menu A.highlight {background:highlight; color:highlighttext}
.menu {background:menu}
.menu P {margin-left:5pt; margin-right:5pt}
.menu A {color:menutext; text-decoration:none; font:menu}
/* Определение полей по умолчанию. */
body {margin-top:0pt; margin-left:0pt}
.centerIndent {margin-left:5pt; margin-right:5pt}
.leftIndent {margin-left:5pt; margin-right:5pt}
.rightIndent {margin-left:5pt; margin-right:5pt}
H1 {text-align:center}
.outline {border:1pt solid gray; margin:2pt 2pt 2pt 2pt}
</STYLE>
<STYLE TYPE="text/css" ID="narrowScreen">
/* Дополнительные правила стилей для узкого экрана;
все содержание для широких экранов скрыто. */
.wide {display:none}
</STYLE>
<STYLE TYPE="text/css" ID="midScreen">
/* Правила для экранов среднего размера. Содержание для узкого экрана скрывается. */
.narrow {display:none}
.floatLeft {margin-left:0; width:150; float:left}
</STYLE>
<STYLE TYPE="text/css" ID="wideScreen">
/* Наилучшая схема размещения на самом широком экране. */
.centerIndent {margin-left:15%; margin-right:15%}
.leftIndent {margin-left:35%; margin-right:5%}
.rightIndent {margin-left:5%; margin-right:35%}
.floatLeft {margin-left:-154; width:150; float:left}
.narrow {display:none}
</STYLE>
<STYLE TYPE="text/css" ID="4bit">
/* Число цветов равно 4 или меньше */
BODY {color:red; background:white}
</STYLE>
<STYLE TYPE="text/css" ID="8bit">
/* Таблицы стилей для 8 или большего числа битов */
BODY {background:URL(fancy.gif)}
H1 {color:purple}
H2 {color:navy}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
// Выберите таблицу стилей для доступного количества цветов.
var ss = document.styleSheets;
ss["4bit"].disabled = (screen.colorDepth >= 8);
ss["8bit"].disabled = !(ss["4bit"].disabled);
function updateLayout() {
// Изменение таблицы стилей на основе доступной ширины экрана.
var ss = document.styleSheets;
ss["wideScreen"].disabled =
(450 > document.body.offsetWidth);
ss["midScreen"].disabled =
(!ss["wideScreen"].disabled ||
300 > document.body.offsetWidth);
ss["narrowScreen"].disabled =
!(ss["wideScreen"].disabled &&
ss["midScreen"].disabled);
}
function highlight() {
// Highlight the Anchor element in the menu.
if ("A" == event.toElement.tagName)
event.toElement.className = "highlight";
}
function cleanup() {
// Clear the class.
if ("A" == event.fromElement.tagName) {
event.fromElement.className = "";
}
</SCRIPT>
</HEAD>
<BODY ONRESIZE="updateLayout();">
<SCRIPT LANGUAGE="JavaScript">
/* Данный вызов находится в теле, поскольку метод updateLayout основан на доступном элементе Body. */
updateLayout();
</SCRIPT>
<!-- Вывод строки меню с использованием пользовательских установок для меню. -->
<DIV CLASS="menu" ONMOUSEOVER="highlight()"
ONMOUSEOUT="cleanup()">
<P><A HREF="home.htm">Home</A>   
<A HREF="search.htm">Search</A>   
<A HREF="about.htm">About</A></P>
</DIV>
<H1>Adaptive Layout</H1>
<DIV CLASS="centerIndent">
Данный пример демонстрирует использование динамических стилей для создания страницы, которая адаптируется к окружающей среде. Строка меню использует системные установки для количества цветов. Для систем с ограниченной цветовой поддержкой в документе используется только черный и белый цвета. Схема размещения будет изменяться в зависимости от размера окна. Содержание также модифицируется при изменении окружения.
</DIV>
<DIV CLASS="leftIndent"> <H2>Floating Elements</H2>
<TABLE ID="tleft" CLASS="floatLeft">
<TR>
<TD CLASS="outline" VALIGN="Top">
Adaptive Layout and <BR>
Dynamic HTML!
<P>Resize the window<BR>
for an example.
</TD>
</TR>
</TABLE>
<!-- Обращение к плавающему элементу изменяется в зависимости от размера экрана. -->
<P>The figure <SPAN CLASS="wide">to the left</SPAN>
<SPAN CLASS="narrow">above</SPAN> demonstrates that elements can move into and out of the
flow based on the window size.
</P>
<P>The rendering of the page changes based on the window size
and the number of colors supported. The text and the
floating element are repositioned to optimize the amount
of real estate available on the screen.
</P>
</DIV>
<DIV CLASS="rightIndent">
<H2>Conditional Data</H2>
<P>
В зависимости от окружения будут отображаться различные данные. </P>
<P CLASS="wide" STYLE="color:red">
Вы просматриваете версию документа для широкого экрана.
</P>
<P CLASS="narrow" STYLE="color:red">
Документ имеет отличный стиль, поскольку ширина окна
просмотра мала.
</P>
</DIV>
<DIV STYLE="display:none">
<!-- Данное сообщение отображается, только если не поддерживается таблица стилей. -->
Данную страницу лучше всего просматривать в браузере, который поддерживает CSS и динамический HTML. </DIV>
</BODY>
</HTML>

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



Методы отображения данных

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



Использование указателей мыши для выделения содержания

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

Пo умолчанию указатель мыши над информационным элементом принимает I-образную форму, что указывает на возможность выделения текста. Над элементами поведения, например, ссылками в документе, указатель мыши превращается в изображение руки, что указывает на возможность нажатия элемента.

Браузер Internet Explorer 4.0 предоставляет Web-разработчику возможность управления видом указателя мыши с помощью свойства CSS cursor, позволяющему определять вид указателя мыши при подведении его к элементу. Например, при создании области нажатия лучше использовать указатель мыши в виде руки или другого типа указателя, чем I-образная форма. В главе 1 приведена таблица, содержащая список всех типов указателей мыши, которые можно установить посредством свойства cursor.

Приведенный ниже код отображает указатель в виде руки, когда он находится над элементом H1:


<H1 STYLE="cursor:hand" ONCLICK="alert('clicked');" ONSELECTSTART="event.returnValue = false;">
Указатель мыши превращается в руку при подведении его к данному заголовку.
</H1>

Событие onselectstart обрабатывается для отключения возможности выделения текста внутри заголовка. Отмена данного события путем возвращения значения false запрещает пользователю выделять текст внутри заголовка. Это не запрещает пользователю выделять текст. Выделение текста может быть начато за пределами заголовка и будет расширено с включением содержания заголовка. Данная модель поведения установлена по умолчанию для ссылок.



Скрытие и отображение данных

Приведенный ниже пример содержит общий код, который динамически отображает и скрывает имеющиеся данные.


<HTML>
<HEAD>
<TITLE> Отображение и скрытие данных </TITLE>
<STYLE TYPE="text/css">
body {background:white}
.expandable {color:blue; cursor:hand}
.expanded {color:black; font-size:"12pt"}
.collapsed {display:none}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
// Общий код отображения
function outliner() {
// Получение дочернего элемента.
var child =
document.all[event.srcElement.getAttribute("child",
false)];
// Если дочерний элемент существует, то он будет // развернут или свернут.
if (null != child) child.className = child.className == "collapsed" ?
"expanded" : "collapsed";
}
</SCRIPT>
</HEAD>
<BODY ONCLICK="outliner();">
<H1 CLASS="expandable" child="info">
Click here for more information.
</H1>
<DIV ID="info" CLASS="collapsed">
Данное содержание не отображается в исходном состоянии. Для отображения содержания щелкните по заголовку выше данного текста.
</DIV>
</BODY> </HTML>

В этом примере любой элемент ведет себя как источник нажатия (click source), управляющий отображением или скрытием определенной информации. Чтобы установить подобное поведение элемента, назначьте ему имя класса expandable и укажите для него индивидуальный атрибут child.

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

Индивидуальный атрибут child должен содержать идентификатор (ID) данных, которые должны быть отображены или спрятаны. Щелчок мышью по разворачиваемому элементу приводит к изменению имени класса данных с collapsed на expandable или наоборот, в зависимости от того, отображается элемент или скрыт. Вам следует установить для класса данных имя collapsed или expanded для определения его исходного внешнего вида.



Развертывание и свертывание списков

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


<HTML>
<HEAD>
<TITLE> Разворачивание и сворачивание списков </TITLE>
<STYLE TYPE="text/css">
/* Определение таблицы стилей */
UL {cursor:hand; color:navy}
UL UL {display:none; margin-left:5pt}
.leaf {cursor:text; color:black}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
function checkParent(src, dest) {
// Поиск определенного предка текущего элемента.
while (src != null) {
if (src.tagName == dest)
return src;
src = src.parentElement;
}
return null;
}
function outline() {
// Разворачивание или сворачивание при нажатии элемента списка.
var open = event.srcElement;
// Проверка того, что щелчок был произведен внутри элемента // LI. Данная проверка позволяет использовать форматирование // HTML внутри списков.
var el = checkParent(open, "LI");
if (null != el) {
var pos = 0;
// Search for a nested list.
for (pos = 0; pos < el.children.length; pos++)
if ("UL" == el.children[pos].tagName)
break;
if (pos == el.children.length)
return;
}
else
return;
el = el.children[pos];
if ("UL" == el.tagName) {
// Разворачивание или сворачивание вложенных списков.
if ("" == el.style.display)
el.style.display = "block";
else
el.style.display = "";
}
event.cancelBubble = true;
}
document.onclick = outline;
</SCRIPT>
</HEAD>
<BODY>
<UL>
<LI>Item 1
<UL>
<LI CLASS="leaf">Subitem 1
<LI>Subitem 2
<UL>
<LI CLASS="leaf">Subsubitem 1
</UL>
</UL>
</LI>
<LI CLASS="leaf">Item 2
</UL>
</BODY>
</HTML>



Создание разворачиваемой таблицы содержания

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

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

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


    /* Для указания открытой и закрытой папки используются файлы GIF
    вместо стандартных маркеров. */
    UL.toc LI {list-style-image:url(close.gif)}
    UL.toc LI.open {list-style-image:url(open.gif)}
    /* Цвета для выделенных команд меню и для выделенных ссылок. */
    UL.toc A:active, UL.toc A.select {color:white;
    background:blue}
    UL.toc .over {color:red} /* Цвет выделенного фрагмента */

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


    <LI>
    <A HREF="ch1/overview.htm">Overview of HTML and CSS</A>
    <UL>
    <LI><A HREF="ch1/html40.htm" TITLE="HTML 4.0">
    HTML "4.0"</A></LI>
    <LI><A HREF="ch1/css.htm" TITLE="CSS Features">
    CSS Features</A></LI>
    <LI><A HREF="ch1/cssp.htm" TITLE="CSS Positioning">
    CSS Positioning</A></LI>
    <LI><A HREF="ch1/settings.htm" TITLE="System">
    System Settings</A></LI>
    </UL>
    </LI>

  3. Объедините данную схему размещения с соответствующим сценарием для создания полностью разворачиваемого списка.

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


<HTML>
<HEAD>
<TITLE> Содержание </TITLE>
<STYLE TYPE="text/css">
BODY {background:navy; color:white}
UL.toc {cursor:hand}
/* Установка изображения для маркированного списка. */
UL.toc LI {list-style-image:url(close.gif)}
UL.toc LI.open {list-style-image:url(open.gif)}
UL.toc UL {list-style:none}
/* Скрытие дочерних элементов по умолчанию. */
UL.toc UL {display:none} /* Display the child elements. */
UL.toc UL.expanded {display:block}
UL.toc LI A {text-decoration:none; color:yellow;
font-weight:bold}
UL.toc LI UL A {color:white} UL.toc A:active, UL.toc A.select
{color:white; background:blue}
UL.toc .over {color:red} /* Highlight color */
UL.toc UL P {margin-top:0; margin-bottom:0}
</STYLE>
<STYLE TYPE="text/JavaScript">
/* Метод отображения списка в Netscape
Navigator 4.0. */
/* Определение альтернативного стиля для "UL.toc UL". */
contextual(classes.toc.UL, tags.UL).display = "block";
</STYLE>
<BASE TARGET="DEMO">
<SCRIPT LANGUAGE="JavaScript">
// Общий код отображения
// Данный метод позволяет писать общий код, который // автоматически отображает или прячет содержание.
var curSelection = null;
function setStyle(src, toClass) {
// Format the element to the specified class.
if (null != src) src.className = toClass;
}
function mouseEnters() { // Проверьте, что элемент не является выделенным и
// является якорем.
if ((curSelection != event.toElement) &&
("A" == event.toElement.tagName))
setStyle(event.toElement,"over");
}
function mouseLeaves() {
// Снова проверьте, что элемент не является выделенным и // является якорем.
if ((curSelection != event.fromElement) &&
("A" == event.fromElement.tagName))
setStyle(event.fromElement, "");
}
function outliner() {
var child = null, el = null;
/* Предполагает, что элемент DIV, содержащий дочерние элементы находится сразу же после якоря заголовка. */
switch (event.srcElement.tagName) {
case "A": el = event.srcElement.parentElement;
child = document.all[event.srcElement.sourceIndex + 1];
break;
case "LI":
el = event.srcElement;
child = document.all[event.srcElement.sourceIndex + 2];
break;
}
/* Проверка наличия дочернего элемента и что это дочерний элемент LI. */
if ((null != child) && ("UL" == child.tagName) &&
("LI" == child.parentElement.tagName)) {
if ("" == child.className) {
// Collapse the item.
child.className = "expanded";
el.className = "open";
}
else { // Разворачивание элемента.
child.className = "";
el.className = "closed";
}
}
if ("A" == event.srcElement.tagName) {
if (null != curSelection)
setStyle(curSelection, "");
// Сохранение и выделение нового выбора.
curSelection = event.srcElement;
setStyle(curSelection, "select");
}
}
</SCRIPT>
</HEAD>
<BODY>
<UL CLASS="toc" ONCLICK="outliner();"
ONSELECTSTART="return false;" ONMOUSEOVER="mouseEnters();"
ONMOUSEOUT="mouseLeaves();">
<LI>
<A HREF="ch1/overview.htm">HTML and CSS Overview</A>
<UL>
<LI>
<A HREF="ch1/html40.htm" TITLE="HTML 4.0">
HTML "4.0"</A>
</LI>
<LI>
<A HREF="ch1/css.htm" TITLE="CSS Features">
CSS Features</A>
</LI>
<LI>
<A HREF="ch1/cssp.htm" TITLE="CSS Positioning">
CSS Positioning</A>
</LI>
<LI>
<A HREF="ch1/settings.htm" TITLE="System Settings">
System Settings</A>
</LI>
</UL>
</LI>
<LI>
<A HREF="ch2/overview.htm">
Fundamentals of HTML Scripting</A>
<UL>
<LI>
<A HREF="ch2/langs.htm" TITLE="Supported Languages">
Supported Languages</A>
</LI>
<LI>
<A HREF="ch2/guidelns.htm" TITLE="Variable Naming Guidelines">
Naming Conventions</A>
</LI>
</UL>
</LI>
<!-- Новые варианты могут быть добавлены путем внесения дополнительных элементов списка. -->
</UL>
</BODY>
</HTML>

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

Хотя данная страница плавно деградирует в браузерах низкого уровня, которые не поддерживают таблицы стилей, в страницу введен специальный код для корректного отображения в браузере Netscape Navigator 4.0. В данной версии браузера значение display:none распознается и дочерние элементы не отображаются. Поскольку Netscape Navigator не поддерживает манипуляции динамическими стилями, то список не может быть динамически развернут для отображения вложенных данных. Для корректного отображения в Netscape Navigator в данном документе используется сценарий таблицы стилей JASS. Данная таблица стилей распознается только Netscape Navigator 4.0 и используется для повторного отображения скрытых элементов. Таблица стилей JASS подчиняется определенной в CSS таблице стилей в документе.


<STYLE TYPE="text/JavaScript">
/* Определение альтернативного стиля для "UL.toc UL". */
contextual(classes.toc.UL, tags.UL).display = "block";
</STYLE>

Данный метод определения таблицы стилей JASS полезен для переключения режимами между воспроизведением браузеров Internet Explorer 4.0 и Netscape Navigator 4.0. Вы можете определить другие стили для применения в Netscape Navigator, использующем JASS. Более подробную информацию по данному вопросу можно найти на Web-узле компании Netscape (www.netscape.com).



Методы анимации текста

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

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

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


Эластичный текст

Приведенный ниже пример демонстрирует изменение свойства CSS letter-spacing определенного элемента в ответ на сигналы таймера. Данный метод может быть использован для добавления интересных эффектов в заголовки или другие элементы содержания.


<HTML>
<HEAD>
<TITLE> Эластичный текст </TITLE>
<SCRIPT LANGUAGE="JavaScript">
// Массив значений размеров var sizes = new Array("0px", "1px", "2px", "4px", "8px");
sizes.pos = 0;
function rubberBand() {
var el = document.all.elastic;
if (null == el.direction)
el.direction = 1;
else if ((sizes.pos > sizes.length - 2) ||
(0 == sizes.pos))
el.direction *= -1;
el.style.letterSpacing = sizes[sizes.pos += el.direction];
}
</SCRIPT>
</HEAD>
<BODY ONLOAD="window.tm = setInterval('rubberBand()', 100);"
ONUNLOAD="clearInterval(window.tm);">
<H1 ID="elastic" ALIGN="Center">This Is Elastic Text</H1>
</BODY>
</HTML>


Пульсирующие элементы

Приведенный ниже код расширяет возможности предыдущего примера путем ежесекундного изменения нескольких элементов (период изменения показаний таймера) и посредством использования нового класса для определения альтернативного стиля:


<HTML>
<HEAD>
<TITLE> Пульсирующие кнопки </TITLE>
<STYLE TYPE="text/css">
.pulsate {letter-spacing:2; font-weight:bolder; color:blue}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
function pulsate() {
// Получение всех элементов с именем "pulsate" или ID.
var pEl = document.all.pulsate;
if (null == pEl.length) // Только один элемент
pEl.className = pEl.className == "pulsate" ?
"" : "pulsate";
else // Повторение всех пульсирующих элементов.
for (var i = 0; i < pEl.length; i++)
with (pEl[i])
className = className == "pulsate" ?
"" : "pulsate";
}
</SCRIPT>
</HEAD>
<BODY ONLOAD="window.tm = setInterval('pulsate()', 1500);"
ONUNLOAD="clearInterval(window.tm);">
<INPUT TYPE=BUTTON NAME="pulsate" VALUE="Click Me!">
<INPUT TYPE=BUTTON NAME="pulsate" VALUE="Click Me Too!">
</BODY>
</HTML>