Опубликован: 10.12.2007 | Доступ: свободный | Студентов: 821 / 20 | Оценка: 5.00 / 5.00 | Длительность: 58:33:00
Лекция 14:

Шаблоны

14.3.2. Основные теги

Тег верхнего уровня шаблона - родительский тег <template>. Он называется базовым тегом шаблона. Это обычный XUL-тег, наподобие <tree> или <box>. Этот тег должен содержать часть конфигурационной информации шаблона.

Специальные атрибуты, которые могут быть добавлены к такому тегу верхнего уровня:

datasources flags coalesceduplicatearcs allownegativeassertions 
xulcontentgenerated ref containment

Атрибут datasources означает, что в шаблоне будут использоваться RDF данные. Это разделенный пробелами список имен RDF файлов, таких как test.rdf, и имен источников данных, таких как rdf:bookmarks.

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

Если XUL-документ инсталлирован в chrome, либо безопасность обеспечена каким-то иным образом, в начало списка источников данных автоматически добавляется внутренний источник: rdf:local-store. Этот источник добавляет информацию о конфигурации профиля пользователя из файла localstore.rdf. Это важно, потому что часто приходится обращаться к источникам информации из скриптов, и прикладной программист должен знать, что информация доступна.

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

dont-build-content. Это ключевое слово относится к шаблонам деревьев. Оно предписывает стандартному конструктору шаблона передать ответственность по выводу на дисплей найденного контента встроенному конструктору дерева. Конструктор шаблона по-прежнему генерирует контент, основанный на RDF, но он используется только как снимок, который задействует конструктор дерева. Различные конструкторы описываются в "Списки и Деревья" , "Списки и деревья". Преимущество этой системы состоит в том, что генерация контента откладывается до тех пор, пока его не нужно будет выводить на экран. Это выгодно, когда генерация контента требует большой вычислительной мощности, например запрос к серверу каталогов. Таким образом можно и уберечь систему от "вспышек" ("flashing"), то есть вывода части информации на экран до завершения выполнения запроса.

dont-test-empty. Это ключевое слово предписывает запросу не обследовать контейнер, чтобы узнать, не пуст ли он. Это оптимизация, которая позволяет не выполнять тест, который может оказаться весьма дорогим. Она также позволяет системе шаблонов справиться с динамическими иерархическими данными, где такой тест вообще невозможен. Например, исследование сети может привести к такой ситуации. В этом случае ответить на вопрос "не пусто ли множество элементов сети?" невозможно, потому что код может ожидать, пока придет ответ "нет" бесконечно. dont-test-empty - удачный выбор для шаблонов, основанных на источнике данных rdf:null.

coalesceduplicatearcs, allownegativeassertions, и xulcontentgenerated также несколько улучшают быстродействие и модифицируют запрос.

Атрибут coalesceduplicatearcs, когда он указан, затрагивает факты, которые могут быть извлечены из нескольких источников данных шаблона. Большинство флагообразных атрибутов в Mozilla считаются установленными, когда их значение равно true. Не так устроен этот атрибут, его значение должно быть false. Он воздействует на то, каким образом JavaScript обращается с фактами, а не с результатами запроса. Если этот атрибут не установлен, идентичные данные из различных источников данных шаблона будут обнаружены лишь единожды, а не по одному результату на копию. Если он имеет значение false, все факты будут обнаружены, независимо от того, дублируются они или нет. Запросы выполняются быстрее, если этот атрибут установлен.

Атрибут allownegativeassertions, когда он установлен, также затрагивает факты, которые могут быть извлечены из нескольких источников данных шаблона. Большинство флагообразных атрибутов в Mozilla считаются установленными, когда их значение равно true. Но этот атрибут также может быть установлен в значение false. Он воздействует на то, как JavaScript обращается с фактами, а не с результатами запроса. Если этот атрибут не установлен, факт, который утверждается и позитивно, и негативно, никогда не будет обнаружен, поскольку два факта "погасят" друг друга. RDF документы содержат только позитивно установленные факты. Негативные факты можно постулировать, только используя JavaScript. Если этот атрибут установлен, взаимного погашения не произойдет, и обо всех фактах будет сообщено. Запросы выполняются быстрее, если этот атрибут установлен.

