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

XBL-связки

15.2.5. Тег <content>

Тег <content> содержит весь анонимный контент связки. Он может включать XML теги из любого пространства имен XML, такого как HTML, XUL или MathML. Он может содержать также тег <children>, специфичный для XBL. Источники событий и наблюдатели XUL, как и тег <script>, не работают в анонимном контенте.

Тег <content> имеет два специальных атрибута:

includes excludes

Оба атрибута считаются устаревшими, их следует избегать. Используйте вместо них в анонимном контенте тег <children>. Если в теге <content> появляются любые другие атрибуты, они будут скопированы в граничный тег.

Атрибуты граничного тега могут быть добавлены тегам внутри тега <content> с помощью атрибута inherits. Эксплицитный контент граничного тега может быть слит с тегами внутри тега <content> с помощью тега <children>.

Если связка использует атрибут extends, так что строится на основе другой связки, тег <content> в этой другой связке игнорируется.

Если тег <content> связки пуст, граничный тег также не будет иметь контента.

15.2.5.1. Объединение атрибутов с помощью xbl:inherits=

Анонимный контент тега <content> может быть фрагментом документа любого типа и любого размера. Тег <children> может появиться в любом месте этого фрагмента.

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

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

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

att1 
att1=att2 
xbl:text=att2 
att1=xbl:text

att1 и att2 - любые правильные имена атрибутов XML.

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

Вторая форма записи говорит о том, что атрибут att1 анонимного тега должен иметь значение атрибута att2 граничного тега.

Третья форма использует специальное зарезервированное имя xbl:text. Она говорит, что <текстовое> содержание анонимного тега (a DOM 1 Text Node) должно иметь значение атрибута att2 граничного тега. Это дает тот же эффект, что и использование тега <textnode> в шаблонах XUL.

Четвертая форма говорит, что атрибут att1 анонимного тега должен получить значение эксплицитного контента граничного тега, который в этом случае должен быть текстовым содержанием, DOM 1 text node.

Поскольку атрибут inherits является атрибутом XBL, он не может появиться в не-XBL теге. Он должен быть полностью определен, включая его пространство имен XML. Это достигается благодаря префиксу xbl: (или подобному) и добавлению полной декларации пространства имен в начале документа XML. В силу этих причин XBL документы часто имеют две ссылки на пространство имен XBL:

<bindings id="test" 
xmlns="http://www.mozilla.org/xbl" 
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >

Первое пространство имен XBL обычное по умолчанию, второе указывается специально для атрибута inherits.

Если все это соединить, получится следующий пример атрибута inherits:

<xul:label dir="ltr"
xbl:inherits="xbl:text=value,style,align=justify"/>

Если граничный тег был таким:

<mytag value="Test" style="color:red" justify="start"/>

то после замены анонимный тег <xul:label> будет заменен на:

<xul:label dir="ltr" style="color:red" align="start"> Test
</xul:label>

Атрибут inherits может быть использован в любом месте анонимного контента, и может связать один атрибут граничного тега со многими атрибутами тегов анонимного контента, если потребуется. Теги анонимного контента всегда могут определять атрибуты явно, как dir="ltr". Если специальный атрибут xbl:text использован более одного раза, все определенные значения появятся в текстовой ноде анонимного тега.

15.2.5.2. Слияние тегов с помощью тега <children>

Тег <children> управляет слиянием эксплицитного контента граничного тега (если он есть) с анонимным контентом (если он есть) тега <content>. Тег <children> может появиться в любом месте анонимного контента связки. Он представляет любой эксплицитный контент, который имеет граничный тег. Он имеет следующий специальный атрибут:

includes

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

  1. Если эксплицитного контента нет, любые теги <children> в анонимном контенте игнорируются. Это все равно что удалить все теги <children> из секции <content>, но оставить остальные теги нетронутыми. Финальный контент является копией оставшегося анонимного контента.
  2. Если анонимного контента нет, то граничный тег после слияния вовсе не будет иметь контента.
  3. Если есть и эксплицитный, и анонимный контент, подсчитываются все теги эксплицитного контента, являющиеся непосредственными дочерними тегами граничного тега. Каждому такому тегу должен соответствовать один тег <children>. Если это условие выполняется, финальным контентом будет объединенная копия эксплицитного и анонимного контентов.
  4. Если что-то из этих условий не выполняется, то либо теги <children> в анонимном контенте использовались некорректно, либо в граничном теге есть некоторый неучтенный эксплицитный контент. В этом случае результат объединения непредсказуем.

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

