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

Верстка с XUL

2.3. Теги для размещения данных в виде блоков

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

2.3.1. Блоки

Как уже было сказано, ко всем тегам XUL, включая неизвестные, применяется правило display: -moz-box. Затем для некоторых из элементов это правило переопределяется разработчиком, а все остальные остаются аналогичными <box>. То есть <xyzzy>/ и <happysad> - тоже теги XUL и тоже блоки, хоть это и неочевидно. В качестве стандартных блоков предлагаются три элемента.

  1. <box>. Содержимое этого блока выравнивается по горизонтали, а его атрибуты по умолчанию описаны выше в разделе "Основные атрибуты размещения блоков".
  2. <hbox>. Горизонтальный блок. Выполняет те же функции, что и <box>. Его имя просто напоминает о его функциях.
  3. <vbox>. Вертикальный блок. Выполняет те же функции, что и <box orient="vertical">, только <vbox> набирается быстрее. Имя также служит для упрощения чтения кода.

Тег <vbox> - не больше, чем какой-либо не зависящий от формата, определенный пользователем тег <xyzzy> с расширением стиля -moz-box-orient:vertical. Это расширение эквивалентно использованию атрибута orient="vertical" и является основной чертой <vbox>. Можно, конечно, сказать, что <vbox> следует стилю, а не наоборот. Тег <vbox> не совсем полноправен.

Другой источник блоков - корневые теги XUL-документов. <window>, <dialog>, <page> и <wizard> - все они ведут себя как блоки и будут обсуждаться подробнее в "Окна и панели" , "Окна и панели", кроме <wizard>, который мы рассмотрим отдельно в "Система распространения и установки - XPInstall" , "Установка приложений". С точки зрения размещения объектов, эти теги ведут себя как <box> с атрибутом flex, описанным ниже.

2.3.2. Атрибут flex и элементы-разделители

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

2.3.2.1. flex= и align=

Единственный механизм для "растягивания" XUL-тегов - применение атрибутов flex и align. flex и align могут использоваться со всеми тегами, выполняющими функции блока; flex также может использоваться с несколькими специальными тегами. align описывался в разделе "Основные атрибуты размещения блоков". Вот типичный пример использования flex:

<hbox flex="1"> ... content ... </hbox>

Значение этого атрибута не наследуется потомками от родительского тега.

Тег с атрибутом flex может "растягиваться" в обоих измерениях: по x и по y. Тем не менее, добавление flex="1" или align="stretch" не гарантирует того, что занимаемая тегом площадь увеличится: это зависит от внешнего, объемлющего тега (то есть от родительского тега). Для любого данного тега правила "растягивания" по горизонтали и по вертикали различны. Вспомним, что родительский тег определяет основное направление размещения объектов. Перпендикулярное основному направление, как легко догадаться, находится под прямым углом к основному. Вот правила для "растягивания" относительно оси основного направления:

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

Правило "растягивания" относительно оси перпендикулярного направления:

  • если у родительского тега есть атрибут align="stretch" (или если этот атрибут отсутствует), тег сможет растягиваться в перпендикулярном направлении.

Из этих правил следует, что если тег должен менять размеры в обоих направлениях, когда пользователь меняет размеры окна, у этого тега и всех его предков должны быть атрибуты flex и/или align="stretch". Обычно это означает, что атрибут flex нужно добавлять к очень большому числу тегов.

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

Если <box> содержит несколько тегов, все эти теги могут расширяться относительно оси основного направления по-разному. Пустое место внешнего блока будет разделено между ними согласно следующему алгоритму. Все значения атрибутов flex суммируются, а все свободное место делится на количество частей, равное этой сумме. Затем каждому тегу выделяется дополнительное пространство, чей объем пропорционален значению его атрибута flex. Пример, более наглядно объясняющий этот принцип, показан в листинге 2.4.

<box width="400px">
  <box id="one" flex="1"/>
  <box id="two" flex="2"/>
  <box id="three" flex="3"/>
</box>
Листинг 2.4.

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

  • Количество свободного места: 400 - 100 = 300 пикселов.
  • Сумма значений атрибутов flex у внутренних блоков: 1 + 2 + 3 = 6.
  • Свободное место для тега с flex="1": 300 / 6 = 50 пикселов.

