开发基础

本文档介绍了小工具开发过程中的基本概念和任务。有关使用小工具 API 的简介,请参阅“使用入门”。

目录

  1. 选择 Content 类型
    1. HTML
    2. URL
  2. 将现有的网页或应用程序转换为小工具
  3. 使用 Userpref 数据类型
    1. 使用 list 数据类型
    2. 使用 location 数据类型
  4. 保存状态
  5. 对特殊字符进行转义
  6. 编写需要登录或 Cookie 的小工具

选择 Content 类型

当您开发新的小工具时,最初的决策之一是使用哪种 Content 类型。例如:

<Content type="html">

Content 类型决定:

  • 作为小工具作者,哪些 API 功能对您可用。
  • 如何渲染小工具。
  • 部署小工具的位置。

下表介绍了可用 Content 类型以及何时应使用这些 Content 类型:

Content 类型 说明 何时使用
html 使用 html Content 类型时,小工具的主要内容都会放在 Content 标记中。type="html" 小工具包含 HTML,可能带有嵌入的 JavaScript、Flash、ActiveX 或其他浏览器对象。此为默认类型。 最灵活、通用的 Content 类型为 html。当有疑惑时,请选择 html Content 类型。
url 使用 url Content 类型时,小工具将会在其 Content 标记中引用指定的网页的 url。该远程网页是所有 HTML 标记和 JavaScript 所放的地方。您不能将任何 HTML 标记或 JavaScript 代码置于小工具规范本身中。 type="url" Content 类型当前不完全受 gadgets.* 或 OpenSocial API 的支持。如果您想使用带有小工具 JavaScript 库的 type="url" Content 类型,请使用传统的小工具 API

HTML

使用 html Content 类型时,小工具的主要代码都会放在 Content 标记中。这包括小工具 XML,以及任何 HTML 标记和 JavaScript。本开发人员指南中几乎所有的示例都使用 html Content 类型。该类型是最灵活通用的类型,除非您在编写有特殊要求的小工具,否则通常应当选择该类型。

以下示例是 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 Content 类型的小工具还可以引用外部 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" Content 类型时,href= 属性会提供网址,并且小工具规范中的其他任何内容都会被忽略。具有 url Content 类型时,假设与此小工具的用户界面和编程逻辑相关的所有信息均放在此网址引用的文件中。不能将任何 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 Content 类型。请参阅“编写需要登录或 Cookie 的小工具”获得可能的帮助。请注意,HTTPS 小工具在 Internet Explorer 下会发出“混合内容”警告,这可能会让用户感到不快。
  • 对用户界面进行必要的更改,以使您的页面或应用程序能适应小型小工具空间。对于业务爱好者和专业人员构建的原型,makeRequest() 可以用于代理内容。对于商业开发的小工具,建议只创建一个新的小页面,然后使用 type="url" 指向它。

使用 Userpref 数据类型

在小工具规范中,每个用户使用偏好都有一个数据类型。datatype 是一个可选字符串,可指定属性的数据类型。datatype 的值可以为 stringboolenumhidden(用户不可编辑的非可见字符串)、list,以及 location(用于基于 Google 地图的小工具)。默认数据类型为 string

请参阅参考以获得有关用户使用偏好数据类型的详细信息。

本部分介绍了两个更专用的数据类型:listlocation。您可以找到有关如何在整个文档中使用其他数据类型(例如 enumhiddenbool)的示例。

使用 list 数据类型

具有 list 数据类型的用户使用偏好是一个在运行时由用户动态提供的值的数组。当用户向用户使用偏好编辑框中键入值时,这些值将被添加到列表中。在运行时此列表可以通过编程方式由小工具进行访问,就像任何其他用户使用偏好一样。任何时候想要允许用户动态提供值的任意列表,都可以使用 list 数据类型。例如,天气小工具可以允许用户输入邮政编码列表。

您可以通过使用 datatype="list" 声明 userpref 具有 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");

您还可以使用以管道符分隔的字符串设置列表类型的默认值:

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

您可以使用 Prefs 函数 setArray(name, val) 通过编程方式向该列表添加值。要使用此函数,您的小工具必须包括 <ModulePrefs> 下的 <Require feature="setprefs"/>。例如,以下代码段将值“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>

使用 location 数据类型

基于 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 为空字符串(表示空位置), x.latx.long 是空字符串。
  • 如果 x 无法进行地理编码(表示无效位置),x.latx.long 为 0.0。

早期版本的小工具 API 不允许为 location 类型指定 default_value。现在情况已经改变。

保存状态

用户普遍都可以使用编辑框明确地设置其用户使用偏好。但有时通过编程方式设置用户使用偏好的值(用户不直接参与)很有用。例如,对于游戏小工具,您可能想要永久地存储用户的最高分数。您可以通过以编程方式设置“high_score”用户使用偏好来实现这一目的。

要使用 setprefs 功能,您的小工具应包括以下内容:

  • <Require feature="setprefs"/> 标签(位于 <ModulePrefs> 下),用于通知小工具加载 setprefs 库。
  • 您要通过编程方式设置并永久存储其值的 userpref。通常,要将此 userpref 的数据类型设置为 hidden
  • 对 JavaScript 函数 set() 的调用,针对您要保存其值的 userpref。

请注意,使用偏好大小目前受网址限制,大小为 2K。

以下示例小工具由两个按钮组成:一个按钮可以增加计数器的值,另一个按钮可以将计数器的值重设为 0。在此示例中,“counter”是用户使用偏好。其数据类型为 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 块中无需此类转义。但是,在 CDATA 块中进行转义仍然是一种好做法。

在 JavaScript 代码中,您可以使用 _hesc(str) 函数返回 HTML 字符串 str,其中以下字符已转义: <>'".

编写需要登录或 Cookie 的小工具

Microsoft Internet Explorer 和 Apple Safari 的默认隐私政策不允许第三方站点设置 Cookie。因此,某些小工具可能运行不正常。特别是使用 Cookie 登录的站点在 iGoogle 页面中的 iframe 中可能运行不正常。此处是可能的解决方案:

  • 使用网址参数(而不是 Cookie)。例如,Orkut 生日小工具通过网址传递验证凭证。警告:如果您选择该方式,请注意不要将这些网址参数泄露到 HTTP 引用字段中的其他网站。
  • 使用 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,则可以通过选择“工具”>“Internet 选项”更改您的安全设置。打开“隐私”标签,点击“高级”,然后选中“替代自动 cookie 处理”。在“第三方 Cookie”下,点击“接受”。 此外,您可以尝试其他网络浏览器,例如 Firefox。

 

返回页首