• Содержание
  • Разработка приложений с помощью Mozilla / автор: Н.Макфарлейн
    12. Глава: Оверлеи и Chrome

    В этой главе описывается инфраструктура оверлеев и каталога chrome платформы Mozilla. Данная инфраструктура предоставляет механизмы для модульной разработки XUL-приложений. И оверлеи, и chrome сильно зависят от файлов данных в формате RDF.

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

    Пример документа, использующего оверлеи, приведен в листинге 12.1

    <?xml version="1.0"?> 
    <?xul-overlay href="chrome://test/content/overlayA.xul"?> 
    <?xul-overlay href="chrome://test/content/overlayB.xul"?> 
    <window xmlns="http://www.mozilla.org/keymaster/
      gatekeeper/there.is.only.xul"> 
      <description id="start">Anything</description>
    </window>
    
    Листинг 12.1. Простой XUL документ с двумя оверлеями

    Этот документ забирает контент из двух файлов: overlayA.xul и overlayB.xul. Эти два файла также содержат XUL-код. Этот совокупный контент добавляется к содержимому исходного файла. Мы видим результат. Ни один из исходных файлов при этом не изменяется.

    Регистр chrome - также компонентная технология. Он отслеживает и содержит данные о компонентах, таких как пакеты, скины и локализация. Эти компоненты - просто группы файлов в директории chrome. Здесь они полностью доступны для платформы в виде URL специального типа. Регистр chrome можно использовать, чтобы управлять информацией об этих файлах. Этот механизм связан с инсталляционной системой, описываемой в главе 17, "Установка".

    Разрабатываемый нами пример, NoteTaker, использовал структуру директории chrome, начиная с главе 1, "Основные Концепции", но многое из этой системы было оставлено за скобками в процессе описания. В этой главе мы опишем модель RDF, лежащую в основе chrome, более тщательно.

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

    Оверлеи и регистр chrome вдобавок предоставляют нам шанс поупражняться в RDF. В этой главе описываются база данных оверлеев overlayinfo и база данных chrome chrome.rdf. Кроме того, мы рассмотрим сохранение данных между сессиями.

    12.1. Оверлеи

    Система оверлеев довольно проста. Один XUL-документ является мастером. Он - стартовая точка для финального контента. Любой иной XUL документ - это оверлей. Контент оверлея присоединяется, или добавляется, к мастер-документу. Это происходит в оперативной памяти и не оказывает эффекта на исходные файлы.

    Оверлей - это XUL-документ, основанный на теге <overlay> вместо тега <window>. Такой файл имеет расширение .xul и является корректным (well-formed) XML, но он не предназначается для самостоятельного использования. Mozilla может показать оверлей сам по себе, но это имеет смысл только для тестирования.

    Mozilla также поддерживает стилевые оверлеи. Это обычные CSS2 файлы с расширением .css. Они должны располагаться в директории skin в chrome. Они не используют тег <overlay>.

    crome классической Mozilla содержит также так называемые JavaScript- оверлеи. Это не оверлеи в прямом смысле этого слова, это обычные JavaScript файлы с расширением .js. Они присоединяются к оверлею с помощью тега <script> в любом месте оверлей-файла. В этом они не отличаются от обычного XUL.

    И мастер, и оверлеи могут содержать синтаксис, специфичный для системы оверлеев.

    Система оверлеев имеет два метода, чтобы решить, какие файлы следует сливать вместе. Эти методы называются "сверху-вниз" и "снизу-вверх", потому что первый инициируется мастер- файлом (сверху-вниз), а второй - особой базой данных оверлеев (снизу- вверх).

    Система оверлеев использует один механизм слияния файлов. Этот механизм основан на XUL id-атрибуте и имеет несколько незначительных вариаций.

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

    <window> 
      <box id="one"/> 
      <box id="two"> 
        <label value="Amber"/> 
      </box>
    </window>
    
    Листинг 12.2. Пример кода, работающего как мастер.

    Предположим далее, что оверлей-документы приведены в листинге 12.3

    <overlay>
      <box id="one"> 
        <label="Red"/> 
      </box>
      <box id="three"> 
        <label="Purple"/>  
      </box> 
    </overlay> 
    <overlay> 
      <box id="two"> 
        <label value="Green"/> 
      </box> 
    </overlay>
    
    Листинг 12.3. Пример кода двух оверлеев

    Если эти два оверлея сольются с мастер-документом, то результирующий документ представлен в листинге 12.4

    <window> 
      <box id="one"> 
        <label="Red"/> 
      <box id="two"> 
        <label value="Amber"/> 
        <label value="Green"/> 
      </box> 
    </window>
    
    Листинг 12.4. Документ, объединенный из мастера и двух оверлеев

    Если атрибут id в мастер-документе совпадает с id оверлея, дочерние теги оверлея копируются в мастер. Они добавляются к содержанию тега в мастере, если таковое содержание было. Если совпадающего id не обнаруживается (случай Purple), к мастеру ничего не добавляется. Если не считать некоторых тонких моментов, это и есть вся система оверлеев.

    12.1.1. Теги оверлеев

    Система оверлеев добавляет к тегам, которые понимает Mozilla, еще два: <?xul-overlay?> и <overlay>. На процесс слияния влияют еще четыре новых атрибута.

    12.1.1.1. Тег <?xul-overlay?>

    <?xul-overlay?> - это расширение XML, допустимое XML- стандартом. Это инструкция, специфичная для Mozilla. Данная инструкция означает: пожалуйста, добавьте содержание указанного документа к данному документу. Этот тег имеет один специальный атрибут:

    href
    

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

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

    Mozilla не поддерживает тег <?xul-overlay?> для файлов HTML.

    12.1.1.2. Тег <overlay>

    Тег <overlay> используется вместо тега <window> в оверлей-документе. Так же как <dialog> или <page>, <overlay> демонстрирует специальное использование XUL контента. В отличие от этих тегов, <overlay> подразумевает неполный документ. Пример приведен в листинге 12.5.

    <?xml version="1.0"?>
    <overlay xmlns="http://www.mozilla.org/keymaster/
     gatekeeper/there.is.only.xul" id="style-id" > 
      <description>Sample content</description> 
    </overlay>
    
    Листинг 12.5. Образец оверлей-документа

    Атрибут xmlns по-прежнему требуется. Тег <overlay> имеет три специальных атрибута:

    id class style
    

    Все три имеют те же значения, что и в XUL и HTML.

    Стили CSS2, основанные на этих атрибутах, могут вести себя необычно. Когда оверлей сливается с мастером, тег <overlay> может полностью передать свое содержание тегам мастера и, следовательно, исчезнуть. В этом случае CSS2 правила, основанные на этом теге, не будут применены.

    Существует соглашение присваивать id тегу <overlay> в любом случае. Этот атрибут полезен только если выполняется одно из следующих условий:

    Оверлей включает другой оверлей (иерархия оверлеев).

    Этот id используется в процессе слияния файлов.

    Наоборот, по умолчанию оверлей не следует добавлять, если нет соответствующего id.

    Эти три условия - следствия обсуждаемого здесь процесса слияния файлов.

    Тег <overlay> необязательно ведет себя как блочный тег. Если мы добавим верстальный атрибут, такой как, например, orient, это будет иметь эффект, только если <overlay> сольется с подходящим тегом в мастере.

    12.1.1.3. Тег <overlaytarget>

    Тег <overlaytarget> иногда используется, чтобы указать id, соответствующий id в оверлее. Это user-defined тег без какого-либо специального значения.

    12.1.2. Поиск оверлеев

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

    Первый метод обнаружения файлов называется "сверху-вниз". Для него требуется, чтобы программист указал в мастере все оверлеи. Этот метод эквивалентен технике включения одного файла в другой, которой обладают многие языки программирования. В C/C++ есть #include, в Perl use и require, а в XUL есть the <?xul-overlay?>.

    Метод сверху-вниз дает программисту приложения возможность разбить XUL документ на иерархию отдельных файлов.

    Второй метод называется "снизу-вверх". Он требует, чтобы программист указал в базе данных все оверлеи и их мастер-файл. База данных, называемая overlayinfo, опрашивается в момент старта платформы. Этот метод эквивалентен линкующим системам как make(1) and ld(1) в UNIX. Это также напоминает концепции проектов в программных инструментах IDE наподобие Visual Basic.

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

    Один мастер-документ может наполняться обоими методами сразу. Листинг 12.1 использует метод сверху-вниз. Однако невозможно сказать, глядя на XUL-документ, используется ли метод снизу-вверх. Это можно узнать, лишь заглянув в базу overlayinfo.

    Пакет приложений классической Mozilla включает множество оверлеев, и еще больше может быть добавлено. Таким образом можно улучшить пакет. Наш NoteTaker основан на этой системе, как и большинство экспериментов на сайте www.mozdev.org. Подобно этому, оверлеи классической Mozilla могут быть добавлены в отдельное приложение. В любом случае, это пример неоднократного использования XUL-контента.

    12.1.2.1. Сверху-вниз

    Оверлеи могут быть вызваны прямо из XUL мастер-документа. Это можно сделать в любом XUL-файле. Доступ к chrome не обязателен.

    Чтобы присоединить файл-оверлей методом сверху-вниз, нужно включить одну строчку в мастер-документ:

    <?xul-overlay href="chrome://mytest/content/Overlay.xul"?>
    

    Обычно эту строчку помещают в начало документа, после <?xml?> заголовка. Если добавляется более одного такого тега, указанные файлы добавляются в порядке этих строк. Если файл указан дважды, он будет присоединен дважды. Указываемые файлы не обязаны находиться в каталоге chrome.

    Простой пример сверху-вниз оверлеев можно найти в коде консоли JavaScript. См. файл console.xul в toolkit.jar в chrome. Более сложный пример см. в navigator.xul в comm.jar там же. Это мастер-документ для всего классического браузера. Не на все оверлеи, включаемые в эти приложения, указывается сверху-вниз, но на значительную часть.

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

    12.1.2.2. Снизу вверх

    Метод загрузки оверлеев снизу вверх не использует тег <?xul-overlay?>. Вместо этого Mozilla получает информацию из базы данных в chrome. Этот метод требует, чтобы и мастер, и оверлей-документы были установлены в каталоге chrome.

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

    Самый общий пример дизайна снизу-вверх - это Классический Браузер, включающий пакет navigator, инсталлированный в chrome (в comm.jar). Многие программисты вносят вклад в его усовершенствование. Когда они разрабатывают плагины к браузеру, они создают оверлеи, которые система слияния снизу-вверх присоединит к окну Классического Браузера. Эти оверлеи содержат элементы GUI, которые появятся в окне браузера. Для нас эти плагины - части привычного интерфейса.

    Простой пример - DOM Inspector. Он доступен по умолчанию в классической Mozilla, но не в Netscape 7.0. Нет ни DOM Inspector, ни соответствующего элемента меню. Однако DOM Inspector может быть установлен позже. После его установки появляется элемент в меню Tools | Web Development в окне Навигатора. Это меню содержится в новом оверлее, появившемся при установке приложения DOM Inspector.

    Необязательно интегрировать оверлеи с классической Mozilla и ее приложениями. Любое окно XUL может быть мастер-документом.

    Чтобы использовать подход снизу-вверх, нужно знать, как работать с RDF.

    12.1.2.3. Чтение базы данных оверлеев

    База данных оверлеев - это множество директорий и RDF файлов. Она находится в директории chrome/overlayinfo в области установки платформы.

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

    Внутри каждой директории overlayinfo/package есть поддиректория content, в которой лежит файл overlays.rdf. Этот файл эквивалентен make(1) makefile для отдельного пакета. Он действует как множество <?xul-overlay?> инструкций для этого пакета. В нем хранится набор фактов о каждом chrome URL, имеющем оверлеи снизу-вверх. Например, overlayinfo/editor/content/overlays.rdf имеет набор сведений, приведенный в листинге 12.6

    <?xml version="1.0"?> 
    <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> 
      <Seq about="chrome://editor/content/editor.xul"> 
        <li> chrome://messenger/content/mailEditorOverlay.xul </li> 
        <li> chrome://cascades/content/cascadesOverlay.xul </li> 
      </Seq> 
    </RDF>
    
    Листинг 12.6. RDF-факты об оверлеях для Mozilla Composer.

    В нем сказано, что при загрузке URL chrome://editor/content/editor.xul нужно загрузить и слить с ним два оверлея, а именно mailEditorOverlay.xul и cascadesOverlay.xul.

    Во многих случаях мастер-документ, упоминаемый в этом файле, сам по себе оверлей, один из тех, что грузятся в мастер-документ сверху-вниз. Эта техника слияния имеет своей целью работу с id тегов, описанных в оверлее, но не в самом главном документе. Эти id значимы для промежуточного оверлея, сконструированного специально для этой цели. Данный промежуточный оверлей иногда определяется в overlays.rdf. Он может быть описан в главном документе с помощью одного-единственного id. Сливаясь с главным, он потянет за собой весь свой контент.

    Отдельно от базы данных overlayinfo, но все еще в chrome, хранится файл chrome/chrome.rdf. Этот файл нужен для регистра chrome, который отвечает за систему оверлеев. Он содержит ряд конфигурационных сведений. Существует три специфичных для оверлеев предиката:

    hasOverlays hasStylesheets disabled
    

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

    Факт с этими предикатами имеет своим подлежащим URI пакета, такое как urn:mozilla:package:editor, а дополнением строку "true". В этих сообщениях подлежащее не может быть "false". Чтобы придать ему занчение "false", нужно удалить всю строчку. Пример такого сообщения:

    <- urn:mozilla:package:editor, hasOverlays, "true" ->
    

    Так что типичная строчка в файле chrome.rdf может гласить:

    <Description about="urn:mozilla:package:editor" 
      hasOverlays="true"/>
    
    12.1.2.4. Изменение базы данных оверлеев

    База данных оверлеев Mozilla сконструирована так, чтобы поддерживать автодетектирование новых оверлеев. Она тесно связана с инсталляционной системой XPInstall, описываемой в главе 17, "Установка". Несмотря на это ее легко использовать и вручную.

    Заглядывая вперед, в систему XPInstall, мы видим следующее:

    Прикладные пакеты при установке добавляют строчки в chrome файл, называемый installed-chrome.txt

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

    Когда Mozilla стартует, она считывает файл installed-chrome.txt, но только если дата его последнего исправления больше, чем дата, хранящаяся в файле chrome.rdf директории overlayinfo в chrome.

    Если installed-chrome.txt прочитан, Mozilla находит все файлы всех пакетов, упомянутые в contents.rdf. Затем на основании информации из contents.rdf воссоздается директория overlayinfo.

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

    Чтобы добавить новый оверлей в базу данных вручную, нужно остановить платформу и отредактировать файл overlays.rdf пакета, которому принадлежит мастер-документ. Мастер-документ - это подлежащее сообщения, имеющее дополнением тег <Seq>. В Листинге 12.6 приведено все, что необходимо.

    Способ сделать эти изменения еще более постоянными - создать файл contents.rdf во время разработки пакета. Этот файл затем добавит необходимые строки в базу overlayinfo при установке пакета. Заметьте, что RDF-контейнры, используемые в файле contents.rdf отличны от контейнеров в файлах overlays.rdf. Когда платформа создает базу overlayinfo, она также пересортирует ее записи по порядку имен пакетов.

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

    <!-- Указывает документ, получающий оверлей --> 
    <Seq about="urn:mozilla:overlays"> 
    <li resource="chrome://package1/content/master.xul"/> 
    </Seq> 
    <!-- указывает оверлей, добавляемый к мастеру --> 
    <Seq about="chrome://package1/content/master.xul">
    <li> chrome://package2/content/overlay.xul</li> 
    </Seq>
    

    Контейнер <Seq about="urn:mozilla:overlays"/> - это служебный список chrome-документов, имеющих оверлеи типа снизу-вверх. Заметьте, что второе сообщение указывает оверлей буквально, а не в виде URI. Это очень важно (см. раздел "Отладка").

    Чтобы изменить конфигурационную информацию об оверлеях в chrome.rdf, нужно либо отредактировать ее вручную (временное решение), либо использовать интерфейс nsIXULChromeRegistry, обсуждаемый в разделе "Объекты XPCOM" главе 17. Этот файл можно также модифицировать, используя систему XPInstall, или добавляя сообщения в файлы contents.rdf.

    12.1.3. Процесс слияния

    Оверлеи присоединяются на основе id атрибута. Если идентификаторы отсутствуют, используется более простая система. Другие специальные случаи зависят от атрибутов, модифицирующих способ, которым обрабатываются ids.

    В следующем обсуждении id источника - это id оверлея. id цели, или целевой id - это id мастер-документа.

    12.1.3.1. Простое слияние

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

    Если в мастер-документе тег <window> или <dialog> имеет атрибут dir="rtl", контент оверлея будет присоединен в начало, а не в конец, но в обратном порядке. Если мастер имеет orient="horizontal", контент оверлея появится справа. И так далее.

    12.1.3.2. Слияние на основе id

    Мощь системы оверлеев базируется на идентификаторах id тегов XUL-а. Можно использовать ids, чтобы влить оверлей в мастер часть за частью. Это делается так.

    Предположим, мастер-документ имеет тег с целевым id. Этот тег - контейнер для любых тегов внутри него, но он может быть и пуст. Далее, предположим, что оверлей имеет тег с тем же самым id (id источника). Тег c id источника тоже имеет теги внутри.

    Когда два документа сливаются, происходит следующий процесс.

    1. Обнаруживается, что id тега-цели и id-тега источника совпадают.
    2. Контент тега с id источника добавляется к содержанию контента тега с id цели.
    3. Любые XML атрибуты источника копируются в целевой тег, перекрывая значения атрибутов с теми же именами.
    4. Тег источника отбрасывается.

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

    Достоинство этой системы состоит в том, что она действует выборочно. Оверлей может иметь несколько фрагментов, каждый со своим id. Эти фрагменты будут слиты с различными частями мастера, а именно с теми, где обнаружится соответствующий id. Таким образом, оверлеи - более мощный инструмент, чем C/C +'s #include или директива use языка Perl. Эти системы могут вставить контент (код) только в одном месте.

    Вот пример. Листинг 12.7 - мастер-документ с двумя целевыми id.

    Листинги 12.8 и 12.9 показывают два оверлея, соответствующие id мастера. Стилевые таблицы опущены для краткости.

    <?xml version="1.0"?>
    <?xul-overlay href="part1.xul"?> 
    <?xul-overlay href="part2.xul"?>
    <window xmlns="http://www.mozilla.org/keymaster/
      gatekeeper/there.is.only.xul"> 
      <vbox id="osite1"> 
        <description>Main Box A</description> 
      </vbox> 
      <vbox id="osite2"> 
        <description>Main Box B</description> 
      </vbox> 
    </window>
    
    Листинг 12.7. Мастер-документ с двумя оверлеями

    Мастер имеет два блока, каждый из которых имеет один тег.

    <?xml version="1.0"?> 
    <overlay xmlns="http://www.mozilla.org/keymaster/
      gatekeeper/there.is.only.xul"> 
      <box id="osite1"> 
        <description>Box C</description>
      </box> 
      <box id="osite2"> 
        <description>Box D</description> 
      </box>
    </overlay>
    
    Листинг 12.8. Первый оверлей имеет два фрагмента для включения.

    Этот оверлей имеет два тега с id, соответствующим id мастера (osite1, osite2). Листинг 12.9 точно такой же, с тем только отличием, что его контент "Box E, Box F" вместо "Box C, Box D" и блок с id="osite2" имеет один добавочный атрибут: orient="horizontal".

    <?xml version="1.0"?> 
    <overlay xmlns="http://www.mozilla.org/keymaster/
      gatekeeper/there.is.only.xul"> 
      <box id="osite1"> 
        <description>Box E</description>
      </box> 
      <box id="osite2" orient="horizontal"> 
        <description>Box F</description> 
      </box> 
    </overlay>
    
    Листинг 12.9. Второй оверлей также содержит два фрагмента для включения

    показывает мастер-документ с этими оверлеями и без них.

    Рис. 12.1.  показывает мастер-документ с этими оверлеями и без них.

    Контент обоих оверлеев был добавлен к контенту мастера. К каждому тегу было добавлено соответствующее содержание. Тег со вторым целевым id изменил свой внешний вид, благодаря дополнительному атрибуту. Не имеет значения то, что мастер-документ имеет теги <vbox>, а оверлеи - <box>. Имена тегов в оверлеях не имеют значения. Но использование подходящего имени упрощает чтение кода.

    Этот пример можно слегка усложнить. Мастер-документ можно изменить следующим образом:

    <vbox id="osite1"> 
    <description>Main Box A
    </description> 
    </vbox>
    

    На это:

    <vbox id="osite1"> 
    <description>Main Box A
    </description> 
    <box id="innersite"/> 
    </vbox>
    

    А любой из оверлеев пусть имеет следующий тег:

    <box id="innersite"> 
    <description>Inner Content
    </description> 
    </box>
    

    Неважно, где именно в оверлее он появится, он может быть даже вложенным тегом. Результат этих двух добавлений показан на рисунке 12.2

    Новый контент был добавлен на новом месте. Он появился перед добавленным контентом первого блока, потому что принадлежит существующему тегу в мастере. Он был добавлен к контенту тега <box> мастера, а не тега <vbox>.

    Мастер-документ с дополнительным контентом

    Рис. 12.2.  Мастер-документ с дополнительным контентом

    Этот пример с добавлением контента к блокам довольно прост. В реальном XUL есть множество тегов, очень чувствительных к добавляемому контенту. В <commandset> можно добавить новые команды. В <deck> - новые слои. В <menupopup> - новые элементы. <toolbar> может получить новые <toolbarbutton>.

    12.1.3.3. Параметры слияния

    Основанная на id система слияния может слегка модифицироваться. Контент оверлея не всегда должен быть присоединен к контенту мастера. XML-атрибуты могут модифицировать место назначения контента. Следующие атрибуты предоставляют эти дополнительные возможности:

    position insertbefore insertafter removeelement
    

    position используется как дополнение к атрибуту id. Его значение - индекс позиции. Он присваивается одному или нескольким тегам внутри тега, имеющего исходный id. Контент тега с этим атрибутом будет добавлен к контенту тега, имеющего позицию, равную индексу, внутри тега с целевым id. То есть position="3" добавит контент к тегу после двух первых тегов внутри тега с соответствующим id. При этом не может возникать коллизий, поскольку теги добавляются последовательно.

    insertbefore и insertafter используются вместо id исходного тега. Вместо того чтобы добавить контент тега с исходным id в мастер-документ, туда добавляется сам исходный тег (и его контент). То есть в мастере становится на один тег больше. insertbefore вставляет контент перед тегом с указанным id, insertafter - после. В обоих случаях вставляемый контент в иерархии DOM - братский тег указанному с помощью id.

    removeelement может иметь значение true и используется вместе с атрибутом id. Если этот атрибут установлен, соответствующий тег попросту будет уничтожен. Нет смысла присваивать тегу с этим атрибутом какой-либо контент.

    Листинг 12.10 иллюстрирует этот синтаксис.

    <?xml version="1.0"?> 
    <overlay xmlns="http://www.mozilla.org/keymaster/
      gatekeeper/ there.is.only.xul">
      <box insertbefore="Box1">
        <description>insertbefore="Box1"</description> 
      </box> 
      <box insertafter="Box2"> 
        <description>insertafter="Box2"</description>
      </box> 
      <box id="Box3"> 
        <description position="3">position="3" 
          in content item</description> 
      </box> 
      <box id="Box4" removeelement="true"/> 
    </overlay>
    
    Листинг 12.10. Пример синтаксиса параметров оверлея

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

    Мастер-документ. Параметры слияния за работой.

    Рис. 12.3.  Мастер-документ. Параметры слияния за работой.

    12.2. Регистр chrome

    Регистр chrome Mozilla - это множество RDF-сообщений, описывающих приложения, установленные в chrome. Он используется, чтобы поддерживать URL вида "chorme:" и чтобы накладывать некоторые простые ограничения на приложения. Он используется автоматически, когда загружаются XUL-документы и устанавливаются новые пакеты.

    Использование термина "регистр" не вполне удачно, потому что Mozilla имеет несколько регистров, и все в различных форматах. Более точно, регистр chrome - база данных о системе и ее функционировании. Регистр chrome используется на уровне работы приложений платформы. Другой регистр, регистр Mozilla, используется на более низком уровне функционирования самой платформы.

    Без chrome платформе пришлось бы выполнять поиск файлов по всему дереву поддиректорий директории chrome. Пришлось бы искать пакеты, скины и информацию, зависящую от локализации для каждого XUL документа. С помощью chrome информация в формате RDF может быть быстро найдена в базе данных (хранилище фактов), расположенной в оперативной памяти, и путь к любому файлу может быть найден до обращения к диску. Это оперативное хранилище сообщений можно использовать для переключения тем и локализаций и для добавления новых пакетов. Теоретически эти изменения можно выполнять даже не перезапуская платформу, но текущая реализация платформы все же требует рестарта.

    Основной способ использования регистра chrome - присваивание URL типа chrome: для определенного пакета нового конкретного значения. Обычно префиксу chrome: присваивается значение с префиксом resource:/chrome/. Эта разметка имеет две мало используемые особенности, которые иллюстрируют роль регистра chrome. Во-первых, пакет может быть установлен в профиле пользователя, а не вместе с платформой. Во-вторых, пакет может быть установлен вообще где угодно в системе. В обоих случаях регистр гарантирует, что URL этого пакета по- прежнему выглядит как

    chrome://package-name/content/
    

    Так же как и система оверлеев, регистр chrome транслирует исходные файлы, созданные программистом приложения, в генерируемые файлы. Оба множества файлов имеют RDF синтаксис. Исходные файлы - это файлы описания contents.rdf для пакетов, тем и локализаций. Регистр chrome игнорирует информацию об оверлеях в этих файлах. Есть только один генерируемый файл, он называется chrome.rdf и имеет URL resource:/chrome/chrome.rdf.

    В разделе "Практика" лекций 2, 3, и 4 мы приводили примеры RDF chrome описаний для пакетов, локализаций и тем соответственно. Здесь мы рассмотрим систему, которую эти примеры иллюстрировали, в целом.

    Каждый файл chrome.rd - полнофункциональная копия модели данных регистра chrome. Просмотрите содержимое этого файла, чтобы увидеть свойства модели, которые мы будем обсуждать далее. Файл contents.rdf содержит только часть модели данных. Эта часть касается лишь информации о конкретном пакете, локализации и тем.

    RDF-информация для chrome основана на модели данных, состоящей из последовательности URNs. Эти URNs начинаются с трех RDF <Seq> контейнеров:

    urn:mozilla:package:root 
    urn:mozilla:locale:root 
    urn:mozilla:skin:root
    

    Каждый контейнер указывает, какие пакеты, локализации или темы доступны платформе. Хотя возможны некоторые отступления, URN-имена конкретного пакета, локализации и темы, то есть содержание контейнеров, должны иметь форму:

    urn:mozilla:package:{package-name} 
    urn:mozilla:locale:{locale-name}
    urn:mozilla:skin:{skin-name}/{skin-version}
    

    Вот пример некоторых URN:

    urn:mozilla:package:navigator
    urn:mozilla:locale:en-US 
    urn:mozilla:skin:classic/1.0
    

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

    http://www.mozilla.org/rdf/chrome#

    Доступные предикаты перечислены в Таблице 12.1

    Таблица 12.1. Предикаты верхнего уровня регистра chrome

    ПредикатПрименениеЗначениеЦель
    accessKeyскинсимволКлавиатурный ключ в классическом браузере, используемый для смены тем
    authorпакет, локализация, скинлюбой текстСоздатель пакета
    baseURLпакетURLРасположение пакета; не используйте схему chrome:
    disabledпакет"true"Запрещает внешние оверлеи, не используйте значение "false"
    displayNameПакет, скинлюбой текствидимое имя
    hasOverlaysпакет"true"XUL оверлеи существуют; не используйте значение "false"
    hasStylesheetsпакет"true"CCS2 оверлеи существуют; не используйте значение "false"
    nameпакетНазвание пакетаИмя пакета должно соответствовать имени директории
    nameскинлюбой текстИмя скина, любой текст
    imageскинURLИзображение, иллюстрирующее скин; не используйте схему chrome:
    localeVersionпакетномер версииМинимальная версия локати, требуемая пакетом
    locTypeпакет, скинInstall, profileМесто, где установлен пакет или скин
    packagesлокализация,скинURNТег <Seq>, содержащий вторичные контейнеры
    previewURLURLДокумент, иллюстрирующий пакет; не используйте схему chrome:
    selectedLocaleURNТекущая локализация; применим только к глобальным пакетам

    В дополнение к главным контейнерам существует два множества вторичных контейнеров. Они доступны из URN локализации и скина, через предикат packages. Эти добавочные контейнеры содержат информацию о реализациях тем и локализаций, специфичных для конкретного приложения. Это также контейнеры вида <Seq> и они имеют следующие имена:

    urn:mozilla:locale:{locale-name}:packages
    urn:mozilla:skin:{skin-name}:packages
    

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

    urn:mozilla:locale:{locale-name}:{package-name}
    urn:mozilla:skin:{skin-name}/{skin-version}:{package-name}
    

    Например, если пакет Navigator (классический браузер) получает французскую локализацию (FR), то требуется вот такой URN, чтобы платформа "знала", что эта локализация реализована и доступна.

    urn:mozilla:locale:FR:navigator
    

    Каждый из этих специфичных скинов или локализационных ресурсов может быть уточнен с помощью RDF пар вида свойство/значение. Доступные предикаты перечислены в Таблице 12.2

    Более новые версии Браузера Mozilla несколько расширяют Таблицы 12.1 и 12.2 дополнительными предикатами.

    Таблица 12.2. Предикаты верхнего уровня регистра chrome

    ПредикатПрименениеЗначениеЦель
    allowScriptsскин"true"Скин может иметь скрипт; не используйте значение "false"
    baseURLлокализация,скинURLРасположение реализации; не используйте схему chrome:
    localeVersionлокализацияНомер версииВерсия реализации
    packageлокализация,скинURNПакет, использующий данную реализацию
    skinVersionскинНомер версииВерсия реализации

    12.3. Сохранение состояния окна

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

    Система сохранения информации состоит из одного RDF-файла и одного XUL-атрибута и автоматически инициируется платформой Mozilla. Она записывает состояние (значение) одного или более атрибутов определенных XUL-тегов. Иногда это выполняется автоматически, а иногда требует указания со стороны программиста приложения. Поскольку атрибут может содержать произвольную строку, некритичную информацию можно добавить в атрибут позже. Для программиста приложения это альтернатива использованию cookies.

    RDF-файл сохранения состояния называется localstore.rdf, он сохраняется в профиле пользователя. Он записывается каждый раз, когда закрывается какое-нибудь окно. Для каждого сохраняемого атрибута файл содержит два сообщения. Одно утверждает, что XUL-документ (URL-подлежащее) сохраняет (сказуемое-предикат) кое-что в некотором теге (дополнение). Нужно лишь сообщение для всех сохраняемых атрибутов конкретного тега. Во втором сообщении тег (URL-подлежащее) имеет предикат/свойство, равное имени атрибута, и строку-подлежащее, равное значению атрибута. Листинг 12.11 демонстрирует эти сообщения для тега в документе editor.xul, имеющем id="editorWindow" и атрибут width.

    <RDF:Description about="chrome://editor/content/
     editor.xul">
      <NC:persist resource="chrome://editor/content/
      editor.xul#editorWindow"/>
    </RDF:Description> 
    <RDF:Description about="chrome://editor/content/
      editor.xul#editorWindow" width="884"/>
    
    Листинг 12.11. Пример данных, сохраняемых в localstore.rdf.

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

    checked collapsed height hidden moz-collapsed open offsetX 
    offsetY ordinal screenX screenY sizemode state width
    

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

    Сохраняемые значения атрибута - это его текущие значения. Если некоторые значения не прописаны в XUL, например, размеры окна, сохранятся текущие значения.

    Указание, которое программист приложения помещает в XUL-код, чтобы сохранить некоторый атрибут, также есть XUL-атрибут:

    persist
    

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

    <window dir="ltr" orient="vertical" persist="dir orient"/>
    

    Если используется сохранение атрибутов, их тег должен иметь id.

    12.4. Родственные AOM и XPCOM объекты

    Оверлеи и регистр chrome реализованы с помощью следующих свойств XPCOM:

    @mozilla.org/chrome/chrome-registry;1 nsIXULChromeRegistry
    

    Некоторые методы этого интерфейса поддерживают простые операции с системой оверлеев, но они не позволяют программисту управлять системой оверлеев полностью вручную. Использования этого интерфейса требуют весьма редкие задачи. Например, создание инструмента, подобного DOM Inspector или собственной инсталляционной системы.

    Чтобы сохранить атрибут из JavaScript, используйте этот системный вызов:

    document.persist(tagid, attname);
    

    Это сохранит значение атрибута attname тега с id равным tagid.

    12.5. Практика: панель инструментов Notetaker

    В этом коротком разделе "Практика" мы перенесем фрагмент кода NoteTaker, ответственный за панель инструментов, в оверлей, который корректно встроится в окошко браузера Mozilla. Действия, которые следует предпринять, очевидны.

    Найти id, который можно использовать, чтобы встроить панель инструментов NoteTaker в окно классического браузера.

    Найти id, который можно использовать, чтобы встроить меню NoteTaker в окно классического браузера.

    Пересмотреть код панели, чтобы включить пункт меню Tools, подходящие ids и тег <overlay>.

    Отредактировать регистр registry, чтобы внести в него новый оверлей.

    Уничтожить существующую базу данных оверлеев и перезапустить платформу, чтобы посмотреть результат.

    Чтобы определить ids, нам нужно заглянуть в XUL код мастер-документа приложения "классическая Mozilla" (то есть тот документ, который содержит тег <window> для браузера).

    Посмотрим в директорию chrome. Единственный файл, который может, вероятно, содержать код браузера, это comm.jar. "comm" - это аббревиатура слова Communicator. Этот .jar файл содержит большое количество XUL файлов, распределенных по многим поддиректориям, но если мы заглянем в них, то увидим, что многие из них - это <dialog>, <page>, или <overlay> документы. А в файле navigator.xul директории content/navigator содержится многообещающий код:

    <window id="main-window" ... >
    

    Мы можем проверить, не является ли файл navigator.xul стартовой точкой классического браузера, просто загрузив его:

    mozilla -chrome "chrome://navigator/content/navigator.xul"
    

    Если мы так сделаем, то увидим, что действительно обнаружили стартовую точку браузера. Необходимый нам id находится или в этом файле, или в одном из его оверлеев. Мы можем использовать DOM Inspector для исследования финального объединенного XUL документа или просто исследовать код, для чего нужно знать полный список всех оверлеев документа. Чтобы получить список, объедините:

    • Оверлеи, объявленные в файле navigator.xul тегом <?xul-overlay?>
    • Оверлеи, объявленные для chrome://navigator/content/navigator.xul в файле chrome/overlayinfo/navigator/contents/overlays.rdf

    Повторите оба пункта для всех оверлеев, обнаруженных на первом и втором шаге.

    В нашем случае это все необязательно, поскольку подходящий id обнаруживается в самом файле navigator.xul.

    Для панели инструментов NoteTaker мы находим:

    <toolbox id="navigator-toolbox" class="toolbox-top" 
    deferattached="true">
    

    Для меню NoteTaker:

    <menu id="tasksMenu"> <menupopup id="taskPopup">
    

    Тег <menupopup> - подходящее место для добавочного пункта меню. Это может быть и не идеальное место, но здесь мы хотим найти что-нибудь более или менее подходящее.

    Заглянув в код нашей панели инструментов, мы видим, что сливать нужно тег <commandset>. Для него мы находим в navigator.xul строку <commandset id="commands">

    Содержание тега <script> выполняется непосредственно после и не нуждается в слиянии с мастером.

    Мы переименовываем toolbar.xul в browserOverlay.xul для соответствия соглашениям об именовании файлов, и изменяем его содержание. В листинге 12.12 приведено его новое содержание.

    <?xml version="1.0"?> 
    <!DOCTYPE overlay> 
    <overlay xmlns="http://www.mozilla.org/keymaster/
    gatekeeper/there.is.only.xul"> 
    <script src="controllers.js"/> 
    <script src="toolbar_action.js"/> 
      <commandset id="commands"> 
        ... existingcommands go here ... 
      </commandset> 
      <menupopup id="taskPopup">
        <menuitem label="Edit Note" command="
          notetaker.toolbar.command.edit"/>
      </menupopup> 
      <toolbox id="navigator-toolbox"> 
        <toolbar id="notetaker-toolbar"> 
          ... existing toolbar content goes here ...
        </toolbar> 
      </toolbox> 
    </overlay>
    
    Листинг 12.12. Структура оверлея для панели инструментов NoteTaker

    Если мы используем стиль оверлеев снизу-вверх, то нам не нужно модифицировать код классического браузера. Мы сделаем это именно таким образом. Все, что нам остается сделать, это зарегистрировать RDF- документ в регистре chrome, используя файл chrome://navigator/content/contents.rdf file. В главе 2, "Верстка XUL" был создан файл contents.rdf. Его содержание приведено в листинге 12.13.

    <?xml version="1.0"?> 
    <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:chrome="http://www.mozilla.org/rdf/chrome#"> 
    <Seq about="urn:mozilla:package:root"> 
      <li resource="urn:mozilla:package:notetaker"/> </Seq> 
    <Description about="urn:mozilla:package:notetaker" 
      chrome:displayName="NoteTaker"
      chrome:author="Nigel McFarlane" 
      chrome:name="notetaker">
    </Description> 
    </RDF>
    
    Листинг 12.13. Регистрационный фал chrome для пакета без оверлеев.

    Мастер-документ с содержанием, добавленным из оверлеев

    Рис. 12.4.  Мастер-документ с содержанием, добавленным из оверлеев

    В этом файле сказано, что приложение NoteTaker существует. Теперь мы должны добавить туда сообщение, что URL оверлея и целевой URL также существуют. Целевой URL - это документ, к которому оверлей будет присоединен. Эти добавочные сообщения приведены в листинге 12.14.

    <!-- State the document that receives the overlay --> 
    <Seq about="urn:mozilla:overlays"> 
      <li resource="chrome://navigator/content/navigator.xul"/> 
    </Seq> 
    <!-- state the overlay that applies to the target --> 
    <Seq about="chrome://navigator/content/navigator.xul">
      <li>chrome://notetaker/content/browserOverlay.xul</li> 
    </Seq>
    
    Листинг 12.14. Регистрация единственного оверлея

    В далеком прошлом имена оверлеев были строками, а не URL. Поэтому последний <li> тег не использует форму resource= attribute. Это верно вплоть до версии 1.4.

    После того, как все изменения будут сделаны, классический браузер будет выглядеть как на рисунке 12.4. Чтобы увидеть эти изменения, мы должны остановить платформу, удалить существующий файл chrome.rdf и директорию overlayinfo и затем рестартовать платформу.

    На этом заканчивается раздел "Практика" данной главе.

    12.6. Отладка: оверлеи - советы и подсказки

    Оверлеи просты и не требуют сложного процесса отладки, но есть пара "ухабов", которые лучше объехать.

    Самое узкое место с оверлеями находится в файле contents.rdf, расположенном в директории contents каждого пакета. Когда мы записываем URl оверлея, его нужно описать как чистый XML, а не URI. Следующее неверно:

    <li resource="chrome://package/content/overlay.xul"/>
    

    Следует писать так:

    <li>chrome://package/content/overlay.xul</li>
    

    Если документ сам является мастером (то есть сам включает оверлеи), то он должен быть описан как атрибут resource при регистрации его мастер-документом. А когда его регистрируют как оверлей, его нужно описать как XML. Эта нелогичность - дефект системы chrome.

    Если в оверлее содержится синтаксическая ошибка в XML, и он зарегистрирован в базе данных оверлеев, любое приложение, включающее этот оверлей, может и не загрузиться. Начиная с версии 1.3 ошибочный оверлей даст сообщение желтого цвета внизу финального документа. Чтобы это поправить, нужно остановить платформу и удалить RDF информацию об этом файле или поправить его синтаксис. Чтобы удалить информацию об оверлее, удалите базу данных оверлеев целиком и и все упоминания проблемного документа в файле contents.rdf.

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

    12.7. Итоги

    Система оверлеев Mozilla дает программисту крупно- или, в крайнем случае, средне-блочную технологию для работы. Это компонентная технология годится для основанных на XML GUI-систем, однако сама Mozilla работает не с XML, а с XUL. Оверлеи могут быть добавлены прямо в XUL-содержание. Но можно использовать свойства платформы, чтобы включать оверлеи не вручную, но автоматически.

    Оверлеи, регистр chrome и сохраняемые данные используют RDF пассивно. RDF-файлы записываются автоматически, программисту не нужно даже пытаться их генерировать. Это не лучший повод убедиться в мощи RDF для приложений. В следующей главе мы вернемся к XUL, чтобы изучить два могущественных тега, <listbox> и <tree>. Кроме того, что они сами по себе необходимы, они продвинут нас еще на один шаг вперед к полноценному программированию RDF.


    об авторе

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





    Сайт создан в системе uCoz