Основные принципы разработки

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

Содержание

  1. Выбор типа содержания
    1. HTML
    2. URL
  2. Превращение существующей веб-страницы или приложения в гаджет
  3. Работа с типами данных Userpref
    1. Использование информации в виде списков
    2. Использование данных о местоположении
  4. Сохранение состояния
  5. Перевод специальных символов
  6. Создание гаджетов, которые требуют входа или наличия файлов "cookie"

Выбор типа содержания

Одно из первых решений, принимаемых при разработке гаджета, - выбор типа содержания. Например:

<Content type="html">

Тип содержания определяет следующие параметры:

  • какие функции API доступны вам как автору гаджета;
  • как происходит визуализация гаджета;
  • где можно разместить свой гаджет.

В таблице ниже приведен перечень доступных типов содержания и рекомендуемого времени их использования.

Тип содержания Описание Время использования
html В типе содержания все содержание обычно находится в спецификации гаджета. html Гаджет type="html" содержит HTML, часто со встроенным JavaScript, Flash, ActiveX или другими объектами браузера. Это значение по умолчанию. Наиболее гибкий и универсальный тип содержания – html. Если у вас есть сомнения, выбирайте именно html.
url С типом содержания url содержание гаджета находится на удаленной веб-странице, на которую ссылается URL в спецификации гаджета. Удаленная веб-страница – это то место, где находится вся разметка HTML и JavaScript. Их НЕЛЬЗЯ размещать в самой спецификации гаджета. Тип содержания type="url" не поддерживается полностью на настоящий момент gadgets.* и API OpenSocial. Если вы хотите использовать тип содержания type="url" с библиотеками JavaScript гаджетов, воспользуйтесь устаревшими API гаджетов.

HTML

В типе содержания html все содержание обычно находится в спецификации гаджета. Это, в том числе, XML гаджета, JavaScript и разметка HTML. Почти все примеры в этом руководстве разработчика используют тип содержания html. Это наиболее гибкий тип, который может применяться в разных сферах. Его следует выбирать во всех случаях, кроме тех, когда создаваемый гаджет должен отвечать особым требованиям.

Следующий пример – это реализация ROT13 в виде гаджета. ROT13 шифрует текст, заменяя каждую его букву буквой, отстоящей от нее в алфавите на 13 позиций вправо. При повторном применении ROT13 все буквы снова перемещаются и восстанавливается исходный текст.

Это спецификация гаджета:

<?xml version="1.0" encoding="UTF-8" ?> 

<Module>
  <ModulePrefs title="Magic Decoder"/> 
  <Content type="html">
  <![CDATA[
     <script type="text/javascript">

       // The gadget version of ROT13.
       // Encodes/decodes text strings by replacing each letter with the letter
       // 13 positions to the right in the alphabet. 
       function decodeMessage (form) {
          var alpha = "abcdefghijklmnopqrstuvwxyz";
          var input = form.inputbox.value; 
          var aChar;
          var message = "";
          for (var i = 0; i <input.length; i++)
          { 
             aChar = input.charAt(i);
             var index = alpha.indexOf(aChar.toLowerCase());

             // if a non-alphabetic character, just append to string
             if (index==-1)
             {
                message += aChar;
             }

             // if you have to wrap around the end of the alphabet
             else if(index > 12) { // compensate for 0-based index
                index = 25 - index; // last item in array is at [25]
                index = 12 - index; // because array starts with 0
                aChar = alpha.charAt(index);
                message += aChar;
             }

             // if you don't have to wrap
             else {
                aChar = alpha.charAt(index+13);
                message += aChar;
             }
          }
          document.getElementById('content_div').innerHTML = "<b>Your message: </b>" + message; 
     }
     </script>

     <FORM NAME="myform" ACTION="" METHOD="GET">Message: <BR>
<INPUT TYPE="text" NAME="inputbox" VALUE=""><P>
<INPUT TYPE="button" NAME="button" Value="Transform" onClick="decodeMessage(this.form)"> </FORM> <div id="content_div"></div> ]]> </Content> </Module>

Правила для гаджета type="html" таковы.

  • Гаджет type="html" должен включать раздел CDATA и весь HTML должен быть в этом разделе.
<Content type="html"> 
    <![CDATA[ HTML here... ]]>

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

  • Нельзя использовать теги <html>, <head>, и <body>. Гаджеты создаются со своими собственными тегами <html>, <head>, и <body>. Просто включайте содержание, которое обычно было бы в теге <body>.

