Россия, Звенигород |
XBL-связки
15.3. Комбинируя несколько связок
Система наследования XBL была рассмотрена ранее в разделе "Объектоподобные свойства связок" ранее в этой лекции. Здесь мы рассмотрим ее использование. Только создатель связки может использовать наследуемые связки.
15.3.1. Простое наследование с extends=
Листинг 15.13 показывает связки, связанные наследованием.
<!-- both bindings contained in example.xml --> <binding id="smileyA"> <content> <xul:image src="faceA.png"/> </content> <implementation> <method name="methodA"> <body> return true; </body> </method> </implementation> </binding> <binding id="smileyB" extends="example.xml#smileyA"> <content> <xul:image src="faceB.png"/> </content> <implementation> <method name="methodB"> <body> return false; </body> </method> </implementation> </binding>Листинг 15.13. Простейший пример наследования связки.
В таблице 15.2 описывается, как наследуются различные части связки.
Если связка smileyA соединяется с XUL-тегом, этот тег будет иметь в качестве контента лишь тег <image src="faceA.png">, и один метод, methodA(). В этом случае цепочка наследования граничного тега имеет длину 1 и содержит лишь связку smileyA. Здесь нет наследования, и smileyA - первичная связка.
Если с XUL-тегом связывается smileyB, то этот тег будет иметь в качестве контента единственный тег <image src="faceB.png">, и два метода, methodA() и methodB(). В этом случае цепочка наследования граничного тега имеет длину 1 и содержит связку smileyB в начале и связку smileyA в хвосте цепочки. В этом случае наследование есть, и smileyB - первичная связка.
Обе связки можно применять к разным тегам в одно и то же время.
Невозможно сказать, наследуется ли данная связка, поскольку ее URL может быть использован откуда угодно. Если связка расположена в chrome, то аудит всего его кода укажет все случаи использования ее из chrome. Но даже в этом случае приложения, инсталлированные вне chrome, могут наследовать связку из chrome и не будут обнаружены.
15.3.2. Связки без контента
Популярный прием, часто используемый в Mozilla - использовать логику набора связок в связке без содержания. Такая связка не имеет секций <resources> или <content>, и никогда (или редко) непосредственно связывается с тегом. Она содержит главным образом программную логику и информацию о состоянии.
Если другая связка использует данную как основу, методы и обработчики связки с нулевым контентом будут присоединены к расширяемой связке во время выполнения. Связку с нулевым контентом можно использовать много раз с разными целями. В терминах объектно- ориентированного программирования, связка с нулевым содержанием может быть названа "базовый класс с виртуальным содержанием".
Примером такой связки с нулевым контентом может быть связка button-base в файле button.xml архива toolkit.jar в the chrome. Она содержит:
properties: accessible type dlgType group open checked check- State autoCheck handlers: event="command"
Эти свойства и события отвечают за управление рядом состояний, используемых кнопкоподобными виджетами. Например, свойство checked имеет скриптовые логики <setter> и <getter>, которые позволяют граничному тегу иметь <checkbox> или <radio> -подобные состояния. Эти логики выполняют домашнюю работу в граничном теге, устанавливая атрибуты XML и координируя состояние checked с другими возможными атрибутами.
Логика в такой связке наследуется многими другими связками. Эти связки, в свою очередь, наследуются многими тегами XUL: всеми разновидностями <button>, всеми вариантами <toolbarbutton>, <thumb>, <dropmarker>, <radio>, <menu>, кнопками в <wizard> и <dialog> -подобными окнами и т.д. Ясно, что связка button-base используется очень широко.
Теги, основанные на связках с нулевым контентом, позволяют избежать ненужного удвоения кода. Когда некоторый тег использует такую связку, он должен иметь секцию <content>.
15.3.3. Связки, обеспечивающие ввод данных
Можно создать связку XBL для обработки пользовательского ввода. Такая связка имеет большую секцию <handlers> и понемногу всего остального, хотя может иметь также методы и свойства.
Такие связки называются "фасадом ввода" по двум причинам. Во-первых, они создают слой обработки событий и пользовательского ввода в форме набора обработчиков. Это похоже на прилавок магазина. Во вторых, они полагаются на некие иные связки для обеспечения требуемого виджет-специфичного поведения. Это "тонкие" связки, а фасад - тонкая вещь. Вот простейший пример "фасада ввода":
<binding id="click-facade" extends="bindings.xml#base-widget"> <handlers> <handler event="click"> this.click(); </handler> </handlers> </binding>
Эта простая связка возводит фасад ввода между вводом единичного клика и виджетом. Она не обрабатывает метод click() - эта задача остается для некоторой иной связки. Данный метод может быть стандартным (в этом случае его обеспечивает связка base-widget ), или высокоспециализированным (в этом случае его обеспечит связка, расширяющая связку click-facade ).
Код обработчика в этой связке может быть и посложнее. Может потребоваться управлять состоянием, включающим и выключающим определенный тип ввода, в зависимости от истории ввода. Фасад ввода - это еще одно место, где можно разместить функциональность обработки пользовательского ввода.
Так же, как и связка с нулевым содержанием, связки фасада ввода редко непосредственно связываются прямо с тегом. Их главная цель - извлечение из набора связок общей семантики пользовательского ввода и сохранение этой семантики в одном месте. Отсутствие секции <content> подразумевает, что она должна быть расширена (наследоваться) перед использованием.
В Платформе Mozilla (до версии 1.4) нет фасадов ввода, но есть простор для их применения. Если вы заглянете в связки XBL для тегов <tree>, <listbox>, <tabbox> и HTML <select>, то увидите одинаковое поведение при обработке клавиатурного ввода во всех этих связках. Это подмножество кода может быть объединено в фасадах ввода и затем использоваться в любом виджете, обеспечивая однотипное поведение.
Mozilla сейчас имеет одну разновидность фасадов ввода. Это документы XUL, содержащие набор связок <key>. Эти документы включаются в большинство приложений Mozilla через оверлеи. Так же как фасады ввода XBL характерны для связок XBL, фасады ввода XUL в форме наборов связок <key> характерны для документов XUL.
15.3.4. Связки внутреннего контента
Название этой лекции предполагает, что связки используются для создания законченного виджета, и это конечно так. Но возможны связки для реализации лишь части виджета. Такие связки называются связками внутреннего контента.
Связки внутреннего контента создавать просто. Нужно сделать некоторые предположения о родительском теге граничного тега такой связки. Мы предполагаем, что граничный тег будет предоставлять контент своему родительскому тегу, который должен являться контейнером. Контейнер отвечает за границы виджета. Связка внутреннего контента полагается на то, что родительский тег будет работать корректно. В XUL очевидными контейнерами являются <box>, <button>, <menupopup>, <scrollbar> и <toolbar>.
Связки внутреннего контента зависят от родительского тега граничного тега и тесно связаны с ним. Такая связка может предоставлять методы и свойства, ожидаемые родительским тегом, либо иную информацию. Эта тесная связка подразумевает, что связка сама по себе будет выглядеть неважно. А вызванная из соответствующего контейнера, она будет отлично ему соответствовать.
В XUL несколько связок следуют этой философии. Например, теги, используемые внутри тега <scrollbar>: <thumb>, <slider> и <scrollbarbutton>. Не все эти теги имеют XBL-связки, но все они полагаются на родительский тег для корректного функционирования. Примеры тегов с XBL связками: тег <dropmarker> внутри тега <button> и <tabs> внутри <tabbox>.
15.4. Как протекает процесс связывания
Когда связка привязывается к тегу в целевом документе, она проходит следующий путь:
- При загрузке целевого документа верстальная машина Mozilla обнаруживает необходимость связки, заметив стиль -moz-binding у некоторого загружаемого тега.
- У каждого документа есть список еще не выполненных шагов. Этот список увеличивается на единицу. Пока список дел не выполнен, в целевом документе не возникнет событие onload.
- Если полная законченная копия связки еще не существует для целевого документа, выполняются шаги 4-7. Если существует, процесс продолжается с пункта 8.
- XBL документ, описывающий связку, извлекается и заносится в кэш Mozilla. Это делается параллельно с загрузкой целевого документа.
- Извлеченный XBL документ парсится и компилируется во внутреннюю структуру данных.
- Если присутствует атрибут extends, шаги 2-7 повторяются (параллельно) для каждой связки в цепочке наследования. Так что какая-то другая связка может достичь шага 7 до первичной связки.
- Скомпилированная связка добавляется в менеджер связок документа. Это XPCOM-компонент, содержащий список всех связок документа.
- Теперь доступна, то есть загружена и скомпилирована, вся цепочка наследования. Целевой тег документа теперь связан со связкой - по крайней мере, в форме внутреннего указателя в Mozilla. До этого шага скрипт, инспектирующий граничный тег, связки не обнаружит. После этого шага скрипт тоже не сможет инспектировать граничный тег, пока не будут выполнены все оставшиеся шаги. Потому что оставшиеся шаги займут единственную нитку вычислений в Mozilla, пока все они не будут выполнены.
- Атрибуты тега <content> копируются в граничный тег.
- Эксплицитный и анонимный контенты сливаются, а результат копируется в граничный тег с помощью операций DOM.
- Обработчики <handler> устанавливаются в граничном теге с помощью менеджера связывания.
- Свойства <property> и <method> добавляются DOM-объекту граничного тега.
- Запускается каждый код <constructor> в цепочке наследования.
- Если, как результат этих шагов, возникают некоторые изменения в стилевых таблицах, они выполняются как последний шаг.
- Список намеченных к выполнению перед запуском события onload задач уменьшается на единицу.