среда, 18 июня 2008 г.

Итак, близятся предварительные итоги первого месяца конкурса. Разработки продолжают поступать, хотя конечно, летнее настроение захватило всех. Напоминаем, что среди призов конкурса — субноутбук ASUS Eee PC, плееры и полезные аксессуары.

Информация для разработчиков, зарегистрированных на beta.pcmag.ru: напоминаем, что в конце месяца информация о текущих версиях разработок, открывается для публичного доступа, так, что пожалуйста, у позаботьтесь об оформлении страничцы (как минимум, рекомендуется заполнить поля "Условия использования" и "Домашняя страница".

воскресенье, 8 июня 2008 г.

Структура гаджета и API

Программные интерфейсы, доступные разработчикам Google Gadgets (как «унаследованный», так и gadgets.*), ясно структурированы и позволяют реализовать практически любые идеи. Единственное ограничение накладывается скорее соображениями скорости работы и требованиями к пропускной способности каналов связи. Строго говоря, возможность подключения внешних модулей предоставляет возможности создать гаджет даже с трехмерной интерактивной игрой (благо, сегодня существуют «движки» 3D-графики для онлайновых применений). И это первое, о чем следует помнить разработчику.

Рассмотрим особенности внутренней организации гаджета и доступные API на примерах разработок, представленных на конкурс гаджетов, организованный компаниями Google и журналом PC Magazine/RE (подробнее о конкурсе можно прочитать в блоге проекта, http://ru-googlegadget.blogspot.com/).

Самый простой способ создания гаджета — воспользоваться заранее подготовленными экранными формами, доступными с персональной страницы iGoogle. Работа с ними предельно проста: достаточно заполнить несколько полей, получить код или кликнуть по ссылке добавления гаджета на Web-страницу. В то же время такие разработки не представляют особого интереса, поскольку их функциональность довольно невелика.

Разработчику, желающему воплотить более оригинальную идею, чем трансляция RSS-потока или демонстрация фотографий из Flickr, целесообразно воспользоваться онлайновым редактором, размещенным по адресу http://code.google.com/intl/en/apis/gadgets/docs/legacy/gs.html#GGE. Эта утилита, помимо базовых функций редактирования программного текста, содержит большой набор примеров — зачастую после их изучения можно обойтись даже без чтения документации; как уже говорилось, структура API вполне стройна и очевидна.

Обратите внимание: XML-файл должен предоставляться в кодировке UTF-8. Теоретически можно указать и другие кодировки, однако в этом случае API ядра системы управления гаджетами может работать некорректно (русские буквы просто преобразуются в спецсимволы HTML). При необходимости использовать русский язык в текстах (например, в диалогах) файл следует конвертировать в UTF-8 (а лучше использовать специальные функции подсистемы «интернационализации», но их мы рассмотрим в следующих обзорах). Самый наглядный способ — просто скопировать исходный текст гаджета в окно редактора и сохранить файл (он автоматически будет размещен на сервере Google).

Чрезвычайно полезная возможность, реализованная в редакторе, — предварительный просмотр. Разработчик может оперативно оценить внешний вид своей разработки и, что важнее, ее работоспособность. Кроме того, там же можно загрузить завершенную программу в глобальный каталог гаджетов Google.

Структура XML вполне очевидна, следует только отметить, если программный код разработки размещается в ее теле (используется тег ), а не во внешнем файле, то его следует обрамлять сигнатурами , указывающими XML-парсеру на то, что это — не часть структуры XML-файла, а данные, которые следует передать для обработки в неизменном виде (CDATA — это Character Data, стандартное XML-определение). Обычно в этом поле содержится не только HTML, но и JavaScript, который и обеспечивает прикладную функциональность гаджета.

Листинг 2. Гаджет, содержащий ссылку на программный модуль


title_url="http://gagdetmaster.
googlepages.com/"
category="games"/>



Разработчик данного гаджета разместил исходный текст программы на собственном сайте, ссылка на который размещена в атрибуте href тега . Это позволяет эффективно отделить функциональную часть модуля от интерфейсной. Такой подход накладывает и несколько ограничений. В частности, необходимо в явном виде декларировать необходимые разделы API гаджетов и выполнять специальную обработку адресной строки, передавая параметры вызывающего модуля. Иными словами, роль iGoogle здесь практически сводится к выводу внешнего содержимого в заданном фрейме, ну и небольшой библиотеки полезных функций. Это не то, чего бы хотелось.

В то же время такая техника может быть полезна, если гаджет получается очень объемным и (или) его функциональность вынесена в модули, подготовленные с помощью Flash/Flex, Silverliht и др. (хороший пример: размещение в теле гаджета видеороликов, транслируемых с помощью внешнего Flash-плеера). Тег описывает реквизиты разработки, к этому тегу мы еще вернемся.

Листинг 3. Гаджет, извлекающий данные из RSS- или XML-потока


scrolling="true"
author_email="info@antivirus-digest.net"
author="info@antivirus-digest.net"
width="340" height="230"
description="Рейтинг антивирусов"
thumbnail="http://antivirus-digest.net/img/current_week_antivir.png"/>

function displayRSSData() {
// Адрес RSS/XML-файла для загрузки
var url = "http://antivirus-digest.net/rss.php";
//Загружаем данные, в случае ошибки сообщаем пользователю
_IG_FetchXmlContent(url, function (response) {
if (response == null || typeof(response) != "object" || response.firstChild ==
null) {
_gel("content_div").innerHTML = "Сбой при загрузке";
return;
}
// Начало формирования HTML-текста (часть неинформативных строк, связанных
// с оформлением, в листинге опущена)
var html = "";
//Разбираем полученный массив информации, извлекая ключи и их значения
var itemList = response.getElementsByTagName("item");
for (var i = 0; i < itemList.length ; i++) {
var nodeList = itemList.item(i).childNodes;
for (var j = 0; j < nodeList.length ; j++) {
var node = nodeList.item(j);
if (node.nodeName == "title") {
var name = node.firstChild.nodeValue;
}
if (node.nodeName == "description") {
if (node.firstChild.nodeName == "#cdata-section")
var data = node.firstChild.nodeValue;
}
}
// В цикле добавляем значения переменных в переменную, содержащую HTML-код
html += name;
html += "
";
html += data;
html += "
";

}
html += "
";

// Выводим сформированный HTML-текст
_gel(‘content_div’).innerHTML = html;
});
}
//Важный момент: эта функция обеспечивает извлечение свежих данных из XML-потока
// при загрузке гаджета
_IG_RegisterOnloadHandler(displayRSSData);




Более сложный пример: гаджет, загружающий данные XML с внешнего (по отношению к iGoogle) сайта. Эта разработка была предоставлена проектом «Антивирусный дайджест» (www.antivirus-digest.net). Сайт (на нем размещается рейтинг антивирусов), формируемый, как заявляют создатели, «на основе реальных данных». На сервере размещается виртуальная машина, которая играет роль жертвы для вирусов, «троянов», червей, затем проверяется несколькими антивирусами, после чего формируется еженедельный дайджест успехов разных антивирусных программ в ловле всяческой «заразы». Данные рейтинга доступны в RSS, откуда их и извлекает гаджет.

Логика работы вполне прозрачна: загружается XML (посредством функции _IG_FetchXmlContent), формируется структура записей, откуда и извлекаются данные. Обратите внимание: второй параметр _IG_FetchXmlContent — функция, которая определяется по месту вызова; она содержит практически всю функциональность разработки, связанную с генерацией HTML. Функция _gel — просто короткий синоним для вызова JavaScript document.getElementById(), _IG_RegisterOnloadHandler более интересна — она позволяет зарегистрировать в системе функцию-обработчик события «загрузка гаджета».

API гаджетов разделен на две основные группы: ядро и расширения. Среди функций первой группы — средства и объекты для управления подсистемой хранения пользовательских данных, используемых для настройки параметров гаджета (_IG_Prefs()). Разработчику доступны инструменты для создания типизированных параметров (строка, целое число, булева переменная, массив). Кроме того, там же содержатся API общего назначения, такие, как загрузка текстового и XML-содержимого (что и использовано в листинге 3), средства для управления некоторыми событиями (_IG_RegisterOnloadHandler) и изображениями (_IG_GetImage, _IG_GetCachedUrl).

В «расширенных» библиотеках размещаются группы функций для выполнения специальных задач: динамическая настройка высоты окна гаджета (модуль dynamic-height), управление интерфейсными вкладками (tabs), обработка событий «перетаскивания» (drag), вывод табличных данных (grid), блокировок (locked-domain) и др.