Гаджет с типом содержания html может ссылаться на внешний файл JavaScript:

<Module>
  <ModulePrefs ... /> 
  <Content type="html"><![CDATA[
    <script src="http://www.example.com/gadgets/clock/clock.js" type="text/javascript"></script>

  ]]></Content> 
</Module>

URL

Если тип содержания гаджета – type="url", атрибут href= определяет URL, а все остальное содержание в спецификации гаджета игнорируется. При использовании типа содержания url предполагается, что вся информация, относящаяся к интерфейсу пользователя гаджета и логике программирования, находится в файле, на который ссылается URL. Разметку HTML или JavaScript не надо размещать в самом гаджете. Например:

<Module>
  <ModulePrefs ... /> 
  <Content type="url" href="http://www/cgi-bin/example/gadgets/mystats.cgi" /> 
</Module>

Превращение существующей веб-страницы или приложения в гаджет

Существующую веб-страницу или приложение можно превратить в гаджет, выполнив указанные ниже рекомендации.

  • Уберите теги <html>, <head> и <body> (иными словами, просто предоставьте само содержание HTML). Эти рекомендации относятся только к гаджетам type="html". Они не относятся к гаджетам type="url".
  • Для событий загрузки используйте gadgets.util.registerOnLoadHandler().
  • Если гаджет требует входа в систему, используйте тип содержания URL. Возможные сложности описаны в разделе Создание гаджетов, требующих входа или наличия файлов "cookie". Учтите, что гаджеты HTTPS выводят на экран предупреждения о "смешанном содержании" при открытии в Internet Explorer, что может раздражать пользователей.
  • Внесите необходимые изменения в интерфейс пользователя, чтобы ваша страница или приложение уместились в маленькую область, отведенную для гаджета. Любители и профессионалы, создающие пробные образцы могут использовать makeRequest() для замещения содержания. Для гаджетов на коммерческой основе, мы рекомендуем создать новую небольшую страницу и указать на нее type="url".

Работа с типами данных Userpref

В спецификации гаджета всякая настройка пользователя имеет тип данных. datatype – это дополнительная строка, указывающая тип данных атрибута. Возможные значения для datatypestring, bool, enum, hidden (скрытая, не изменяемая пользователем строка), list и location (для гаджетов на основе карт Google). Тип данных по умолчанию – string.

В справочном руководстве доступна подробная информация о типах данных настроек пользователей.

В этом разделе описаны два более специализированных типа данных: list и location. Примеры того, как использовать другие типы данных, можно найти в документации (например, enum, hidden и bool).

Использование информации в виде списков

Настройка пользователя с типом данных list – это массив значений, которые динамически предоставляются пользователями во время выполнения. Когда пользователи вводят значения в окно изменения настроек пользователя, они добавляются в список. Этот список можно вызвать программным способом во время выполнения гаджета, как и любую другую настройку пользователя. Тип данных list можно использовать тогда, когда вам нужно, чтобы пользователи динамически предоставляли произвольный список значений. Например, гаджет "Погода" может давать пользователям возможность вводить список почтовых индексов.

Вы объявляете, что userpref имеет тип данных list, используя datatype="list". Например:

<UserPref name="mylist" display_name="Add Search Terms" datatype="list" required="true"/> 

Этот гаджет получает доступ к значениям в списке, используя функцию Prefs getArray(), например:

var search_terms = prefs.getArray("mylist");

В пределах этого массива элементы хранятся в виде списка, разделенного вертикальной чертой. Функцию Prefs getString() можно использовать для возвращения этого списка одной строкой, в которой значения разделены вертикальной чертой, например:

prefs.getString("mylist");

Можно также использовать разделенную чертой строку для установки значений по умолчанию для типа list:

<UserPref name="mylist" display_name="Add Search Terms" datatype="list" default_value="zdnet|pc|Apple Insider"/>

Можно использовать функцию Prefs setArray(name, val) для программного добавления значений в список. Для использования этой функции гаджет должен включать <Require feature="setprefs"/> под <ModulePrefs>. Например, следующий фрагмент добавляет в список значения "Nokia" и "CNET".

...

<ModulePrefs title="Feed Searcher" scrolling="true">
   <Require feature="setprefs" />