Атрибут xulcontentgenerated применим к любому тегу в шаблоне, и к любому тегу, сгенерированному шаблоном. Он приведен в данном списке атрибутов, поскольку он также влияет на оптимизацию. Начинайте экспериментировать с этим атрибутом только после того, как полностью разберетесь с шаблонами. Атрибут xulcontentgenerated может иметь значение true. Он сказывается в тот момент, когда запрос еще выполняется, а контент генерируется. Если шаблон строится лениво, то в каждый момент часть контента уже порождена, а часть нет. Если мы обращаемся к тегу с какой-либо DOM операцией (наподобие добавления дочернего тега), а тег имеет неполный, ленивый контент, может возникнуть неясность. Куда добавить дочерний тег, если множество дочерних тегов еще только предстоит вычислить? Mozilla решает эту проблему, просто заставляя шаблон породить необходимый контент перед выполнением DOM операций. Атрибут xulcontentgenerated отменяет эту работу, чтобы ничего не пересчитывалось в данный момент в XUL дереве. Это ускоряет DOM операции и отменяет ненужные вычисления.

Атрибут ref определяет начальную точку запроса. Он содержит полный URI подлежащего в факте. Этим подлежащим должно быть имя <Seq>, <Alt>, или <Bag> контейнера.

Атрибуты ref и containment обсуждаются в следующем разделе.

14.3.2.1. Атрибуты ref и containment: тесты контейнера

Атрибуты ref и containment можно использовать, чтобы определить стартовую точку запроса, который не задействует официальный RDF-тег container. Это полезно для простых RDF фактов, образующих простую иерархию, но не использующих теги <Seq>, <Bag>, или <Alt>. Эти псевдоконтейнеры нуждаются в дополнительном комментарии.

Рассмотрим обычный RDF-контейнер. Пример приведен в листинге 14.9.

<Description about="urn:eg:ownerA"> 
  <prop1> 
  <Seq about="urn:eg:ContainerA"> 
    <li> 
      <Description about="urn:eg:item1" prop2="blue"/> 
    </li> 
  </Seq> 
  </prop1> 
</Description>
Листинг 14.9. Фрагмент RDF контейнера, содержащего три факта.

Предикаты в этом примере умышленно выбраны простыми. Листинг 14.9 эквивалентен трем фактам:

<- urn:eg:ownerA, prop1, urn:eg:containerA -> 
<- urn:eg:containerA, rdf:_1, urn:eg:item1 -> 
<- urn:eg:item1, prop2, blue ->

Первый факт в качестве подлежащего имеет RDF контейнер. Это факт, который "владеет" контейнером. Второй факт сообщает, что item1 - член этого контейнера. В третьем факте записана некоторая полезная информация о цвете данного item1. Это все обычный RDF. Эти три факта прямо следуют из синтаксиса <Seq> листинга 14.9.

Предположим, программа имеет информацию об этих трех фактах, а не исходный RDF файл. Как она может узнать, был ли контейнер? В данном простом случае нам достаточно заметить предикат rdf:_1, чтобы понять, что container A и есть RDF контейнер. В Mozilla выполняются различные тесты (включая rdf:instanceOf predicate ), но в этом примере достаточно заметить rdf:_1.

Теперь предположим, что в эти три факта внесено единственное изменение. Пусть предикат rdf:_1 был заменен на rdf:member (или что- нибудь еще). Тогда три факта будут выглядеть так:

<- urn:eg:ownerA, prop1, urn:eg:containerA -> 
<- urn:eg:containerA, rdf:member, urn:eg:item1 -> 
<- urn:eg:item1, prop2, blue ->

В Листинге 14.10. показан фрагмент RDF, который может соответствовать этим измененным фактам. Это просто серия вложенных фактов:

<Description about="urn:eg:ownerA"> 
  <prop1> 
<Description about="urn:eg:ContainerA"> 
  <rdf:member> 
<Description about="urn:eg:item1" prop2="blue"/> 
  </rdf:member> 
</Description>
  </prop1> 
</Description>
Листинг 14.10. Фрагмент RDF без контейнера, соответствующий трем фактам.

Есть ли по-прежнему контейнер в этих трех фактах? В конце концов, оба случая так похожи. Можно утверждать, что контейнер действительно существует. Во-первых, способ организации трех фактов не изменился. Во-вторых, выбор rdf:member в качестве предиката предполагает, что item1 принадлежит чему-то. В-третьих, любой запрос, построенный с тегом <Seq>, может работать с новым предикатом точно так же, как он работал со старым.

Суть в том, что рассматривая RDF разметку, мы можем решать для себя, существует контейнер или нет. Можно создать RDF документ без тега container, но продолжать рассматривать RDF так, как будто контейнер существует. Почему же Mozilla должна выбрать одну точку зрения, а не другую?

