Комментарии (7) к “Гаджеты для рабочего стола”. Разрабатываем свой Sidebar Gadget

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

Сразу покажу то, что получилось в итоге


Гаджет будет получать информацию с сайта в виде xml, парсить и, собственно, отображать. Также гаджет будет проверять наличие новых версий, и в случае их присутствия, отказываться работать:)
Изначально, ради получения опыта, хотел написать гаджет полностью на VBScript (так как с ним еще не имел дела), но в конечном итоге пришлось делать вставки на JavaScript.
Перейдем непосредственно к коду. Весь код здесь я рассматривать не буду, покажу лишь основные моменты. Ссылка на готовый гаджет – в конце статьи.
Главный файл гаджета – его манифест – файл Gadget.xml. Он должен называться именно так и располагаться в корне нашего архива (гаджет есть ни что иное, как архив ZIP с расширением.gadget).

Weather from Info.Denms.Ru 1.0.1232 Full Weather Widget (Info.Denms.Ru)

Рассмотрим его более подробно.
Элемент должен содержать apiVersion, равный 1.0.0 (на данный момент), а также атрибут src, в котором указан главный файл нашего гаджета;
Разрешения для гаджета. Устанавливаем равным full;
Минимальная версия Widows Sidebar. На данный момент – 1.0;
Параметры - имя гаджета, - версия, - информация об авторе, - ссылка на страницу с гаджетом, - иконка гаджета и будут отображаться на панели установленных гаджетов.

Файл main.html – обычный html файл, приводить его полностью не буду, остановлюсь лишь на некоторых моментах.
С помощью элемента g:background задается фон гаджета. Сделаем его прозрачным.

Гаджет может находиться в двух состояниях – docked (слева на скрине выше), и undocked (справа). Будем хранить текущее состояние гаджета в переменной JavaScript docked.

Функция-обертка isDocked потребуется нам в дальнейшем, чтобы из VBScript узнать текущее состояние гаджета (как я не старался, но реализовать это на чистом VBScript не смог). Еще одно замечание – скрипты корректно работают именно в этом порядке, т.е. сначала описываем скрипты VBScript, потом JavaScript.

Остальные элементы в main.html представлены элементами DIV с абсолютным позицированием. Впоследствии из скриптов мы будем обращаться к ним по их id.

С помощью JavaScript зададим состояния docked и undocked для гаджета, а так же укажем файл настроек (main.js)

System.Gadget.onDock = resize; System.Gadget.onUndock = resize; System.Gadget.settingsUI = "settings.html"; System.Gadget.onSettingsClosed = SettingsClosed; docked=0; //начальное состояние гаджета resize(); //инициализация

Как видно из листинга выше, при смене состояний гаджета будет вызываться функция resize().

