Опубликован: 10.12.2007 | Уровень: специалист | Доступ: платный
Лекция 2:

Верстка с XUL

2.2.3. Основные атрибуты размещения блоков

Как и в HTML, размещение можно оставить браузеру, а можно заняться им самому. Для группирования содержимого тега <box> используется стандартный набор атрибутов. Эти атрибуты применимы к любому блоку, так как многие XUL-элементы ведут себя как блоки. На рисунке 2.4 схематично изображено действие этих атрибутов.

В данном примере значением orient является "horizontal", для <box> это значение по умолчанию. Чтобы понять, как будет выглядеть случай с orient="vertical", поверните эту книгу на 90 градусов по часовой стрелке. Каждое слово на схеме - атрибут XUL, влияющий на то, как будет размещаться содержимое тега. Каждый объект, содержащийся в <box>, сам должен быть XUL-тегом.

Исторически некоторые из этих атрибутов происходят от свойств из стандарта CSS 2. И скоро стало казаться странным, что эти XUL-атрибуты и CSS-свойства совершенно независимы друг от друга. В частности, CSS- свойство valign использовать не рекомендуется, хотя оно и поддерживается до сих пор. Ниже приведен список корректных атрибутов размещения. На рисунке 2.5 проиллюстрировано их действие.

  • orient = "horizontal" | "vertical". Этот атрибут определяет, должно ли содержимое размещаться по горизонтали или по вертикали, а также задает основное направление: вправо по умолчанию для horizontal или вниз - для vertical. По умолчанию orient="horizontal".
  • dir = "ltr" | "rtl" | "normal" | "reverse". Этот атрибут похож на одноименный атрибут в HTML и определяет основное направление для размещения содержимого: слева направо или наоборот. Значение normal эквивалентно ltr, а reverse - rtl. В случае вертикального ориентирования "слева направо" значит размещение сверху вниз, а "справа налево" - снизу вверх. По умолчанию dir="ltr".
  • pack = "start" | "center" | "end". Этот атрибут выравнивает содержимое контейнера относительно основного направления, его действие похоже на действие команды "Выровнять" в текстовых процессорах. start соответствует выравниванию влево или вверх, center - по центру, end - вправо или вниз. Обычно блок может расширяться, чтобы занять все доступное место, в таких случаях атрибут pack может оказаться полезным. Если блок не может расширяться, этот атрибут не имеет никакого эффекта. Возможность расширения зависит от значения атрибута align. По умолчанию pack="start".
Стандартные атрибуты верстки тегов-контейнеров.

Рис. 2.4. Стандартные атрибуты верстки тегов-контейнеров.
  • align = "start" | "center" | "end" | "baseline"| "stretch". Данный атрибут выравнивает содержимое блока относительно направления, перпендикулярного основному. В этом направлении всегда можно выравнивать только один объект, поэтому атрибут просто смещает каждый объект вверх/вниз или вправо/влево. Его стоит использовать, только если ширина блока по направлению, перпендикулярному основному, больше ширины содержимого. В случае горизонтального ориентирования значение baseline смещает содержимое до уровня нижней базовой линии шрифта, как и в CSS 2: текст смещается до нижней базовой линии, а все остальные объекты смещаются к нижней границе блока. Значение stretch предполагает полное выравнивание, но так как выравнивать можно только один объект, он просто увеличивается, пока не достигнет границ. Это относится ко вложенным блокам, изображениям, элементам управления, но не к тексту. По умолчанию align="stretch".
  • equalsize = "always". Если значение этого атрибута - always и у всех тегов-потомков есть атрибут flex, всем объектам текущего тега будет задан один и тот же размер относительно основного направления. Это свойство часто используется для табличного размещения (например, с помощью grid ). Любое другое значение отключает эту функцию.

Mozilla также поддерживает атрибут ordinal, он записывается автоматически, когда Mozilla сохраняет и восстанавливает информацию о XUL-документах при помощи атрибута persist. Механизм сохранения свойств документа обсуждается в "Оверлеи и Chrome" , "Оверлеи и chrome". Для нас это пока не особенно важно, но знать его основные принципы работы полезно.

ordinal относится ко всем потомкам любого данного тега; значением этого атрибута может быть целое неотрицательное число. Оно определяет порядок следования потомков внутри данного тега. Обычно отсчет ведется автоматически и соответствует порядку следования тегов в XUL- документе. Атрибут ordinal часто используется для записи состояния столбцов тега <tree>.