Если у тега <children> нет атрибута includes, эксплицитным контентом будет замещен и сам тег <children>, и поддерево его контента в анонимном контенте. В этом случае должен быть ровно один тег <children>.

Если атрибут includes есть, тег <children> будет замещен лишь частью эксплицитного контента. Будут размещены все непосредственные дочерние теги граничного тега, чьи имена совпадают со списком в атрибуте includes. Они будут помещены в той точке анонимного контента, где был данный тег <children>. Они будут размещены в том же порядке, в каком были в граничном теге.

3. Если пункт 2 повторяется аккуратно, то окажется достаточно тегов <children includes=>, чтобы разместить весь эксплицитный контент. В этом случае весь эксплицитный и анонимный контенты будут слиты правильно.

4. Если пункт 2 не повторяется достаточное количество раз, некоторые непосредственные дочерние теги граничного тега не найдут для себя соответствующего тега <children includes=>. Это неполный охват эксплицитных тегов. Mozilla сама добавит весь эксплицитный контент в финальный контент, а весь анонимный контент будет отброшен.

Если пункт 2 реализован небрежно, некоторые дочерние теги граничного тега могут соответствовать более чем одному тегу <children>. Это непорядок, в таком случае результат может быть непредсказуем. В итоге разработчик связки должен либо (a) не делать никаких предположений об эксплицитном контенте граничного тега и избегать использовать includes, либо (b) полностью предвидеть, что граничный тег будет размещать в анонимном контенте и использовать includes везде; или (c) делать обоснованные догадки и положиться на то, что система XBL придумает здесь что-то более или менее рациональное.

Листинг 15.4 демонстрирует корректный пример этой системы в действии.

<!-- tag to be bound --> 
<mytag> 
  <image src="face.png"/> 
    <description label="Smile"/> 
  <image src="face.png"/> 
</mytag> 

<!-- Example 1: unknown explicit content --> 
<content> 
  <box> 
    <children/> 
  </box>
</content>

<!-- Example 2: known explicit content --> 
<content> 
  <children includes="description"/> 
  <box> 
    <children includes="image"/> 
  </box>
</content> 

<!-- Example 3: known but optional explicit content -->
<content> 
  <children includes="image|description"> 
    <label value="No emoticon supplied"/> 
  </children> 
</content>
Листинг 15.4. Исходный код примера объединения контента XBL.

В данном листинге тег <mytag> - граничный. Остальные фрагменты принадлежат трем разным связкам. Пример 1 добавляет весь, неважно какой, эксплицитный контент. Пример 2 корректно добавит каждый тип эксплицитного контента в соответствующем месте. Пример 3 также добавит эксплицитный контент, но если его нет, вместо него будет использоваться тег <label>. В листинге 15.5. приведен финальный контент для всех этих случаев.

<!-- Example 1: unknown explicit content --> 
<mytag> 
  <box> 
    <image src="face.png"/> 
      <description label="Smile"/> 
    <image src="face.png"/>
  </box> 
</mytag> 

<!-- Example 2: known explicit content --> 

<mytag>
  <description label="Smile"/> 
  <box> 
    <image src="face.png"/> 
    <image src="face.png"/> 
  </box> 
</mytag> 

<!-- Example 3: known but optional explicit content --> 
<mytag> 
  <image src="face.png"/> 
    <description label="Smile"/> 
  <image src="face.png"/> 
</mytag>
Листинг 15.5. Сгенерированный контент для примеров объединения контентов.

Если исходный контент тега <mytag> сильно изменить, пример 1 останется работающим, в то время как 2 и 3 могут дать неожиданные результаты.

В примере листинга 15.6 приведена конструкция, которая никогда не будет работать надежно, потому что теги <image> эксплицитного контента не соответствуют ни одному из двух тегов контента анонимного.

<content> 
  <children/> 
    <box> 
      <children includes="image"/> 
    </box>
</content>
Листинг 15.6. Плохо сконструированный контент для связки XBL.
15.2.5.3. Слияние граничных тегов

Анонимный контент внутри тега <content> сам, в свою очередь, может включать граничные теги для некоторой XBL связки. Это вполне допустимо, поскольку большинство XUL-тегов - граничные теги.

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

Можно сконструировать циклы вложения, но этого следует избегать. Тег <content> не должен содержать свой собственный граничный тег.

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