Function resize() { bd = document.body.style; System.Gadget.beginTransition(); if (System.Gadget.docked) { // small state bd.width=148; //устанавливаем размеры гаджета bd.height=201; docked = 1; bd.background="url(images/gadget.png) no-repeat"; //устанавливаем фон //далее следует перенос значений из состояния undocked в docked и обнуление элементов для состояния undocked document.getElementById("small_needupdate").innerHTML = document.getElementById("big_needupdate").innerHTML; document.getElementById("big_needupdate").innerHTML = ""; //... } else { // big state bd.width=230; bd.height=160; bd.background="url(images/gadgeth.png) no-repeat"; docked=0; //перенос значений из состояния docked в undocked и обнуление элементов для состояния docked document.getElementById("big_needupdate").innerHTML = document.getElementById("small_needupdate").innerHTML; document.getElementById("small_needupdate").innerHTML = ""; //... } System.Gadget.endTransition(System.Gadget.TransitionType.morph,1); }

Также можно описать функцию сохранения настроек. В моем гаджете их нет, но для примера покажу как это делается

Function SettingsClosed(event) { if (event.closeAction == event.Action.commit) { //alert System.Gadget.Settings.readString("test"); } }

ReadString – читает ранее сохраненную строку, writeString, соответственно, записывает.
Методы System.Gadget.beginTransition(); и System.Gadget.endTransition(); нужны для “плавного» изменения размера гаджета. В Windows Seven они игнорируются , но я все же оставил их для обратной совместимости.

Как уже говорилось выше, сервер предоставляет нам информацию о погоде в формате xml.

1.7 41 пасмурно снег 87 Ю-З 5 -3 -1 -1 26 1 -9 41 0 …

Скачивать и парсить xml будем на VBScript.

Sub DownloadXML2 Set objXML = CreateObject("Microsoft.XmlHttp") objXML.Open "GET", "http://info.kovonet.ru/weather.xml", True objXML.OnReadyStateChange = GetRef("objXML_onreadystatechange") objXML.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" objXML.Send iTimeoutID = window.SetTimeout("mySleep", 1000) End Sub

Функция mySleep будет проверять наше соединение на таймаут.

Sub mySleep if bRespReceived = "false" then "ответ еще не получен iTimeout = iTimeout + 1 if (iTimeout > 30) then "таймаут timerFirstRun = window.SetTimeout("Update", 60000) "попытка повторного обновления через минуту else "таймаут еще не достигнут, продолжаем считать секунды iTimeoutID = window.SetTimeout("mySleep", 1000) end if end if End Sub

В случае успешного скачивания objXML.readyState будет равен четырем, а статус (objXML.status) вернет значение 200.

Function objXML_onreadystatechange() If (objXML.readyState = 4) Then "msgbox objXML.statusText If (objXML.status = 200) Then bRespReceived=true SaveFile(objXML.responseText) else timerFirstRun = window.SetTimeout("Update", 60000) "попытка повторного обновления через минуту End If End If End Function

В этом случае сохраняем файл во временную папку Windows

Function SaveFile(what) Set fso = CreateObject("Scripting.FileSystemObject") tempFolder = fso.GetSpecialFolder(2) filepath = tempFolder+"\weather.xml" Dim fso1, tf Set fso1 = CreateObject("Scripting.FileSystemObject") Set tf = fso1.CreateTextFile(filepath, True, True) "rewrite, unicode tf.Write(what) tf.Close ParseXML End Function

И начинаем парсить файл.

Sub ParseXML Set fso = CreateObject("Scripting.FileSystemObject") tempFolder = fso.GetSpecialFolder(2) filepath = tempFolder+"\weather.xml" Set xmlDoc = CreateObject("Msxml2.DOMDocument") xmlDoc.async="false" xmlDoc.load(filepath) "главная нода – в нашем случае Set currNode = xmlDoc.documentElement "дни недели – Set dayNode = currNode.firstChild While Not dayNode Is Nothing Set currNode = dayNode.firstChild While Not currNode Is Nothing if currNode.parentNode.getAttribute("id") = "today" then "сегодняшний день if currNode.nodeName = "temp" then document.getElementById(prefix+"maintemp").innerHTML = currNode.childNodes(0).text+Chr(176) "отображаем остальные элементы Else "не сегодняшний день, отображаем более мелко "... end If Set currNode = currNode.nextSibling Wend Set dayNode = dayNode.nextSibling Wend End Sub

Проверка на новые версии производится точно таким же способом.
Не забываем создать файл настроек - settings.html, о существовании которого мы объявили выше.

Настройки

Вот, собственно, и все. Буду рад, если моя (первая:)) статья оказалась кому-то полезной.

Использованные источники.

Основные шаги

Здесь описано несколько основных шагов при создании и размещении гаджетов.

  • Составьте спецификацию гаджета в текстовом редакторе, а затем сохраните ее на общедоступном веб-сервере.
  • Добавьте гаджет в контейнер, например iGoogle или Orkut. Контейнер – это приложение или сайт, которые могут выполнять гаджеты.
  • Структура гаджета

    Разобравшись в способах изменения и публикации гаджетов, можно начинать включать в спецификации гаджетов более "продвинутые" функции. XML-cпецификация гаджета состоит из 3 основных частей.

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

    Создавая гаджет, следует начинать с раздела .

    Определение содержания

    Раздел представляет собой "мозг" гаджета. Раздел определяет тип содержания и содержит само содержание или ссылается на внешнее содержание. Раздел – это место, где атрибуты гаджета и пользовательские настройки объединяются с логикой программирования и сведениями о форматировании в работающий гаджет.

    Простейший способ создать гаджет – просто поместить HTML (а возможно и JavaScript или Flash) в раздел . Опытные веб-разработчики могут почитать , где описаны другие варианты контроля доступа, удаленного хостинга, использование других языков создания сценариев и многое другое. Вот простой пример гаджета. В этом гаджете имеется фотография, которую нужно нажать, чтобы открыть фотоальбом на новой странице HTML:

    Определение пользовательских настроек

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

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

    • Имя, используемое в приветствии. Это имя пишется также в строке заголовка.
    • Цвет фона.
    • Нужно ли показывать фотографию.

    Вот как выглядит гаджет, когда пользователь нажимает изменить для изменения пользовательских настроек:

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





    Необходимо учесть следующее.

    Вот весь гаджет, вместе с кодом JavaScript, который отображает текст приветствия для этого гаджета.

    Список атрибутов см. в .

    Пользовательские настройки можно вызывать из своего гаджета с помощью специальных API JavaScript, например:

    var prefs = new gadgets.Prefs(); var someStringPref = prefs.getString("StringPrefName"); var someIntPref = prefs.getInt("IntPrefName"); var someBoolPref = prefs.getBool("BoolPrefName");

    Список всех функций JavaScript см. в .

    Подстановка переменных для пользовательских настроек

    Вы можете использовать подстановку переменных формата __UP_userpref __ в разделах или , где userpref соответствует названию атрибута пользовательской настройки. После запуска гаджета строковое значение соответствующей пользовательской настройки подставляется вместо переменной, без перевода. Например, в этом фрагменте значение, представляемое пользователем во время выполнения для пользовательской настройки projects подставляется вместо __UP_projects__ в строке title_url :

    Ниже приводится общее руководство по применению подстановки переменных для пользовательских настроек.

    • Для атрибута title используйте __UP_name __ . Это переведено в HTML .
    • Для атрибута title_url используйте __UP_name __ . Это переведено в HTML .
    • В HTML в разделе используйте __UP_name __. Это переведено в HTML.
    • В коде JavaScript в разделе используйте функцию gadgets.Prefs() .
    Совместный доступ к настройкам пользователей

    С помощью функции shareable-prefs можно предоставить нескольким пользователям возможность изменять настройки гаджета. Таким образом, пользователи могут совместно пользоваться гаджетом и видеть, кто что изменил. Например, члены семьи могут иметь общий гаджет со списком покупок и каждый человек может добавлять свои любимые продукты. Данные настроек пользователей – часть состояния гаджета, хранящаяся на iGoogle. Дополнительные сведения о пользовательских настройках можно найти в .

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

    Вот код гаджета:

    ]]>

    Добавив на iGoogle гаджет, поддерживающий настройки совместного доступа, его можно сделать доступным для совместного использования следующим образом.

    Шаг 1 : Нажмите треугольник на том гаджете, к которому нужно предоставить совместный доступ, и выберите Открыть доступ к этому гаджету .

    Шаг 2 : Если вы используете Gmail, выберите друзей, которым вы хотите открыть доступ к гаджету или введите их адреса электронной почты.

    Шаг 3: Решите, смогут ли друзья редактировать содержание гаджета или только просматривать его на своих страницах iGoogle.

    • При выборе Просматривать и редактировать содержание друзья смогут редактировать пользовательские настройки гаджета. Их изменения будут отражаться в вашей версии гаджета и во всех остальных совместно используемых версиях этого гаджета.
    • При выборе Просматривать содержание друзья не смогут изменять как сам гаджет, так и его копии на собственных страницах. Только вы сможете изменять гаджет, а ваши изменения будут применены ко всем совместно используемым версиям гаджета.

    Нажмите Отправить приглашения . Друзья получат от вас письмо с приглашением добавить гаджет на свои страницы iGoogle.

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

    Определение настроек гаджетов

    В разделе XML-файла указаны характеристики гаджета (например, название, автор, предпочитаемый размер и т.д.). Например:


    30) then "таймаут timerFirstRun = window.SetTimeout("Update", 60000) "попытка повторного обновления через минуту else "таймаут еще не достигнут, продолжаем считать секунды iTimeoutID = window.SetTimeout("mySleep", 1000) end if end if End Sub

    В случае успешного скачивания objXML.readyState будет равен четырем, а статус (objXML.status) вернет значение 200.

    Function objXML_onreadystatechange() If (objXML.readyState = 4) Then "msgbox objXML.statusText If (objXML.status = 200) Then bRespReceived=true SaveFile(objXML.responseText) else timerFirstRun = window.SetTimeout("Update", 60000) "попытка повторного обновления через минуту End If End If End Function

    В этом случае сохраняем файл во временную папку Windows

    Function SaveFile(what) Set fso = CreateObject("Scripting.FileSystemObject") tempFolder = fso.GetSpecialFolder(2) filepath = tempFolder+"\weather.xml" Dim fso1, tf Set fso1 = CreateObject("Scripting.FileSystemObject") Set tf = fso1.CreateTextFile(filepath, True, True) "rewrite, unicode tf.Write(what) tf.Close ParseXML End Function

    И начинаем парсить файл.

    Sub ParseXML Set fso = CreateObject("Scripting.FileSystemObject") tempFolder = fso.GetSpecialFolder(2) filepath = tempFolder+"\weather.xml" Set xmlDoc = CreateObject("Msxml2.DOMDocument") xmlDoc.async="false" xmlDoc.load(filepath) "главная нода – в нашем случае Set currNode = xmlDoc.documentElement "дни недели – Set dayNode = currNode.firstChild While Not dayNode Is Nothing Set currNode = dayNode.firstChild While Not currNode Is Nothing if currNode.parentNode.getAttribute("id") = "today" then "сегодняшний день if currNode.nodeName = "temp" then document.getElementById(prefix+"maintemp").innerHTML = currNode.childNodes(0).text+Chr(176) "отображаем остальные элементы Else "не сегодняшний день, отображаем более мелко "... end If Set currNode = currNode.nextSibling Wend Set dayNode = dayNode.nextSibling Wend End Sub

    Проверка на новые версии производится точно таким же способом.
    Не забываем создать файл настроек - settings.html, о существовании которого мы объявили выше.

    Настройки

    Вот, собственно, и все. Буду рад, если моя (первая:)) статья оказалась кому-то полезной.

    Использованные источники.