Для всех этих атрибутов значение inherit эквивалентно значению inherit в свойствах CSS: значение атрибута будет таким же, как у аналогичного атрибута родительского тега. Однако значение inherit может быть задано только с помощью правил CSS 2, эквивалентных перечисленным XUL-атрибутам (см. раздел "Альтернатива: таблицы стилей"). На рисунке 2.5 показано, как будут выглядеть элементы с применением тех или иных атрибутов.

Для создания снимка окна на этом рисунке понадобилось 82 тега <box>, хотя размещение, приведенное там, и кажется несколько надуманным и чрезмерно сложным. Другие часто используемые атрибуты можно применять ко всем элементам, а не только к блочным контейнерам. Вот эти атрибуты:

  • collapsed = "true" | "false". Если значение данного атрибута - true, тег будет "свернут" так, как если бы к нему применили правило CSS 2 visibility: collapse. Он не будет занимать на экране никакого места, что повлияет на размещение остальных объектов внутри внешнего по отношению к нашему тегу контейнера. Если его значение - false или любое другое, отличное от true, элемент снова станет виден. Динамическая смена значений collapsed приводит к полной перерисовке документа, а это достаточно трудоемкий процесс для Mozilla. Кроме того, следует помнить, что в CSS 2 используется свойство collapse (без "d" на конце), а в XUL - атрибут collapsed (с "d" на конце).
  • hidden = "true" | "false". Если значение этого атрибута - true, тег исчезнет с экрана, как при использовании правила CSS 2 display: none. Тег будет невидим, но занимаемое им место не освободится. Если его значение - false или любое другое, отличное от true, тег снова станет виден. Динамическая смена значений hidden не приводит к перерисовке всего документа.
  • flex = "integer". Если значение этого атрибута - натуральное число, тогда тег, для которого определен данный атрибут, может занимать больше места, чем необходимо. При этом эффект от использования атрибута pack для внешнего контейнера сводится к нулю, если, конечно, границы, до которых может расширяться наш тег, не ограничены каким-либо образом. flex рассматривается в разделе "Элементы размещения блоков" настоящей лекции. Эквивалент этому атрибуту в CSS 2 - расширение -moz-box-flex.
  • debug = "true". Если значение данного атрибута - true, вам будет доступна вся информация о структуре размещения содержимого текущего тега. Этот атрибут подробнее рассматривается ниже в разделе "Отладка". Важно помнить, что при использовании этого атрибута внешний вид документа не будет соответствовать "настоящему".
Стандартные варианты размещения XUL-блоков

Рис. 2.5. Стандартные варианты размещения XUL-блоков

Многие другие атрибуты также влияют на размещение, но эти - самые важные. Чтобы продолжить анализ системы размещения, нам нужно вернуться к системе стилей Mozilla.

2.2.4. Понятие фрейма и расширение стилей

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

2.2.4.1. Что такое фрейм

Фрейм - это модель реализации, используемая внутри платформы Mozilla и управляющая видимым состоянием одного тега. В сложных случаях одному тегу могут соответствовать несколько фреймов или вообще ни одного, но на практике лучше руководствоваться правилом "один фрейм, один тег". Фрейм с содержащейся в нем информацией - модель, дополняющая "объекты", описанные в стандартах W3C DOM. Объекты DOM, а на самом деле просто интерфейсы к объектам, - внутренние представления XML-сущностей, обычно целого тега. Они позволяют рассматривать теги с точки зрения содержащихся в них данных. Фреймы - внутренние представления CSS-стилей, связанных с целыми тегами. Почти всем тегам соответствуют фреймы, которые дают нам пространственную, визуальную и геометрическую интерпретацию этих тегов. Фреймы включают в себя и стандартные стили CSS, и их расширения Mozilla.

Фреймы важны для XUL, так как (очевидно) вам нужно знать, есть ли у данного элемента фрейм: у тегов <box>, например, всегда есть фрейм.

При каскадном наследовании стилей, изменении размеров окна и динамическом обновлении тега именно фреймы отвечают за координирование изменений в отображении документа. Все это происходит внутри Mozilla автоматически, как и обработка событий, определенных стандартом DOM.