</ModulePrefs> ... prefs.setArray("mylist", ["Nokia","CNET"]);

Вот простой пример, выводящий элементы списка, которые пользователи вводят в окно редактирования:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs 
    title="List Data Type Example" 
    scrolling="true"/> 
  <UserPref name="mylist" 
    display_name="Add Terms" 
    datatype="list" />
  <Content type="html">
  <![CDATA[ 
  <div id=content_div></div>

  <script type="text/javascript"> 
    // Get userprefs
    var prefs = new gadgets.Prefs();

    // Get the array of search terms entered by the user
    var terms = prefs.getArray("mylist");  
    var html = "";

    // If the user has not added any terms yet, display message.
    if (terms.length == 0)
    {
      html += "Edit the userprefs to add terms.";
    }
    else {
      html += "Your terms are:<br /><br />";
      for (var i = 0; i < terms.length ; i++) {
        var term = (terms[i]);
        html += term + "<br />";
      }
    }
    document.getElementById("content_div").innerHTML = html; 
  </script>

  ]]> 
  </Content>
</Module>

Использование данных о местоположении

Гаджеты, основанные на картах Google, могут использовать тип данных location. Следующий пример гаджета показывает, как использовать тип данных location. В гаджетах значения, поддерживаемые типом данных location , это крупный город или почтовый индекс в США, Канаде или Англии. Возможно, вам больше понравится использовать почтовые индексы.

Используя тип данных location, можно применять getString(), чтобы получать долготу и широту указанного пользователем места.

