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

Списки и Деревья

13.1. Текстовые таблицы

Поля ввода текста могут быть организованы в текстовую таблицу. Текстовая таблица - неформальный термин для описания двуразмерных массивов редактируемых блоков (boxes). Очевидный пример текстовой таблицы - электронная таблица, с колонками и строчками. Небольшая текстовая таблица - идеальный инструмент для уточнения структуры данных и для работы с набором записей. XUL не имеет непосредственного инструмента для работы с текстовыми таблицами, но их легко создавать с помощью тега <textbox>.

Web-странички, кажется, игнорируют гибкость тега <textbox>. На web мы обычно видим формы для ввода данных сконструированными так, что их поля отдалены одно от другого. Запросы персональной информации или деталей заказа зачастую представлены так, что под каждое поле вывода отводится целая строка. Это делает текстовые таблицы громоздкими.

На деле же и HTML тег <INPUT>, и XUL тег <textbox> могут быть сконструированы весьма компактно. Для этого требуются очень простые стили:

textbox { 
border : solid thin; 
border-width : 1px; 
padding : 0px;
margin : 0px; } 

input:focus { 
background-color : lightgrey; 
}

Второй стиль нужен лишь для того, чтобы поле, получающее фокус, было подсвечено. Вернемся к "Формы и меню" , "Формы и Меню", и вспомним, что <texbox> содержит также и тег <html:input>. На рисунке 13.1 показан пример такой компактной таблицы.

Каждый <textbox> - содержание одной ячейки в теге <grid>. Код шаблонен. Навигационная модель XUL и управление фокусом ввода гарантирует, что при нажатии клавиши Tab мы будем переключены на каждый <textbox> по очереди, и что каждое поле будет подсвечиваться, получив фокус. В результате мы получаем привычные по виду и удобные для работы приложения.

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

Простая таблица списка, используется тэг <textbox>

Рис. 13.1. Простая таблица списка, используется тэг <textbox>

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

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

13.2. Списки

Тег <listbox> подобен по конструкции тегу <grid>, но по внешнему виду и поведению напоминает тег <menulist>. Список - это упорядоченное по вертикали множество записей, каждая из которых может иметь несколько полей.

Тег HTML <SELECT rows= > подобен тегу XUL <listbox>. Этот HTML тег дает строковое, а не выпадающее меню. Тег <SELECT> ясный и стандартный, но <listbox> не обладает, увы, такими свойствами. В Mozilla версий до 1.4, <listbox> работает не очень стабильно, поэтому будьте аккуратны. Несмотря на такой недостаток, это мощный инструмент, если его правильно использовать.

13.2.1. Внешний вид списков

Чтобы увидеть, как выглядит <listbox>, откройте вкладку ( Edit | Preferences ) в настройках Mozilla и посмотрите на панель "Темы" справа. Белая панель, на которой вы видите имена тем, такие как Classic и Modern, - это список.

На рисунке 13.2 показаны два списка и их свойства.

Список слева имеет одну колонку. Этот формат использует и тег HTML <SELECT>. Список имеет стили высоты и ширины, которые имеют по умолчанию 200px. Если площадь списка не позволяет вместить его содержание, появится вертикальная полоса прокрутки, и содержание тега <label> может быть обрезано. Как мы видим, каждая строка может иметь в начале пиктограмму и флажок. В реальном приложении пиктограммы и флажки могут иметь все строки, а не только некоторые, как показано здесь. В этом примере строка 4 была помечена кликом на флажке, а потом фокус получила строка 3.

Два списка, демонстрирующие их свойства

Рис. 13.2. Два списка, демонстрирующие их свойства

Список справа многоколонный. Он имеет две колонки, но их может быть сколько угодно. Верхняя строка - добавочная, для заголовков. Первая заголовочная строка имеет пиктограммы и слева, и справа от текста. Левая пиктограмма - необязательное изображение, добавляемое стилем. Правая пиктограмма имеет специальное значение, и показывает порядок сортировки всех нижележащих строк. Правая пиктограмма размещается с помощью XML-атрибута. Остальные строки (также называемые элементами) этого списка имеют по две ячейки каждая. Пиктограммы могут быть помещены в этих строках, хотя вряд ли это целесообразно. Флажки также могут быть размещены в этих строках, но нет способа выбрать их все автоматически, поэтому это тоже не имеет большого смысла. На снимке третья строка выбрана (она выделена серым), но второй список не имеет фокуса. Фокус имеет список слева - на снимке он темно-серый, а в реальности голубой.

Содержанием ячейки может быть простой тег <label> или любой блочный тег с произвольным содержанием. Если используется произвольный контент, внешний вид контролировать нельзя, и список может обрезать строки, если изменять его размер. Это может вызвать трудности с CSS2 и другие неприятные последствия, поэтому благоразумно использовать простейшие теги <label>. Многоколонные списки могут иметь строки с меньшим числом ячеек, чем число колонок, и это будет работать (включая флажки), но делать так не рекомендуется.

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

13.2.2. Строение списков

Рисунок 13.3 повторяет 13.2, но с включенной диагностикой.

Демонстрация внутренней структуры двух списков.

Рис. 13.3. Демонстрация внутренней структуры двух списков.

Как всегда, тонкие прерывистые - теги <label>, тонкие сплошные - изображения, а толстые серые линии - блоки. Смайлики слева слегка сплющены только потому, что добавочные линии несколько исказили верстку. Список справа может показаться сложноватым, но приглядевшись, мы заметим, что эти блоки очень напоминают блоки тега <grid>, обсуждавшиеся в "Верстка с XUL" , "Проектирование с XUL".

