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

    В этой главе описывается большая часть XUL-тегов, использующихся для ввода данных. Также здесь будет рассказано, как отправлять содержимое форм в Internet. Об элементах управления и тегах, связанных с перемещением пользователя по документам, речь пойдет в главе 8, "Навигация".

    Лучший способ помочь пользователям при вводе данных - давать им подсказки и обеспечивать обратную связь. Бумажные документы, оформленные для этого особым образом, называются формами. В главе 4, "Первые элементы управления и темы", подробно рассматривались кнопки. В этой главе будут описаны другие основные элементы управления для создания форм, необходимые наряду с кнопками: меню, флажки, текстовые поля и т.д. Каждый из этих элементов управления плюс элементы управления меню является совершенно новым элементом или новой их группой.

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

    Формы и меню подчиняются тем же ограничениям, что и тег <button>: чтобы их признали как формы (или меню), они должны выглядеть похожими на формы (меню). Следовательно, информация о стиле играет важную роль для этих элементов управления. Иллюстрация в начале главы также подчеркивает важность XBL-определений (связок). Теги форм и меню обычно активно используются в скриптах, и программисту нужны XBL- определения для этих тегов, чтобы знать, какие свойства и методы доступны.

    Наконец, иллюстрация показывает, что в реализации форм участвуют некоторые XPCOM-компоненты. Отправка заполненной формы на сервер - классическое применение технологии Mozilla и первый пример использования платформы как клиентского программного обеспечения по отношению к какому-либо серверу.

    HTML-теги форм широко распространены. XUL-формы похожи на HTML- формы, поэтому мы начнем с краткого сравнениях обоих вариантов. Затем мы рассмотрим все XUL-теги, из которых составляются формы.

    7.1. Сравнение XUL- и HTML-форм

    В HTML/XHTML есть тег <FORM>. Этот тег объединяет теги <BUTTON>, <SELECT>, <INPUT> и <TEXTAREA> в одну группу. У DOM-объекта, соответствующего <FORM>, есть методы, составляющие значения полей формы в HTTP-запрос GET или POST. Это автоматизация процесса постоянного сбора данных формы путем их отправки на какой-либо web-сервер. В результате web-приложения на основе HTML теперь распространены повсеместно.

    В XUL нет эквивалента тегу <FORM>. Эквивалентные элементы управления форм в XUL не объединяются в группы (за исключением группы <radiogroup>). В XUL нет аналога <INPUT TYPE="reset"> или <INPUT TYPE="submit"> и нет полуавтоматического процесса отправки данных формы. Если пользователю дан один лишь только XUL-документ, при вводе информации ничего не произойдет.

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

    С другой стороны, элементы управления XUL-форм более разнообразны, чем в HTML. Теги <button>, <textbox> и <menu> более гибки, чем их HTML-аналоги. Кроме того, в XUL существует множество более функциональных тегов вроде <menubar>, <listbox> и <tree>, гораздо более сложных, чем то, что может предложить HTML. Эти дополнительные теги рассматриваются в более поздних главах.

    В таблице 7.1 перечислены XUL-теги, наиболее похожие на HTML-теги форм и меню.

    Таблица 7.1. Сравнение HTML- и XUL-тегов форм и меню

    HTML-тегXUL-тегПримечания
    <FORM>нетИспользуйте объект XMLHttpRequest
    <BUTTON><button>
    <INPUT TYPE="button"><button>
    <INPUT TYPE="text"><textbox>
    <INPUT TYPE="radio"><radio>Или <button type="radio">
    <INPUT TYPE="checkbox"><checkbox>Или <button type="checkbox">
    <INPUT TYPE="password"><textbox type="password">
    <INPUT TYPE="submit">нетИспользуйте <button> и скрипт
    <INPUT TYPE="reset">нетИспользуйте <button> и скрипт
    <INPUT TYPE="file">нетИспользуйте объект FilePicker
    <INPUT TYPE="hidden">нетИспользуйте обычную переменную JavaScript
    <INPUT TYPE="image"><button>В любом случае для отправки формы используйте скрипт
    <SELECT><menulist> или <listbox>
    <OPTGROUP>нетВместо этого используйте <menuseparator>
    <OPTION><menuitem>
    <TEXTAREA><textbox multiline="true">Поддерживает атрибуты rows и cols
    <LABEL><label>См. обзор альтернативных возможностей доступа
    <FIELDSET><groupbox>
    <LEGEND><caption>
    <INPUT TYPE="radio" NAME=><radiogroup>

    7.2. Где найти информацию о меню

    Формы и меню в приложениях с графическим интерфейсом обычно появляются вместе. Поддержка меню в XUL почти так же разнообразна, как поддержка кнопок. В отличие от обзора кнопок в главе 4, "Первые элементы управления и темы", меню описываются в разных частях книги. Краткое сравнение всех типов меню представлено в разделе "Варианты меню" текущей главы. Или же можно руководствоваться в поиске следующим списком:

    • в этой главе описываются выпадающие меню как элементы управления форм. Эти элементы управления основываются на теге <menulist>, который строится из <menupopup>, <menuitem> и других тегов, также описанных здесь;
    • кнопки, похожие на меню, описываются в главе 4, "Первые элементы управления и темы";
    • невыпадающие меню появляются в документе как обычный многострочный список. В XUL и HTML такие меню называются окнами списка. XUL-тег <listbox> описывается в главе 13, "Списки и деревья";
    • меню, открывающиеся на панелях меню и представленные тегом <menu>, описываются в главе 8, "Навигация". Но в этой главе рассказано об использовании <menu> для создания подменю;
    • контекстные меню, создаваемые тегом <menupopup>, описываются в главе 10, "Окна и панели".

    Единственное существенное различие между меню в XUL заключается в разнице между <listbox> и <menulist>. Первый из них гораздо сложнее. Все остальные упомянутые теги - вариации на тему <menulist>. Все выпадающие меню реализуются с помощью тега <menupopup>.

    7.3. Формы

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

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

    В этой главе мы обсудим простейшие XUL-теги для создания форм. Набор основных тегов таков:

    <button> <checkbox> <radio> <radiogroup> <textbox> <label>
    

    7.3.1. Общие представления о формах

    Любой графический элемент формы называется элементом управления формы ("form control" в терминологии Microsoft) или просто элементом формы ("form element" - термин, изначально появившийся в графическом дизайне и заимствованный оттуда Netscape и W3C). Такие элементы могут взаимодействовать с пользователем самыми разными способами, но все они объединяются общим дизайном.

    7.3.1.1. Навигация

    Если пользователю нужно что-то ввести в форму, самый простой подход - взаимодействие в каждый момент только с одним элементом формы. И в XUL, и в HTML разрешается выделять один элемент управления за раз. Кроме того, интерактивные элементы форм в документе упорядочиваются. В терминах W3C это называется порядком переходов. В Mozilla упорядоченный набор таких элементов управления называется кольцом фокуса, так как, перейдя от последнего в наборе элемента далее, пользователь попадает снова на первый элемент. Все элементы форм входят в кольцо фокуса.

    Более подробно изменение фокуса рассматривается в главе 8, "Навигация".

    7.3.1.2. Общие свойства элементов XUL-форм

    В процессе разработки стандарта CSS 3 консорциум W3C создал черновой документ "User Interface for CSS 3" ("Пользовательский интерфейс для CSS 3"). Хотя этот документ появился уже достаточно давно, он все еще доступен по адресу www.w3.org/TR/1999/WD-css3-userint-19990916. Этот документ - ранняя попытка описания новых функций, которые должны будут поддерживаться в CSS 3. Любопытное совпадение: эта часть стандарта 1) больше всего похожа на некоторые разработки Microsoft's .NET; 2) вероятно, дольше всего будет оставаться незавершенной.

    Mozilla реализует множество положений этого черновика стандарта. В частности, она воплощает четыре свойства стиля, представляющие интерактивные возможности простых элементов XUL-форм. Эти стили в Mozilla реализуются интерфейсом nsINSDOMCSS2Properties. В системе стилей они доступны как расширения с префиксом -moz. Вот они:

    user-input user-modify user-select user-focus
    

    Эти свойства стиля в некотором смысле не зависят друг от друга и они очень важны, так как облегчают понимание системы ввода данных пользователем. Достичь этого понимания раньше было сложно, так как результаты применения обработчиков событий наподобие onclick и DOM-методов вроде focus() обычно зависят от нескольких из этих четырех состояний сразу. Теперь, когда эти состояния обозначены отдельно друг от друга, легче понять, какой эффект произведут обработчики элементов формы. Вы можете взять набор из этих четырех состояний и события и написать новые состояния, которые появятся, если определенный элемент формы с такими состояниями получит данное событие.

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

    Активные и неактивные элементы управления формой

    Рис. 7.1.  Активные и неактивные элементы управления формой

    Наконец, у всех простых элементов формы есть общий набор обработчиков событий и соответствующих объектных методов для интерактивных событий вроде получения и потери фокуса.

    7.3.1.3. Доступность для разных пользователей

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

    Во всех обсуждениях до этого момента XUL-тег <label> был идентичным тегу <description> во всем, за исключением возможности сведения к атрибуту label. Но если взглянуть с точки зрения доступности, сразу будут видны отличия <label> от <description>. Тег <label> позволяет предоставлять альтернативное содержимое, необходимое для создания системы доступности.

    Если у элемента формы есть атрибут label, Mozilla предоставит его значение как вспомогательную информацию, которую система доступности передает пользователю. Если у элемента формы нет такого атрибута, Mozilla будет искать его тег-потомок <label> и использует его. Если подходящего потомка не найдется, она будет искать тег <label>, чье значение атрибута control совпадает с идентификатором, заявленным в атрибуте id тега элемента формы. Если и такой тег не найден, тогда вспомогательная информация недоступна.

    Поддержка расширенной доступности в Mozilla предусмотрена для всех простых элементов XUL-форм. Эта поддержка есть и для тегов <menuitem>, <menulist> и <tab>.

    Как работает такая доступность, подробнее рассматривается в главе 8, "Навигация".

    7.3.2. Простые теги XUL-форм

    На рисунке 7.2 показаны простые теги форм с примененными к ним дополнительными стилями, так что их структура становится понятнее. Пунктирные линии означают теги <label>, толстые сплошные - теги <box>, а тонкие сплошные - теги <image>. Два средних раздела - теги <radiogroup>, второй из которых содержит теги <button type="radio">.

    Простые элементы XUL-форм с открытой внутренней структурой

    Рис. 7.2.  Простые элементы XUL-форм с открытой внутренней структурой

    Из рисунка 7.2 видно, что все простые теги форм содержат, по крайней мере, один другой тег, даже если этот тег - <image> без содержимого. Все эти теги форм определены в XBL.

    В Mozilla есть специальные обработчики событий, написанные на C/C++. Они добавляются к объекту XUL-документа с помощью C/C++-версии addEventListener(). Такие обработчики событий перехватывают информацию, связанную с простыми элементами управления. Так реализуется недоступная через XBL функциональность элементов форм. Простого способа взаимодействовать с этими встроенными обработчиками из JavaScript нет, но это и не нужно.

    У таких тегов есть DOM-интерфейсы, очень похожие на соответствующие HTML-интерфейсы. Все имена XPCOM-интерфейсов начинаются с префикса nsIDOMXUL.

    7.3.2.1. Тег <button>

    Тег <button> широко обсуждается в главе 4, "Первые элементы управления и темы". Вспомните, что атрибут type позволяет превращать кнопку в флажок, переключатель или кнопку раскрытия меню.

    7.3.2.2. Тег <checkbox>

    Тег <checkbox> составляется из простых содержательных XUL- тегов. У него есть XBL-определение. Изображения флажков, появляющиеся при отображении этого элемента управления, составляются из обычных картинок. С помощью стилей можно сделать их больше или меньше или даже заменить их. У <checkbox> есть следующие собственные атрибуты:

    src label crop checked disabled accesskey
    

    src передается необязательному изображению, которое появляется между флажком и текстом. crop передается <label>, содержащему текст. checked принимает булевы значения, соответствующие состояниям <checkbox>, а disabled, если его значение - true, делает флажок полностью недоступным пользователю. Сопроводительный текст может появиться справа от флажка, если указан атрибут dir="rtl". Состояние каждого флажка не зависит от состояний других флажков. Если щелкнуть по тексту (<label>) флажка, эффект будет тот же, что и при щелчке по пиктограмме самого флажка.

    С помощью системы команд, описанной в главе 9, "Команды", тег <checkbox> отправляет событие CheckboxStateChange при смене состояния. За этим состоянием, если нужно, может наблюдать код приложения.

    7.3.2.3. Тег <radio>

    Тег <radio> составляется из простых XUL-тегов. У него есть XBL-определение. Пиктограммы переключателей - обычные изображения, и с помощью стилей их можно увеличить, уменьшить или заменить другими. У тега <radio> есть следующие собственные атрибуты:

    src label crop selected disabled accesskey
    

    Эти атрибуты имеют то же значение, что и для тега <checkbox>, только checked заменяется атрибутом selected. Если тег <radio> является потомком <radiogroup>, только у одного переключателя из группы может быть атрибут selected="true". У нижнего тега <radio> в первой группе переключателей на рисунке 7.2 задан атрибут dir="rtl". Для выбора переключателя можно щелкать и по тексту (<label>), и по его пиктограмме.

    До недавних версий Mozilla тег <radio> не всегда правильно определял, когда он должен получать фокус. Чтобы прояснить ситуацию с <radio> в конкретной версии Mozilla, нужно обратиться к ее базе данных ошибок.

    7.3.2.4. Тег <radiogroup>

    Тег <radiogroup> связывает набор тегов <radio> или <button type="radio"> вместе и превращает в единое целое. Если любой переключатель в такой группе выбран, все остальные теряют выделение. Тег <radiogroup> поддерживает следующие атрибуты:

    disabled selectedItem focusedItem selectedIndex
    

    disabled делает недоступной для пользователя всю группу. selectedItem и focusedItem сообщают, какой переключатель в группе выбран или получил фокус, соответственно. selectedIndex содержит номер текущего выбранного переключателя в группе, начиная с 0.

    С помощью системы команд, описанной в главе 9, "Команды", тег <radio> отправляет события RadioStateChange и selected при смене состояния. За этими событиями, если нужно, может наблюдать код приложения.

    7.3.2.5. Тег <textbox>

    Тег <textbox> позволяет пользователю вводить текст. Это четыре тега в одном: обычное поле ввода, поле ввода пароля, многострочное поле ввода и поле ввода с автодополнением. У <textbox> есть XBL-определение. Тег <textbox> реализуется с помощью HTML-тегов <input type="text"> или <textarea>. У стандартного тега <textbox> есть следующие особые атрибуты:

    value disabled readonly type maxlength size multiline
    

    Все эти атрибуты, кроме multiline и type, соответствуют атрибутам HTML-тега <input type="text">. Значением multiline может быть true, а значением type - password или autocomplete. Если type="password", <textbox> действует так, как HTML-тег <input type="password">; однако иначе и быть не может - они одинаковы. Если значение multiline - true, у <textbox> появляется другой набор атрибутов:

    value disabled readonly rows cols wrap
    

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

    Для всех этих трех вариантов текстового поля начальное значение может быть задано, только если поле не многострочное. В случае многострочных полей начальное значение задается из JavaScript с помощью свойства value соответствующего объекта. Вот пример для тега <textbox id="txt"/>:

    document.getElementById("txt").value = "initial text";
    

    Четвертый вариант <textbox> имеет место, когда значением type является autocomplete. Это сложный тег с большой долей зависящей от приложения функциональности. После тщательного тестирования мы не рекомендуем использовать тег <textbox type= "autocomplete"> как основной инструмент в своих приложениях. Дело в том, что данный тег применим еще далеко не во всех случаях.

    Где этот тег на высоте, так это в классическом браузере. Простого объявления вроде приведенного ниже достаточно для предоставления быстрого доступа к журналу посещений браузера, мини-базам данных адресов электронной почты или адресов LDAP:

    <textbox type="autocomplete" searchSessions="addrbook"/>
    

    Так как ни одна из этих баз данных не может быть доступна как отдельное приложение, применение <textbox> довольно ограничено. Однако можно применять его к любой мини-базе данных, даже такой простой, как массив значений в JavaScript. Делая это, вы обрекаете себя на борьбу с интерфейсом, который еще не до конца стабилен или вообще не предназначался для повторного использования. Затратив примерно день, вы можете проанализировать XBL-определение autocomplete.xml для этого тега и найти какие-то обходные пути, подходящие вашим данным. Это может быть одноразовое решение, но можно и создать собственное XBL-определение с нуля, если вы задумали серьезное приложение.

    7.3.3. Отправка форм

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

    7.3.3.1. Отправка данных XUL-форм с помощью HTML

    Первый метод отправки данных XUL-формы, очень быстрый и не самый аккуратный, подразумевает использование пространств имен XML. Можно создать документ, который начинается с XUL, но включает все функции HTML. В листинге 7.1 показан такой документ.

    <?xml version="1.0"?> 
    <!DOCTYPE window> 
    <window xmlns="http://www.mozilla.org/keymaster/
     gatekeeper/there.is.only.xul" 
      xmlns:html="http://www.w3.org/1999/xhtml"> 
      <vbox> 
    <script> 
      function copy() { 
        var getID = document.getElementByID; 
        getID("h1").value = getID("x1").value; 
        getID("h2").value = getID("x2").value; 
        return true; 
    } 
    </script> 
    <html:form action="test.cgi" method="GET" 
      enctype="application/x-www-form-urlencoded"> 
    <html:input id="h1" type="hidden"/> 
    <html:input id="h2" type="hidden"/> 
    <radiogroup> 
      <button id="x1" label="Кнопка 1" type="radio"/> 
      <button id="x2" label="Кнопка 2" type="radio"/> 
    </radiogroup> 
    <html:input type="submit" onsubmit="return copy();"> 
    </html:form> 
    </vbox> 
    </window>
    
    Листинг 7.1. Смесь HTML- и XUL-форм

    Этот документ отображает форму, состоящую из двух XUL-кнопок и одной XHTML-кнопки для отправки данных. В обычном XHTML нельзя поместить кнопки в группу переключателей, но здесь это допустимо, так как Mozilla поддерживает сочетание XUL и HTML. XHTML-элементы формы связываются с процессом отправки данных формы, но XUL-элементы - нет. Простая функция на JavaScript копирует необходимые данные в скрытые поля перед отправкой информации.

    Можно создать действительный документ из XHTML+XUL, не прибегая к пространствам имен xmlns. Для этого нужно начать с "чистого" XHTML-документа (или XUL-документа) и добавить DTD-сущности для XUL- приложения (или XHTML-приложения) в объявление <!DOCTYPE>. Такой документ не использует особый механизм xmlns, с помощью которого Mozilla определяет тип документа. Это значит, что для таких дополнительных тегов не будет использоваться никакая дополнительная обработка (поддержка). Это отсутствие определения типов - причина того, что добавление тега <A> в XUL-документ не приводит к созданию XHTML-ссылки.

    7.3.3.2. Объект XMLHttpRequest

    Во второй методике отправки данных XUL-формы используется объект XMLHttpRequest. Это доступный из скриптов AOM-объект, применимый во всех XML-документах, как, например, объект Image в HTML-документах. Он позволяет отправлять HTTP-запросы напрямую из JavaScript. Ответ сервера на такой запрос не замещает текущий отображаемый документ. Такой ответный документ просто читается как одна большая строка. Объект XMLHttpRequest основывается на следующем XPCOM-компоненте:

    @mozilla.org/xmlextras/xmlhttprequest;1
    

    Этот компонент реализует XPCOM-интерфейсы nsIXMLHttpRequest и nsIJSXMLHttpRequest, которые хорошо объясняются в файлах определений. Эти интерфейсы позволяют отправлять HTTP-запросы синхронно и асинхронно. Синхронная отправка означает, что скрипт приостанавливает свою работу, пока не будет получен полный ответ. Асинхронная отправка - аналог самонаводящегося снаряда, только этот запрос можно отслеживать, а конечный результат - забрать. В листинге 7.2 показано, как работают синхронные запросы.

    var req = new XMLHttpRequest(); 
    // Запрос 
    var res = null; 
    // Ответ 
    var params = encodeURI("param1=value1;param2=value2");
    // -- GET-запрос
    req.open("GET", "test.cgi" + "?" + params); 
    req.send(""); 
    if ( req.status / 100 == 2 ) 
    // Ответ HTTP 2xx? 
    res = req.responseText;
    // -- POST-запрос
    req.open("POST", "test.cgi"); 
    req.send(params); 
    if ( req.status / 100 == 2 ) 
    // Ответ HTTP 2xx? 
    res = req.responseText;
    
    Листинг 7.2. Примеры синхронных запросов XMLHttpRequest

    Функция encodeURI() - аналог escape() для ECMAScript; поддерживаются обе. Второй аргумент open() - любой корректный URL. Так как send() не возвращает ничего, пока пара запрос-ответ не будет полной, программист должен предоставить пользователю какой-нибудь индикатор вроде "Ожидается..." сразу перед вызовом send(), чтобы пользователь знал, что приложение продолжает работу, а не просто "зависло".

    Асинхронная отправка данных форм полезна, когда нужно выполнить несколько HTTP-запросов. Более эффективно отправить все запросы за раз, а затем время от времени проверять их состояние. Простейший способ выполнить асинхронную отправку - поместить ее в функцию и запланировать с помощью setTimeout(). В листинге 7.3 показан более формальный и структурированный подход с использованием интерфейса nsIXMLHttpRequest.

    var req = new XMLHttpRequest(); // Запрос var res = null; 
      // Ответ var url = "test.cgi?text1=value1";
    // Часть, специфичная для асинхронных запросов
    function finished() {
      res = req.responseText; 
    } 
    function inprogress() { 
      if ( req.readyState != req.COMPLETED ) { 
        res = "Waiting ..."; 
        setTimeout(inprogress, 100); 
      } 
    } 
    
    req.COMPLETED = 4; 
    // из интерфейса 
    req.onload = finished; 
    
    // -- GET-запрос (POST аналогичен)
    req.open("GET", url, false); 
    // false == асинхронный req.send(); 
    
    // следующая инструкция выполняется немедленно 
    setTimeout(inprogress,100);
    
    Листинг 7.3. Пример асинхронного запроса XMLHttpRequest

    В этом примере метод send() возвращает ? почти сразу, оставляя HTTP-запрос в обработке. Функция finished() создана как обработчик событий, который запускается, когда ответ наконец-то получен полностью. Между этими двумя точками во времени используется setTimeout() для простой регулярной проверки состояния. При использовании таких асинхронных запросов пользователю могут не требоваться уведомления о состоянии. Тем не менее, программист должен позаботиться о том, чтобы последующие действия пользователя не повлияли на обработку ответа, когда он появится. Например, пользователи, покупающие акции, не должны иметь возможность опустошить свои банковские счета во время процесса покупки акций.

    7.4. Меню

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

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

    Для списков в теле документа Mozilla не использует меню. Для этого используется тег <listbox>. XUL-меню применяются только для всплывающих меню. Меню Mozilla следуют правилам дизайна, применимым к простым элементам форм, потому могут считаться своего рода простым элементом форм.

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

    <menulist> <menupopup> <menuitem> <menuseparator> 
    <menu> <button> <toolbarbutton>
    

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

    <dropmarker> <arrowscrollbox> <scrollbox> <autorepeatbutton>
    

    На рисунке 7.3 показана структура полнофункционального, но простого XUL-меню с двумя элементами.

    Полная структура XUL-меню

    Рис. 7.3.  Полная структура XUL-меню

    На этом рисунке показаны два аспекта одного и того же меню. В схеме слева показаны теги, указанные автором приложения. В схеме справа меню состоит из тегов, которые на самом деле создаются XUL/XBL-системой Mozilla. Очевидно, что задействуется много тегов. Система меню спроектирована так, что меню всегда составляется из полного набора данных, но ненужные части скрываются. Например, теги <autorepeatbutton> не показываются, если элементов меню так мало, что они все видны сразу. Второй пример - различные надписи и изображения. У каждого пункта меню может быть пиктограмма и клавиша доступа, а также обычный описательный текст - вместе один тег <image> и два <label>. Эти теги проявляются благодаря атрибутам, предоставленным программистом, или в зависимости от условий отображения меню.

    Сложная структура тегов меню не означает сложной обработки событий. Событие command и его обработчик oncommand - все, что нам нужно для связывания простых меню с логикой работы своего приложения.

    Возможны также различные виды адаптации XUL-меню на уровне тегов. Внутри меню теги <menuitem> можно заменить тегами <menuseparator> или <menu>. Снаружи теги, окружающие <menupopup>, можно переорганизовать, заменив <menulist> на что-то другое.

    7.4.1. Тег <menuitem>

    Тег <menuitem> представляет один пункт меню. У него есть несколько XBL-определений, из которых применяется только одно. Атрибуты этого тега со специальными значениями:

    type disabled image validate src checked label 
     accesskey acceltext crop value
    

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

    Следующий набор атрибутов относится к пиктограмме пункта меню. Если она указана, то по умолчанию появляется слева, но стандартные атрибуты выравнивания содержимого блоков вроде dir могут изменить ситуацию. И image, и src задают URL изображения пиктограммы. В стандартном меню <menulist> текущий выбранный пункт появляется на кнопке меню, если меню не раскрыто. Если используется src, то пиктограмма выбранного пункта меню также появится на кнопке меню. Если заданы и type, и src или image, пиктограмма переключателя или флажка получает больший приоритет, чем пиктограмма самого пункта меню. У validate то же значение, что и в случае тега <image>; у checked смысл тот же, что и в тегах <radio> и <checkbox>.

    Третий набор атрибутов относится к обычному сопроводительному тексту пункта меню. Этот текст может отсутствовать. Текст предоставляется label. accesskey предоставляет клавишу доступа к пункту меню, как описано в главе 8, "Навигация".

    acceltext и crop применимы только к меню, создаваемым с помощью тега <menu>. crop поступает с текстом пункта меню так же, как и в случае <label>. acceltext предоставляет текст справа от текста пункта меню, который сообщает о том, какая комбинация клавиш выбирает этот пункт меню. Такой текст никогда не обрезается. Обычно это просто описание комбинации клавиш, например, "Shift-A". Если acceltext присутствует, отображается его значение. Если он отсутствует, но есть атрибут key, тогда текст берется из соответствующего тега <key>. Этот тег предоставит текст из своего атрибута keytext или, если таковой отсутствует, из атрибута key, или, если и его нет, то из атрибута keycode. Во всех трех случаях текст будет дополнен содержимым атрибута modifiers тега <key>. Это простое напоминание пользователю, что любое нажатие клавиш может соответствовать пункту меню, и обозначение связи между нажатиями и пунктами меню.

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

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

    Примеры разных <menuitem>

    Рис. 7.4.  Примеры разных <menuitem>

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

    7.4.2. Тег <menuseparator>

    Тег <menuseparator> - почти анонимный XUL-тег с некоторыми собственными правилами стилей. Он отображается как горизонтальная линия, визуально разделяющая пункты меню. Множество примеров можно найти в строке меню самой Mozilla. Этот тег находится на одном уровне с <menuitem>. У него нет особых атрибутов, но иногда полезно присваивать ему идентификатор (id).

    Платформа Mozilla определяет этот тег при выполнении операций с меню.

    7.4.3. Теги <arrowscrollbox> и <scrollbox>

    Теги <arrowscrollbox> и <scrollbox> позволяют пользователю перемещаться по содержимому, расположенному в виде прямоугольника, который не помещается на экран целиком. Оба тега обсуждаются в главе 8, "Навигация", но у них есть применения и в меню. В меню оба создаются автоматически.

    Тег <arrowscrollbox> создается для отображения слишком длинного меню, выходящего за пределы экрана. Если меню длинное, автоматически появляются кнопки <autorepeatbutton> - части <arrowscrollbox>. Проще всего увидеть работу этого тега на личной панели Навигатора Mozilla.

    Для этого следует убедиться, что папка закладок находится на личной панели и что в ней много закладок. Закладок и папок должно быть столько, чтобы их список занимал, по крайней мере, половину высоты экрана. Переместите окно Навигатора так, чтобы личная панель по высоте находилась примерно в середине экрана, и нажмите на кнопку закладок (напоминаем, закладок должно быть много). Появится список закладок, вверху и внизу которого будут пиктограммы <arrowscrollbox>. Они также появятся, если задать тегу <menupopup> атрибут maxheight с каким-нибудь маленьким значением, например, 200 пикселов.

    Тег <scrollbox> создает перемещаемую область внутри <arrowscrollbox>. Полосы прокрутки показываются, только если они используются внутри тега <textbox type="autocomplete">. При использовании внутри <arrowscrollbox> у него нет класса стиля и обычно его не стоит трогать.

    Кнопки тега <arrowscrollbox> можно менять с помощью стилей. Они также не могут прокручивать содержимое вбок, только вверх и вниз.

    7.4.4. Тег <menupopup>

    Тег <menupopup> - сердце системы XUL-меню. Он отвечает за создание окна вне нормального потока размещения элементов XUL-документа и может выходить за пределы окна Mozilla. Для этого используется функциональность графической среды. У этого тега хорошая поддержка в С/C++-части Mozilla. Есть у него и XBL-определение.

    Тег <menupopup> универсален. Он создает маленькое окно, действующее как <vbox>, в которое можно поместить простейшее XUL-содержимое. Почему это сделано так, не совсем ясно, но такая особенность позволяет создавать очень красиво оформленные меню. Единственное, что можно выделять в <menupopup> - теги <menuitem> и <menu>. Тег <menupopup> можно указывать и без содержимого вообще. Содержимое может добавляться позднее с помощью JavaScript, шаблонов или других XUL-техник.

    При создании меню автор приложения должен использовать этот тег. Атрибуты, имеющие особое значение в <menupopup>:

    popupanchor popupalign position allowevents onpopupshowing 
    onpopupshown onpopuphiding onpopuphidden
    

    popupanchor задает угол родительского тега, рядом с которым появится <menupopup> - так называемую опорную точку. popupalign определяет угол всплывающего меню, который будет зафиксирован относительно опорной точки. Следовательно, меню будет выравниваться по заданному углу родительского тега. Оба атрибута могут принимать одно из следующих значений:

    topleft topright bottomleft bottomright none
    

    Атрибут position предоставляет использовавшийся ранее и менее гибкий способ выравнивания, и его следует избегать. Он устарел.

    Значением атрибута allowevents может быть true, но обычно этого делать не рекомендуется. В платформе Mozilla производится специальная обработка меню. На рисунке 7.3 показан сложный набор тегов, составляющих меню. Если применять к этому набору полноценную DOM-модель событий, выбор пункта меню приводил бы к созданию множества событий. Платформа Mozilla сводит эти события в одно управляемое событие команды.

    Оставшиеся четыре атрибута - обработчики упоминавшихся ранее DOM- событий. Это парные цели событий. События -showing -shown запускаются в начале и в конце процесса открытия меню соответственно. События -hiding и -hidden запускаются в начале и в конце процесса сворачивания меню соответственно. Процесс отображения проходит три стадии, каждая из которых помечается Mozilla заданием значения true одному из следующих трех временных атрибутов:

    menutobedisplayed menugenerated menuactive
    

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

    7.4.5. Тег <menu>

    Полезное содержимое <menupopup> состоит из трех тегов: <menuitem>, <menuseparator> и <menu>. Тег <menu> очень похож на <menuitem>, но создает новое меню сбоку от уже существующего. Вот особые атрибуты этого тега:

    label accesskey crop acceltext disabled
    

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

    Тег <menu> также используется в строках меню:

    <menulist id="foo" editable="true"/>
    

    7.4.6. Тег <menulist>

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

    Внутри <menulist> может находиться только тег <menupopup>. Особые атрибуты <menulist>:

    src label crop accesskey disabled editable value
    

    Смысл этих атрибутов тот же, что и у соответствующих атрибутов <menuitem>, только disabled делает недоступным все меню целиком. Новый атрибут - editable.

    Название этого атрибута не совсем корректно. Если его значение - true, надпись на кнопке <menulist> заменяется текстовым полем HTML <input type="text">, куда пользователь может ввести строку. Когда фокус переходит с <menulist>, эта строка будет сравниваться с существующими пунктами меню. Если она совпадает с основным текстом какого-нибудь пункта, этот пункт станет выбранным. Все пункты меню обрабатываются так, как если бы у них был атрибут type="checkbox". Атрибут editable не дает возможности вставлять, удалять и обновлять пункты меню.

    7.4.7. Варианты меню

    Тег <menulist> - оболочка для тега <menupopup>. Есть и другие оболочки. Вот их полный список:

    <menulist> <menulist editable="true"> <menu> 
    <button type="menu"> <button type="menu-button> 
    <toolbarbutton type="menu"> <toolbarbutton type="menu-button"> 
    <textbox type="autocomplete"> <menubutton>
    

    Использование любого из этих тегов, кроме <textbox>, подразумевает добавление <menupopup> как единственного их содержимого. <menubutton> - анонимный тег, использующийся для хранения стилей и обработчиков меню, появляющихся на панелях инструментов (см. лекцию 8, "Навигация").

    В MacOS можно добавлять пункт "Настройки..." и нужные подменю в меню приложения. Чтобы это сделать, следует убедиться, что у подходящего тега <menuitem> есть специальный идентификатор id="menu_preferences".

    7.5. Альтернатива: таблицы стилей

    Как и в случае статического содержимого и кнопок, Mozilla дублирует большую часть информации о формах и меню в системе стилей.

    Возможно, самые важные особенности стилей - те правила, которые определяют XBL-связку, относящуюся к данному XUL-тегу. Атрибут type (для <button>, <toolbarbutton> и <textbox>) и атрибут editable (для <menulist>) - все они указываются в правилах стиля. Эти правила определяют для основного XUL-тега конкретную связку, которая в итоге влияет на содержимое тега, его внешний вид и поведение. Изучив XBL, вы сможете добавлять собственные связки и соответствующие правила стилей. Атрибут type затем может предоставить другие варианты элементов управления.

    7.5.1. CSS-стили из HTML-форм

    Некоторые стандартные стили HTML-форм доступны и для XUL-форм. Они перечислены в таблице 7.2. Более подробную информацию о новых стилях можно найти в черновике документа CSS 3: www.w3.org/TR/1999/WDcss3-userint-19990916.

    Таблица 7.2. Расширения стилей для XUL, соответствующие HTML-формам

    Свойство или селекторЗначенияОписание
    :-moz-drag-over(селектор)Любой элемент, над которым мышью перетаскивается объект
    :-moz-selection(селектор)В версии 1.2.1 почти полная поддержка ::selection из CSS 3
    -moz-key-equivalentСм. черновик стандартаЭквивалент key-equivalent из черновика CSS 3
    -moz-outline-radiusТе же, что и для margin, но используйте пикселыЭти атрибуты похожи на атрибут margin, но они определяют скругленность углов границы или контура
    -moz-outline-radius-topleft -moz-outline-radius-topright -moz-outline-radius-bottomleft -moz-outline-radius-bottomrightПикселыСкругленность конкретного угла; 0 означает отсутствие скругления
    -moz-outlineТо же, что и для outlineПочти полная поддержка outline из CSS 2
    -moz-outline-colorТо же, что и для colorПочти полная поддержка outline-color из CSS 2
    -moz-outline-styleТо же, что и для border-styleПочти полная поддержка outline-style из CSS 2
    -moz-outline-widthТо же, что и для border-widthПочти полная поддержка outline-width из CSS 2
    -moz-user-focus См. черновик стандартаЭквивалент user-focus из черновика CSS 3
    -moz-user-inputСм. черновик стандартаЭквивалент user-input из черновика CSS 3
    -moz-user-modifyСм. черновик стандартаЭквивалент user-modify из черновика CSS 3
    -moz-user-selectСм. черновик стандарта плюс -moz-allЭквивалент user-select из черновика CSS 3

    Стили, относящиеся к контурам, до определенной степени соответствуют стилям границ (см. раздел "Альтернатива: таблицы стилей" главе 2, "Проектирование с XUL"). Значения -moz-all для стиля -moz-user-select позволяют быть выбранными нескольким элементам форм. Это полезно, если вы разрабатываете графическую среду разработки для XUL и хотите иметь возможность группировать элементы формы одним действием.

    7.5.2. Собственные типы отображения элементов управления

    Тег <menupopup> основывается на следующем стиле:

    display: -moz-popup
    

    Свойство стиля -moz-appearance заставляет данный тег принимать внешний вид, характерный для графической среды пользователя. Такие типы отображения работают для следующих тегов, описанных в этой главе:

    radio checkbox textfield menulist menulist-button menulist-text 
    menulist-textfield checkbox-container radio-container
    

    7.6. Практика: события и формы в NoteTaker

    После многих лекций, в которых мы закладывали фундамент приложения, у нас наконец-то появились некоторые полезные элементы управления. В этом разделе мы избавимся от некоторых накопившихся в окне NoteTaker несуразностей и заменим их нормальными элементами XUL-форм. Мы избавимся от файла .properties и будем отправлять собранные в форме данные на web-сервер. Если диалог будет появляться в результате HTTP-запроса GET, значения параметров из этого запроса также будут использоваться.

    Прежде всего, займемся наведением порядка. Мы откажемся от атрибута subpanel и функции handle_click(). Если мы еще хотим отключать какое-либо содержимое, имеет смысл делать это теперь собственными средствами тегов. То есть все источники событий и половина действий и описаний клавиш будут выброшены. Задача, которую решает load_data(), все еще актуальна, но текущая реализация нам больше не подходит.

    Наконец, мы избавимся от вспомогательных стилей boxes.css / boxesTemp.css и их тегов <box>. Вместо них у нас будут:

    1. однострочное поле <textbox> для раздела Summary;
    2. многострочное поле <textbox> для раздела Details;
    3. два тега <checkbox> для раздела Options;
    4. четыре небольших поля <textbox> для раздела Size.

    Как показано в листинге 7.4, соответствующие теги очень просты.

    <textbox id="dialog.summary"/> 
    <textbox id="dialog.details multiline="true" flex="1"/>
    <checkbox id="dialog.chop-query" dir="rtl" 
     label="Chop Query" checked="true"/>
    <checkbox id="dialog.home-page" dir="rtl" 
     label="Home Page" checked="true"/> 
    <textbox id="dialog.width" value="100" maxwidth="3" size="3"/> 
    <textbox id="dialog.height" value="90" maxwidth="3" size="3"/> 
    <textbox id="dialog.top" value="80" maxwidth="3" size="3"/> 
    <textbox id="dialog.left" value="70" maxwidth="3" size="3"/>
    
    Листинг 7.4. Новые теги элементов форм для диалога NoteTaker

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

    Диалог на основе форм

    Рис. 7.5.  Диалог на основе форм

    Перед заменой load_data() мы немного поэкспериментируем. DOM-объекты тегов XUL-форм очень похожи на DOM-объекты тегов HTML-форм. Мы можем многое сделать, обратившись к стандарту DOM 2 HTML или XBL-связкам <checkbox> и так далее, либо просто вспоминая разные трюки, использовавшиеся на web-страницах. Заменим этот код в load_data():

    desc = document.createElement("description"); 
    desc.setAttribute("value",value); 
    box = document.getElementById("dialog." + names); 
    box.appendChild(desc);
    

    на этот:

    if (box.value) box.value = value;

    Так как у большинства элементов форм есть свойство value, нам удалось загрузить большую часть файла .properties в форму одним простым действием.

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

    Чтобы сохранить заметку NoteTaker, мы используем уже знакомый по этой главе код, только слегка адаптируем его и поместим в метод action(). Мы также сохраним массив имен (names), который ранее был локальным для load_data(), но сейчас мы сделаем его глобальным. В листинге 7.5 показан новый алгоритм.

    if (task == "save") { 
      var req = new XMLHttpRequest(); // Request 	
      var params = ""; 
      var i = names.length -1; // build up params 	
       while (i>=0) { var widget = document.getElementById
        ("dialog." + names); 	
      if (widget.tagName == "checkbox") 
        params += names + "=" + widget.checked + ";"; 
      else 	
        params += names + "=" + widget.value + ";"; i--;
      }
        params = encodeURI(params); req.open("POST", "test.cgi");
        req.send(params);
      if ( req.status / 100 != 2 ) // HTTP 2xx Response?
      throw("Save attempt failed"); 
    }
    
    Листинг 7.5. Отправка заметки NoteTaker на web-сервер

    Конечно, на web-сервере должен быть test.cgi или его аналог. Если мы запускаем приложение из chrome, test.cgi можно заменить на любой адрес любого сервера.

    NoteTaker работает с классическим браузером, поэтому вряд ли он будет загружаться с удаленного сервера. Тем не менее возможно, что во время создания окна ему будут передаваться какие-то аргументы. Так как программное окружение нашего приложения то же, что и у остального chrome, эти аргументы могут передаваться любым способом. Один простой способ - добавить в конец URL NoteTaker параметры в стиле HTTP-запроса GET. Сейчас предполагается

    chrome://notetaker/content/editDialog.xul
    

    но тот же документ можно загрузить с помощью

    chrome://notetaker/content/editDialog.xul?top=440;left=200
    

    Эта информация далее может быть прочитана с помощью AOM-свойства window.location. Мы сделаем это, создав новую задачу для метода action(), которую назовем load. В отличие от остальных задач, которые как-либо связаны с графическим интерфейсом, эта функция - чистый скрипт. Новый обработчик onload тега <window> будет:

    onload="action('load')"
    

    Код, добавляемый в метод action(), показан в листинге 7.6. Объект window.location - один из немногих AOM-объектов, которые доступны и в HTML-, и в XUL-документах. Он предоставляет объект с помощью интерфейса nsIDOMLocation и полезен в XUL только в описанном случае.

    if (task == "load" ) {
      var pair, widget; 
      params = window.location.toString(); 
    if ( params.indexOf("?") == -1 ) 
      return; 
      params = params.replace(/.*\?/,""); 
      params = params.split(/[;&]/); 
      i = params.length - 1; 
      while (i >=0 ) { 
        pair = params.split(/=/); 
        pair[0] = decodeURI(pair[0]); 
        pair[1] = decodeURI(pair[1]); 
        widget = document.getElementById("dialog."+ pair[0]) 
    if (widget.tagName == "checkbox") 
          widget.checked = ( pair[1] == "true" ); 
    else widget.value = pair[1]; 
        i--; 
      }
    }
    
    Листинг 7.6. Чтение параметров из URL в стиле GET-запроса

    В этом коде используется поддержка регулярных выражений из ECMAScript 1.3. Метод replace() применяется для удаления всех символов до символа ?, с которого начинается строка параметров. split() разделяет оставшуюся строку на массив строк с разделением везде, где происходит совпадение с шаблоном регулярного выражения. В нашем случае совпадение происходит на каждом символе ; или &. Наконец, каждая пара параметр=значение снова разбивается, и ее половинки используются для поиска элемента формы с соответствующим идентификатором. Затем этот элемент обновляется.

    7.7. Отладка: события в формах

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

    7.7.1. Неоткрывающиеся меню

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

    menupopup { display: -moz-box ! important }
    

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

    Пример встраивания содержимого <menupopup> в документ

    Рис. 7.6.  Пример встраивания содержимого <menupopup> в документ

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

    7.7.2. Разбор сложных элементов управления

    Для освоения сложных элементов управления вроде <menulist> могут потребоваться некоторые усилия, особенно если вам не нравится содержимое, внешний вид или поведение по умолчанию. Простейшая стратегия - анализировать данный тег с помощью Инспектора DOM. Этот инструмент раскроет содержимое, идентификаторы и классы стилей данного тега, вам нужно будет только нажать на кнопку. Это так просто, почему бы не поэкспериментировать?

    Другая используемая в этой главе и некоторых других стратегия - применение специальных таблиц стилей. Некоторые из примеров в этой книге дополнены простыми стилями, которые создают визуальные подсказки. В листинге 7.7 показаны примеры таких вспомогательных стилей.

    label { 
      border: dashed thin; 
      padding: 2px; 
      margin: 2px;
    } 
    image { 
      border: solid thin; 
      padding: 2px; 
      margin: 2px; 
    } 
    .radio-check { 
      width:20px; 
      height:20px;
    } 
    .checkbox-check { 
      width:20px; 
      height:20px;
    } 
    vbox, hbox, box, deck { 
      border: solid; 
      padding: 2px; 
      margin: 2px; 
      border-color: grey;
    } 
    * { 
    font-family:Arial; 
    font-weight: bold;
    }
    
    Листинг 7.7. Пример вспомогательных стилей

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

    7.7.3. Поиск свойств для форм и меню

    В этой главе описывается XUL-интерфейс для форм и меню Mozilla, но не JavaScript-интерфейсы для соответствующих DOM-объектов этих тегов. Есть несколько способов поиска AOM- и DOM-свойств и методов этих объектов.

    • Догадка. Многие из свойств XUL-интерфейсов точно копируют свойства элементов HTML-форм. SelectedIndex, focus() и blur() - все они работают ожидаемым образом. Они также задокументированы в стандарте DOM 1 Core, в разделе, посвященном HTML.
    • Пользуйтесь Инспектором DOM. Выберите тег в левой панели, а из меню инструментов вверху правой панели выберите JavaScript Object. Откроются имена всех свойств и методов. Чтобы найти значения свойств объекта, обратитесь к данной книге или стандартам CSS 2 и CSS 3.
    • Прочитайте XBL-определения. XBL-связки для каждого элемента формы или меню находятся в архиве chrome toolkit.jar. После прочтения главе 15, "XBL-связки", эти определения воспринимаются как некоторая подсказка. XBL-определения содержат имена параметров для каждого метода, чего пока еще нет в Инспекторе DOM.

    7.8. Итоги

    Формы и меню - первая жизненно важная точка доступа для пользователей, которые хотят взаимодействовать с приложениями на основе Mozilla. XUL поддерживает простые элементы управления формы (или просто элементы формы), с которыми пользователи браузеров уже знакомы. Однако поддержка в XUL такими простыми элементами форм и меню не ограничивается. Эта поддержка идет гораздо дальше и не связана жестко с действиями пользователя, как в случае HTML-форм.

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

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


    об авторе

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





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