Тогда размеры всех трех внутренних блоков изменятся так:

  • Блок "one" получает дополнительно 1 * 50 = 50 пикселов.
  • Блок "two" получает дополнительно 2 * 50 = 100 пикселов.
  • Блок "three" получает дополнительно 3 * 50 = 150 пикселов.

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

2.3.2.2. <spacer> и другие теги-разделители

В разделе "Основные атрибуты размещения блоков" рассказывалось о том, как пользоваться XUL-атрибутами для выравнивания содержимого блоков. Но таким образом не удастся отделить друг от друга два блока, если только не использовать для этого несколько тегов <box>. Создать дистанцию между двумя блоками можно с помощью тега <spacer> и атрибута flex.

Тег <spacer> - обычный определенный пользователем тег. Он не обрабатывается каким-либо особым образом, к нему не применяются никакие стили. Его использование - всего лишь дань традиции XUL, и в словарь XUL он попал только поэтому. Используется он примерно так:

<hbox flex="1"><box/><spacer flex="1"/><box/><box/></hbox>

Этот код соответствует горизонтальному блоку, содержащему четыре тега. Чтобы понять, как он будет отображаться, вам нужно знать только описанные выше правила. Только у <spacer> есть атрибут flex, позволяющий ему занимать свободное место, поэтому если оно появится, он займет его полностью. Таким образом: слева будет блок, потом пустое место, а потом два блока справа. <spacer> отделяет блоки справа и слева друг от друга.

<spacer> вообще никак не проявляется визуально, если у него отсутствует атрибут flex="1" и атрибуты ширины и высоты. Он может казаться бесполезным, но он позволяет динамически сжимать свободное пространство между элементами, если это нужно. Некоторые считают, что к <spacer> следовало бы автоматически применять стиль со свойством flex. Пока этого еще нет. На рисунке 2.6 показаны результаты различных значений flex для предыдущей строки кода. Правило стиля border: solid thin было добавлено, чтобы можно было сразу понять, где находится <spacer>. Обычно он невидим.

Варианты использования <spacer> и разных значений атрибута flex.

Рис. 2.6. Варианты использования <spacer> и разных значений атрибута flex.

Есть и другие XUL-теги, выполняющие те же функции, что и <spacer>. Вот их неполный список: <separator>, <menuseparator>, <toolbarseparator>, <treeseparator> и <spring>. На самом деле любой определенный пользователем тег с атрибутом flex="1" будет вести себя как разделитель. Но для чего тогда нужны перечисленные теги?

<separator> и <toolbarseparator> - пользовательские теги с определенными стилями. Они нужны больше для упрощения оформления, чем для внесения дополнительной функциональности. Они делают то же, что и <spacer>, но у них особая роль, и каждая тема для Mozilla должна предоставлять стили для них. <toolbarseparator> - объект, к которому можно применить стили, появляющийся между кнопками на панели инструментов, а <separator> можно вставлять между панелями инструментов и любым другим обычным содержимым. Наличие этих элементов открывает дополнительные возможности для оформления тем. Они чем-то похожи на <HR> в HTML или прозрачных GIF-изображениях размером 1х1 пиксел. Единственные люди, заинтересованные в этих тегах - дизайнеры тем. Для таких тегов атрибут flex не используется.

<menuseparator> - то же самое, только для выпадающих меню. Он отображается как прямая вроде <HR>, проходящая поперек меню и разделяющая его на две части. Меню обсуждаются в "Формы и меню" , "Формы и меню", и "Навигация" , "Навигация".

Из этих элементов выделяется <treeseparator>, который будет описан в "Списки и Деревья" , "Списки и деревья". Как можно понять из имени тега ( tree separator - разделитель для деревьев), он относится к деревьям. Не следует использовать <treeseparator> отдельно.

Наконец, <spring> - тег, который также применяется для упрощения оформления, но только в классическом Компоновщике. Поведение XUL- блоков с атрибутом flex должно искоренить использование объектов <spring>, но в некоторых случаях без них обойтись трудно. Компоновщик - единственный компонент Mozilla, в котором переход на <spacer> еще не завершен. Тега <spring> следует избегать не только потому, что он значительно усложнит разметку, но и потому, что как концепция XUL он более не приветствуется. Если вы считаете, что вам нужен тег <spring> или <strut>, прежде всего, следует прочитать раздел "Отладка" этой лекции.

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