Лишь самые простые приложения могут обойтись единственным окном. По мере развития приложения у разработчика рано или поздно возникает необходимость заменить часть содержимого существующего окна или создать новое. И то, и другое описано в этой лекции.
Разные аспекты платформы Mozilla существенно различаются по
сложности. Работа с окнами очень проста. Средства управления окнами,
доступные приложениям XUL, во многом подобны средствам, используемым в
традиционном web-программировании. Для тех, кому раньше приходилось
использовать метод window.open(), эта лекция будет просто
повторением пройденного. XUL (а также
Mozilla позволяет создавать множество различных типов
самостоятельных окон, начиная с крошечных всплывающих подсказок к
элементам интерфейса ( , в локализациях многих программ они
называются просто "подсказками") и заканчивая сложными
окнами больших приложений. Кроме того, она позволяет создавать внутри
окон другие, "встроенные" окна, в которых могут отображаться
другие документы. В этой книге для таких окон используется термин
"панели". Средства защиты web-браузера накладывают
ограничения на типы встроенных окон, однако эти ограничения не
действуют, если приложение установлено в каталог
Окна Mozilla могут преподнести несколько сюрпризов. Пространства
имен XML позволяют сочетать различные
На схеме в начале лекции показаны элементы архитектуры Mozilla,
имеющие отношение к управлению окнами. Как показано на схеме, это, в
первую очередь, фреймы JavaScript. Документы могут нуждаться в более
сложном контейнере, чем фрейм, описываемый простым тегом <box>,
поэтому существует несколько типов фреймов. В связи с окнами
заслуживают внимания несколько компонентов XPCOM. Но в любом случае,
это несложная тема.
Прежде чем обратиться к новым тегам XUL, мы кратко рассмотрим
хорошо известный тег <window>. Этот тег поддерживает следующие
специальные атрибуты:
sizemode windowtype screenX screenY width height
Атрибут sizemode применим только к тегам <window> (или < ), описывающим окна верхнего уровня. Он отражает
состояние окна на рабочем столе и может принимать значения normal, или maximized (нормальное, свернутое, развернутое на весь
экран).
Атрибут windowtype позволяет задавать группы однотипных окон.
Значением этого атрибута может быть любая строка, определенная
программистом. Атрибут имеет смысл, если одновременно открыто два или
более окон одного и того же типа. При открытии второго и последующих
окон, Mozilla пытается сместить их относительно существующих окон
данного типа. Это сделано для того, чтобы пользователь не
"потерял" однотипные окна из-за их полного перекрытия.
Атрибуты screenX screenY определяют смещение окна в пикселах
относительно левого верхнего угла экрана.
Атрибуты width и height задают высоту и
ширину окна в пикселах.
Ни один из атрибутов screenX, screenY, width, height не может быть изменен после
того, как окно отображено на экране.
Диалоговое окно может быть создано при помощи тега <window>,
как описано ниже в разделе о функции window.open(). Как правило, в
системах семейства UNIX диалоговые окна не являются модальными,
поэтому в специальной семантике диалога необходимости нет. В целом,
при наличии специального тега < для диалогового окна
использование тега <window> для этой цели не имеет практического
смысла.
Окно XUL может перекрываться другим содержимым, заданным в том же документе, ("всплывающим содержимым") при использовании следующих тегов:
<tooltip> <menupopup> <popup> <popupgroup> <popupset>
Однако не все эти теги рекомендованы к использованию, и не все они
применимы в любом месте документа. Так, <menupopup> следует
использовать только внутри тегов <menu> или <menulist>.
Следующие атрибуты других тегов XUL, определяющих элементы интерфейса,
также могут определять различные виды всплывающего содержимого для
этих элементов:
tooltiptext grippytooltiptext popup menu context contextmenu contentcontextmenu
Некоторые из перечисленных атрибутов также объявлены устаревшими.
Тег <menupopup> рассматривается в лекции 7 "Формы и
меню". Прочие теги и атрибуты описываются в этой лекции.
Для создания некоторых визуальных эффектов может использоваться тег <, представленный в лекции 2 "Управление
Система тегов и атрибутов, используемая для всплывающего содержимого, несет на себе отпечаток долгой истории развития Mozilla. Безусловно, лучше использовать современные теги, чем те, которые объявлены устаревшими. Однако и устаревшие теги сейчас корректно обрабатываются, и их поддержка вряд ли прекратится в версиях Mozilla 1.x.
Существует три основных типа всплывающих окон: всплывающие подсказки, контекстные меню и обычные меню.
При использовании большинства современных тегов содержимое,
описывающее всплывающие подсказки и контекстные меню, следует помещать
внутрь тега <popupset>. Это тег, который не имеет собственного
визуального отображения и используется для организации других тегов,
подобно тегу <keyset>. При необходимости в документе XUL может
быть несколько тегов <menupopup>.
Всплывающая подсказка определяется при помощи тега <,
а контекстные меню – посредством тега <menupopup>. Обычные меню
также могут быть описаны внутри тега <popupset> при помощи <menupopup>, однако рекомендуется использовать для создания
обычных меню другие средства – теги <menu> и <menulist>.
Традиционной, но устаревшей практикой является описание контекстных
меню при помощи тега <popup>. Редко встречающиеся теги < и <popupset> еще более архаичны. Эти и другие
теги могут быть заключены в очень старый тег <popupgroup>. Этот
тег может использоваться в пределах документа только один раз. Не
стоит задействовать ни один из этих трех тегов, хотя <popup> все
еще широко применяется при описании интерфейса Mozilla. Они объявлены
устаревшими, и для них существуют современные альтернативы.
Всплывающая подсказка – небольшое окно, которое появляется над элементом графического интерфейса, если курсор мыши задерживается над ним некоторое время (как правило, около секунды). Смысл использования этого средства – дать пользователю краткое пояснение к элементу интерфейса, назначение которого может быть непонятно (в силу неудачного дизайна), или который может быть частично скрыт. Вид всплывающей подсказки может быть полностью переопределен, так что традиционный желтый цвет не является обязательным.
Тег < поддерживает следующие атрибуты:
label crop default titletip
Если < не имеет содержимого, его текст определяется
значением атрибута label. Атрибут
Если значение атрибута default - true, данная подсказка является
всплывающей подсказкой по умолчанию для всего документа. Если атрибут titletip имеет значение true, всплывающая подсказка отображается для
элемента интерфейса в том случае, если он частично скрыт. Оба эти
атрибута имеют смысл только для подсказок к заголовкам столбцов тега <tree>.
Тег < может иметь любое содержимое – он функционирует
подобно тегу <. Однако большое количество содержимого для
данного тега не имеет смысла, поскольку пользователь не может
пролистывать это содержимое при помощи мыши или иным способом.
Размерами всплывающей подсказки можно управлять при помощи атрибутов minwidth и minheight, однако это может вызывать проблемы при
размещении элементов в родительском окне, так что использовать эти
атрибуты не рекомендуется.
Чтобы связать всплывающую подсказку с каким-либо элементом
интерфейса, нужно присвоить атрибуту нужного тега значение id
тега <, определяющего подсказку. Сокращенная нотация
позволяет обойтись без специального тега <, задав текст
подсказки в качестве значения атрибута нужного элемента
интерфейса. Еще один вариант – включить тег < в
содержимое тега, описывающего элемент интерфейса, для которого
создается подсказка. В этом случае следует указать для родительского
тега атрибут .
Атрибут contenttooltip, который может использоваться только с тегом <tabbrowser>, определяет подсказку для содержимого этого
тега.
Кроме того, всплывающая подсказка появляется над заголовком окна, если текст заголовка не помещается в него целиком.
Ссылка на элемент интерфейса, к которому относится всплывающая
подсказка, видимая в настоящий момент, может быть получен при помощи
свойства window.tooltipNode.
Контекстное меню – один из видов раскрывающихся меню. Оно выглядит так же, как и прочие меню, но появляется в ответ на "контекстный" щелчок мыши (щелчок правой кнопкой на большинстве платформ, щелчок с удержанием клавиши "Яблоко" на Macintosh). При этом меню появляется в том месте, где находится курсор мыши, а не каком-либо заранее определенном месте документа.
Для создания контекстного меню используется тег <menupopup>,
описанный в лекции 7 "Формы и меню". Чтобы связать меню с
элементом интерфейса, необходимо установить значение атрибута contextmenu этого тега равным значению атрибута id тега <menupopup>. Исключение составляет тег <tabbrowser> - у
него следует устанавливать атрибут contentcontextmenu.
В прошлом для указания контекстного меню различных элементов
интерфейса применялись атрибуты popup, menu и . Сейчас они
объявлены устаревшими, и их использования следует избегать, хотя
атрибут поддерживается до сих пор.
Атрибуты popupanchor и popupalign применимы к контекстным меню так
же, как и к обычным меню, созданным при помощи тега <menupopoup>.
Ссылка на элемент интерфейса, к которому относится контекстное
меню, видимое в настоящий момент, может быть получена при помощи
свойства window.popupNode.
Если в ходе работы приложения возникает необходимость вывести на экран простенький фрагмент данных, логично использовать диалоговое окно. Диалоговое окно представляет собой обычное окно XUL, имеющее весьма ограниченную область применения. Как правило, диалоговые окна не являются независимыми и существуют в контексте какого-либо другого, более значительного окна (т.е. используют его ресурсы).
Диалоговые окна используются в приложениях с двумя основными целями. Первая из них – получить от пользователя данные, необходимые для дальнейшей работы программы. Однако при этом пользователь сталкивается со сложностью логики приложения. Оптимальным для пользователя вариантом является немедленное выполнение отданной команды без каких-либо дополнительных действий с его стороны. Диалоговое окно требует от пользователя принятия дополнительных решений, необходимых для выполнения команды. С точки зрения пользователя это нарушает непрерывность исполнения программы.
Вторая цель применения диалоговых окон – необходимость привлечь внимание пользователя к какой-либо частной задаче или аспекту работы приложения. Как правило, такие диалоговые окна являются модальными – они приводят к остановке работы приложения до тех пор, пока пользователь не решит возникшую проблему. Этот способ нарушает процесс нормальной работы пользователя с программой.
Обе цели не слишком хорошо согласуются с идеей приложения,
рассчитанного на высокопроизводительную работу. В идеальном мире
диалоговых окон не существовало бы вовсе. Опытные разработчики
приложений сводят использование диалоговых окон к минимуму и избегают
отображения бессмысленных для пользователя конфигурационных
параметров. Большое количество диалоговых окон, используемых для
конфигурации, указывает на ошибки в моделировании взаимодействия
пользователя с приложением, допущенные на этапе проектирования. Если
система требует большого количества
Однако если диалоговые окна действительно необходимы, Mozilla представляет развитые средства для работы с ними.
Основой создания диалоговых окон является тег <. Он во
многом подобен тегу <window>, однако обладает дополнительной
функциональностью по сравнению с ним. По умолчанию тег <
создает немодальное окно, которое не блокирует возможность работы с
другими окнами приложения.
Для знакомства с тегом < достаточно в любом документе
XUL заменить тег <window> на <. Нужно иметь в виду,
что тег < рассчитан на использование в
На рисунке 10.1 показаны различные примеры использования тега <. При этом стандартные диагностические стили включены, а
единственным содержимым документа является слово Content внутри тега <description>. Два окна в первом ряду имеют одно и то же
содержимое, заключенное в тег верхнего уровня < и <window> соответственно. Как мы видим, < при
отображении автоматически добавляет тег <box> для своего
содержимого, а также два тега <button>. Во втором ряду показано
диалоговое окно со всеми кнопками, которые предусмотрены для тега <. Для отображения кнопок использовался атрибут buttons
этого тега. В примере, приведенном в последнем ряду, к диалоговому
окну было добавлено дополнительное содержимое – шесть кнопок. Эти
кнопки заменяют стандартные кнопки, которые в данном случае не
отображаются. Обратите внимание на то, что текст у кнопок во втором и
третьем ряду различается. Давайте рассмотрим, каким образом это
сделано.
(рис 10.1) Различные примеры использования тега <dialog>.Тег < определен при помощи XBL. Это определение
предусматривает дополнительные контейнеры для содержимого и кнопки.
Отображение тега также зависит от файла свойств, входящего в состав
< поддерживает следующие атрибуты:
buttonpack buttondir buttonalign buttonorient title buttons
Значением атрибута buttons является список строк, разделенных
запятыми. Также допускаются пробелы между строками. Это строка
параметров, подобная используемой методом window.open(), но в данном
случае ее синтаксис проще. Допустимы следующие значения строк:
accept cancel extra1 extra2 help disclosure
Нужные строки следует просто перечислить через запятую, например:
<dialog buttons="accept,cancel,help"/>
В дополнение к обработчикам событий, предусмотренным для тега <window>, для < можно использовать следующие
обработчики:
ondialogaccept ondialogcancel ondialogextra1 ondialogextra2 ondialoghelp ondialogdisclosure
Атрибут title, как и в случае тега <window>, задает текст
заголовка окна. Атрибуты buttonpack/dir/align/orient служат для
управления контейнером <hbox> диалогового окна, предназначенным
для размещения кнопок. Они аналогичны атрибутам pack/dir/align/orient
обычного контейнера. Атрибут buttons указывает, следует ли отображать
стандартные кнопки диалогового окна.
Эти кнопки отображаются с предопределенным содержимым и имеют
предопределенное поведение. Например, нажатие на кнопку cancel
закрывает диалоговое окно. Кнопки extra1 и extra2 зарезервированы для
использования приложением, однако чтобы задать для них метки,
необходимо переопределить значения, задаваемые в файле свойств. Каждый
из обработчиков событий, перечисленных выше, соответствует одной из
кнопок и запускается при ее активизации (например, при щелчке мышью по
кнопке).
Перечисленные атрибуты тега < позволяют создать все
окна, показанные на рисунке 10.1, кроме последнего. При его создании
был использован атрибут dlgtype, который обычно применяется с тегом <button>.
Значением атрибута dlgtype может быть любой из стандартных типов
кнопок:
accept cancel extra1 extra2 help disclosure
Атрибут dlgtype никак не влияет на отображение кнопки или другого
элемента, с которым он используется. Фактически он служит указанием
для объемлющего тега <. При отображении диалогового окна
его содержимое просматривается на предмет тегов, имеющих атрибут dlgtype. Если такой тег найден, он используется вместо соответствующей
стандартной кнопки диалогового окна. Это обеспечивает необходимую
гибкость при создании диалогов, позволяя разработчику управлять
размещением элементов. В качестве замены стандартных кнопок могут
использоваться только элементы интерфейса, поддерживающие событие command. Если для такого элемента не задана метка, будет
использоваться стандартная строка, заданная для диалогового окна в
файле свойств.
Окно, основанное на теге <, можно открыть тем же
способом, что и любое другое окно. Чтобы создать window.openDialog(), описанный ниже.
Не следует в явном виде задавать размер диалогового окна при помощи
атрибутов width и height.
Хотя определение тега <dialogheader> (заголовок диалогового
окна) включено в <box> с текстовым содержимым. Он не
имеет специального значения в контексте диалогового окна.
Тег <wizard> (мастер) представляет собой специализированный
вариант тега <. <wizard>, а также тег <wizardpage>, обсуждаются в лекции 17 "Развертывание
приложений".
Диалоговые окна могут создаваться Java-апплетами. Фактически при
этом используется платформа Java –
Диалоговые окна могут создаваться и из программ на JavaScript с
использованием ресурсов XPCOM и АОМ/
Разработчики встраиваемых приложений также могут использовать такие
языки как Perl или
Новые окна приложений можно создавать из программ на JavaScript.
Напомним, что интерпретатор JavaScript предоставляет разработчику
приложения глобальный объект. В контексте документа XUL этот объект
имеет свойство window, которое фактически также является глобальным
объектом. Этот объект поддерживает целый ряд методов, которые могут
использоваться для создания окон.
Следует отметить, что иерархия свойств JavaScript, доступная
разработчику на платформе Mozilla, отличается от интерфейсов XPCOM.
Хотя некоторые свойства JavaScript, например window и window.document
выглядят идентичными соответствующим компонентам XPCOM, фактически они
представляют собой самостоятельные конструкции, созданные для удобства
разработчика.
Это существенный момент. У разработчика может сложиться
впечатление, что свойства
Инспектор
Объект window сообщает, что его тип - ChromeWindow. В модели XPCOM
нет такого объекта, хотя существует интерфейс nsIDOMChromeWindow.
Однако свойства и поведение объекта ChromeWindow в большей степени
связаны с интерфейсами nsIJSWindow и nsIDOMWindowInternal.
Механизмы работы JavaScript с окнами ориентированы, в первую
очередь, на традиционного разработчика web-приложений. По умолчанию в
качестве нового окна создается окно приложения Navigator. Это окно
XUL, элементы которого образуют полноценный web-браузер. Оно содержит
панели инструментов, другие элементы интерфейса, некоторые элементы
Окно браузера предоставляет web-разработчику ограниченный набор
window и window.document обеспечивают доступ лишь
к содержимому, находящемуся в панели отображения документа.
Web-разработчик не имеет доступа к содержимому XUL, формирующему интерфейс
браузера; элементы интерфейса за пределами отображаемого документа
являются для него "window.open(). Эти параметры позволяют скрыть некоторые элементы
интерфейса у нового окна, например панели инструментов.
С точки зрения разработчика XUL, окно браузера способно либо
облегчить ему работу, либо оказаться серьезной помехой. Если
разработчик занят незначительным усовершенствованием существующего
браузера (например, добавляет к нему оверлеи), окно браузера
предоставляет его приложению дополнительную функциональность. Однако
при разработке нового приложения вся функциональность браузера может
оказаться ненужным грузом. В этом случае несложные меры (например,
использование ключа - ) позволяют начать "с чистого
окна".
Метод window.open() создает новое окно. Этот интерфейс
target = window.open(URL, name, features);
URL – действительный
name – имя нового окна. Чтобы создать безымянное окно,
следует использовать в качестве этого параметра null или "_blank".
– разделенный запятыми список дополнительных параметров и
их значений (строка параметров), определяющих вид и поведение нового
окна.
Функция возвращает ссылку на объект window созданного окна. При
помощи этой ссылки можно получить доступ к элементам
Строка параметров применяется часто, однако возможные значения параметров документированы плохо, поэтому ниже приводится их полное описание.
Каждый параметр передается в виде пары имя_параметра=значение,
нечувствительной к регистру символов. Значение может быть либо булевым
флагом, либо скалярным (числом). Для булева параметра достаточно
привести его имя без части =значение или указать "имя_параметра=
yes" для того, чтобы присвоить параметру значение
"истина". Любое другое значение, присвоенное параметру,
означает "ложь". В случае скалярного параметра значение
интерпретируется как число, любые символы, следующие за числом,
игнорируются. Пары разделяются запятыми, за которыми могут следовать
дополнительные пробелы, хотя это может привести к проблемам при
отображении HTML-документов в некоторых устаревших браузерах.
Следующий пример иллюстрирует эти правила:
"toolbar,location=yes,menubar=no,top=100, left=100px,width=100cm"
В этом примере новое окно будет иметь панель инструментов (
Строка параметров определяет тип нового окна – будет ли оно окном
браузера (создается по умолчанию) или же окном
chrome
Следующие параметры имеют смысл только для окна браузера:
toolbar location directories personalbar status menubar scrollbars extrachrome
Если указанные параметры или вся строка параметров отсутствуют, считается, что они имеют значение по умолчанию - "истина".
Булев параметр extrachrome определяет, будет ли при создании нового
окна браузера загружено и отображено содержимое, определяемое
пользователем (в классическом браузере – боковая панель или
Следующие параметры могут применяться как к окнам браузера, так и к
окнам
resizable dependent modal dialog centerscreen top left height width innerHeight innerWidth outerHeight outerWidth screenX screenY
Значением по умолчанию, которое используется, если параметр или вся
строка опущены, для параметров и centerscreen является
"истина", а для и – "ложь".
Однако, если текущее окно является модальным, по умолчанию создается
Если новое окно создано с параметром (изменяемый размер),
менеджер окон в системах Microsoft Windows или X11 создает стандартные
<resizer> в
данном окне.
(зависимое) создает дочернее окно – закрытие
родительского окна приводит к закрытию вновь созданного. Новое окно
всегда открывается поверх родительского (окна, код которого вызывает window.open() ).
При использовании параметра созданное окно будет модальным.
Родительское окно не может получить фокус ввода до тех пор, пока
Если указан параметр , новое окно будет создано с
единственной кнопкой на заголовке окна – "Закрыть".
Параметр centerscreen обеспечивает расположение нового окна в центре экрана.
Прочие параметры – скаляры, определяющие размер и положение нового
окна. Если из параметров top, left, screenX или screenY указан только один,
соответствующий параметр для второго измерения считается равным нулю.
Параметры, определяющие положение и размер окон браузера,
игнорируются, если был использован атрибут , предназначенный
для окон классического браузера.
Следующие параметры имеют смысл только для окон, созданных с
необходимыми привилегиями защиты, например из приложения,
установленного в
titlebar close alwaysLowered z-lock alwaysRaised minimizable
Значение по умолчанию двух первых параметров – "истина",
остальных – "ложь". titlebar обеспечивает добавление
элементов окна, создаваемых close
обеспечивает создание кнопки "Закрыть" на заголовке окна.
Если указаны параметры alwaysLowered или z-lock, окно будет оставаться
на заднем плане, получая фокус ввода; если указан параметр alwaysRaised, окно будет оставаться на переднем плане при потере
фокуса. Параметр minimizable, по всей видимости, никак не меняет
поведение окна.
Если параметр close имеет значение "ложь", пользователь,
тем не менее, может закрыть окно средствами
Метод window.openDialog() доступен лишь в том случае, если он
вызывается из документа, который считается защищенным, например
установленного в window.open(), и приводит практически к тем же
результатам.
target = window.open(URL, name, features, arg1, arg2,...);
arg1, arg2 и т.д. – любые аргументы, допустимые для функций на
JavaScript. В новом окне они доступны как элементы массива window..
Фактически, метод openDialog() эквивалентен методу window.open() с
параметрами ". Это поведение можно
переопределить, присвоив какому-либо из этих параметров в явном виде
значение "ложь". openDialog() также поддерживает параметр all. Если указать его в строке параметров, новое окно будет создано со
всеми элементами, позволяющими пользователю управлять окном. В
частности, на заголовке окна будут доступны кнопки "Закрыть"
и "Свернуть".
В окне классического браузера тегом XUL c id="content"
является тег <tabbrowser>, соответствующий панели для
отображения web-документа. Этот тег недоступен для web-разработчика,
однако весьма полезен для разработчика приложений на основе браузера.
Он предоставляет обширную функциональность, которая может быть
использована в программах, и заслуживает внимательного изучения при
помощи Инспектора
Если окно является обычным окном браузера на основе XUL, указанный
объект <tabbrowser> доступен как свойство content объекта window. Объект, доступный таким образом, не только реализует интерфейс nsIWebNavigation, но и имеет свойство document, указывающее на
документ HTML (или XML), который отображается в текущей вкладке
браузера.
Интерфейс nsIWebNavigation содержит все методы, необходимые для
управления web-документами, отображаемыми в данной панели – их
загрузки, перезагрузки и перемещения между ними. Объект AOM <tabbrowser> имеет свойство webNavigation, обеспечивающее доступ
к этому интерфейсу. Наиболее полезным методом является loadURI(),
который во многом сходен с объектом , речь о котором шла
в лекции 7 "Формы и меню". Основное различие между ними
состоит в том, что просто возвращает ответ на
HTTP-запрос в виде данных, в то время как loadURI() отображает полученный
документ в окне. Одновременно метод задействует другие функции
классического браузера, например, добавляет полученный документ к
истории посещений. loadURI() такова:
void loadURI(uri, flags, referrer, postData, headers)
–
flags (по умолчанию null ) – набор однобитовых флагов, определяющих
поведение при загрузке документа. Отдельные флаги доступны как
свойства объекта webNavigation, имеющие префиксы LOAD_FLAGS, и имеют
различную семантику – не использовать копию документа из кэша,
перезагрузить страницу и т.п.
referrer (по умолчанию null ) –
postData (по умолчанию null ) – строка данных POST, передаваемая в
составе HTTP-запроса.
headers (по умолчанию null ) – строка дополнительных заголовков
HTTP-запроса.
Последние два аргумента редко применяются в программах на
JavaScript. Если вам необходимо использовать их, предаваемую строку
следует преобразовать в объект, соответствующий интерфейсу nsIInputStream. Пример того, как это можно сделать, показан на
листинге 10.1.
var str, C, obj, iface, arg;
str = "put data here";
C = Components;
obj = C.classes["@mozilla.org/io/string-input-stream;1"];
iface = C.interfaces.nsIStringInputStream;
arg = obj.createInstance(iface);
arg.setData(str, str.length);
loadURI("page.cgi", null, null, arg, null);
Эти три метода объекта window позволяют создавать простейшие
диалоговые окна для взаимодействия с пользователем. Метод alert()
создает окно с сообщением и единственной кнопкой. Метод
позволяет пользователю сделать выбор, нажав одну из кнопок, а метод prompt() служит для получения от пользователя данных. Кроме того,
метод alert() является простейшим способом создать точку прерывания в
вашем коде на JavaScript – выполнение приостанавливается до того
момента, когда окно будет закрыто.
Механизм создания этих окон был переработан в процессе создания
Mozilla. В printf() в стиле языка C. В них не поддерживаются символы
Пунктирными контурами на рисунке показаны элементы, соответствующие
тегам <description>. Чтобы изучить структуру окон, нужно
добавить отладочные стили к файлу userChrome.css в каталоге профиля
пользователя, а затем перезапустить платформу. Окно на рисунке было
получено при помощи следующей строки кода:
alert("Line 1\nLine2");
(рис 10.2) Структура XUL диалогового окна alert().Mozilla разбивает строку, переданную методам alert(), и prompt(), согласно <description> где, в свою очередь, может
отображаться в несколько строк. Максимальная ширина тега <description> (свойство maxwidth ) – 45 <description> с id="info.header" может использоваться
разработчиком.
Эти диалоговые окна определены в commonDialog внутри архива
Методы alert(), и prompt() используют для создания
диалоговых окон следующие компонент и интерфейс XPCOM:
@mozilla.org/embedcomp/prompt-service;1 nsIPromptService
Объект с помощью этой пары может быть создан лишь из документа, который считается защищенным. Этот объект позволяет создавать множество различных диалоговых окон, которые перечислены в таблице 10.1.
Интерфейс nsIPromptService содержит обширную документацию по
аргументам каждого из этих методов. Создавая приложение для установки
в alert(),
предназначены для скриптов внутри HTML-документов.
| Имя метода | Диалоговое окно |
|---|---|
alert() |
Обычное окно alert(). |
alertCheck() |
Обычное окно alert(), но с дополнительной строкой, содержащей флажок и текст |
|
Обычное окно |
confirmCheck() |
Обычное окно , но с дополнительной строкой, содержащей флажок и текст |
confirmEx() |
Полностью настраиваемое диалоговое окно, содержащее до трех кнопок со стандартными метками или метками, определенными пользователем. Дополнительно может содержать флажок и текст |
prompt() |
Обычное окно prompt() |
promptUsernameAndPassword() |
Диалоговое окно с полями ввода для имени пользователя и пароля. Дополнительно может содержать флажок и текст |
promptPassword() |
Диалоговое окно с полем ввода для пароля. Дополнительно может содержать флажок и текст |
select() |
Диалоговое окно со списком, из которого может быть выбран один элемент. Каждый элемент списка представляет собой простой текст |
В Mozilla определены несколько специализированных диалоговых окон,
которые описаны в архиве
Каждое из этих окон имеет соответствующий компонент XPCOM и должно
управляться при помощи интерфейсов XPCOM, а не посредством URL
документов
Ниже кратко рассмотрены два из них.
FilePicker представляет собой пару из компонента и интерфейса
XPCOM, а также набор диалоговых окон. В некоторых случаях эти окна
основаны на XUL, но могут использоваться и стандартные окна выбора
файла, предоставляемые операционной системой. В последнем случае это
окно не может быть исследовано при помощи Инспектора
Для создания окна используется следующая пара XPCOM:
@mozilla.org/filepicker;1 nsIFilePicker
Как легко убедиться, просмотрев соответствующий файл XPIDL,
интерфейс nsIFilePicker предоставляет ряд простых методов для работы с
диалоговым окном. Чтобы воспользоваться окном, нужно выполнить
следующие действия:
init().show(). При этом будет создано FilePicker.Последний этап является не вполне тривиальным, поскольку информация
о выбранном файле не может быть передана в виде простой строки,
содержащей путь. Это связано с тем, что в некоторых операционных
системах, чтобы однозначно идентифицировать файл, следует указать не
только путь, но и устройство. Специализированные объекты и интерфейсы
платформы для работы с файлами описаны в лекции 16 "Объекты
XPCOM". Рекомендуется ознакомиться с ними, прежде чем приступать
к использованию объекта FilePicker.
В листинге 10.2 приведен пример получения от пользователя имени
файла для вывода данных при помощи объекта FilePicker.
var Cc = Components.classes; var Ci = Components.interfaces; var fp; fp = Cc["@mozilla.org/filepicker;1"]; fp = fp.createInstance(Ci.nsIFilePicker); fp.init(window, "Example File Save Dialog", fp.modeSave); fp.show(); // fp.file содержит объект nsILocalFile, указывающий на выбранный файл
Платформа Mozilla предоставляет ряд объектов для взаимодействия с системой печати, а также несколько диалоговых окон на основе XUL для задания параметров печати. Примерно с версии 1.3 Mozilla позволяет распечатывать документы XUL, отображаемые в окне браузера, подобно обычным HTML-документам.
Система печати Mozilla довольно сложна, и ее обсуждение выходит за
рамки данной книги. В качестве отправных точек для самостоятельного
изучения системы печати можно порекомендовать интерфейсы XPCOM nsIPrintingPromptService и nsIWebBrowserPrint.
Вместо создания нового окна при необходимости отобразить новое
содержимое, можно создать в пределах существующего окна панель и
динамически управлять ее содержимым. В качестве аналогии можно
привести обычный
XUL позволяет отображать в определенной области окна документ, независимый от основного окна. Для этого предусмотрено несколько тегов.
Тег <iframe> лежит в основе механизма включения одних
документов в другие на платформе Mozilla. Он во многом подобен тегу
HTML <iframe>, однако менее гибок. Между открывающим и
<iframe> не может находиться никакого
содержимого. Элементом интерфейса, соответствующим тегу <iframe>, является фрейм, в который может быть загружен
независимый документ. При этом фокус ввода может быть передан
содержимому этого фрейма. Размеры последнего можно задавать и изменять
так же, как и для любого элемента-контейнера:
<iframe minwidth="100px" flex="1" src="about:blank"/>
Специфичным для <iframe> является только атрибут src, который
задает URL документа для отображения в <iframe>. Также полезно
указать значение атрибута name, чтобы документ, загруженный во фрейм,
мог обращаться к нему.
В лекции 8 "Навигация" было отмечено, что тег <scrollbox> является особой разновидностью контейнера, которой
соответствует отдельный интерфейс XPCOM. То же самое справедливо и для
тега <iframe>. Это единственная реализация компонента,
называемого
@mozilla.org/layout/xul-boxobject-iframe;1
Объект AOM, соответствующий тегу <iframe>, имеет свойство boxObject, как и все остальные объекты – контейнеры XUL. Как и в
случае с тегом <scrollbox>, при помощи метода boxObject.QueryInterface() можно получить специализированный
интерфейс, который для тега <iframe> называется nsIIFrameBoxObject. Хотя этот тег имеет единственное свойство, docShell, оно, в свою очередь, обеспечивает доступ к интерфейсу nsIDocShell, который обладает богатой функциональностью.
DocShell означает "Document Shell", [, или командная строка DOS являются
оболочками для доступа к командам операционной системы.
Многочисленные свойства и методы интерфейса nsIDocShell
обеспечивают доступ к основным операциям, необходимым для загрузки
документа и управления его отображением. Кроме того, этот документ
предоставляет доступ к другим интерфейсам, также полезным для
управления документами. В некотором смысле интерфейс nsIDocShell похож
на водительское кресло автомобиля – большинство средств управления
находятся в непосредственной досягаемости. Этот интерфейс хорошо
документирован и заслуживает хотя бы беглого ознакомления. Информация
о нем содержится в загружаемых файлах, упомянутых во
"Введении".
В большинстве случаев разработчик использует интерфейс nsIDocShell,
автоматически возникающий в результате загрузки какого-либо документа.
Только в сложных проектах у разработчика может возникнуть
необходимость вручную создавать оболочку документа и управлять
загрузкой документа на низком уровне.
Содержимое фрейма, заданного тегом <iframe>, должно иметь
статус отдельного документа XML, в отличие от большинства тегов-
контейнеров, содержимое которых определяется их потомками в исходном
документе XUL. <iframe> является важнейшим тегом, лежащим в
основе браузера Mozilla – именно с его помощью реализована панель, в
которой отображаются загружаемые документы.
Таким образом, тег <scrollbox> дополняет обычный контейнер
возможностью прокрутки содержимого (часть документа XML) в
отображаемой области. Дополнительные возможности тега <iframe>
гораздо шире – он предоставляет различные способы управления
содержимым (отдельным документом XML) и его отображением. В обоих
случаях сама отображаемая область представляет собой простой
прямоугольник без какого-либо дополнительного оформления.
XBL-определение тега <iframe> содержится в файле general.xml
архива nsIDocShell:
docShell contentWindow webNavigation contentDocument
docShell является отправной точкой для управления содержимым
фрейма. Еще три свойства являются эквивалентами свойств JavaScript window, window.webNavigation и соответственно для
содержимого фрейма.
Свойство commandDispatcher, которое есть у любого документа XUL,
имеет метод advanceFocusIntoSubtree(), с помощью которого можно
передать фокус ввода содержимому тега <iframe>, если оно
способно получить фокус.
Если документ, содержащийся во фрейме, шире или выше, чем область
отображения фрейма, будут показаны полосы прокрутки. У всякого
документа XUL, отображаемого в <iframe>, корневым тегом должен
быть <page>. Теги <iframe> могут быть вложенными, при
условии, что каждый из них содержит самостоятельный
Тег <page> (страница) следует использовать вместо тега <window> в том случае, когда документ XUL предназначен для
отображения внутри <iframe>. Тег <page> не имеет
специализированных атрибутов.
Хотя документ с тегом <page> может отображаться в виде
отдельного окна, такая практика не рекомендуется. Этот тег
предназначен для документов, отображаемых во фреймах.
Тег <editor>, подобно тегу <iframe>, представляет собой
специализированный контейнер для отображения отдельного документа.
Единственным специализированным атрибутом этого тега является src,
который указывает на URL отображаемого документа. Некоторые версии
Mozilla поддерживают также атрибут editortype, который может принимать
значения "html" или "txt". Кроме того, существует
атрибут type, который может принимать значения "content" или "content-primary". В последнем случае свойство window.content указывает на свойство contentWindow тега <editor>. Этому тегу соответствует следующая пара XPCOM:
@mozilla.org/layout/xul-boxobject-editor;1 nsIEditorBoxObject
Интерфейс nsIEditorBoxObject поддерживает всю ту же
функциональность docShell, что и тег <iframe>, а также богатую
функциональность интерфейса nsIEditor, доступную через свойство editor. Интерфейс nsIEditor предоставляет все возможности, необходимые
для реализации визуального редактирования HTML-документов – выделение
текста, копирование и т.д. Тег <editor> лежит в основе
классического Компоновщика подобно тому, как тег <iframe> лежит
в основе браузера.
Тег <editor> не предоставляет дополнительных элементов
управления для редактирования документа.
<browser> – еще один специализированный тег, который, подобно
тегу <iframe>, предназначен для отображения независимых
документов и имеет атрибут src. <browser> является
тегом-контейнером, ему соответствует следующий компонент XPCOM:
@mozilla.org/layout/xul-boxobject-browser;1
Этот компонент реализует интерфейс nsIBrowserBoxObject, во многом
сходный с интерфейсом nsIIFrameBoxObject. Вообще, теги <browser>
и <iframe> имеют много общего.
Тем не менее, тег <browser> имеет отдельное XBL-определение,
которое содержится в файле browser.xml архива <iframe>
решаются путем нескольких обращений к различным интерфейсам, свойствам
и методам, в случае <browser> часто требуют вызова единственного
метода. В XBL-определении метода <browser> также предусмотрены
поддержка истории просмотра документов, средств защиты и
перетаскивания при помощи мыши.
Кроме того, <browser> поддерживает режим каретки (текстового
курсора), который активизируется нажатием клавиши F7. В этом режиме,
как в текстовом редакторе, пользователь может перемещать по HTML-
странице курсор.
Тег <iframe> лучше использовать в тех случаях, когда нужно
загрузить во фрейм единственный документ, который затем не будет
изменяться. <browesr> более удобен, если предполагается
последовательно загружать во фрейм разные документы или необходимо
обеспечить
Подобно тому, как <browser> является переработанным вариантом
тега <iframe>, тег <tabbrowser> (браузер с вкладками)
представляет собой усовершенствованный <browser>. В отличие от
двух других тегов, <tabbrowser> не имеет соответствующего
компонента XPCOM. Фактически, он представляет собой одно большое XBL-
определение в файле tabbrowser.xml архива
<tabbrowser> является комбинацией тегов <tabbox> и <browser>. Каждая вкладка тега <tabbox> содержит отдельный <browser>, причем вкладки можно динамически добавлять и удалять.
Именно <tabbrowser> лежит в основе области отображения
web-документов в окне классического браузера.
Тег <tabbrowser> имеет следующие специализированные свойства:
onnewtab contenttooltip contentcontextmenu
Свойство onnewtab – обработчик событий, который запускается, когда
пользователь создает новую вкладку при помощи меню или специальной
кнопки. Значения двух других атрибутов передаются тегам <browser>, находящимся на вкладках в качестве атрибутов
и contextmenu соответственно.
Хотя с помощью многочисленных методов можно автоматизировать работу
с тегом <tabbrowser>, как правило, в этом нет практического
смысла. Этот тег предназначен для пользователя, просматривающего
несколько web-документов. Максимум того, что обычно бывает нужно
разработчику – получить информацию о текущем
Эти теги HTML или XHTML используются при создании web-страниц для помещения документов во фреймы. Внутри такого фрейма может отображаться и документ XUL.
Существует несколько комбинаций тегов, которые игнорируются при отображении документов во фреймах.
По умолчанию в документе XUL игнорируется тег <html>. Он
обрабатывается так же, как любой тег, определенный пользователем.
Некоторую пользу из этого тега можно извлечь, применяя пространства
имен XML, как описано ниже в разделе "Составные
документы".
Тег <window>, являющийся потомком другого тега XUL, также
игнорируется. Теги верхнего уровня - <window>, <, <page> - не могут быть вложенными, за исключением того случая,
когда они относятся к отдельным документам, отображаемым во фреймах <iframe>.
Атрибут chromehidden тега <window> не имеет практического
значения для разработчика приложений. Он устанавливается из метода window.open() и используется внутренним механизмом работы с панелями
инструментов в классическом браузере. Атрибут windowtype, которому
может быть присвоено строковое значение, используется для управления
окнами (см. раздел "Управление существующими окнами"). Он не
влияет на отображение окна.
Тег <package>, который иногда упоминается в устаревшей
документации, в настоящее время не используется.
Можно объединять несколько различных документов в один, не изолируя
их друг от друга при помощи тега <iframe>.
Очень мощная, хотя и сложная в использовании особенность Mozilla –
способность отображать документ, теги которого относятся к различным
стандартам (типам документов XML). Это означает, что один документ
может объединять, например, содержимое HTML,
Случаи смешивания содержимого различных типов в одном документе можно условно разделить на "поверхностное" и "глубокое" смешивание. В последнем случае более вероятны проблемы с отображением документов.
В случае поверхностного смешивания документ состоит из нескольких
фрагментов, каждый из которых относится к отдельному
Глубокое смешивание означает, что в документе невозможно выделить
крупные фрагменты, относящиеся к различным стандартам. В таком
документе разные
Поверхностное смешивание, как правило, не создает проблем с
отображением документов. При глубоком смешивании проблемы возникают
довольно часто. Наименее рискованным является глубокое смешивание HTML
и MathML. Смешивание XUL с HTML или MathML требует осторожности, а
глубокое смешивание
Смешивание различных типов содержимого может быть весьма полезным, но требует осторожности. На то есть несколько причин:
Иногда возникает соблазн просто добавить к документу XUL тег HTML <A HREF=>, чтобы создать в окне справки ссылку на сайт
разработчика. Вы можете добавить к документу тег HTML <FORM> и
автоматически отправлять данные формы из XUL. Однако и в том, и в
другом случае можно обойтись без всякого HTML. Необходимо следить за
"чистотой" своего XUL.
Более поздние стандарты createElementNS() и getAttributeNS(). NS в их именах
означает namespace (пространство имен). Эти методы позволяют при
работе с тегами и атрибутами XML указывать для них конкретное
пространство имен.
Тег < подобен усложненной версии директивы #include
языков C/C++. Он позволяет объединить несколько документов XUL в один,
используя атрибут id. Эта технология описана в лекции 12 "Оверлеи
и
В процессе работы приложения может возникнуть необходимость
обратиться к ранее созданным окнам. Например, команда File | в меню Инспектора
Попытка жонглировать множеством независимых окон может привести к
неудачной архитектуре приложения. В большинстве случаев пользователь
может закрыть любое окно в любой момент. При этом удаляется вся
информация о состоянии приложения, связанная с эти окном (возможно, за
исключением и в строке параметров метода window.open(). Возможно, однако, что
приложение должно следовать метафоре рабочего стола, когда независимые
документы находятся в независимых окнах. В этом случае либо все окна
должны быть полностью независимы друг от друга без возможности
взаимодействия, либо приложение должно иметь возможность установить,
какие окна открыты в настоящий момент.
Mozilla предоставляет несколько компонентов и интерфейсов для управления окнами. Простейшей парой является следующая:
@mozilla.org/appshell/window-mediator;1 и nsIWindowMediator
Этот интерфейс позволяет получить список окон, открытых в данный
момент. К моменту выхода версии Mozilla 1.2.1 он не был окончательно
зафиксирован ( frozen ), и существовала возможность того, что в будущем
он несколько изменится. Различные методы этого интерфейса позволяют
получить список окон в разных формах. На листинге 10.3 показано, как
получить статический список окон, открытых в настоящий момент.
var C, obj, iface, mediator, enum, windows; C = Components; obj = C.classes["@mozilla.org/appshell/window-mediator"]; iface = C.interfaces.nsIWindowMediator; mediator = obj.createInstance(iface); enum = mediator.getEnumerator(null); windows = []; // получить список окон, используя полученный объект-перечислитель (интерфейс nsISimpleEnumerator) while ( enum.hasMoreElements() ) windows.push(enum.getNext()); // сделать что-либо с первым окном windows[0].document.GetElementById ...
Чтобы отфильтровать получаемый список окон, методу getEnumerator()
можно передать строку в качестве аргумента. При этом в возвращаемый
список войдут только окна с корневым тегом <html>, <window>, < или <wizard>, чей атрибут windowtype совпадает с этой строкой.
Чтобы включить в список только окна XUL, вместо метода getEnumerator() следует использовать getXULWindowEnumerator().
Обсуждаемый интерфейс также позволяет получить порядок расположения
окон (очередность перекрытия). Минимизированные окна будут перечислены
как находящиеся в самом низу.
В ходе работы приложения окна могут постоянно открываться и
закрываться, и может возникнуть необходимость динамически отслеживать
этот процесс (как это делается для поддержания списка открытых окон в
меню "Окно"). Один из способов сделать это – создать объект-
приемник ( ) для соответствующих событий. Данному объекту,
реализующему интерфейс nsIWindowMediatorListener, сообщается об
открытии и закрытии окон, а также об изменении заголовка окна. Более
сложное решение, требующее некоторого кодирования – использовать
источник данных непосредственно из XUL. Работа с
Платформа Mozilla добавляет к системе стилей
В частности, внешний вид подсказки, определяемой тегом <, как и в случае с <menupopup>, о котором шла
речь в лекции 7 "Формы и меню", определяется значением -moz-popup свойства display.
Свойство -moz-, которое используется для поддержки тем
операционной системы (рабочей среды), может также принимать следующие
значения:
window dialog tooltip caret
Кроме того, существует целая система расширений, которые также могут использоваться для поддержки этих тем. Полезно, когда окна, а особенно - диалоговые окна, создаваемые при помощи XUL, выглядят в точности как собственные окна операционной системы или рабочей среды (например, Windows или GNOME). Диалоговые окна и сами по себе, без экзотических форм и цветов, могут представлять собой раздражающий фактор для пользователя. Поэтому Mozilla включает целый набор расширений, которые позволяют диалоговым и прочим окнам имитировать системные цвета и шрифтовое оформление рабочей среды. Эти расширения могут использоваться в любых правилах стиля, где можно задействовать обычные имена шрифтов или цветов.
Кроме того, Mozilla поддерживает имена шрифтов и цветов,
установленные спецификацией
Продуманное использование этих расширений может сделать приложение XUL неотличимым от приложений, традиционных для данной среды, например написанных для Windows при помощи Visual Basic или для UNIX – на основе библиотеки GTK.
Дополнительные значения для системных цветов, поддерживаемые
Mozilla, перечислены в таблице 10.2. Актуальный список таких
расширений для текущей версии можно найти в файле nsCSSProps.
| Имя системного цвета | Соответствующий элемент | Дополнительные имена цветов для Macintosh |
|---|---|---|
-moz-field |
Фон поля ввода | -moz-mac-focusring -moz-mac-menuselect -moz-mac-menushadow -moz-mac-menutextselect -moz-mac-accentlightesthighlight -moz-mac-accentregularhighlight -moz-mac-accentface -moz-mac-accentlightshadow -moz-mac-accentregularshadow -moz-mac-accentdarkshadow -moz-mac-accentdarkestshadow |
-moz-fieldtext |
Текст в поле ввода | |
-moz- |
Фон диалогового окна | |
-moz-dialogtext |
Текст в диалоговом окне | |
-moz-dragtargetzone |
Цвет, которым выделяется элемент при перетаскивании над ним объекта при помощи мыши | |
-moz-hyperlinktext |
Текст ссылки, например, на Active Desktop в Windows | |
-moz-visitedhyperlinktext |
Текст посещенной ссылки |
Mozilla также поддерживает расширения для
| Имя системного шрифта |
|---|
-moz-window |
-moz-document |
-moz- |
-moz-desktop |
-moz-info |
-moz- |
-moz-button |
-moz- |
-moz-list |
-moz-field |
Исключением является значение -moz-fixed, которому соответствует
моноширинный шрифт. Этот шрифт действительно отображается, причем для
любого заданного размера и, следовательно, для любых значений свойства
CSS font-size.
В ходе этого занятия мы используем различные техники работы с
диалоговыми окнами, чтобы оптимизировать код окна Edit. Мы также
поработаем над взаимодействием основного окна приложения и диалогового
окна Edit. Эти две задачи распадаются на ряд мелких подзадач:
<window> на <dialog > для диалогового окна Edit.<button>, на обработчики, связанные с <dialog >.notetaker-open-dialog для создания диалогового окна Edit при помощи метода window.openDialog().notetaker-close-dialog .Прежде всего, обратимся к окну Edit. Заменить тег <window> на < несложно. Новый корневой тег точно так же позволяет
указать текст для заголовка окна:
<dialog xmlns="http://www.mozilla.org/keymaster/
gatekeeper/there.is.only.xul"
id="notetaker.dialog"
title="Edit NoteTaker Note"
onload="execute('notetaker-load')">
Нам больше не нужно вручную создавать кнопки для окна, поскольку
для < они создаются автоматически. Однако в то же время
мы кое-что теряем – мы не можем просто использовать тег <command> для <, поскольку с каждым тегом можно
связать лишь одну команду. При желании можно было бы отключить
автоматическое <button>
с <command> для каждого из них. Однако логично использовать
собственные кнопки диалогового окна, имеющие стандартный вид на каждой
из платформ. Вместо команд мы можем добавить следующие обработчики
событий:
ondialogaccept="execute('notetaker-save');
execute('notetaker-close-dialog');"
ondialogcancel="execute('notetaker-close-dialog');"
Поскольку диалоговое окно автоматически закрывается при нажатии
кнопки Cancel или кнопки "Закрыть" на заголовке окна, в этих
случаях мы можем обойтись без вызова команды notetaker-close-. В
дальнейшем при необходимости мы сможем добавить обработчик onclose, а
пока нам необходим только ondialogaccept.
Таким образом, нам осталось реализовать команды -open- и -close-.
Пока у нас нет полностью интегрированной панели инструментов, но мы
можем использовать фрагмент XUL для тестирования команд. Функция action() панели инструментов нуждается в очень простом улучшении:
if ( task == "notetaker-open-dialog" )
{
window.openDialog("editDialog.xul","_blank","modal=yes");
}
В данном случае мы используем параметр – главное окно
браузера будет недоступно, пока пользователь работает с диалоговым
окном. Это позволяет нам не беспокоиться о переходах фокуса ввода
между двумя окнами или, что еще хуже, между полями ввода различных
окон.
Столь же простое усовершенствование требуется и для функции action() диалогового окна Edit:
if (task == "notetaker-close-dialog") window.close();
Наконец, мы должны позаботиться об управлении данными. NoteTaker позволяет создавать не более одной заметки для каждого URL и в каждый момент работать только над одной заметкой. Однако само наше приложение уже содержит два окна. Как панель инструментов, так и диалоговое окно содержат поля, в которые пользователь может вводить данные. Какое из окон должно хранить состояние текущей заметки?
Ответ зависит от того, каким образом хранится это состояние. В
последующих лекциях мы познакомимся с хранением данных в формате
var note = {
url : null;
summary : "",
details : "",
chop_query : true, home_page : false,
width : 100, height : 90, top : 80, left : 70
}
Для доступа к этому объекту из диалогового окна Edit используется
следующий простой синтаксис:
window.opener.note
Каждому окну браузера соответствует один такой объект. В дальнейшем к этому объекту можно добавить методы, которые обновляют его свойства на основе данных полей ввода и, наоборот, отображают значения свойств в этих полях. В этом смысле хранение данных является централизованным. Если бы диалоговое окно было более сложным, оно могло бы иметь собственное состояние и специализированные объекты для его представления, но в данном случае в этом нет необходимости.
При использовании свойства opener следует быть осторожным. Хотя с
его помощью мы получаем доступ к другому окну, код JavaScript
продолжает выполняться в контексте текущего окна, которому принадлежит
исходный скрипт. Такие , setAttribute() и другие всегда применяются к текущему окну даже в том
случае, когда их вызывает функция, определенная в другом окне. Листинг
10.4 демонстрирует логику функции action(), определенной в диалоговом
окне.
if (task == "notetaker-save")
{
var field, widget, note = window.opener.note;
for (field in note)
{
widget = document.getElementById("dialog." + field.replace(/_/,"-");
if (!widget) continue;
if (widget.tagName == "checkbox")
note[field] = widget.checked;
else
note[field] = widget.value;
}
}
if (task == "notetaker-load" )
{
var field, widget, note = window.opener.note;
for (field in note)
{
widget = document.getElementById("dialog." + field.replace(/_/,"-");
if (!widget) continue;
if (widget.tagName == "checkbox")
widget.checked = note[field];
else
widget.value = note[field];
}
}
Первая и вторая половины этого листинга выполняют противоположные
действия. Оператор continue позволяет игнорировать те свойства объекта note, которые неизвестны диалоговому окну. Более тщательно подбирая
имена свойств, мы могли бы избежать необходимости замены символов (с
учетом того, что символ "-" является недопустимым в именах
свойств JavaScript), но в данном случае это несущественно. Теперь
объект note основного окна является "официальным"
представлением заметки, а диалоговое окно способно
"загружать" данные из этого объекта и "сохранять"
их в нем. В дальнейшем нам понадобится расширить логику приложения для
того, чтобы сохранять эти данные во "внешнем мире".
Наконец, займемся представлением заметки с точки зрения
пользователя. Цель приложения NoteTaker – позволить снабжать
web-страницы комментариями, поэтому заметка должна отображаться поверх
просматриваемой страницы. Данные заметки хранятся на локальном
компьютере, и ее отображением управляет локальный код, однако страница
может быть загружена с любого сайта. Поскольку наше приложение
установлено в
Такая заметка могла бы быть реализована с помощью XUL, XBL и
JavaScript. Как известно, web-страница в браузере отображается внутри
тега <iframe>, который является содержимым тега <tabbox>,
а тот, в свою очередь, является содержимым тега <tabbrowser>.
Если бы <iframe> был "завернут" в тег <,
мы могли бы расположить нашу заметку в этом стеке поверх web-страницы.
Мы могли бы задать размер и положение заметки при помощи
<box> с
рамкой, фоном и содержимым. Представьте себе записку, приклеенную к
окну, - вы можете видеть сад за окном, хотя часть стекла закрыта
запиской.
Однако эта стратегия потребовала бы от нас изменить XBL-определение
тега <tabbox>. Технически это возможно, однако переопределение
одного из стандартных тегов XUL – серьезный шаг, который требует
значительного тестирования. Фактически, нам пришлось бы проверить
корректность работы нового тега со всеми приложениями, выполняемыми на
платформе Mozilla, включая сам браузер, - слишком много труда для
нашего несложного приложения.
Поэтому мы используем другую стратегию – создание заметки
средствами HTML и CSS. Из приложения, установленного в < с
необходимым содержимым. При помощи стилей может быть задано абсолютное
позиционирование тега, а также большое значение свойства z-index,
которое обеспечит отображение заметки поверх страницы. Существует
незначительная вероятность –около одной миллиардной, - что заметка
окажется перекрыта частью страницы, однако для наших целей этой
величиной можно пренебречь. Данная стратегия хороша тем, что она не
затрагивает остального
Внешний вид заметки NoteTaker показан на Рисунке 10.3. В браузер загружена обыкновенная web-страница.
Следует с осторожностью подходить к выбору используемых возможностей HTML, поскольку мы не знаем, какому именно стандарту будет соответствовать отображаемая страница. В частности, это означает, что код HTML и XML должен быть действительным с формальной точки зрения, поскольку страница может отображаться в режиме строгого соответствия стандартам. В то же время, мы можем использовать любые расширения HTML, характерные для Mozilla, поскольку наше приложение предназначено для данной платформы. Эта ситуация отличается от традиционного подхода к разработке web-страниц, рассчитанных на отображение в различных браузерах. Код HTML для заметки, показанной на рисунке, представлен в листинге 10.5.

(рис 10.5) Пример заметки NoteTaker, реализованной на основе HTML.(рис 10.3) Код HTML для заметки NoteTaker<span id="notetaker-note"> <span id="notetaker-note-summary"> Note Summary </span> <span id="notetaker-note-details"> All the details go here </span> </span>
Строго говоря, нам следовало бы выполнить некоторые дополнительные действия для того, чтобы этот код, добавленный к web-документу, всегда относился к правильному пространству имен. Однако сейчас мы не будем вдаваться в подробности. Стили CSS для этого кода приведены в листинге 10.6.
#notetaker-note {
display : block;
position : absolute;
z-index : 2147483646; /* на один уровень ниже, чем всплывающие меню */
overflow : auto;
background-color : lightyellow;
border : solid;
border-color : yellow;
width : 100px;
height : 90px;
top : 80px;
left : 70px;
}
#notetaker-note-summary {
display : block;
font-weight: bold;
}
#notetaker-note-details {
display : block;
margin-top : 5px;
}
В дальнейшем можно усовершенствовать эту технологию, например,
добавив возможность перетаскивать заметки при помощи мыши, изменять их
размер или редактировать текст непосредственно в заметке. Все это
может быть реализовано при помощи технологий
Для того чтобы просто добавить к web-странице заметку, нам необходимо представить фрагменты кода HTML и стилей CSS в виде строк JavaScript. Вместо того, чтобы жестко закодировать конкретные параметры в тексте программы, мы можем использовать шаблоны, в которых строка вида:
"... width : 100px ..."
представлена как
"... width : {width}px ..."
С помощью регулярных выражений JavaScript мы можем подставить в эту
строку значения, введенные пользователем в панели инструментов или
диалоговом окне Edit. Имея готовую строку, мы можем создать заметку,
как показано на листинге 10.7.
function display_note()
{
var style = generate_style();
var html = generate_html();
var doc = window.content.document;
var stree = doc.getElementById("notetaker-styles");
if ( !stree ) // add the topmost <style>
{
stree = doc.createElement("style");
stree.setAttribute("id","notetaker-styles");
var head = doc.getElementsByTagName('head').item(0);
head.appendChild(stree);
}
stree.innerHTML = style;
var htree = doc.getElementById("notetaker-note");
if ( !htree ) // add the topmost <span>
{
htree = doc.createElement("span");
htree.setAttribute("id","notetaker-note");
var body = doc.getElementsByTagName('body').item(0);
body.appendChild(htree);
}
htree.innerHTML = html;
}
В этом коде используется функция getElementsByTagName() для того,
чтобы получить теги <head> и <body> web-документа – мы не
знаем идентификаторов ( id ) этих тегов. Затем код создает теги для
стилей и заметки, которые добавляет к содержимому тегов <head> и <body> соответственно. Затем специальное свойство innerHTML,
поддерживаемое Mozilla, используется для того, чтобы добавить
остальное содержимое заметки, существующее в форме строки. Для
простоты мы полагаем, что отображаемая страница не является системой
фреймов ( ), а также содержит теги <head> и <body>.
Мы могли бы обойти эти ограничения, но для этого нам пришлось бы лишь
написать больше кода generate_html(), представленная на листинге 10.8, тривиальна; функция generate_style() устроена аналогичным образом.
function generate_html() {
var source =
'<span id="notetaker-note-summary">{summary}</span>' +
'<span id="notetaker-note-details">{details}</span>';
source = source.replace(/\{summary\}/, note.summary);
source = source.replace(/\{details\}/, note.details);
return source;
}
Новый код не так просто протестировать, поскольку для этого необходима его интеграция с браузером. Для корректной интеграции необходимы оверлеи, с которыми мы познакомимся в лекции 12. Пока же нам придется прибегнуть к временному решению – модифицировать код браузера.
Для этого нужно скопировать файл navigator.xul, находящийся в
архиве
mozilla -chrome chrome://notetaker/content/navigator.xul
мы получим обычное окно браузера. Именно эту копию мы и будем
модифицировать. Прежде всего, нужно добавить теги вида <script src=> для всех необходимых скриптов. Затем следует найти строку
вида:
<toolbar id="nav-bar" ...
Этот тег описывает основную панель навигации. Сразу же после указанной строки необходимо добавить следующий тег:
<toolbarbutton label="Test" onclick="display_note()"/>
После того, как мы сохраним и вновь запустим измененный файл, к
панели навигации браузера добавится новая кнопка. Нажатие на эту
кнопку приведет к открытию заметки при условии, что в окно браузера
загружена web-страница. Мы можем использовать для этой кнопки любой
обработчик события onclick, включая обращения к execute(), action() и
любым другим методам. При желании мы можем поместить в этот файл даже
тег < приложения NoteTaker со всем его содержимым.
В ходе тестирования пользователь, прежде чем нажать кнопку, должен дождаться загрузки web-страницы. Однако мы не можем требовать этого от пользователя окончательной версии NoteTaker. Поэтому наше приложение должно самостоятельно определять, загружена ли страница в окно. Самый простой способ – периодически опрашивать главное окно браузера.
function content_poll() {
if ( !window.content ) return;
var doc = window.content.document;
if ( !doc ) return;
if ( doc.getElementsByTagName("body").length == 0 ) return;
if ( doc.location.href == "about:blank" ) return;
if ( doc.visited ) return;
display_note();
doc.visited = true;
}
setInterval("content_poll()", 1000);
Чтобы определить, нужно ли отображать заметку, этот код
периодически исследует содержимое окна. Если в окне нет документа, еще
не загружен тег <body>, в окне содержится пустой документ или
заметка уже отображена, код не делает ничего. В противном случае
загружается заметка для данной страницы.
Итак, посмотрим, чего мы достигли к настоящему моменту. Мы создали окна, которые используются для взаимодействия NoteTaker с пользователем. Текущая заметка представлена в памяти объектом JavaScript. Мы создали логику, связывающую отображаемую заметку с этим объектом, а также обеспечили определенное взаимодействие между окнами. Для того чтобы этот механизм обрел завершенную форму, нам нужно поработать над связью данных, вводимых пользователем, и объектом JavaScript, представляющим заметку. Кроме того, в приложении пока отсутствует корректная работа с URL.
Предполагается, что каждой web-странице соответствует отдельная
заметка. Наше приложение хранит заметки на web-сервере и загружает их
оттуда. Заметка даже перезагружается при перезагрузке страницы.
Существующий механизм подразумевает, что мы должны отправить запрос
web-серверу, чтобы получить текст заметки – это не слишком эффективно.
Единственная альтернатива, которой мы располагаем к настоящему
моменту, – хранить заметки в локальном текстовом файле. Однако
платформа Mozilla предусматривает более эффективное решение – хранение
заметок в виде данных
Прежде чем приступить к обсуждению диагностики окон, следует
сделать одно замечание о работе под Microsoft Windows. В процессе
разработки и
Помочь в диагностике проблемы может тот факт, что окно
К счастью, по мере того, как платформа становится все более зрелой, эта проблема встречается все реже. Однако знать о ней не помешает, это поможет избежать длительного и безрезультатного тестирования. В процессе отладки вы можете столкнуться со многими проблемами, и это лишь одна из них. Причины остальных следует искать в вашем собственном коде.
При
Простейший из них – использовать метод , описанный в лекции 5,
"скрипты". Вывод этого метода отображается в текстовой
консоли, которая открывается при запуске Mozilla с ключом - console.
Почти столь же просто изучать работу приложения при помощи многочисленных панелей отладчика JavaScript. Сначала запустите отладчик вручную. Для знакомства с ним можно открыть все возможные панели, используя меню Вид | Показать / Скрыть. Как можно раньше по ходу исполнения скриптов JavaScript в документе HTML или XUL, который вы хотите отлаживать, добавьте команду:
debugger;
При выполнении этой строки скрипта управление передается отладчику, и с этого момента можно выполнять скрипты пошагово. Следует использовать панель инструментов для управления процессом отладки и внимательно изучать содержимое различных панелей отладчика.
В HTML объект document предоставляет методы open(), close() и write(). Поскольку содержимое начинает отображаться до окончательной
загрузки документа, на основе этих методов можно организовать
последовательный вывод диагностической информации. Окно HTML можно
открыть из другого окна при помощи метода window.open(), а затем по
мере необходимости добавлять к нему содержимое при помощи метода document.write().
XUL не поддерживает последовательного отображения загружаемых
данных в стиле HTML, однако сходного результата можно достичь другими
средствами. При помощи метода window.open() необходимо создать окно
для вывода диагностической информации на основе простейшего документа
XUL. Этот документ не должен иметь никакого содержимого помимо <window orient=". Для добавления содержимого
в это окно следует использовать код, показанный в листинге 10.9:
var win = window.open( …new window …);
function logger(message)
{
var obj = win.document.createElement("description");
var txt = win.document.CreateTextNode(message);
obj.appendChild(txt);
win.document.appendChild(obj);
}
Нужно иметь в виду, что элементы нового документа создаются с
использованием свойств и методов данного, а не исходного документа.
Эту систему можно дополнить полосами прокрутки и другими элементами
управления. Если приложение считается защищенным (т.е. установлено в
// Find the console
var C = Components;
var obj = C.classes["@mozilla.org/consoleservice;1"];
var iface = C.interfaces.nsIConsoleService;
var cons = obj.getService(iface);
// Log a message
cons.logStringMessage("test message");
Аналогичным образом можно организовать вывод на консоль Java.
Преимущество этого метода состоит в том, что консоль Java не является
окном XUL. Для ее использования не требуется браузера, собранного с
возможностью отладки, а также текстовой консоли операционной системы
(которая нужна для вывода при помощи ). Сообщения могут
выводиться на консоль Java, не нарушая состояния существующих окон
XUL. Эта консоль не видна при получении списка открытых окон
средствами XUL. Для вывода сообщения непосредственно на консоль Java
можно использовать следующую старомодную строку, хорошо знакомую
разработчикам со времен
window.java.lang.System.out.println("my message");
Защищенное приложение может самостоятельно создать консоль Java, как показано в листинге 10.11.
var C = Components; var obj = C.classes["@mozilla.org/oji/jvm-mgr;1"]; var iface = C.interfaces.nsIJVMManager; var cons = obj.getService(iface); if (cons.JavaEnabled) cons.showJavaConsole();
Прежде чем открыть окно, этот код проверяет, не отключил ли пользователь подсистему Java в целом.
Система управления окнами в Mozilla разработана под значительным
влиянием технологии, используемой в традиционных браузерах. Применение
метода window.open() и ряда специализированных тегов XUL позволяет
достичь значительных результатов. Эти теги представляют интерес, в
первую очередь, для разработчиков, чьи приложения подобны
браузеру.
Архитектура XPCOM содержит целый ряд интересных объектов для управления отображаемыми документами, среди которых следует особо отметить DocShell. Эти объекты насыщены функциональностью, необходимой для сложной работы с содержимым.
Стили CSS обеспечивают дополнительные возможности настройки окон Mozilla. При помощи стилей разработчик приложения может придать окнам вид, характерный для данной платформы, чтобы приложение не выглядело чужеродным.
Многие из тегов XUL, уже обсуждавшихся в этой книге, носят
статический характер и сходны с тегами для разметки отображаемого
содержимого. Однако приложения часто бывают динамическими и
ориентированными на работу с данными, а не статическими и
ориентированными на отображение содержимого. Mozilla идет навстречу
этим потребностям, предлагая новаторскую поддержку для задач обработки
данных. Мы познакомимся со средствами этой поддержки в нескольких
следующих лекциях, начав с языка
Лишь самые простые приложения могут обойтись единственным окном. По мере развития приложения у разработчика рано или поздно возникает необходимость заменить часть содержимого существующего окна или создать новое. И то, и другое описано в этой лекции.
Разные аспекты платформы Mozilla существенно различаются по
сложности. Работа с окнами очень проста. Средства управления окнами,
доступные приложениям XUL, во многом подобны средствам, используемым в
традиционном web-программировании. Для тех, кому раньше приходилось
использовать метод window.open(), эта лекция будет просто
повторением пройденного. XUL (а также
Mozilla позволяет создавать множество различных типов
самостоятельных окон, начиная с крошечных всплывающих подсказок к
элементам интерфейса ( , в локализациях многих программ они
называются просто "подсказками") и заканчивая сложными
окнами больших приложений. Кроме того, она позволяет создавать внутри
окон другие, "встроенные" окна, в которых могут отображаться
другие документы. В этой книге для таких окон используется термин
"панели". Средства защиты web-браузера накладывают
ограничения на типы встроенных окон, однако эти ограничения не
действуют, если приложение установлено в каталог
Окна Mozilla могут преподнести несколько сюрпризов. Пространства
имен XML позволяют сочетать различные
На схеме в начале лекции показаны элементы архитектуры Mozilla,
имеющие отношение к управлению окнами. Как показано на схеме, это, в
первую очередь, фреймы JavaScript. Документы могут нуждаться в более
сложном контейнере, чем фрейм, описываемый простым тегом <box>,
поэтому существует несколько типов фреймов. В связи с окнами
заслуживают внимания несколько компонентов XPCOM. Но в любом случае,
это несложная тема.
Прежде чем обратиться к новым тегам XUL, мы кратко рассмотрим
хорошо известный тег <window>. Этот тег поддерживает следующие
специальные атрибуты:
sizemode windowtype screenX screenY width height
Атрибут sizemode применим только к тегам <window> (или < ), описывающим окна верхнего уровня. Он отражает
состояние окна на рабочем столе и может принимать значения normal, или maximized (нормальное, свернутое, развернутое на весь
экран).
Атрибут windowtype позволяет задавать группы однотипных окон.
Значением этого атрибута может быть любая строка, определенная
программистом. Атрибут имеет смысл, если одновременно открыто два или
более окон одного и того же типа. При открытии второго и последующих
окон, Mozilla пытается сместить их относительно существующих окон
данного типа. Это сделано для того, чтобы пользователь не
"потерял" однотипные окна из-за их полного перекрытия.
Атрибуты screenX screenY определяют смещение окна в пикселах
относительно левого верхнего угла экрана.
Атрибуты width и height задают высоту и
ширину окна в пикселах.
Ни один из атрибутов screenX, screenY, width, height не может быть изменен после
того, как окно отображено на экране.
Диалоговое окно может быть создано при помощи тега <window>,
как описано ниже в разделе о функции window.open(). Как правило, в
системах семейства UNIX диалоговые окна не являются модальными,
поэтому в специальной семантике диалога необходимости нет. В целом,
при наличии специального тега < для диалогового окна
использование тега <window> для этой цели не имеет практического
смысла.
Окно XUL может перекрываться другим содержимым, заданным в том же документе, ("всплывающим содержимым") при использовании следующих тегов:
<tooltip> <menupopup> <popup> <popupgroup> <popupset>
Однако не все эти теги рекомендованы к использованию, и не все они
применимы в любом месте документа. Так, <menupopup> следует
использовать только внутри тегов <menu> или <menulist>.
Следующие атрибуты других тегов XUL, определяющих элементы интерфейса,
также могут определять различные виды всплывающего содержимого для
этих элементов:
tooltiptext grippytooltiptext popup menu context contextmenu contentcontextmenu
Некоторые из перечисленных атрибутов также объявлены устаревшими.
Тег <menupopup> рассматривается в лекции 7 "Формы и
меню". Прочие теги и атрибуты описываются в этой лекции.
Для создания некоторых визуальных эффектов может использоваться тег <, представленный в лекции 2 "Управление
Система тегов и атрибутов, используемая для всплывающего содержимого, несет на себе отпечаток долгой истории развития Mozilla. Безусловно, лучше использовать современные теги, чем те, которые объявлены устаревшими. Однако и устаревшие теги сейчас корректно обрабатываются, и их поддержка вряд ли прекратится в версиях Mozilla 1.x.
Существует три основных типа всплывающих окон: всплывающие подсказки, контекстные меню и обычные меню.
При использовании большинства современных тегов содержимое,
описывающее всплывающие подсказки и контекстные меню, следует помещать
внутрь тега <popupset>. Это тег, который не имеет собственного
визуального отображения и используется для организации других тегов,
подобно тегу <keyset>. При необходимости в документе XUL может
быть несколько тегов <menupopup>.
Всплывающая подсказка определяется при помощи тега <,
а контекстные меню – посредством тега <menupopup>. Обычные меню
также могут быть описаны внутри тега <popupset> при помощи <menupopup>, однако рекомендуется использовать для создания
обычных меню другие средства – теги <menu> и <menulist>.
Традиционной, но устаревшей практикой является описание контекстных
меню при помощи тега <popup>. Редко встречающиеся теги < и <popupset> еще более архаичны. Эти и другие
теги могут быть заключены в очень старый тег <popupgroup>. Этот
тег может использоваться в пределах документа только один раз. Не
стоит задействовать ни один из этих трех тегов, хотя <popup> все
еще широко применяется при описании интерфейса Mozilla. Они объявлены
устаревшими, и для них существуют современные альтернативы.
Всплывающая подсказка – небольшое окно, которое появляется над элементом графического интерфейса, если курсор мыши задерживается над ним некоторое время (как правило, около секунды). Смысл использования этого средства – дать пользователю краткое пояснение к элементу интерфейса, назначение которого может быть непонятно (в силу неудачного дизайна), или который может быть частично скрыт. Вид всплывающей подсказки может быть полностью переопределен, так что традиционный желтый цвет не является обязательным.
Тег < поддерживает следующие атрибуты:
label crop default titletip
Если < не имеет содержимого, его текст определяется
значением атрибута label. Атрибут
Если значение атрибута default - true, данная подсказка является
всплывающей подсказкой по умолчанию для всего документа. Если атрибут titletip имеет значение true, всплывающая подсказка отображается для
элемента интерфейса в том случае, если он частично скрыт. Оба эти
атрибута имеют смысл только для подсказок к заголовкам столбцов тега <tree>.
Тег < может иметь любое содержимое – он функционирует
подобно тегу <. Однако большое количество содержимого для
данного тега не имеет смысла, поскольку пользователь не может
пролистывать это содержимое при помощи мыши или иным способом.
Размерами всплывающей подсказки можно управлять при помощи атрибутов minwidth и minheight, однако это может вызывать проблемы при
размещении элементов в родительском окне, так что использовать эти
атрибуты не рекомендуется.
Чтобы связать всплывающую подсказку с каким-либо элементом
интерфейса, нужно присвоить атрибуту нужного тега значение id
тега <, определяющего подсказку. Сокращенная нотация
позволяет обойтись без специального тега <, задав текст
подсказки в качестве значения атрибута нужного элемента
интерфейса. Еще один вариант – включить тег < в
содержимое тега, описывающего элемент интерфейса, для которого
создается подсказка. В этом случае следует указать для родительского
тега атрибут .
Атрибут contenttooltip, который может использоваться только с тегом <tabbrowser>, определяет подсказку для содержимого этого
тега.
Кроме того, всплывающая подсказка появляется над заголовком окна, если текст заголовка не помещается в него целиком.
Ссылка на элемент интерфейса, к которому относится всплывающая
подсказка, видимая в настоящий момент, может быть получен при помощи
свойства window.tooltipNode.
Контекстное меню – один из видов раскрывающихся меню. Оно выглядит так же, как и прочие меню, но появляется в ответ на "контекстный" щелчок мыши (щелчок правой кнопкой на большинстве платформ, щелчок с удержанием клавиши "Яблоко" на Macintosh). При этом меню появляется в том месте, где находится курсор мыши, а не каком-либо заранее определенном месте документа.
Для создания контекстного меню используется тег <menupopup>,
описанный в лекции 7 "Формы и меню". Чтобы связать меню с
элементом интерфейса, необходимо установить значение атрибута contextmenu этого тега равным значению атрибута id тега <menupopup>. Исключение составляет тег <tabbrowser> - у
него следует устанавливать атрибут contentcontextmenu.
В прошлом для указания контекстного меню различных элементов
интерфейса применялись атрибуты popup, menu и . Сейчас они
объявлены устаревшими, и их использования следует избегать, хотя
атрибут поддерживается до сих пор.
Атрибуты popupanchor и popupalign применимы к контекстным меню так
же, как и к обычным меню, созданным при помощи тега <menupopoup>.
Ссылка на элемент интерфейса, к которому относится контекстное
меню, видимое в настоящий момент, может быть получена при помощи
свойства window.popupNode.
Если в ходе работы приложения возникает необходимость вывести на экран простенький фрагмент данных, логично использовать диалоговое окно. Диалоговое окно представляет собой обычное окно XUL, имеющее весьма ограниченную область применения. Как правило, диалоговые окна не являются независимыми и существуют в контексте какого-либо другого, более значительного окна (т.е. используют его ресурсы).
Диалоговые окна используются в приложениях с двумя основными целями. Первая из них – получить от пользователя данные, необходимые для дальнейшей работы программы. Однако при этом пользователь сталкивается со сложностью логики приложения. Оптимальным для пользователя вариантом является немедленное выполнение отданной команды без каких-либо дополнительных действий с его стороны. Диалоговое окно требует от пользователя принятия дополнительных решений, необходимых для выполнения команды. С точки зрения пользователя это нарушает непрерывность исполнения программы.
Вторая цель применения диалоговых окон – необходимость привлечь внимание пользователя к какой-либо частной задаче или аспекту работы приложения. Как правило, такие диалоговые окна являются модальными – они приводят к остановке работы приложения до тех пор, пока пользователь не решит возникшую проблему. Этот способ нарушает процесс нормальной работы пользователя с программой.
Обе цели не слишком хорошо согласуются с идеей приложения,
рассчитанного на высокопроизводительную работу. В идеальном мире
диалоговых окон не существовало бы вовсе. Опытные разработчики
приложений сводят использование диалоговых окон к минимуму и избегают
отображения бессмысленных для пользователя конфигурационных
параметров. Большое количество диалоговых окон, используемых для
конфигурации, указывает на ошибки в моделировании взаимодействия
пользователя с приложением, допущенные на этапе проектирования. Если
система требует большого количества
Однако если диалоговые окна действительно необходимы, Mozilla представляет развитые средства для работы с ними.
Основой создания диалоговых окон является тег <. Он во
многом подобен тегу <window>, однако обладает дополнительной
функциональностью по сравнению с ним. По умолчанию тег <
создает немодальное окно, которое не блокирует возможность работы с
другими окнами приложения.
Для знакомства с тегом < достаточно в любом документе
XUL заменить тег <window> на <. Нужно иметь в виду,
что тег < рассчитан на использование в
На рисунке 10.1 показаны различные примеры использования тега <. При этом стандартные диагностические стили включены, а
единственным содержимым документа является слово Content внутри тега <description>. Два окна в первом ряду имеют одно и то же
содержимое, заключенное в тег верхнего уровня < и <window> соответственно. Как мы видим, < при
отображении автоматически добавляет тег <box> для своего
содержимого, а также два тега <button>. Во втором ряду показано
диалоговое окно со всеми кнопками, которые предусмотрены для тега <. Для отображения кнопок использовался атрибут buttons
этого тега. В примере, приведенном в последнем ряду, к диалоговому
окну было добавлено дополнительное содержимое – шесть кнопок. Эти
кнопки заменяют стандартные кнопки, которые в данном случае не
отображаются. Обратите внимание на то, что текст у кнопок во втором и
третьем ряду различается. Давайте рассмотрим, каким образом это
сделано.
(рис 10.1) Различные примеры использования тега <dialog>.Тег < определен при помощи XBL. Это определение
предусматривает дополнительные контейнеры для содержимого и кнопки.
Отображение тега также зависит от файла свойств, входящего в состав
< поддерживает следующие атрибуты:
buttonpack buttondir buttonalign buttonorient title buttons
Значением атрибута buttons является список строк, разделенных
запятыми. Также допускаются пробелы между строками. Это строка
параметров, подобная используемой методом window.open(), но в данном
случае ее синтаксис проще. Допустимы следующие значения строк:
accept cancel extra1 extra2 help disclosure
Нужные строки следует просто перечислить через запятую, например:
<dialog buttons="accept,cancel,help"/>
В дополнение к обработчикам событий, предусмотренным для тега <window>, для < можно использовать следующие
обработчики:
ondialogaccept ondialogcancel ondialogextra1 ondialogextra2 ondialoghelp ondialogdisclosure
Атрибут title, как и в случае тега <window>, задает текст
заголовка окна. Атрибуты buttonpack/dir/align/orient служат для
управления контейнером <hbox> диалогового окна, предназначенным
для размещения кнопок. Они аналогичны атрибутам pack/dir/align/orient
обычного контейнера. Атрибут buttons указывает, следует ли отображать
стандартные кнопки диалогового окна.
Эти кнопки отображаются с предопределенным содержимым и имеют
предопределенное поведение. Например, нажатие на кнопку cancel
закрывает диалоговое окно. Кнопки extra1 и extra2 зарезервированы для
использования приложением, однако чтобы задать для них метки,
необходимо переопределить значения, задаваемые в файле свойств. Каждый
из обработчиков событий, перечисленных выше, соответствует одной из
кнопок и запускается при ее активизации (например, при щелчке мышью по
кнопке).
Перечисленные атрибуты тега < позволяют создать все
окна, показанные на рисунке 10.1, кроме последнего. При его создании
был использован атрибут dlgtype, который обычно применяется с тегом <button>.
Значением атрибута dlgtype может быть любой из стандартных типов
кнопок:
accept cancel extra1 extra2 help disclosure
Атрибут dlgtype никак не влияет на отображение кнопки или другого
элемента, с которым он используется. Фактически он служит указанием
для объемлющего тега <. При отображении диалогового окна
его содержимое просматривается на предмет тегов, имеющих атрибут dlgtype. Если такой тег найден, он используется вместо соответствующей
стандартной кнопки диалогового окна. Это обеспечивает необходимую
гибкость при создании диалогов, позволяя разработчику управлять
размещением элементов. В качестве замены стандартных кнопок могут
использоваться только элементы интерфейса, поддерживающие событие command. Если для такого элемента не задана метка, будет
использоваться стандартная строка, заданная для диалогового окна в
файле свойств.
Окно, основанное на теге <, можно открыть тем же
способом, что и любое другое окно. Чтобы создать window.openDialog(), описанный ниже.
Не следует в явном виде задавать размер диалогового окна при помощи
атрибутов width и height.
Хотя определение тега <dialogheader> (заголовок диалогового
окна) включено в <box> с текстовым содержимым. Он не
имеет специального значения в контексте диалогового окна.
Тег <wizard> (мастер) представляет собой специализированный
вариант тега <. <wizard>, а также тег <wizardpage>, обсуждаются в лекции 17 "Развертывание
приложений".
Диалоговые окна могут создаваться Java-апплетами. Фактически при
этом используется платформа Java –
Диалоговые окна могут создаваться и из программ на JavaScript с
использованием ресурсов XPCOM и АОМ/
Разработчики встраиваемых приложений также могут использовать такие
языки как Perl или
Новые окна приложений можно создавать из программ на JavaScript.
Напомним, что интерпретатор JavaScript предоставляет разработчику
приложения глобальный объект. В контексте документа XUL этот объект
имеет свойство window, которое фактически также является глобальным
объектом. Этот объект поддерживает целый ряд методов, которые могут
использоваться для создания окон.
Следует отметить, что иерархия свойств JavaScript, доступная
разработчику на платформе Mozilla, отличается от интерфейсов XPCOM.
Хотя некоторые свойства JavaScript, например window и window.document
выглядят идентичными соответствующим компонентам XPCOM, фактически они
представляют собой самостоятельные конструкции, созданные для удобства
разработчика.
Это существенный момент. У разработчика может сложиться
впечатление, что свойства
Инспектор
Объект window сообщает, что его тип - ChromeWindow. В модели XPCOM
нет такого объекта, хотя существует интерфейс nsIDOMChromeWindow.
Однако свойства и поведение объекта ChromeWindow в большей степени
связаны с интерфейсами nsIJSWindow и nsIDOMWindowInternal.
Механизмы работы JavaScript с окнами ориентированы, в первую
очередь, на традиционного разработчика web-приложений. По умолчанию в
качестве нового окна создается окно приложения Navigator. Это окно
XUL, элементы которого образуют полноценный web-браузер. Оно содержит
панели инструментов, другие элементы интерфейса, некоторые элементы
Окно браузера предоставляет web-разработчику ограниченный набор
window и window.document обеспечивают доступ лишь
к содержимому, находящемуся в панели отображения документа.
Web-разработчик не имеет доступа к содержимому XUL, формирующему интерфейс
браузера; элементы интерфейса за пределами отображаемого документа
являются для него "window.open(). Эти параметры позволяют скрыть некоторые элементы
интерфейса у нового окна, например панели инструментов.
С точки зрения разработчика XUL, окно браузера способно либо
облегчить ему работу, либо оказаться серьезной помехой. Если
разработчик занят незначительным усовершенствованием существующего
браузера (например, добавляет к нему оверлеи), окно браузера
предоставляет его приложению дополнительную функциональность. Однако
при разработке нового приложения вся функциональность браузера может
оказаться ненужным грузом. В этом случае несложные меры (например,
использование ключа - ) позволяют начать "с чистого
окна".
Метод window.open() создает новое окно. Этот интерфейс
target = window.open(URL, name, features);
URL – действительный
name – имя нового окна. Чтобы создать безымянное окно,
следует использовать в качестве этого параметра null или "_blank".
– разделенный запятыми список дополнительных параметров и
их значений (строка параметров), определяющих вид и поведение нового
окна.
Функция возвращает ссылку на объект window созданного окна. При
помощи этой ссылки можно получить доступ к элементам
Строка параметров применяется часто, однако возможные значения параметров документированы плохо, поэтому ниже приводится их полное описание.
Каждый параметр передается в виде пары имя_параметра=значение,
нечувствительной к регистру символов. Значение может быть либо булевым
флагом, либо скалярным (числом). Для булева параметра достаточно
привести его имя без части =значение или указать "имя_параметра=
yes" для того, чтобы присвоить параметру значение
"истина". Любое другое значение, присвоенное параметру,
означает "ложь". В случае скалярного параметра значение
интерпретируется как число, любые символы, следующие за числом,
игнорируются. Пары разделяются запятыми, за которыми могут следовать
дополнительные пробелы, хотя это может привести к проблемам при
отображении HTML-документов в некоторых устаревших браузерах.
Следующий пример иллюстрирует эти правила:
"toolbar,location=yes,menubar=no,top=100, left=100px,width=100cm"
В этом примере новое окно будет иметь панель инструментов (
Строка параметров определяет тип нового окна – будет ли оно окном
браузера (создается по умолчанию) или же окном
chrome
Следующие параметры имеют смысл только для окна браузера:
toolbar location directories personalbar status menubar scrollbars extrachrome
Если указанные параметры или вся строка параметров отсутствуют, считается, что они имеют значение по умолчанию - "истина".
Булев параметр extrachrome определяет, будет ли при создании нового
окна браузера загружено и отображено содержимое, определяемое
пользователем (в классическом браузере – боковая панель или
Следующие параметры могут применяться как к окнам браузера, так и к
окнам
resizable dependent modal dialog centerscreen top left height width innerHeight innerWidth outerHeight outerWidth screenX screenY
Значением по умолчанию, которое используется, если параметр или вся
строка опущены, для параметров и centerscreen является
"истина", а для и – "ложь".
Однако, если текущее окно является модальным, по умолчанию создается
Если новое окно создано с параметром (изменяемый размер),
менеджер окон в системах Microsoft Windows или X11 создает стандартные
<resizer> в
данном окне.
(зависимое) создает дочернее окно – закрытие
родительского окна приводит к закрытию вновь созданного. Новое окно
всегда открывается поверх родительского (окна, код которого вызывает window.open() ).
При использовании параметра созданное окно будет модальным.
Родительское окно не может получить фокус ввода до тех пор, пока
Если указан параметр , новое окно будет создано с
единственной кнопкой на заголовке окна – "Закрыть".
Параметр centerscreen обеспечивает расположение нового окна в центре экрана.
Прочие параметры – скаляры, определяющие размер и положение нового
окна. Если из параметров top, left, screenX или screenY указан только один,
соответствующий параметр для второго измерения считается равным нулю.
Параметры, определяющие положение и размер окон браузера,
игнорируются, если был использован атрибут , предназначенный
для окон классического браузера.
Следующие параметры имеют смысл только для окон, созданных с
необходимыми привилегиями защиты, например из приложения,
установленного в
titlebar close alwaysLowered z-lock alwaysRaised minimizable
Значение по умолчанию двух первых параметров – "истина",
остальных – "ложь". titlebar обеспечивает добавление
элементов окна, создаваемых close
обеспечивает создание кнопки "Закрыть" на заголовке окна.
Если указаны параметры alwaysLowered или z-lock, окно будет оставаться
на заднем плане, получая фокус ввода; если указан параметр alwaysRaised, окно будет оставаться на переднем плане при потере
фокуса. Параметр minimizable, по всей видимости, никак не меняет
поведение окна.
Если параметр close имеет значение "ложь", пользователь,
тем не менее, может закрыть окно средствами
Метод window.openDialog() доступен лишь в том случае, если он
вызывается из документа, который считается защищенным, например
установленного в window.open(), и приводит практически к тем же
результатам.
target = window.open(URL, name, features, arg1, arg2,...);
arg1, arg2 и т.д. – любые аргументы, допустимые для функций на
JavaScript. В новом окне они доступны как элементы массива window..
Фактически, метод openDialog() эквивалентен методу window.open() с
параметрами ". Это поведение можно
переопределить, присвоив какому-либо из этих параметров в явном виде
значение "ложь". openDialog() также поддерживает параметр all. Если указать его в строке параметров, новое окно будет создано со
всеми элементами, позволяющими пользователю управлять окном. В
частности, на заголовке окна будут доступны кнопки "Закрыть"
и "Свернуть".
В окне классического браузера тегом XUL c id="content"
является тег <tabbrowser>, соответствующий панели для
отображения web-документа. Этот тег недоступен для web-разработчика,
однако весьма полезен для разработчика приложений на основе браузера.
Он предоставляет обширную функциональность, которая может быть
использована в программах, и заслуживает внимательного изучения при
помощи Инспектора
Если окно является обычным окном браузера на основе XUL, указанный
объект <tabbrowser> доступен как свойство content объекта window. Объект, доступный таким образом, не только реализует интерфейс nsIWebNavigation, но и имеет свойство document, указывающее на
документ HTML (или XML), который отображается в текущей вкладке
браузера.
Интерфейс nsIWebNavigation содержит все методы, необходимые для
управления web-документами, отображаемыми в данной панели – их
загрузки, перезагрузки и перемещения между ними. Объект AOM <tabbrowser> имеет свойство webNavigation, обеспечивающее доступ
к этому интерфейсу. Наиболее полезным методом является loadURI(),
который во многом сходен с объектом , речь о котором шла
в лекции 7 "Формы и меню". Основное различие между ними
состоит в том, что просто возвращает ответ на
HTTP-запрос в виде данных, в то время как loadURI() отображает полученный
документ в окне. Одновременно метод задействует другие функции
классического браузера, например, добавляет полученный документ к
истории посещений. loadURI() такова:
void loadURI(uri, flags, referrer, postData, headers)
–
flags (по умолчанию null ) – набор однобитовых флагов, определяющих
поведение при загрузке документа. Отдельные флаги доступны как
свойства объекта webNavigation, имеющие префиксы LOAD_FLAGS, и имеют
различную семантику – не использовать копию документа из кэша,
перезагрузить страницу и т.п.
referrer (по умолчанию null ) –
postData (по умолчанию null ) – строка данных POST, передаваемая в
составе HTTP-запроса.
headers (по умолчанию null ) – строка дополнительных заголовков
HTTP-запроса.
Последние два аргумента редко применяются в программах на
JavaScript. Если вам необходимо использовать их, предаваемую строку
следует преобразовать в объект, соответствующий интерфейсу nsIInputStream. Пример того, как это можно сделать, показан на
листинге 10.1.
var str, C, obj, iface, arg;
str = "put data here";
C = Components;
obj = C.classes["@mozilla.org/io/string-input-stream;1"];
iface = C.interfaces.nsIStringInputStream;
arg = obj.createInstance(iface);
arg.setData(str, str.length);
loadURI("page.cgi", null, null, arg, null);
Эти три метода объекта window позволяют создавать простейшие
диалоговые окна для взаимодействия с пользователем. Метод alert()
создает окно с сообщением и единственной кнопкой. Метод
позволяет пользователю сделать выбор, нажав одну из кнопок, а метод prompt() служит для получения от пользователя данных. Кроме того,
метод alert() является простейшим способом создать точку прерывания в
вашем коде на JavaScript – выполнение приостанавливается до того
момента, когда окно будет закрыто.
Механизм создания этих окон был переработан в процессе создания
Mozilla. В printf() в стиле языка C. В них не поддерживаются символы
Пунктирными контурами на рисунке показаны элементы, соответствующие
тегам <description>. Чтобы изучить структуру окон, нужно
добавить отладочные стили к файлу userChrome.css в каталоге профиля
пользователя, а затем перезапустить платформу. Окно на рисунке было
получено при помощи следующей строки кода:
alert("Line 1\nLine2");
(рис 10.2) Структура XUL диалогового окна alert().Mozilla разбивает строку, переданную методам alert(), и prompt(), согласно <description> где, в свою очередь, может
отображаться в несколько строк. Максимальная ширина тега <description> (свойство maxwidth ) – 45 <description> с id="info.header" может использоваться
разработчиком.
Эти диалоговые окна определены в commonDialog внутри архива
Методы alert(), и prompt() используют для создания
диалоговых окон следующие компонент и интерфейс XPCOM:
@mozilla.org/embedcomp/prompt-service;1 nsIPromptService
Объект с помощью этой пары может быть создан лишь из документа, который считается защищенным. Этот объект позволяет создавать множество различных диалоговых окон, которые перечислены в таблице 10.1.
Интерфейс nsIPromptService содержит обширную документацию по
аргументам каждого из этих методов. Создавая приложение для установки
в alert(),
предназначены для скриптов внутри HTML-документов.
| Имя метода | Диалоговое окно |
|---|---|
alert() |
Обычное окно alert(). |
alertCheck() |
Обычное окно alert(), но с дополнительной строкой, содержащей флажок и текст |
|
Обычное окно |
confirmCheck() |
Обычное окно , но с дополнительной строкой, содержащей флажок и текст |
confirmEx() |
Полностью настраиваемое диалоговое окно, содержащее до трех кнопок со стандартными метками или метками, определенными пользователем. Дополнительно может содержать флажок и текст |
prompt() |
Обычное окно prompt() |
promptUsernameAndPassword() |
Диалоговое окно с полями ввода для имени пользователя и пароля. Дополнительно может содержать флажок и текст |
promptPassword() |
Диалоговое окно с полем ввода для пароля. Дополнительно может содержать флажок и текст |
select() |
Диалоговое окно со списком, из которого может быть выбран один элемент. Каждый элемент списка представляет собой простой текст |
В Mozilla определены несколько специализированных диалоговых окон,
которые описаны в архиве
Каждое из этих окон имеет соответствующий компонент XPCOM и должно
управляться при помощи интерфейсов XPCOM, а не посредством URL
документов
Ниже кратко рассмотрены два из них.
FilePicker представляет собой пару из компонента и интерфейса
XPCOM, а также набор диалоговых окон. В некоторых случаях эти окна
основаны на XUL, но могут использоваться и стандартные окна выбора
файла, предоставляемые операционной системой. В последнем случае это
окно не может быть исследовано при помощи Инспектора
Для создания окна используется следующая пара XPCOM:
@mozilla.org/filepicker;1 nsIFilePicker
Как легко убедиться, просмотрев соответствующий файл XPIDL,
интерфейс nsIFilePicker предоставляет ряд простых методов для работы с
диалоговым окном. Чтобы воспользоваться окном, нужно выполнить
следующие действия:
init().show(). При этом будет создано FilePicker.Последний этап является не вполне тривиальным, поскольку информация
о выбранном файле не может быть передана в виде простой строки,
содержащей путь. Это связано с тем, что в некоторых операционных
системах, чтобы однозначно идентифицировать файл, следует указать не
только путь, но и устройство. Специализированные объекты и интерфейсы
платформы для работы с файлами описаны в лекции 16 "Объекты
XPCOM". Рекомендуется ознакомиться с ними, прежде чем приступать
к использованию объекта FilePicker.
В листинге 10.2 приведен пример получения от пользователя имени
файла для вывода данных при помощи объекта FilePicker.
var Cc = Components.classes; var Ci = Components.interfaces; var fp; fp = Cc["@mozilla.org/filepicker;1"]; fp = fp.createInstance(Ci.nsIFilePicker); fp.init(window, "Example File Save Dialog", fp.modeSave); fp.show(); // fp.file содержит объект nsILocalFile, указывающий на выбранный файл
Платформа Mozilla предоставляет ряд объектов для взаимодействия с системой печати, а также несколько диалоговых окон на основе XUL для задания параметров печати. Примерно с версии 1.3 Mozilla позволяет распечатывать документы XUL, отображаемые в окне браузера, подобно обычным HTML-документам.
Система печати Mozilla довольно сложна, и ее обсуждение выходит за
рамки данной книги. В качестве отправных точек для самостоятельного
изучения системы печати можно порекомендовать интерфейсы XPCOM nsIPrintingPromptService и nsIWebBrowserPrint.
Вместо создания нового окна при необходимости отобразить новое
содержимое, можно создать в пределах существующего окна панель и
динамически управлять ее содержимым. В качестве аналогии можно
привести обычный
XUL позволяет отображать в определенной области окна документ, независимый от основного окна. Для этого предусмотрено несколько тегов.
Тег <iframe> лежит в основе механизма включения одних
документов в другие на платформе Mozilla. Он во многом подобен тегу
HTML <iframe>, однако менее гибок. Между открывающим и
<iframe> не может находиться никакого
содержимого. Элементом интерфейса, соответствующим тегу <iframe>, является фрейм, в который может быть загружен
независимый документ. При этом фокус ввода может быть передан
содержимому этого фрейма. Размеры последнего можно задавать и изменять
так же, как и для любого элемента-контейнера:
<iframe minwidth="100px" flex="1" src="about:blank"/>
Специфичным для <iframe> является только атрибут src, который
задает URL документа для отображения в <iframe>. Также полезно
указать значение атрибута name, чтобы документ, загруженный во фрейм,
мог обращаться к нему.
В лекции 8 "Навигация" было отмечено, что тег <scrollbox> является особой разновидностью контейнера, которой
соответствует отдельный интерфейс XPCOM. То же самое справедливо и для
тега <iframe>. Это единственная реализация компонента,
называемого
@mozilla.org/layout/xul-boxobject-iframe;1
Объект AOM, соответствующий тегу <iframe>, имеет свойство boxObject, как и все остальные объекты – контейнеры XUL. Как и в
случае с тегом <scrollbox>, при помощи метода boxObject.QueryInterface() можно получить специализированный
интерфейс, который для тега <iframe> называется nsIIFrameBoxObject. Хотя этот тег имеет единственное свойство, docShell, оно, в свою очередь, обеспечивает доступ к интерфейсу nsIDocShell, который обладает богатой функциональностью.
DocShell означает "Document Shell", [, или командная строка DOS являются
оболочками для доступа к командам операционной системы.
Многочисленные свойства и методы интерфейса nsIDocShell
обеспечивают доступ к основным операциям, необходимым для загрузки
документа и управления его отображением. Кроме того, этот документ
предоставляет доступ к другим интерфейсам, также полезным для
управления документами. В некотором смысле интерфейс nsIDocShell похож
на водительское кресло автомобиля – большинство средств управления
находятся в непосредственной досягаемости. Этот интерфейс хорошо
документирован и заслуживает хотя бы беглого ознакомления. Информация
о нем содержится в загружаемых файлах, упомянутых во
"Введении".
В большинстве случаев разработчик использует интерфейс nsIDocShell,
автоматически возникающий в результате загрузки какого-либо документа.
Только в сложных проектах у разработчика может возникнуть
необходимость вручную создавать оболочку документа и управлять
загрузкой документа на низком уровне.
Содержимое фрейма, заданного тегом <iframe>, должно иметь
статус отдельного документа XML, в отличие от большинства тегов-
контейнеров, содержимое которых определяется их потомками в исходном
документе XUL. <iframe> является важнейшим тегом, лежащим в
основе браузера Mozilla – именно с его помощью реализована панель, в
которой отображаются загружаемые документы.
Таким образом, тег <scrollbox> дополняет обычный контейнер
возможностью прокрутки содержимого (часть документа XML) в
отображаемой области. Дополнительные возможности тега <iframe>
гораздо шире – он предоставляет различные способы управления
содержимым (отдельным документом XML) и его отображением. В обоих
случаях сама отображаемая область представляет собой простой
прямоугольник без какого-либо дополнительного оформления.
XBL-определение тега <iframe> содержится в файле general.xml
архива nsIDocShell:
docShell contentWindow webNavigation contentDocument
docShell является отправной точкой для управления содержимым
фрейма. Еще три свойства являются эквивалентами свойств JavaScript window, window.webNavigation и соответственно для
содержимого фрейма.
Свойство commandDispatcher, которое есть у любого документа XUL,
имеет метод advanceFocusIntoSubtree(), с помощью которого можно
передать фокус ввода содержимому тега <iframe>, если оно
способно получить фокус.
Если документ, содержащийся во фрейме, шире или выше, чем область
отображения фрейма, будут показаны полосы прокрутки. У всякого
документа XUL, отображаемого в <iframe>, корневым тегом должен
быть <page>. Теги <iframe> могут быть вложенными, при
условии, что каждый из них содержит самостоятельный
Тег <page> (страница) следует использовать вместо тега <window> в том случае, когда документ XUL предназначен для
отображения внутри <iframe>. Тег <page> не имеет
специализированных атрибутов.
Хотя документ с тегом <page> может отображаться в виде
отдельного окна, такая практика не рекомендуется. Этот тег
предназначен для документов, отображаемых во фреймах.
Тег <editor>, подобно тегу <iframe>, представляет собой
специализированный контейнер для отображения отдельного документа.
Единственным специализированным атрибутом этого тега является src,
который указывает на URL отображаемого документа. Некоторые версии
Mozilla поддерживают также атрибут editortype, который может принимать
значения "html" или "txt". Кроме того, существует
атрибут type, который может принимать значения "content" или "content-primary". В последнем случае свойство window.content указывает на свойство contentWindow тега <editor>. Этому тегу соответствует следующая пара XPCOM:
@mozilla.org/layout/xul-boxobject-editor;1 nsIEditorBoxObject
Интерфейс nsIEditorBoxObject поддерживает всю ту же
функциональность docShell, что и тег <iframe>, а также богатую
функциональность интерфейса nsIEditor, доступную через свойство editor. Интерфейс nsIEditor предоставляет все возможности, необходимые
для реализации визуального редактирования HTML-документов – выделение
текста, копирование и т.д. Тег <editor> лежит в основе
классического Компоновщика подобно тому, как тег <iframe> лежит
в основе браузера.
Тег <editor> не предоставляет дополнительных элементов
управления для редактирования документа.
<browser> – еще один специализированный тег, который, подобно
тегу <iframe>, предназначен для отображения независимых
документов и имеет атрибут src. <browser> является
тегом-контейнером, ему соответствует следующий компонент XPCOM:
@mozilla.org/layout/xul-boxobject-browser;1
Этот компонент реализует интерфейс nsIBrowserBoxObject, во многом
сходный с интерфейсом nsIIFrameBoxObject. Вообще, теги <browser>
и <iframe> имеют много общего.
Тем не менее, тег <browser> имеет отдельное XBL-определение,
которое содержится в файле browser.xml архива <iframe>
решаются путем нескольких обращений к различным интерфейсам, свойствам
и методам, в случае <browser> часто требуют вызова единственного
метода. В XBL-определении метода <browser> также предусмотрены
поддержка истории просмотра документов, средств защиты и
перетаскивания при помощи мыши.
Кроме того, <browser> поддерживает режим каретки (текстового
курсора), который активизируется нажатием клавиши F7. В этом режиме,
как в текстовом редакторе, пользователь может перемещать по HTML-
странице курсор.
Тег <iframe> лучше использовать в тех случаях, когда нужно
загрузить во фрейм единственный документ, который затем не будет
изменяться. <browesr> более удобен, если предполагается
последовательно загружать во фрейм разные документы или необходимо
обеспечить
Подобно тому, как <browser> является переработанным вариантом
тега <iframe>, тег <tabbrowser> (браузер с вкладками)
представляет собой усовершенствованный <browser>. В отличие от
двух других тегов, <tabbrowser> не имеет соответствующего
компонента XPCOM. Фактически, он представляет собой одно большое XBL-
определение в файле tabbrowser.xml архива
<tabbrowser> является комбинацией тегов <tabbox> и <browser>. Каждая вкладка тега <tabbox> содержит отдельный <browser>, причем вкладки можно динамически добавлять и удалять.
Именно <tabbrowser> лежит в основе области отображения
web-документов в окне классического браузера.
Тег <tabbrowser> имеет следующие специализированные свойства:
onnewtab contenttooltip contentcontextmenu
Свойство onnewtab – обработчик событий, который запускается, когда
пользователь создает новую вкладку при помощи меню или специальной
кнопки. Значения двух других атрибутов передаются тегам <browser>, находящимся на вкладках в качестве атрибутов
и contextmenu соответственно.
Хотя с помощью многочисленных методов можно автоматизировать работу
с тегом <tabbrowser>, как правило, в этом нет практического
смысла. Этот тег предназначен для пользователя, просматривающего
несколько web-документов. Максимум того, что обычно бывает нужно
разработчику – получить информацию о текущем
Эти теги HTML или XHTML используются при создании web-страниц для помещения документов во фреймы. Внутри такого фрейма может отображаться и документ XUL.
Существует несколько комбинаций тегов, которые игнорируются при отображении документов во фреймах.
По умолчанию в документе XUL игнорируется тег <html>. Он
обрабатывается так же, как любой тег, определенный пользователем.
Некоторую пользу из этого тега можно извлечь, применяя пространства
имен XML, как описано ниже в разделе "Составные
документы".
Тег <window>, являющийся потомком другого тега XUL, также
игнорируется. Теги верхнего уровня - <window>, <, <page> - не могут быть вложенными, за исключением того случая,
когда они относятся к отдельным документам, отображаемым во фреймах <iframe>.
Атрибут chromehidden тега <window> не имеет практического
значения для разработчика приложений. Он устанавливается из метода window.open() и используется внутренним механизмом работы с панелями
инструментов в классическом браузере. Атрибут windowtype, которому
может быть присвоено строковое значение, используется для управления
окнами (см. раздел "Управление существующими окнами"). Он не
влияет на отображение окна.
Тег <package>, который иногда упоминается в устаревшей
документации, в настоящее время не используется.
Можно объединять несколько различных документов в один, не изолируя
их друг от друга при помощи тега <iframe>.
Очень мощная, хотя и сложная в использовании особенность Mozilla –
способность отображать документ, теги которого относятся к различным
стандартам (типам документов XML). Это означает, что один документ
может объединять, например, содержимое HTML,
Случаи смешивания содержимого различных типов в одном документе можно условно разделить на "поверхностное" и "глубокое" смешивание. В последнем случае более вероятны проблемы с отображением документов.
В случае поверхностного смешивания документ состоит из нескольких
фрагментов, каждый из которых относится к отдельному
Глубокое смешивание означает, что в документе невозможно выделить
крупные фрагменты, относящиеся к различным стандартам. В таком
документе разные
Поверхностное смешивание, как правило, не создает проблем с
отображением документов. При глубоком смешивании проблемы возникают
довольно часто. Наименее рискованным является глубокое смешивание HTML
и MathML. Смешивание XUL с HTML или MathML требует осторожности, а
глубокое смешивание
Смешивание различных типов содержимого может быть весьма полезным, но требует осторожности. На то есть несколько причин:
Иногда возникает соблазн просто добавить к документу XUL тег HTML <A HREF=>, чтобы создать в окне справки ссылку на сайт
разработчика. Вы можете добавить к документу тег HTML <FORM> и
автоматически отправлять данные формы из XUL. Однако и в том, и в
другом случае можно обойтись без всякого HTML. Необходимо следить за
"чистотой" своего XUL.
Более поздние стандарты createElementNS() и getAttributeNS(). NS в их именах
означает namespace (пространство имен). Эти методы позволяют при
работе с тегами и атрибутами XML указывать для них конкретное
пространство имен.
Тег < подобен усложненной версии директивы #include
языков C/C++. Он позволяет объединить несколько документов XUL в один,
используя атрибут id. Эта технология описана в лекции 12 "Оверлеи
и
В процессе работы приложения может возникнуть необходимость
обратиться к ранее созданным окнам. Например, команда File | в меню Инспектора
Попытка жонглировать множеством независимых окон может привести к
неудачной архитектуре приложения. В большинстве случаев пользователь
может закрыть любое окно в любой момент. При этом удаляется вся
информация о состоянии приложения, связанная с эти окном (возможно, за
исключением и в строке параметров метода window.open(). Возможно, однако, что
приложение должно следовать метафоре рабочего стола, когда независимые
документы находятся в независимых окнах. В этом случае либо все окна
должны быть полностью независимы друг от друга без возможности
взаимодействия, либо приложение должно иметь возможность установить,
какие окна открыты в настоящий момент.
Mozilla предоставляет несколько компонентов и интерфейсов для управления окнами. Простейшей парой является следующая:
@mozilla.org/appshell/window-mediator;1 и nsIWindowMediator
Этот интерфейс позволяет получить список окон, открытых в данный
момент. К моменту выхода версии Mozilla 1.2.1 он не был окончательно
зафиксирован ( frozen ), и существовала возможность того, что в будущем
он несколько изменится. Различные методы этого интерфейса позволяют
получить список окон в разных формах. На листинге 10.3 показано, как
получить статический список окон, открытых в настоящий момент.
var C, obj, iface, mediator, enum, windows; C = Components; obj = C.classes["@mozilla.org/appshell/window-mediator"]; iface = C.interfaces.nsIWindowMediator; mediator = obj.createInstance(iface); enum = mediator.getEnumerator(null); windows = []; // получить список окон, используя полученный объект-перечислитель (интерфейс nsISimpleEnumerator) while ( enum.hasMoreElements() ) windows.push(enum.getNext()); // сделать что-либо с первым окном windows[0].document.GetElementById ...
Чтобы отфильтровать получаемый список окон, методу getEnumerator()
можно передать строку в качестве аргумента. При этом в возвращаемый
список войдут только окна с корневым тегом <html>, <window>, < или <wizard>, чей атрибут windowtype совпадает с этой строкой.
Чтобы включить в список только окна XUL, вместо метода getEnumerator() следует использовать getXULWindowEnumerator().
Обсуждаемый интерфейс также позволяет получить порядок расположения
окон (очередность перекрытия). Минимизированные окна будут перечислены
как находящиеся в самом низу.
В ходе работы приложения окна могут постоянно открываться и
закрываться, и может возникнуть необходимость динамически отслеживать
этот процесс (как это делается для поддержания списка открытых окон в
меню "Окно"). Один из способов сделать это – создать объект-
приемник ( ) для соответствующих событий. Данному объекту,
реализующему интерфейс nsIWindowMediatorListener, сообщается об
открытии и закрытии окон, а также об изменении заголовка окна. Более
сложное решение, требующее некоторого кодирования – использовать
источник данных непосредственно из XUL. Работа с
Платформа Mozilla добавляет к системе стилей
В частности, внешний вид подсказки, определяемой тегом <, как и в случае с <menupopup>, о котором шла
речь в лекции 7 "Формы и меню", определяется значением -moz-popup свойства display.
Свойство -moz-, которое используется для поддержки тем
операционной системы (рабочей среды), может также принимать следующие
значения:
window dialog tooltip caret
Кроме того, существует целая система расширений, которые также могут использоваться для поддержки этих тем. Полезно, когда окна, а особенно - диалоговые окна, создаваемые при помощи XUL, выглядят в точности как собственные окна операционной системы или рабочей среды (например, Windows или GNOME). Диалоговые окна и сами по себе, без экзотических форм и цветов, могут представлять собой раздражающий фактор для пользователя. Поэтому Mozilla включает целый набор расширений, которые позволяют диалоговым и прочим окнам имитировать системные цвета и шрифтовое оформление рабочей среды. Эти расширения могут использоваться в любых правилах стиля, где можно задействовать обычные имена шрифтов или цветов.
Кроме того, Mozilla поддерживает имена шрифтов и цветов,
установленные спецификацией
Продуманное использование этих расширений может сделать приложение XUL неотличимым от приложений, традиционных для данной среды, например написанных для Windows при помощи Visual Basic или для UNIX – на основе библиотеки GTK.
Дополнительные значения для системных цветов, поддерживаемые
Mozilla, перечислены в таблице 10.2. Актуальный список таких
расширений для текущей версии можно найти в файле nsCSSProps.
| Имя системного цвета | Соответствующий элемент | Дополнительные имена цветов для Macintosh |
|---|---|---|
-moz-field |
Фон поля ввода | -moz-mac-focusring -moz-mac-menuselect -moz-mac-menushadow -moz-mac-menutextselect -moz-mac-accentlightesthighlight -moz-mac-accentregularhighlight -moz-mac-accentface -moz-mac-accentlightshadow -moz-mac-accentregularshadow -moz-mac-accentdarkshadow -moz-mac-accentdarkestshadow |
-moz-fieldtext |
Текст в поле ввода | |
-moz- |
Фон диалогового окна | |
-moz-dialogtext |
Текст в диалоговом окне | |
-moz-dragtargetzone |
Цвет, которым выделяется элемент при перетаскивании над ним объекта при помощи мыши | |
-moz-hyperlinktext |
Текст ссылки, например, на Active Desktop в Windows | |
-moz-visitedhyperlinktext |
Текст посещенной ссылки |
Mozilla также поддерживает расширения для
| Имя системного шрифта |
|---|
-moz-window |
-moz-document |
-moz- |
-moz-desktop |
-moz-info |
-moz- |
-moz-button |
-moz- |
-moz-list |
-moz-field |
Исключением является значение -moz-fixed, которому соответствует
моноширинный шрифт. Этот шрифт действительно отображается, причем для
любого заданного размера и, следовательно, для любых значений свойства
CSS font-size.
В ходе этого занятия мы используем различные техники работы с
диалоговыми окнами, чтобы оптимизировать код окна Edit. Мы также
поработаем над взаимодействием основного окна приложения и диалогового
окна Edit. Эти две задачи распадаются на ряд мелких подзадач:
<window> на <dialog > для диалогового окна Edit.<button>, на обработчики, связанные с <dialog >.notetaker-open-dialog для создания диалогового окна Edit при помощи метода window.openDialog().notetaker-close-dialog .Прежде всего, обратимся к окну Edit. Заменить тег <window> на < несложно. Новый корневой тег точно так же позволяет
указать текст для заголовка окна:
<dialog xmlns="http://www.mozilla.org/keymaster/
gatekeeper/there.is.only.xul"
id="notetaker.dialog"
title="Edit NoteTaker Note"
onload="execute('notetaker-load')">
Нам больше не нужно вручную создавать кнопки для окна, поскольку
для < они создаются автоматически. Однако в то же время
мы кое-что теряем – мы не можем просто использовать тег <command> для <, поскольку с каждым тегом можно
связать лишь одну команду. При желании можно было бы отключить
автоматическое <button>
с <command> для каждого из них. Однако логично использовать
собственные кнопки диалогового окна, имеющие стандартный вид на каждой
из платформ. Вместо команд мы можем добавить следующие обработчики
событий:
ondialogaccept="execute('notetaker-save');
execute('notetaker-close-dialog');"
ondialogcancel="execute('notetaker-close-dialog');"
Поскольку диалоговое окно автоматически закрывается при нажатии
кнопки Cancel или кнопки "Закрыть" на заголовке окна, в этих
случаях мы можем обойтись без вызова команды notetaker-close-. В
дальнейшем при необходимости мы сможем добавить обработчик onclose, а
пока нам необходим только ondialogaccept.
Таким образом, нам осталось реализовать команды -open- и -close-.
Пока у нас нет полностью интегрированной панели инструментов, но мы
можем использовать фрагмент XUL для тестирования команд. Функция action() панели инструментов нуждается в очень простом улучшении:
if ( task == "notetaker-open-dialog" )
{
window.openDialog("editDialog.xul","_blank","modal=yes");
}
В данном случае мы используем параметр – главное окно
браузера будет недоступно, пока пользователь работает с диалоговым
окном. Это позволяет нам не беспокоиться о переходах фокуса ввода
между двумя окнами или, что еще хуже, между полями ввода различных
окон.
Столь же простое усовершенствование требуется и для функции action() диалогового окна Edit:
if (task == "notetaker-close-dialog") window.close();
Наконец, мы должны позаботиться об управлении данными. NoteTaker позволяет создавать не более одной заметки для каждого URL и в каждый момент работать только над одной заметкой. Однако само наше приложение уже содержит два окна. Как панель инструментов, так и диалоговое окно содержат поля, в которые пользователь может вводить данные. Какое из окон должно хранить состояние текущей заметки?
Ответ зависит от того, каким образом хранится это состояние. В
последующих лекциях мы познакомимся с хранением данных в формате
var note = {
url : null;
summary : "",
details : "",
chop_query : true, home_page : false,
width : 100, height : 90, top : 80, left : 70
}
Для доступа к этому объекту из диалогового окна Edit используется
следующий простой синтаксис:
window.opener.note
Каждому окну браузера соответствует один такой объект. В дальнейшем к этому объекту можно добавить методы, которые обновляют его свойства на основе данных полей ввода и, наоборот, отображают значения свойств в этих полях. В этом смысле хранение данных является централизованным. Если бы диалоговое окно было более сложным, оно могло бы иметь собственное состояние и специализированные объекты для его представления, но в данном случае в этом нет необходимости.
При использовании свойства opener следует быть осторожным. Хотя с
его помощью мы получаем доступ к другому окну, код JavaScript
продолжает выполняться в контексте текущего окна, которому принадлежит
исходный скрипт. Такие , setAttribute() и другие всегда применяются к текущему окну даже в том
случае, когда их вызывает функция, определенная в другом окне. Листинг
10.4 демонстрирует логику функции action(), определенной в диалоговом
окне.
if (task == "notetaker-save")
{
var field, widget, note = window.opener.note;
for (field in note)
{
widget = document.getElementById("dialog." + field.replace(/_/,"-");
if (!widget) continue;
if (widget.tagName == "checkbox")
note[field] = widget.checked;
else
note[field] = widget.value;
}
}
if (task == "notetaker-load" )
{
var field, widget, note = window.opener.note;
for (field in note)
{
widget = document.getElementById("dialog." + field.replace(/_/,"-");
if (!widget) continue;
if (widget.tagName == "checkbox")
widget.checked = note[field];
else
widget.value = note[field];
}
}
Первая и вторая половины этого листинга выполняют противоположные
действия. Оператор continue позволяет игнорировать те свойства объекта note, которые неизвестны диалоговому окну. Более тщательно подбирая
имена свойств, мы могли бы избежать необходимости замены символов (с
учетом того, что символ "-" является недопустимым в именах
свойств JavaScript), но в данном случае это несущественно. Теперь
объект note основного окна является "официальным"
представлением заметки, а диалоговое окно способно
"загружать" данные из этого объекта и "сохранять"
их в нем. В дальнейшем нам понадобится расширить логику приложения для
того, чтобы сохранять эти данные во "внешнем мире".
Наконец, займемся представлением заметки с точки зрения
пользователя. Цель приложения NoteTaker – позволить снабжать
web-страницы комментариями, поэтому заметка должна отображаться поверх
просматриваемой страницы. Данные заметки хранятся на локальном
компьютере, и ее отображением управляет локальный код, однако страница
может быть загружена с любого сайта. Поскольку наше приложение
установлено в
Такая заметка могла бы быть реализована с помощью XUL, XBL и
JavaScript. Как известно, web-страница в браузере отображается внутри
тега <iframe>, который является содержимым тега <tabbox>,
а тот, в свою очередь, является содержимым тега <tabbrowser>.
Если бы <iframe> был "завернут" в тег <,
мы могли бы расположить нашу заметку в этом стеке поверх web-страницы.
Мы могли бы задать размер и положение заметки при помощи
<box> с
рамкой, фоном и содержимым. Представьте себе записку, приклеенную к
окну, - вы можете видеть сад за окном, хотя часть стекла закрыта
запиской.
Однако эта стратегия потребовала бы от нас изменить XBL-определение
тега <tabbox>. Технически это возможно, однако переопределение
одного из стандартных тегов XUL – серьезный шаг, который требует
значительного тестирования. Фактически, нам пришлось бы проверить
корректность работы нового тега со всеми приложениями, выполняемыми на
платформе Mozilla, включая сам браузер, - слишком много труда для
нашего несложного приложения.
Поэтому мы используем другую стратегию – создание заметки
средствами HTML и CSS. Из приложения, установленного в < с
необходимым содержимым. При помощи стилей может быть задано абсолютное
позиционирование тега, а также большое значение свойства z-index,
которое обеспечит отображение заметки поверх страницы. Существует
незначительная вероятность –около одной миллиардной, - что заметка
окажется перекрыта частью страницы, однако для наших целей этой
величиной можно пренебречь. Данная стратегия хороша тем, что она не
затрагивает остального
Внешний вид заметки NoteTaker показан на Рисунке 10.3. В браузер загружена обыкновенная web-страница.
Следует с осторожностью подходить к выбору используемых возможностей HTML, поскольку мы не знаем, какому именно стандарту будет соответствовать отображаемая страница. В частности, это означает, что код HTML и XML должен быть действительным с формальной точки зрения, поскольку страница может отображаться в режиме строгого соответствия стандартам. В то же время, мы можем использовать любые расширения HTML, характерные для Mozilla, поскольку наше приложение предназначено для данной платформы. Эта ситуация отличается от традиционного подхода к разработке web-страниц, рассчитанных на отображение в различных браузерах. Код HTML для заметки, показанной на рисунке, представлен в листинге 10.5.

(рис 10.5) Пример заметки NoteTaker, реализованной на основе HTML.(рис 10.3) Код HTML для заметки NoteTaker<span id="notetaker-note"> <span id="notetaker-note-summary"> Note Summary </span> <span id="notetaker-note-details"> All the details go here </span> </span>
Строго говоря, нам следовало бы выполнить некоторые дополнительные действия для того, чтобы этот код, добавленный к web-документу, всегда относился к правильному пространству имен. Однако сейчас мы не будем вдаваться в подробности. Стили CSS для этого кода приведены в листинге 10.6.
#notetaker-note {
display : block;
position : absolute;
z-index : 2147483646; /* на один уровень ниже, чем всплывающие меню */
overflow : auto;
background-color : lightyellow;
border : solid;
border-color : yellow;
width : 100px;
height : 90px;
top : 80px;
left : 70px;
}
#notetaker-note-summary {
display : block;
font-weight: bold;
}
#notetaker-note-details {
display : block;
margin-top : 5px;
}
В дальнейшем можно усовершенствовать эту технологию, например,
добавив возможность перетаскивать заметки при помощи мыши, изменять их
размер или редактировать текст непосредственно в заметке. Все это
может быть реализовано при помощи технологий
Для того чтобы просто добавить к web-странице заметку, нам необходимо представить фрагменты кода HTML и стилей CSS в виде строк JavaScript. Вместо того, чтобы жестко закодировать конкретные параметры в тексте программы, мы можем использовать шаблоны, в которых строка вида:
"... width : 100px ..."
представлена как
"... width : {width}px ..."
С помощью регулярных выражений JavaScript мы можем подставить в эту
строку значения, введенные пользователем в панели инструментов или
диалоговом окне Edit. Имея готовую строку, мы можем создать заметку,
как показано на листинге 10.7.
function display_note()
{
var style = generate_style();
var html = generate_html();
var doc = window.content.document;
var stree = doc.getElementById("notetaker-styles");
if ( !stree ) // add the topmost <style>
{
stree = doc.createElement("style");
stree.setAttribute("id","notetaker-styles");
var head = doc.getElementsByTagName('head').item(0);
head.appendChild(stree);
}
stree.innerHTML = style;
var htree = doc.getElementById("notetaker-note");
if ( !htree ) // add the topmost <span>
{
htree = doc.createElement("span");
htree.setAttribute("id","notetaker-note");
var body = doc.getElementsByTagName('body').item(0);
body.appendChild(htree);
}
htree.innerHTML = html;
}
В этом коде используется функция getElementsByTagName() для того,
чтобы получить теги <head> и <body> web-документа – мы не
знаем идентификаторов ( id ) этих тегов. Затем код создает теги для
стилей и заметки, которые добавляет к содержимому тегов <head> и <body> соответственно. Затем специальное свойство innerHTML,
поддерживаемое Mozilla, используется для того, чтобы добавить
остальное содержимое заметки, существующее в форме строки. Для
простоты мы полагаем, что отображаемая страница не является системой
фреймов ( ), а также содержит теги <head> и <body>.
Мы могли бы обойти эти ограничения, но для этого нам пришлось бы лишь
написать больше кода generate_html(), представленная на листинге 10.8, тривиальна; функция generate_style() устроена аналогичным образом.
function generate_html() {
var source =
'<span id="notetaker-note-summary">{summary}</span>' +
'<span id="notetaker-note-details">{details}</span>';
source = source.replace(/\{summary\}/, note.summary);
source = source.replace(/\{details\}/, note.details);
return source;
}
Новый код не так просто протестировать, поскольку для этого необходима его интеграция с браузером. Для корректной интеграции необходимы оверлеи, с которыми мы познакомимся в лекции 12. Пока же нам придется прибегнуть к временному решению – модифицировать код браузера.
Для этого нужно скопировать файл navigator.xul, находящийся в
архиве
mozilla -chrome chrome://notetaker/content/navigator.xul
мы получим обычное окно браузера. Именно эту копию мы и будем
модифицировать. Прежде всего, нужно добавить теги вида <script src=> для всех необходимых скриптов. Затем следует найти строку
вида:
<toolbar id="nav-bar" ...
Этот тег описывает основную панель навигации. Сразу же после указанной строки необходимо добавить следующий тег:
<toolbarbutton label="Test" onclick="display_note()"/>
После того, как мы сохраним и вновь запустим измененный файл, к
панели навигации браузера добавится новая кнопка. Нажатие на эту
кнопку приведет к открытию заметки при условии, что в окно браузера
загружена web-страница. Мы можем использовать для этой кнопки любой
обработчик события onclick, включая обращения к execute(), action() и
любым другим методам. При желании мы можем поместить в этот файл даже
тег < приложения NoteTaker со всем его содержимым.
В ходе тестирования пользователь, прежде чем нажать кнопку, должен дождаться загрузки web-страницы. Однако мы не можем требовать этого от пользователя окончательной версии NoteTaker. Поэтому наше приложение должно самостоятельно определять, загружена ли страница в окно. Самый простой способ – периодически опрашивать главное окно браузера.
function content_poll() {
if ( !window.content ) return;
var doc = window.content.document;
if ( !doc ) return;
if ( doc.getElementsByTagName("body").length == 0 ) return;
if ( doc.location.href == "about:blank" ) return;
if ( doc.visited ) return;
display_note();
doc.visited = true;
}
setInterval("content_poll()", 1000);
Чтобы определить, нужно ли отображать заметку, этот код
периодически исследует содержимое окна. Если в окне нет документа, еще
не загружен тег <body>, в окне содержится пустой документ или
заметка уже отображена, код не делает ничего. В противном случае
загружается заметка для данной страницы.
Итак, посмотрим, чего мы достигли к настоящему моменту. Мы создали окна, которые используются для взаимодействия NoteTaker с пользователем. Текущая заметка представлена в памяти объектом JavaScript. Мы создали логику, связывающую отображаемую заметку с этим объектом, а также обеспечили определенное взаимодействие между окнами. Для того чтобы этот механизм обрел завершенную форму, нам нужно поработать над связью данных, вводимых пользователем, и объектом JavaScript, представляющим заметку. Кроме того, в приложении пока отсутствует корректная работа с URL.
Предполагается, что каждой web-странице соответствует отдельная
заметка. Наше приложение хранит заметки на web-сервере и загружает их
оттуда. Заметка даже перезагружается при перезагрузке страницы.
Существующий механизм подразумевает, что мы должны отправить запрос
web-серверу, чтобы получить текст заметки – это не слишком эффективно.
Единственная альтернатива, которой мы располагаем к настоящему
моменту, – хранить заметки в локальном текстовом файле. Однако
платформа Mozilla предусматривает более эффективное решение – хранение
заметок в виде данных
Прежде чем приступить к обсуждению диагностики окон, следует
сделать одно замечание о работе под Microsoft Windows. В процессе
разработки и
Помочь в диагностике проблемы может тот факт, что окно
К счастью, по мере того, как платформа становится все более зрелой, эта проблема встречается все реже. Однако знать о ней не помешает, это поможет избежать длительного и безрезультатного тестирования. В процессе отладки вы можете столкнуться со многими проблемами, и это лишь одна из них. Причины остальных следует искать в вашем собственном коде.
При
Простейший из них – использовать метод , описанный в лекции 5,
"скрипты". Вывод этого метода отображается в текстовой
консоли, которая открывается при запуске Mozilla с ключом - console.
Почти столь же просто изучать работу приложения при помощи многочисленных панелей отладчика JavaScript. Сначала запустите отладчик вручную. Для знакомства с ним можно открыть все возможные панели, используя меню Вид | Показать / Скрыть. Как можно раньше по ходу исполнения скриптов JavaScript в документе HTML или XUL, который вы хотите отлаживать, добавьте команду:
debugger;
При выполнении этой строки скрипта управление передается отладчику, и с этого момента можно выполнять скрипты пошагово. Следует использовать панель инструментов для управления процессом отладки и внимательно изучать содержимое различных панелей отладчика.
В HTML объект document предоставляет методы open(), close() и write(). Поскольку содержимое начинает отображаться до окончательной
загрузки документа, на основе этих методов можно организовать
последовательный вывод диагностической информации. Окно HTML можно
открыть из другого окна при помощи метода window.open(), а затем по
мере необходимости добавлять к нему содержимое при помощи метода document.write().
XUL не поддерживает последовательного отображения загружаемых
данных в стиле HTML, однако сходного результата можно достичь другими
средствами. При помощи метода window.open() необходимо создать окно
для вывода диагностической информации на основе простейшего документа
XUL. Этот документ не должен иметь никакого содержимого помимо <window orient=". Для добавления содержимого
в это окно следует использовать код, показанный в листинге 10.9:
var win = window.open( …new window …);
function logger(message)
{
var obj = win.document.createElement("description");
var txt = win.document.CreateTextNode(message);
obj.appendChild(txt);
win.document.appendChild(obj);
}
Нужно иметь в виду, что элементы нового документа создаются с
использованием свойств и методов данного, а не исходного документа.
Эту систему можно дополнить полосами прокрутки и другими элементами
управления. Если приложение считается защищенным (т.е. установлено в
// Find the console
var C = Components;
var obj = C.classes["@mozilla.org/consoleservice;1"];
var iface = C.interfaces.nsIConsoleService;
var cons = obj.getService(iface);
// Log a message
cons.logStringMessage("test message");
Аналогичным образом можно организовать вывод на консоль Java.
Преимущество этого метода состоит в том, что консоль Java не является
окном XUL. Для ее использования не требуется браузера, собранного с
возможностью отладки, а также текстовой консоли операционной системы
(которая нужна для вывода при помощи ). Сообщения могут
выводиться на консоль Java, не нарушая состояния существующих окон
XUL. Эта консоль не видна при получении списка открытых окон
средствами XUL. Для вывода сообщения непосредственно на консоль Java
можно использовать следующую старомодную строку, хорошо знакомую
разработчикам со времен
window.java.lang.System.out.println("my message");
Защищенное приложение может самостоятельно создать консоль Java, как показано в листинге 10.11.
var C = Components; var obj = C.classes["@mozilla.org/oji/jvm-mgr;1"]; var iface = C.interfaces.nsIJVMManager; var cons = obj.getService(iface); if (cons.JavaEnabled) cons.showJavaConsole();
Прежде чем открыть окно, этот код проверяет, не отключил ли пользователь подсистему Java в целом.
Система управления окнами в Mozilla разработана под значительным
влиянием технологии, используемой в традиционных браузерах. Применение
метода window.open() и ряда специализированных тегов XUL позволяет
достичь значительных результатов. Эти теги представляют интерес, в
первую очередь, для разработчиков, чьи приложения подобны
браузеру.
Архитектура XPCOM содержит целый ряд интересных объектов для управления отображаемыми документами, среди которых следует особо отметить DocShell. Эти объекты насыщены функциональностью, необходимой для сложной работы с содержимым.
Стили CSS обеспечивают дополнительные возможности настройки окон Mozilla. При помощи стилей разработчик приложения может придать окнам вид, характерный для данной платформы, чтобы приложение не выглядело чужеродным.
Многие из тегов XUL, уже обсуждавшихся в этой книге, носят
статический характер и сходны с тегами для разметки отображаемого
содержимого. Однако приложения часто бывают динамическими и
ориентированными на работу с данными, а не статическими и
ориентированными на отображение содержимого. Mozilla идет навстречу
этим потребностям, предлагая новаторскую поддержку для задач обработки
данных. Мы познакомимся со средствами этой поддержки в нескольких
следующих лекциях, начав с языка
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.