Здесь нам придется снова рассмотреть атрибут ref. Он может быть установлен в значение "urn:eg:ContainerA", и этот ресурс может служить начальной точкой запроса, независимо от того, выглядит ли листинг исходного RDF как 14.9 или 14.10. RDF теги <Seq>, <Bag>, или <Alt> необязательны.

При данном гибком использовании ref есть одна хитрость. Mozilla нужно определить, можно ли использовать данный ref URI как контейнер. Существует три стандартных способа выяснить, пройдет ли ref URI этот тест:

  1. URI есть <Seq>, <Bag>, или <Alt> теги.
  2. ref является подлежащим факта, а предикатом является http://home.netscape.com/NC-rdf#child
  3. ref является подлежащим факта, а предикатом является http://home.netscape.com/NC-rdf#Folder.

Для Mozilla проверка на эти условия эквивалентна проверке на rdf:_1.

Если вы не хотите использовать предикаты child или Folder в своих фактах, вы не обязаны это делать. Вы можете использовать ваши собственные предикаты. Чтобы это сделать, создайте RDF контент так, как вам нужно, а в коде XUL шаблона добавьте атрибут containment к основному тегу шаблона.

Атрибут containment может содержать список предикатов, разделенных пробелами. Эти предикаты будут добавлены к списку тестов контейнера. Эти предикаты будут тестироваться точно так же, как тестировались элементы в предыдущем списке. Например, запись

containment="http://www.test.com/Test#member"

означает, что RDF тег <Description> будет рассматриваться Mozilla как контейнер, при условии, что xmlns:Test="http://www.test.com/ Test#" было декларировано где-либо ранее:

<Description about="urn:foo:bar">
<Test:member resource="urn:foo:bar:item1"/> 
<Description>

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

14.3.2.2. Специальные атрибуты тега <tree>

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

flex="1" statedatasource flags="dont-build-content"

Деревья не имеют значения атрибута height по умолчанию. Если шаблон <tree> не имеет атрибута flex="1", содержание шаблона зачастую может не появиться на экране вообще. Всегда используйте flex="1" в шаблоне <tree>.

Атрибут statedatasource - устанавливается для именованного источника данных, используемого для сохранения текущего состояния дерева. Если пользователь откроет или закроет ряд поддеревьев на экране, информация о том, какие поддеревья открыты, а какие закрыты, будет сохранена в этом именованном источнике данных. В настоящее время это используется только в почтовом клиенте Mozilla, на панели, где перечисляются папки.

Если атрибут statedatasource не установлен, используется источник данных, названный в атрибуте datasources.

Значение "dont-build-content" атрибута flags также используется только для деревьев. Оно описывается в разделе "Основные теги".

14.3.2.3. Поддержка сортировки для дочерних тегов <template>

Система шаблонов позволяет сортировать колонки данных. Это свойство реализовано для XUL меню, списков и деревьев.

Процесс сортировки использует несколько атрибутов. Они могут быть установлены для базового тега шаблона, либо для конкретных тегов <listcol> или <treecol>. Это следующие атрибуты:

resource resource2 sortActive sortDirection sortResource sortResource2

Атрибут resource содержит переменную шаблона. Автор XUL-документа указывает его для колонки, которая должна быть отсортирована. Этот атрибут указывает ключ, содержащий данные, которые должны сортироваться. Переменная шаблона, который он именует, представляет предикат/свойство факта, дающего решение запроса для каждой строки. Данные, используемые как ключ для сортировки, являются дополнением/значением этого предиката. Другими словами, данный атрибут указывает свойство, чье значение для каждой строчки должно сортироваться.

sort - альтернативный синтаксис для атрибута resource. Его также применяют, чтобы указать сортируемую колонку в списке или дереве. Используйте resource и sortActive, но не этот атрибут.

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

sortActive может принимать значение true и указывать тем самым, была ли произведена сортировка. Mozilla автоматически устанавливает этот атрибут на нужную колонку списка или дерева. Его может указать и программист приложения. Его можно использовать для доступа к колонке, которая должна сортироваться, то есть его следует указывать всегда, если не использован атрибут sort.

sortDirection может принимать значения ascending, descending, или natural. Он может быть установлен автором XUL документа или Mozilla автоматически после сортировки. Mozilla установит его одновременно и на рассматриваемую колонку, и на базовый тег.

sortResource и sortResource2 - то же самое, что и resource и resource2. Эти атрибуты устанавливает Mozilla. Вторичный критерий сортировки может быть установлен программистом с помощью JavaScript, но не прямо в XUL.

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