<Module>
<ModulePrefs title="Map of __UP_loc__" height="300" author="Jane Smith" author_email="xxx@google.com" />
<UserPref name="loc" display_name="Location" datatype="location" required="true" />
<Content type="html">
<![CDATA[
<script src="http://maps.google.com/maps?file=js" type="text/javascript"></script>
<div id="map" style="width: 100%; height: 100%;"></div>
<script type="text/javascript">
var prefs = new gadgets.Prefs();
var map = new GMap(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.centerAndZoom(new GPoint(prefs.getString("loc.long"), prefs.getString("loc.lat")), 6);
</script> ]]>
</Content> </Module>

При чтении свойства location переменной x:

  • Если х – пустая строка (отсутствие положения), то x.lat и x.long будут также пустыми.
  • Если х не может быть геокодирован (неверное положение), то x.lat и x.long будут 0.0.

Более ранние версии API гаджетов не позволяли указывать default_value для типа местоположения. Этот недочет исправлен.

Сохранение состояния

Часто пользователям разрешается устанавливать настройки напрямую с помощью окна изменения. Но иногда полезно задавать значения пользовательских настроек программным способом, когда пользователь не принимает участия в этом процессе напрямую. Например, если речь идет об игровом гаджете, может потребоваться запись рекордного количества очков пользователя. Это можно сделать, установив программным образом значение пользовательской настройки "high_score".

Чтобы воспользоваться функцией setprefs, гаджет должен включать следующее.

  • Тег <Require feature="setprefs"/> (под <ModulePrefs>) для загрузки гаджетом библиотеки setprefs.
  • Параметр userpref, значение которого требуется установить программно и сохранить. Обычно этому userpref дается тип данных hidden.
  • Вызов к функции JavaScript set() для userpref, значение которого нужно сохранить.

Учтите, что на размер кода настройки влияет ограничение длины URL (2000 символов).

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

Это спецификация гаджета:

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs 
    title="Setprefs New">
    <Require feature="opensocial-0.8"/>
    <Require feature="setprefs" /> 
    </ModulePrefs>
  <UserPref 
    name="counter" 
    default_value="0" 
    datatype="hidden"/>
  <Content type="html">
  <![CDATA[ 
    <div id="content_div" style="height: 100px;"></div>
    <script type="text/javascript">

    // Get user preferences
    var prefs = new gadgets.Prefs();
    var html = "";
    var div = document.getElementById('content_div');
    // Increment value of "counter" user preference
    function incrementCounter() {  
      var count = prefs.getInt("counter");
      div.innerHTML = "The count is " + count + ".";
      // Increment "counter" userpref          
      prefs.set("counter", count + 1);
    }

    // Reset value of "counter" userpref to 0
    function resetCounter(){
      prefs.set("counter", 0);
      div.innerHTML = "Count reset to " + prefs.getInt("counter") + ".";
    }

    </script>
    <input type=button value="Count" name="count" onClick="incrementCounter()">
    <input type=button value="Reset" name="reset" onClick="resetCounter()">
  ]]> 
  </Content>
</Module>

Примечание. Если нужно хранить несколько значений, мы советуем сохранять их в строку JSON.

Перевод специальных символов

В атрибутах XML спецификации гаджета нужно переводить определенные специальные символы. Заметьте, что в спецификации гаджета можно использовать только объекты ASCII. Например, нельзя использовать символы ISO 8859-1. Ниже приводится список поддерживаемых специальных символов.

Символ Код перевода
& &amp;
< &lt;
> &gt;
" &quot;
' &apos;

Например:

  • ПЛОХО: href="http://www.foo.com/bar?x=a&y=b"
  • ХОРОШО: href="http://www.foo.com/bar?x=a&amp;y=b"
  • ПЛОХО: description="this is a "sexy" gadget"
  • ХОРОШО: description="this is a &quot;sexy&quot; gadget"

Заметьте, что этот тип перевода не нужен в блоке CDATA. Однако применять его все равно бывает полезно.

В коде JavaScript можно использовать функцию _hesc(str) для возврата строки HTML str, в которой переведены следующие символы: <>'".

Создание гаджетов, которые требуют входа или наличия файлов "cookie"

Политики конфиденциальности, выбранные по умолчанию в Microsoft Internet Explorer и Apple Safari, не позволяют устанавливать файлы "cookie" со сторонних сайтов. Поэтому некоторые гаджеты могут работать некорректно. В частности, сайты, которые используют для входа файлы "cookie", могут работать с ошибками в окне "iframe" iGoogle. Существует несколько способов решения этой проблемы.

  • Используйте параметры URL вместо файлов "cookie". Например, гаджет дней рождений на Orkut передает учетные данные через URL. Предупреждение: если вы выберете этот подход, будьте осторожны и не допускайте утечки этих параметров на другие веб-сайты.
  • Используйте OAuth. API гаджетов подерживает функцию под названием "прокси OAuth", позволяющую гаджетам безопасно связываться с другим веб-сайтом, хранящим личные данные, связанные с аккаунтом пользователя. OAuth – это стандарт, позволяющий владельцу аккаунта с личными данными разрешить веб-сайту обеспечивать доступ другому приложению к этим данным. Прокси OAuth разработан для того, чтобы гаджетам было проще использовать стандарт OAuth.
  • Напишите заголовки на P3P. В зависимости от политики конфиденциальности на вашем сайте, можно записать заголовки на языке P3P, что позволяет браузеру Internet Explorer (но не Safari) считывать с вашего сайта сторонние файлы "cookie". Если вы применяете PHP и хотите установить заголовки, можно воспользоваться фрагментом этого кода, который приведен сверху на вашей странице PHP:
<?php
  header("P3P: CP=\"CAO PSA OUR\"");
?> 

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

ТРЕБУЕТСЯ ВНИМАТЕЛЬНО ОЗНАКОМИТЬСЯ С ПОЛИТИКОЙ КОНФИДЕНЦИАЛЬНОСТИ, ЧТОБЫ ПОНЯТЬ, КАКИЕ ЗАГОЛОВКИ МОЖНО ИСПОЛЬЗОВАТЬ НА СВОЕМ САЙТЕ. СОВЕТУЕМ ВАМ ПОЛУЧИТЬ КОНСУЛЬТАЦИЮ ЮРИСТА.

  • Проинструктируйте пользователей. Это можно сделать на JavaScript, как в этом примере гаджета (попробуйте). Можно также интегрировать инструкции с логикой проверки подлинности. Обнаружив, что файлы "cookie" блокируются, сообщите пользователям, чтобы они выбрали пониженную настройку конфиденциальности или другой веб-браузер. Например, можно показать следующее сообщение:

Ваш браузер несовместим с этим сайтом в данной конфигурации. Если вы используете Microsoft Internet Explorer, вы можете изменить параметры безопасности, выбрав Сервис > Свойства обозревателя. Откройте вкладку Конфиденциальность, выберите Дополнительно и затем установите флажок Перекрыть автоматическую обработку файлов "cookie". В разделе Сторонние Cookie нажмите Принимать. Кроме того, можно попробовать воспользоваться другим веб-браузером, например Firefox.

 

В начало