Табличная структура используется как базовая стратегия верстки списка, с тегом <button> для заголовков колонок и тегом <label> для содержания ячеек. Заголовок второй колонки и правая половина третьей строки списка показывают, что <label> может быть заменен на произвольный блок. Две затененные строки (по одной в каждом списке) показывают, что эти строки были выбраны. Такая подсветка - всего лишь стиль, применяемый к эквиваленту подтега <row> тега <grid>.

Рисунок 13.4 также демонстрирует нам блок, специфичный именно для списков. Это серая, толстая, прерывистая линия в обоих списках. Данный блок ограничивает все строки каждого списка. Он интенсивно используется в реализации списков. Это отличает систему верстки тега <listbox> от системы верстки тега <grid>.

Тег <listbox> и все относящиеся к нему теги, имеет XBL-определение, хранимое в файле listbox.xml из архива toolkit.jar в каталоге chrome. Платформа Mozilla имеет мощную C/C++ поддержку списков.

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

<listbox> использует пару тегов <listcols> и <listcol> для описания колонок, но он использует <listrows> и <listhead> или <listitem> для строк. Тег <grid>, однако, не имеет точных соответствий тегу <listbox>. Специальный прерывистый блок, показанный на рисунке 13.3 - это граница тега <listboxbody>. Это ключевой момент в обеспечении поддержки скролинга в Mozilla.

Таблица 13.1. Теги списка
Тег Полезен? Обязателен? Только для внутреннего использования? Приблизительный эквивалент <grid>
<listbox> + + <grid>
<listcols> + <columns>
<listcol> + <column>
<listhead> + <row>
<listheader> + one child of <row>
<listheaditem> + one child of <row>
<listboxbody> +
<listrows> + <rows>
<listitem> + + <row>
<listcell> + one child of <row>
<listbox>
  <listhead> 
    <listheader label="Sole Column"> 
  </listhead> 
  <listitem label="first item"/> 
  <listitem label="second item"/> 
  <listitem label="third item"/> 
</listbox>
Листинг 13.1. Простейший список, содержащий три элемента.

В листинге 13.1 описан список с одной колонкой и тремя строками, имеющий заголовок, гласящий "Одна Колонка". Нет ни пиктограмм, ни флажков. Он подобен многим блокам диалога Настроек, например, панели "Внешний вид", "Темы" или "Навигатор", "Языки". Эти примеры не имеют заголовков.

Mozilla, однако, умеет работать со многими дополнительными тегами, как показано на рисунке 13.4.

Теги, соответствующие тегам листинга 13.2, в этом полном дереве тегов затенены. Светлые теги с префиксом "xul:" сгенерированы XBL- определением списка. Это полная структура списка, за исключением того, что если бы он имел две колонки, теги <xul:listcol>, <xul:listheaditem>, и <xul:listcell> появились бы дважды в каждой позиции дерева тегов, а не один раз.

Это дерево демонстрирует, что листинг 13.2 использует весьма сокращенный синтаксис - многие теги подразумеваются, а не выписываются явно.

Изображение списка из трех строк в инспекторе DOM.

Рис. 13.4. Изображение списка из трех строк в инспекторе DOM.

Рисунок также показывает нам подобие и разницу тегов <listbox> и <grid>. Оба тега имеют колонки и строки, <listbox> имеет всего две строки, в то время как <grid> может иметь любое их число. Строки в списке сгруппированы внутри второй основной строки, как если бы эта строка была тегом <vbox>. Первая, заголовочная, строка, может отсутствовать, если заголовков нет.

Вот несколько основных правил построения списков:

  • В каждом <listbox> может быть максимум один <listcols> и максимум один <listhead>.
  • В <listcols>, если он есть, должен быть как минимум один <listcol>.
  • В <listhead>, если он есть, должен быть как минимум один <listheader>.
  • Полей <listitem> в каждой строке должно быть столько же, сколько и <listcols>, либо одно, если <listcols> не описан.
  • Не описывайте <listrows>, <listboxbody>, и <listheaditem> явно. Эти теги - только для внутреннего употребления.

Столь сложный процесс создания списка имеет свои внутренние ловушки. Главная ловушка состоит в том, что XUL не сможет обработать комбинацию тегов, которую сам же создает для тега <listbox>. Если вы создадите код, соответствующий дереву, показанному на рисунке 13.5, то он не будет интерпретирован как список, а Mozilla может даже упасть. Это значит, что XML-спецификация списка и ее XML-реализация существуют сами по себе и отличаются друг от друга.

Mozilla может упасть также, если использовать любой из тегов, упомянутых в пункте 5. Она упадет и в том случае, если определить любое содержание в теге <listcol>. Не отступайте слишком от стандартного пути работы со списками, следуйте образцам, приведенным в книге. В противном случае платформа может вести себя некорректно, дать некрасивую верстку документа и даже упасть. В Листинге 13.2 дана полная спецификация тега "список", которую поддерживает XUL.

<listbox> 
  <listcols> // tag and content optional
    <listcol/> // can be repeated
  </listcols> 
<listhead> // tag and content optional 
  <listheader> // can be repeated
  </listheader> 
</listhead> 
  <listitem> // can be repeated
    <listcell> // can be repeated
    </listcell>
  </listitem> 
</listbox>
Листинг 13.2. Тег "список" со всеми возможными опциями.

Пары открывающих и закрывающих тегов <listitem>, <listcell> и <listheader> могут быть сокращены до одного тега с синтаксисом <tag/>, в этом случае содержимое помещается в атрибут тега. Обсудим эти атрибуты для каждого тега отдельно. Все эти теги имеют XBL-определения в файле listbox.xml архива toolkit.jar в каталоге chrome.

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