Разрабатываем свой Sidebar Gadget

    image
    Как часто вы пользуетесь гаджетами боковой панели Windows? А хотелось бы написать свой? Не простой гаджет «Hello World», а действительно полезный, который помог бы оптимизировать затраты времени на определенный кусок работы. Тогда давайте рассмотрим случай, когда вам нужно мониторить нагрузку 10-20 серверов.

    Моя профессиональная деятельность связана с разработкой VoD сервисов. Приходящие от кинокомпаний фильмы в формате MPEG2 сервис перекодирует в нужные форматы. Для кодирования используются 20 серверов. Нагрузка на сервер мониторится не по загруженности процессора, а исходя из количества задач, которые были поставлены на сервер. Данная информация хранится и постоянно обновляется в базе данных. В любом случае у вас должен быть server side скрипт и веб-сервер, который будет отдавать результат гаджету.

    Следить за постоянной нагрузкой серверов и сбоями можно напрямую через запрос в базу или модуль административной зоны проекта. Оба варианта не дают оперативно и удобно реализовать сам процесс. Выход есть – написать свой Windows Sidebar Gadget, который будет трудолюбиво, самостоятельно вести мониторинг серверов и уведомлять о любых простоях и неполадках.

    Сестра, скальпель


    Гаджет – это обыкновенный zip-файл, который внутри себя хранит нужную информацию для развертывания. Сам гаджет – это набор HTML, CSS, JavaScript файлов, изображений и т.д.
    Гаджет состоит из нескольких файлов с условными названиями:
    • gadget.xml – манифест, который описывает гаджет: название, автора, версию, права, и т.д. Единственный файл, который должен иметь именно такое имя
    • основное окно гаджета
    • Flyout — дополнительное окно позволяющая расширить интерфейс гаджета
    • Settings – окно для сохранения параметров гаджета

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

    gadget.xml


    Мы укажем в манифесте минимально нужную информацию.

    <?xml version="1.0" encoding="utf-8" ?>
    <gadget>
     <name>DivX Server Monitor</name>
     <version>2.0</version>
     <author name="Евгений Жарков">
      <info url="jeje.habrahabr.ru" />
     </author>
     <hosts>
      <host name="sidebar">
       <base type="HTML" apiVersion="1.0.0" src="gadget.html" />
       <permissions>full</permissions>
       <platform minPlatformVersion="0.3" />
      </host>
     </hosts>
    </gadget>


    Обратите внимание на строчку, в которой мы указываем гаджету, какой использовать html файл для основного окна.
    <base type="HTML" apiVersion="1.0.0" src="gadget.html" />

    Детальнее с описанием манифеста можно ознакомится в MSDN.

    Основное окно


    Разметка основного окна ничем не отличается от разметки любой другой веб-страницы. Вдобавок нам предоставляют несколько исключительно гаджетовских тегов. Для задания фона гаджета, используется тег g:background. Любое содержимое, размещенное в данном элементе будет фоновым для всего основного окна.
    <g:background id="background" style="position:absolute;z-index:-1;top:0;left:0;" opacity="0"></g:background>

    Я не стал делать задний фон гаджету, с помощью параметра opacity=«0» фон стал абсолютно прозрачным.

    Тело страницы довольно простое верхний div служит для отображения статуса гаджета, позволяет увидеть, сколько минут осталось до обновления данных, а также поддерживает ручное обновление. Нижний div будет содержать в себе список серверов.
    <div id="status"><a href="javascript:void(0)" id="statusLink">Loading...</a></div>
      <div id="content">
        <ul id="serverList"></ul>
      </div>


    Все стили, JavaScript вынесены во внешние файлы. Для удобства была подключена библиотека jQuery. Целиком разметка основного окна крохотная.
    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <link rel="stylesheet" type="text/css" href="./style/gadget.css" /> 
      <script type="text/javascript" src="./js/jquery-1.3.2.min.js"></script>
      <script type="text/javascript" src="./js/gadget.js"></script>
    </head>
    <body onload="startMonitoring()">
      <g:background id="background" style="position:absolute;z-index:-1;top:0;left:0;" opacity="0"></g:background>
      <div id="status"><a href="javascript:void(0)" id="statusLink">Loading...</a></div>
      <div id="content">
        <ul id="serverList"></ul>
      </div>
    </body>
    </html>


    В CSS хотелось обратить внимание только на стили, которые описывают цвет ячейки сервера, в зависимости от его состояния.
    ul#serverList li.busyLight
    {
        background: #fefe8c;
    }
    ul#serverList li.busy
    {
        background: #ffb154;
    }
    ul#serverList li.free
    {
        background: #d2e582;
    }
    ul#serverList li.down
    {
        background: #dc6161;
    }
     


    Темная сторона, Люк


    Самый главный файл – JavaScript. Сразу оговорюсь, alert и confirm в гаджетах не работают. Для отладки гаджета, можно воспользоваться Visual Studio, но для этого нужно выполнить два хитрых действия. Прежде всего, включить отладчик JavaScript в Internet Explorer



    Добавить в нужном месте кода гаджета строку:
    debugger;

    и перезапустить гаджет.



    Мы объявляем две глобальных переменных, которые отвечают за время в минутах для обновления данных в гаджете, для меня оптимально 30 минут, а также счетчик отсчета оставшихся минут до обновления
    var updateInterval = 30;
    var updateMinutes = updateInterval;


    Функция init содержит действия для инициализации гаджета, мне в данном случае было нужно установить прозрачность гаджета на 40%, чтобы он не перекрывал полностью кусочек рабочего стола.
    function init() {
      System.Gadget.Settings.write("PrivateSetting_GadgetOpacity", 40);
    }

    Функция запуска самого мониторинга, которая обновляет список серверов с их статусом, устанавливает интервал обновления данных, таймера в главном окне и так же добавляет обработчик события для ручного обновления статуса серверов.
    function startMonitoring() {
      init();
       
      updateList();
      setInterval(updateList, updateInterval * 1000 * 60);
      setInterval(updateTimer, 1000 * 60);

      statusLink.onclick = function() {
        updateList();
      }
    }

    Добавление обработчика на нажатие происходит в данном случае двумя способами:
    element.onclick = function(){}
    $(element).get(0).onclick = function(){}

    Продвинутые способы в гаджетах не работают:
    element.attachEvent('onclick', function(){})
    $(element).bind('click', function(){})

    Для обновления самого таймера маленькая функция updateTimer, которая каждую минуту рассчитывает сколько времени осталось до обновления.
    function updateTimer() {
      updateMinutes = updateMinutes == 0 ? updateInterval : updateMinutes - 1;
      $('#statusLink').html('Update in ' + updateMinutes + ' m.');
    }

    И наконец, обновление списка серверов, для возвращенных данных я использую JSON, вид ответа примерно такой:
    [{«ip»:"***.45.**.60",«lastHitTime»:«2009-09-06 00:07:24»,«runningTasks»:«1»}]

    Для получения самих данных – getJSON. Вы можете использовать и AJAX, он прекрасно работает в гаджетах. Прежде всего, используя getJSON мы можем отлаживать код в браузере, не добавляя его в гаджет, AJAX нам такое сделать не позволит. В зависимости от загрузки сервера, я закрашиваю ячейку разным фоном. Одновременно выполняемых задач может быть всего две, мало, но каждая из них выполняется 1,5-2 часа. Так же дополнительная проверка, давно ли отзывался сервер.
    function updateList() {
      $('#statusLink').html('Loading...');
      list = '';
      
      $.getJSON('https://mysite.com/getServerStatus.php', function(json) {
        $.each(json, function(i, server) {
          status = '';
          if (server.runningTasks == 0) {
            status = "free";
          } else if (server. runningTasks == 1) {
            status = "busyLight";
          } else if (server. runningTasks == 2) {
            status = "busy";
          }
          hit = new Date(server.lastHitTime);
          now = new Date();

          if (now.getTime() - hit.getTime() >= 1000 * 60 * 60 * 3 + 1000 * 120) {
            status = 'down';
          }
          list += '<li class="' + status + '">' + server.ip + '</li>';
        });
        $('#serverList').html(list);
      });
      $('#statusLink').html('Updated');
    }

    Код готов к употреблению, осталось несколько взмахов волшебно палочкой. Пакуем все файлы проекта в zip-архив.



    Далее следует изменить расширения файла на .gadget



    И добавить гаджет в систему, пытаясь открыть файл monitoringS.gadget



    Вуаля, у нас появляется опрятный и скромный гаджет со списком серверов. Пример со 100% и 40% прозрачностью.



    Я уверен, что у каждого из нас, есть похожие задачи и проблемы, так почему бы не сделать их красивее, удобнее?

    Дополнительные материалы:

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

    Подробнее
    Реклама
    Комментарии 35
    • 0
      Эх, если бы на WPF
      • +2
        На WPF тоже можно.
        WPF Browser Application никто не отменял.

        И на Silverlight можно.
        • 0
          Как-то не догадался даже, что HTML — это не только JS.
          • 0
            Да, недодумался. Нужно будет попробовать
          • 0
            Вообще говорят, в гаджет можно даже нейтив код вставить.
          • 0
            Хороший мануал!
            осталось заставить себя взять и написать чего полезное :)
            • +2
              Определенно годная статья, не очередной «Hello, world», а что-то более серьезное… Действительно очень удобная вещь :)
              • НЛО прилетело и опубликовало эту надпись здесь
                • +5
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • +2
                      Вы уж простите, но я для работы написал, а там хочешь не хочешь, а смотреть нужно.
                  • +4
                    Держу гаджеты на втором мониторе.
                    • НЛО прилетело и опубликовало эту надпись здесь
                  • –1
                    На флексе кто-то пробывал делать?
                    • 0
                      Было бы прикольно такой виджет на Flash/Flex написать.
                    • –1
                      Кстати а на манер KDE можно делать апплеты для панели?
                      • +1
                        Вот так внезапно и узнаёшь о существовании в Win 7 боковой панели.
                        • +4
                          В семерке нет как такового сайдбара. Гаджеты размещаются в любом месте рабочего стола.
                          • 0
                            А в Vista они не размещаются в любом месте рабочего стола?
                            • 0
                              В висте, есть несколько состояний, и сама боковая панель, в семерки боковой панели нет.
                        • –2
                          так и не понял, чем этот гаджет лучше или информативнее snmpd+mrtg-rrd/cacti/nagios.
                          • 0
                            Абсолютно ничем, она решает маленькую задачу, больше мне и не нужно.
                            • 0
                              да ладно вам. лучше хотя бы тем, что написан собственноручно :)
                              • 0
                                тогда вопросов нет :)
                            • –1
                              Теперь напишите виджет на Оперу или плагин к ФФ!!!
                              • 0
                                Думаю, не стоит все в браузер помещать, или вам написать после этого статью в образовательных целях?
                              • 0
                                А я помню в армии написал себе гаджет для сайдбара, который показывал сколько дней, часов, минут, секунд до дембеля осталось :)
                                • +2
                                  Мастак =) Служил в армии с ноутбуком :D
                                  • 0
                                    … так я офицер ВВС :-P
                                • 0
                                  А вот такой ламерский вопросик: насколько хорошо гаджет для сайдбара может взаимодействовать с другими запущенными программами? Например, можно ли написать гаджеты в виде большой кнопки «Copy» и большой кнопки «Paste», чтобы они висели сбоку и работали в любой программе, в которой есть работа с Clipboard?
                                  • 0
                                    Нет взаимодействовать он не умеет, это же html документ.
                                  • 0
                                    Можно. Нужно просто написать для этого гаджета плигинчик (например на си++) и вызывать его внутри, незаметно для пользователя.

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