Окна и панели
Внешний вид заметки NoteTaker показан на Рисунке 10.3. В браузер загружена обыкновенная web-страница.
Следует с осторожностью подходить к выбору используемых возможностей HTML, поскольку мы не знаем, какому именно стандарту будет соответствовать отображаемая страница. В частности, это означает, что код HTML и XML должен быть действительным с формальной точки зрения, поскольку страница может отображаться в режиме строгого соответствия стандартам. В то же время, мы можем использовать любые расширения HTML, характерные для Mozilla, поскольку наше приложение предназначено для данной платформы. Эта ситуация отличается от традиционного подхода к разработке web-страниц, рассчитанных на отображение в различных браузерах. Код HTML для заметки, показанной на рисунке, представлен в листинге 10.5.
<span id="notetaker-note"> <span id="notetaker-note-summary"> Note Summary </span> <span id="notetaker-note-details"> All the details go here </span> </span>Листинг 10.5. Код HTML для заметки NoteTaker
Строго говоря, нам следовало бы выполнить некоторые дополнительные действия для того, чтобы этот код, добавленный к 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; }Листинг 10.6. Заметка NoteTaker: код CSS
В дальнейшем можно усовершенствовать эту технологию, например, добавив возможность перетаскивать заметки при помощи мыши, изменять их размер или редактировать текст непосредственно в заметке. Все это может быть реализовано при помощи технологий DHTML, которые не являются предметом данной книги.
Для того чтобы просто добавить к 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; }Листинг 10.7. Создание заметки NoteTaker средствами динамического HTML
В этом коде используется функция getElementsByTagName() для того, чтобы получить теги <head> и <body> web-документа – мы не знаем идентификаторов ( id ) этих тегов. Затем код создает теги для стилей и заметки, которые добавляет к содержимому тегов <head> и <body> соответственно. Затем специальное свойство innerHTML, поддерживаемое Mozilla, используется для того, чтобы добавить остальное содержимое заметки, существующее в форме строки. Для простоты мы полагаем, что отображаемая страница не является системой фреймов ( frameset ), а также содержит теги <head> и <body>. Мы могли бы обойти эти ограничения, но для этого нам пришлось бы лишь написать больше кода DHTML, не узнав ничего нового о Mozilla. Функция 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; }Листинг 10.8. Добавление данных заметки к шаблону средствами DHTML
Новый код не так просто протестировать, поскольку для этого необходима его интеграция с браузером. Для корректной интеграции необходимы оверлеи, с которыми мы познакомимся в "Оверлеи и Chrome" . Пока же нам придется прибегнуть к временному решению – модифицировать код браузера.
Для этого нужно скопировать файл navigator.xul, находящийся в архиве comm.jar в каталоге chrome, в подкаталог notetaker/content каталога chrome. Теперь, запустив Mozilla при помощи следующей команды:
mozilla -chrome chrome://notetaker/content/navigator.xul
мы получим обычное окно браузера. Именно эту копию мы и будем модифицировать. Прежде всего, нужно добавить теги вида <script src=> для всех необходимых скриптов. Затем следует найти строку вида:
<toolbar id="nav-bar" ...
Этот тег описывает основную панель навигации. Сразу же после указанной строки необходимо добавить следующий тег:
<toolbarbutton label="Test" onclick="display_note()"/>
После того, как мы сохраним и вновь запустим измененный файл, к панели навигации браузера добавится новая кнопка. Нажатие на эту кнопку приведет к открытию заметки при условии, что в окно браузера загружена web-страница. Мы можем использовать для этой кнопки любой обработчик события onclick, включая обращения к execute(), action() и любым другим методам. При желании мы можем поместить в этот файл даже тег <toolbar> приложения 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 предусматривает более эффективное решение – хранение заметок в виде данных RDF. Мы обсудим этот вариант во второй части книги.