С точки зрения прикладного программирования фреймы - более абстрактное понятие, чем интерфейсы DOM, и работать с ними напрямую необязательно. Все нужные действия по обработке фреймов выполнит механизм визуализации Gecko. Фреймы важны, только если запутаться в проблемах, связанных с отображением документа. Тогда будет полезно вспомнить правило "нет фрейма - нет нормального размещения". Будет визуальному элементу соответствовать фрейм или нет, зависит от программной реализации Mozilla, но обычно верно следующее: у каждого видимого элемента, находящегося на уровне z-index:0 и занимающего на экране отдельный прямоугольный участок, есть фрейм. У многих других видимых элементов, например, абсолютно позиционируемых HTML-элементов, также есть фреймы. У всплывающих подсказок фреймов нет. У XUL-тегов <tree> очень сложная система соответствия фреймам.

Для нас основная причина рассматривать фреймы - необходимость понять, что такое расширения CSS-стилей в Mozilla и для чего они нужны, поскольку в приложениях Mozilla они используются очень активно.

2.2.4.2. Стили и расширения стилей, влияющие на состояние и содержимое фреймов

В Mozilla к стандарту CSS 2 добавлен набор дополнительных свойств. Все эти свойства (расширения стандарта) начинаются с префикса "-moz" или ":-moz". Это могут быть уникальные собственные расширения, скрытые внутренние функции, экспериментальные или отладочные функции или просто свойства, которые могут войти в будущий стандарт. Некоторые из них дополняют модель отображения стилей, а некоторые предназначены скорее для программистов.

Свойства и расширения стилей определены в исходном коде в заголовочных файлах C/C++. Можно заглянуть в файлы, чьи имена заканчиваются на List.h, например, в nsCSSPropList.h, и убедиться, что список расширений просто огромен. Почему же их так много?

Все дело в реализации. Набор стандартных свойств CSS 2 можно представить как большой конечный автомат, так как у каждого отображаемого элемента или фрейма есть конечный набор состояний. Набора состояний, соответствующего свойствам из CSS 2, может быть достаточно для описания отображаемых данных, но недостаточно для полной системы отображения CSS 2. В такой системе должна храниться дополнительная служебная информация. Например, свойств CSS 2 может быть достаточно для описания внешнего вида кнопки, но системе отображения CSS 2 внутри Mozilla нужно также знать, содержит ли XML- код этой кнопки описание элемента управления из какого-либо набора графических элементов. Если да, то нужно работать с этим элементом управления. Вот эта дополнительная информация (используется ли данный элемент управления) также может храниться как расширение стиля Mozilla, например, -moz-gc-wrapper-block. Этот пример на самом деле представляет интерес только для разработчиков Mozilla.

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

Похожее разделение на внешнее и внутреннее относится и к содержимому, к которому применяются стили. Содержимое данного тега, даже если в нем нет тегов-потомков, можно разбить на несколько независимых частей. У этих внутренних частей могут быть собственные стили оформления, пусть даже недоступные извне. Пример: буквица, первый символ абзаца. Хотя в стандарте CSS 3 к стилю этой буквы можно получить доступ через псевдокласс :initial-letter, в Mozilla он реализован как внутренний фрейм. Такие внутренние части элемента скрыты от программиста, как и внутренние расширения стилей. В системе отображения это основные компоненты самого низкого уровня, специфичные для Mozilla и, вероятно, несколько меняющиеся со временем. По возможности следует стараться использовать только внешние функции, хотя бы потому, что они проще и более понятны.

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

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

input:focus {-moz-outline: 1px dotted -moz-FieldText;}

-moz-outline значит "показывать контур". -moz-FieldText значит "использовать для контура стандартный цвет текста в полях форм".

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

<mybox align="start"> ... </mybox>

Все английские слова в приведенном коде ( mybox, align, start ) дают нам подсказки относительно размещения содержимого. Самое простое, что можно сделать с этими ключевыми словами - превратить их в свойства стиля. Действие многих расширений стилей в Mozilla эквивалентно действию какого-либо ключевого слова XUL. Поведение некоторых XUL- тегов полностью зависит от этих стилей, так что смысл тега фактически определяется стилем. Приведенный выше код XUL можно переписать так:

mybox { -moz-box-align: start; }

Для элемента <mybox> нет C/C++-кода: весь элемент полностью зависит от стилей.

В Mozilla, кроме новых свойств стиля, есть и новые правила стилей.

2.2.4.3. Дополнительные состояния доступа к расширениям правил стиля

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

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

Дмитрий Гуменюк
Дмитрий Гуменюк
Россия, Звенигород
Konstantin Grishko
Konstantin Grishko
Россия, Москва, Московский финансово-промышленный университет "Синергия", Москва