My favorites | 中文(简体) | Sign in

OpenSocial API 开发人员指南 (v0.7)

(OpenSocial API v0.7)

该指南将帮助您构建 OpenSocial 应用程序。它是针对在一定程度上熟悉小工具 API 和 JavaScript 一般内容的开发人员设计的,但是如果您需要更多信息的话,里面也提供了其他资源的链接。

本文档进行了修改以反映 OpenSocial API 0.7 版更新所进行的更改。章节标记为新增!更新来帮助您识别相对于上个版本而进行更改的编码实例。

目录

  1. 编写社交应用程序
  2. 导入 OpenSocial Library
  3. 访问用户和个人资料
    1. 获取基本信息
    2. 列出好友的完整代码
  4. 使用持久化数据
  5. 发布活动
  6. 与容器交互
    1. 从一个视图浏览至另一个视图
    2. 查询环境
    3. 包括多个内容部分
  7. 获取远程内容
    1. 缓存
    2. XML 实例
    3. JSON 实例
    4. 使用 POST 方法
    5. 设置授权类型
  8. 许可控制
  9. 了解更多

编写社交应用程序

社交应用程序就是在支持 OpenSocial JavaScript API 的容器上运行的应用程序。

要编写社交应用程序,您需要有:

OpenSocial API 主要针对用户。通过它,用户可以相互共享各自的活动并访问有关其好友的信息。在 OpenSocial API 中有三个主要功能区:

  • 用户和关系
  • 持久化存储
  • 活动

因为许多 API 调用需要服务器请求来检索或更新信息,所以它们是异步的。因此,您需要传送从服务器返回数据后执行的回调函数。

有关 OpenSocial JavaScript API 中的类和方法的详细信息,请参阅 API 参考

导入 OpenSocial Library

要使用 OpenSocial API,请将以下 Requires 部分添加到您的应用程序中:

<ModulePrefs title="Title of Your Application">
  <Require feature="opensocial-0.7"/>
</ModulePrefs>

有关小工具 XML 规范的结构和内容的详细信息,请参阅《小工具 API 开发人员指南》

访问用户和个人资料

我们先以列有好友名称的简单实例开始。但是首先,务必要先了解由 OpenSocial API 定义的角色:

  • 查看者:登录浏览器的用户。作为查看者,您可以查看自己的页面,也可以查看其他用户的个人资料。
  • 所有者:拥有个人资料或相关应用程序的用户。
  • 好友:被所有者或查看者在容器中加为好友的用户。

本节中讨论的“列出好友”实例可以获取查看者和查看者的好友,并显示查看者好友的列表。介绍了如何获取并管理 OpenSocial 应用程序中的数据。基本步骤如下:

  1. 检索数据。
    • 通过调用 opensocial.newDataRequest() 创建 DataRequest
    • 为要检索的每种数据类型都调用一次 DataRequest.add(request)
    • 在将所有单个请求都添加到您的 DataRequest 对象后,调用 DataRequest.send(callback)
  2. 执行回调函数以处理检索到的数据。
    • 处理服务器请求后,执行回调函数。该函数会采用一个具有请求结果的 DataResponse 参数。在“列出好友”中,DataResponse 包含查看者和查看者的好友。回调函数将会处理 DataResponse 中的数据。

下面将详细讨论这些步骤。

检索数据

要获取有关查看者和查看者好友的信息,请为要检索的每种数据类型创建新的 DataRequest 对象并向其添加请求。

 /**
  * Request for friend information when the page loads.
  */
  function getData() {
    var req = opensocial.newDataRequest();
    req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER), 'viewer');
    req.add(req.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS), 'viewerFriends');
    req.send(onLoadFriends);
  };

newFetch*Request() 调用中的最后一个参数是用于检索响应中的数据的字符串关键字。

使用回调函数处理数据

假设您已在上一节做了实例练习。现在,您想要进行有关返回数据的练习,它的类型为 opensocial.DataResponse。以下 onLoadFriends() 回调函数将会解析用作参数的 DataResponse,并显示查看者和查看者好友的姓名:

 /**
  * Parses the response to the friend information request and generates
  * html to list the friends by their display name.
  *
  * @param {Object} dataResponse Friend information that was requested.
  */
  function onLoadFriends(dataResponse) {
    var viewer = dataResponse.get('viewer').getData();
    var html = 'Friends of ' + viewer.getDisplayName(); 
    html += ':<br><ul>';
    var viewerFriends = dataResponse.get('viewerFriends').getData();
    viewerFriends.each(function(person) {
      html += '<li>' + person.getDisplayName() + '</li>';
    });
    html += '</ul>';
    document.getElementById('message').innerHTML = html;
  };

使用传送到 newFetch*Request() 的字符串关键字调用 DataResponse.get(key) 会返回包括请求结果的 ResponseItem

调用 dataResponse.get(key).getData() 会返回成功请求的实际响应数据。以下是与常规请求相关联的响应数据类型:

  • 当请求查看者或所有者时,会返回 opensocial.Person 对象。
  • 当请求一组好友时,会得到 opensocial.Person 对象的 opensocial.Collection

如果指定请求不成功,则 DataResponse.get(key).hasError() 会返回 true

列出好友的完整代码

本节会列出以上讨论的“列出好友”应用程序的完整代码。

在应用程序中,通常需要做的第一件事是请求您的应用程序所需的数据。请注意,代码包含该行:

gadgets.util.registerOnLoadHandler(getData);

这会将 getData() 注册为应用程序的装载处理程序,这意味着应用程序进行的第一件事是获取查看者和查看者好友数据(通过 getData())。

以下是完整实例。它会将其输出写入到 ID 为 "message"<div> 中。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
 <ModulePrefs title="List Friends Example">
   <Require feature="opensocial-0.7"/>
 </ModulePrefs>
 <Content type="html">

 <![CDATA[

 <script type="text/javascript">

 /**
  * Request for friend information.
  */
  function getData() {    
    var req = opensocial.newDataRequest();
    req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER), 'viewer');
    req.add(req.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS), 'viewerFriends');
    req.send(onLoadFriends);
  };

 /**
  * Parses the response to the friend information request and generates
  * html to list the friends along with their display name.
  *
  * @param {Object} dataResponse Friend information that was requested.
  */
  function onLoadFriends(dataResponse) {
    var viewer = dataResponse.get('viewer').getData();
    var html = 'Friends of ' + viewer.getDisplayName(); 
    html += ':<br><ul>';
    var viewerFriends = dataResponse.get('viewerFriends').getData();
    viewerFriends.each(function(person) {
      html += '<li>' + person.getDisplayName() + '</li>';
    });
    html += '</ul>';
    document.getElementById('message').innerHTML = html;
  };

  gadgets.util.registerOnLoadHandler(getData);

  </script>
  <div id="message"> </div>
  ]]>
  </Content>
</Module>

更新使用持久化数据

OpenSocial API 支持保存和检索每个用户和每个应用程序的数据。在 OpenSocial v0.5 和 v0.6 中也支持每个应用程序实例和全局应用程序数据,但是在 v0.7 中没有了。

该代码段显示了将数据保存到共享存储中的方式:

function populateMyAppData() {
  var req = opensocial.newDataRequest();
  var data1 = Math.random() * 5;
  var data2 = Math.random() * 100;
  var data3 = new Date().getTime();
  
  req.add(req.newUpdatePersonAppDataRequest("VIEWER", "AppField1", data1));
  req.add(req.newUpdatePersonAppDataRequest("VIEWER", "AppField2", data2));
  req.add(req.newUpdatePersonAppDataRequest("VIEWER", "AppField3", data3));
  req.send(handlePopulateMyAppData);
};

您可以按以下方式检索存储在以上代码段中的数据:

var req = opensocial.newDataRequest();
//Request the following three app fields
var fields = [ "AppField1", "AppField2", "AppField3" ];
req.add(req.newFetchPersonAppDataRequest("VIEWER", fields), "viewer_data");
req.send(handleRequestMyData);

以下是应用程序的完整代码。它将为查看者设置一些值,然后对其进行检索:

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="Data Persistence Example" > 
    <Require feature="opensocial-0.7"/>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[

  <script type="text/javascript"> 
   gadgets.util.registerOnLoadHandler(populateMyAppData);
   var htmlout = "";
   var me = null;

   /************************************************************************
    * Set user data
    */
   function populateMyAppData() {
     var req = opensocial.newDataRequest();
     var data1 = Math.random() * 5;
     var data2 = Math.random() * 100;
     var data3 = new Date().getTime();
     htmlout += "Setting AppField1 to " + data1 + "<br />";
     req.add(req.newUpdatePersonAppDataRequest("VIEWER", "AppField1", data1)) + "<br />";
     htmlout += "Setting AppField2 to " + data2 + "<br />";
     req.add(req.newUpdatePersonAppDataRequest("VIEWER", "AppField2", data2)) + "<br />";
     htmlout += "Setting AppField3 to " + data3 + "<br />";
     req.add(req.newUpdatePersonAppDataRequest("VIEWER", "AppField3", data3)) + "<br />";
     req.send(handlePopulateMyAppData, "update_appdata");
   }

   /************************************************************************
    * Handle responses from update person app data requests
    */
   function handlePopulateMyAppData(data) {
     if (data.hadError()) {
       htmlout += data.getError();
     }
     requestMyData();
   }
   
   /************************************************************************
    * Fetch app data
    */
   function requestMyData() {
     var req = opensocial.newDataRequest();
     var fields = [ "AppField1", "AppField2", "AppField3" ];
     req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER), "viewer");
     req.add(req.newFetchPersonAppDataRequest("VIEWER", fields), "viewer_data");
     req.send(handleRequestMyData);
   }

   /************************************************************************
    * Handle responses from app data requests
    */
   function handleRequestMyData(data) {
     var mydata = data.get("viewer_data");
     var viewer = data.get("viewer");
     me = viewer.getData();

     if (mydata.hadError()) {
       htmlout += data.getError();
       return;
     }
     // Do something with the returned data - note the getData call
     doSomethingWithMyData(mydata.getData());
   }

   /************************************************************************
   * Operate on user data
   */
   function doSomethingWithMyData(data) {
     //Data is indexed by user id, and represents an object where keys 
     //correspond with the app data fields.
     var mydata = data[me.getId()];
     var div = document.getElementById('content_div');
     htmlout += "My AppField1 data is: " + mydata["AppField1"] + "<br />";
     htmlout += "My AppField2 data is: " + mydata["AppField2"] + "<br />";
     htmlout += "My AppField3 data is: " + mydata["AppField3"] + "<br />";
     div.innerHTML = htmlout;
   }
   
 </script>
 <div id="content_div"></div>
  ]]> 
  </Content>
</Module>

注意:存储在 OpenSocial 应用程序中的数据始终是字符串。在大多数用途中,使其成为 JSON 编码字符串比较实用。因为 OpenSocial 执行自动 HTML(对所有包括应用程序数据的返回数据进行编码),所以必须在解析它们之前对应用程序数据存储中字符串化的 JSON 对象进行解码。例如:

var unescapedString = gadgets.util.unescapeString(jsondata); 
var obj = gadgets.json.parse(unescapedString);

活动

OpenSocial API 可让您通过活动流与好友共享活动。活动流是一种供稿,其中的每个条目都表示用户执行的操作。活动可以是任何形式(从修改应用程序状态到编写电影的在线评论)。

如果请求高活动优先级,则当应用程序没有有许可时,应用程序会要求用户提供其代表用户发布活动的许可。如果请求低优先级,则当应用程序没有发布许可时,该调用无效。

该简单的实例说明了如何创建活动:

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="Activities - v0.7" >
    <Require feature="opensocial-0.7"/>
  </ModulePrefs> 
  <Content type="html">
  <![CDATA[ 
  <div id="content_div"></div>
  <script type="text/javascript">

  var div = document.getElementById('content_div');

  function postActivity(text) {  
    var params = {};  
    params[opensocial.Activity.Field.TITLE] = text;
    var activity = opensocial.newActivity(params); 
    opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH, callback);
    div.innerHTML = "Activity title is: " + activity.getField(opensocial.Activity.Field.TITLE);
  };        
  
  // The parameter passed to the callback is an opensocial.ResponseItem that
  // indicates whether the activity creation request succeeded.
  function callback(status) {
    if (status.hadError())
    {
      alert("Error creating activity.");
    }
    else 
    {
      alert("Activity successfully created.");
    }
  };
  
  postActivity("This is a sample activity, created at " + new Date().toString());

  </script>
  ]]> 
  </Content>
</Module>

更新与容器交互

OpenSocial API 使应用程序可以通过以下方式与其容器交互:

  • 应用程序可以从容器中的一个视图浏览到另一个视图(例如,从个人资料视图到画布视图)。
  • 应用程序可以向容器查询有关它们环境的信息并相应地调整行为。例如,应用程序可获取有关以下内容的信息:
    • 容器的域。
    • 容器是否支持特定方法。
    • 对于特定对象,容器支持哪些字段。例如,对于个人对象,容器可能支持“爱好”。

更新从一个视图浏览至另一个视图

您可以使用 gadgets.views.requestNavigateTo 将应用程序从容器的一个页面带到另一个页面(例如,将个人资料页面链接到画布页面)。

该实例显示了如何使用 API 从一个视图浏览到另一个视图。它显示了链接列表,用户可以单击这些链接以浏览至容器的可用视图。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>  
  <ModulePrefs title="Navigating Between Views (0.7)" description="Navigates between views">    
    <Require feature="opensocial-0.7" />    
    <Require feature="views" />  
  </ModulePrefs>  
  <Content type="html">  
  <![CDATA[    
  <div id="main"></div>    
  <script type="text/javascript">

  /** 
   * Create the list of links to the other views 
   */
  function createLinks() {  
    //Get the environment, current view and an object containing the supported views  
    var env = opensocial.getEnvironment();  
    var views = gadgets.views.getSupportedViews();  
    var currentview = gadgets.views.getCurrentView();  
    var text = [ "You are currently on the ", 
        currentview.getName(), 
      " view.  Other views: " ].join("");  

    //Set up some DOM  
    var outputdom = document.getElementById("main");  
    outputdom.appendChild(document.createTextNode(text));  
    var ol = document.createElement("ol"); 
    outputdom.appendChild(ol);  
    //Iterate over each view  
    for (var viewname in views) {    
      var view = views[viewname];    
      // Make some DOM to present each link    
      var li = document.createElement("li");    
      var a = document.createElement("a");    
      ol.appendChild(li);    
      li.appendChild(a);    
      a.href = "javascript:void(0);";    
      //Put the name of the view in the link    
      a.appendChild(document.createTextNode("Link to " + view.getName()));    
      //Handle when the user clicks a link to the other server    
      a.onclick = getNavigateClosure(view);  
    }
  };
  /** 
   * Returns a function that navigates to the supplied view 
   */
    function getNavigateClosure(view) {  
      return function() { gadgets.views.requestNavigateTo(view); };
    };

  //Execute createLinks when the page is done loading
  gadgets.util.registerOnLoadHandler(createLinks);    
  </script>  
  ]]>  
  </Content>
</Module>

请注意以上实例中的该功能:

function getNavigateClosure(view) { 
   return function() { gadgets.views.requestNavigateTo(view); };
};

它会使用称为闭包的技术。在该上下文中,这意味着从其他函数内调用的函数可以访问外层函数的本地变量。当用户单击选中视图的链接时,在此使用闭包可以将选中视图的名称传送到 requestNavigateTo() 方法。

更新查询环境

Environment 类包含 getDomain 方法,您可以通过此方法了解您所在的站点(例如 orkut.commyspace.com)。这使您的应用程序可以对不同的环境以不同的方式响应。当 API 仅返回相对网址时,getDomain 方法可以帮助构建绝对网址。但是,通常情况下,我们建议您对所有函数改用另一种方法 hasCapability,hasCapability 方法会获取函数名称并告知您该函数在当前容器中是否可用。这可让容器将自身的扩展名添加到 OpenSocial,同时还为开发人员提供了一个通用机制来对其进行访问。该容器特定的扩展也会显示在 supportsField 方法中。容器提供者可添加自己的人物或活动字段。要符合 OpenSocial 规范,需要在 opensocial 名称空间外的某处记录该字段。

该实例应用程序根据用户是在个人资料页面中还是在画布页面中来更改其显示。


<?xml version="1.0" encoding="UTF-8" ?>
  <Module> 
    <ModulePrefs title="My 0.7 Environment">
    <Require feature="opensocial-0.7"/>
  </ModulePrefs> <Content type="html">
  <![CDATA[
  
  <script type="text/javascript">
  /**  
   * Request for friend information when the page loads.  
   */
  function getData() {    
    var req = opensocial.newDataRequest();
    req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER), 'viewer');
    req.send(greetUser);  
  }
  
  /**  
   * Change the display of the user greeting depending on whether the
   * user is in the profile or the canvas. 
   */
  function greetUser(dataResponse) {
    var viewer = dataResponse.get('viewer').getData();
    // Determine whether the getCurrentView feature is supported
    var isAble = gadgets.util.hasFeature("gadgets.views.getCurrentView");
    var html = '<h2>Greetings,  ' + viewer.getDisplayName() + '!</h2>';
    // If the container supports the getEnvironment method, determine whether the user
    // is in the canvas or profile
    if (isAble)
    {      
      var currView = gadgets.views.getCurrentView();
    // If the user is in the canvas, display the canvas view of the greeting 
    if (currView.getName() == 'canvas')
      {
        showCanvasView(html);
      }
    // Otherwise, display the profile view of the greeting
    else
    {
      // If the container supports the field THUMBNAIL_URL for PERSON objects,
      // include it in the profile view greeting page
      var myenv = opensocial.getEnvironment();
      if (myenv.supportsField(opensocial.Environment.ObjectType.PERSON, opensocial.Person.Field.THUMBNAIL_URL))
        {
          var thumb = viewer.getField(opensocial.Person.Field.THUMBNAIL_URL); 
        html += "<img src=" + thumb + "/>";
        }
      // Display the greeting in the profile and include the user's thumbnail
      document.getElementById('profile-div').innerHTML = html;
    }

    }
    // Default: just display the greeting with no image
    else {
      document.getElementById('profile-div').innerHTML = html;
    }
  }

  /** If the user is in canvas, change the display to take advantage of
   * additional screen area
   */
  function showCanvasView(str) {
    var div = document.getElementById('canvas-div');
    div.style.display="";
    str += "<img src='http://gadget-doc-examples.googlecode.com/svn/trunk/my-canvas-photo.jpg' />";
    div.innerHTML = str;
  }
  gadgets.util.registerOnLoadHandler(getData);
  </script>
  <div id="profile-div"> </div>
  <div id="canvas-div" style="display:none; font-family:Tahoma; background-color: #FFC0CB; margin: 5px; height: 570px; text-align: center;"></div>

  ]]>  
  </Content>
</Module>

新增!包含多个内容部分

在小工具 XML 文件中可以包含多个 <Content> 部分,其中每个 <Content> 部分都会公布它要呈现在上面的视图。文档树中所有 <Content> 部分都应该是同一类,并使用可选参数 view= 定义应在其中呈现的视图。

两个内容部分

以下简单实例显示了具有两个内容部分的小工具:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Multiple Content Sections (version 1)">
    <Require feature="opensocial-0.7" />
  </ModulePrefs>
  <Content type="html" view="profile">
  <![CDATA[
    <h1>Profile</h1>
  ]]>
  </Content>
  <Content type="html" view="canvas">
  <![CDATA[
    <h1>Canvas</h1>
  ]]>
  </Content>
</Module>

输出如下:

个人资料视图

<h1>Profile</h1>

画布视图

<h1>Canvas</h1>

画布或个人资料以外的其他任何视图

不显示任何内容

指定了多个视图的内容部分

内容部分可指定多个视图,由逗号隔开:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Multiple Content Sections (version 2)">
    <Require feature="opensocial-0.7" />
  </ModulePrefs>
  <Content type="html" view="canvas,profile">
  <![CDATA[
    <h1>Canvas and Profile</h1>
  ]]>
  </Content>
</Module>

输出如下:

个人资料视图

<h1>Canvas and Profile</h1>

画布视图

<h1>Canvas and Profile</h1>

画布或个人资料以外的其他任何视图

不显示任何内容

指定了视图的内容部分以及没有指定默认内容部分的内容部分

如果指定具有视图参数的内容部分,则该内容部分仅会显示在该视图上。如果未指定默认内容部分,则其他视图将不会显示任何内容。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>  
  <ModulePrefs title="Multiple Content Sections (version 3)">
    <Require feature="opensocial-0.7" />
  </ModulePrefs>
  <Content type="html" view="profile">
  <![CDATA[
    <h1>Profile</h1>
  ]]>        
  </Content>
</Module>

输出如下:

个人资料视图

<h1>Profile</h1>

画布视图

不显示任何内容

画布或个人资料以外的其他任何视图

不显示任何内容

指定了视图并指定了默认内容部分的内容部分

要指定默认内容部分,只需定义没有视图参数的内容部分即可:

<Module>  
  <ModulePrefs title="Multiple Content Sections (version 4)">
    <Require feature="opensocial-0.7" />
  </ModulePrefs>
  <Content type="html" view="profile">
  <![CDATA[
    <h1>Profile</h1>
  ]]>        
  </Content>
  <Content type="html">
  <![CDATA[
    <h1>Default</1>
  ]]>
  </Content>
</Module>

输出如下:

个人资料视图

<h1>Profile</h1>

画布视图

<h1>Default</h1>

画布或个人资料以外的其他任何视图

<h1>Default</h1>

完整示例

您可以在一个小工具中使用所有这些技术:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Multiple Content Sections (version 5)">
    <Require feature="opensocial-0.7" />
  </ModulePrefs>
  <Content type="html" view="profile">
  <![CDATA[
    <h1>Profile</h1>
  ]]>
  </Content>
  <Content type="html" view="canvas">
  <![CDATA[
    <h1>Canvas</h1>
  ]]>
  </Content>
  <Content type="html" view="canvas,profile">
  <![CDATA[
    <h2>This shows up in canvas and profile views</h2>
  ]]>
  </Content>
  <Content type="html">
  <![CDATA[
    <h1>Default</h1>
    <h2>The content in this section only shows up if no other content sections are applicable</h2>
  ]]>
  </Content>
</Module>

输出如下:

个人资料视图

<h1>Profile</h1>
<h2>This shows up in canvas and profile views</h2>

画布视图

<h1>Canvas</h1>
<h2>This shows up in canvas and profile views</h2>

画布或个人资料以外的其他任何视图

<h1>Default</h1>
<h2>The content in this section only shows up if no other content sections are applicable</h2>

更新获取远程内容

您可以使用 gadgets.io.makeRequest() 方法远程获取其他网络服务器和网页的内容。在对旧的小工具 API IG_Fetch... 方法的改进中,gadgets.io.makeRequest() 考虑了 POST 和 GET,您可以指定是否要注册您的请求甚至是进行验证。

gadgets.io.makeRequest() 方法会采用这些参数:

  • 用于获取远程内容的网址。
  • 处理获取内容的回调函数。
  • 指定有关获取内容的方式、内容类型、显示内容的方式等其他信息的参数。

默认情况下,makeRequest() 会使用 GET 方法获取数据,并且内容的默认类型为 TEXT(其中网页的内容作为原始文本获取)。

该实例显示了 API 的简单使用方法。它会获取 www.google.com 上的前 400 个字符,并将它们输出到 <div>

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Fetch Content as Text">
    <Require feature="opensocial-0.7"/>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[
    <div id="content_div"></div>
    <script type="text/javascript">

    function makeNormalRequest() {    
      var params = {};  
      params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;  
      var url = "http://www.google.com";  
      gadgets.io.makeRequest(url, response, params);
    };

    function response(obj) {  
      //obj.text contains the text of the page that was requested  
      var str = obj.text;
      var html =  str.substr(0,400);  
      document.getElementById('content_div').innerHTML = html;
    };

    makeNormalRequest();
    </script>
  ]]>
  </Content>
</Module>

新增!缓存

默认情况下,对 makeRequest 的调用将会进行缓存。在以下实例中,包装函数会采用与 makeRequest 调用相同的参数,但是会接受名为 refreshInterval 的其他参数,您可以通过该参数指定缓存持续时间。但是,缓存很有用,您应注意不要过于频繁地刷新缓存而导致性能降低。缓存可让您更快地获取数据。它也降低了托管远程内容的第三方服务器上的负载。您应当尝试避免完全禁用缓存(通过将其指定为 0 来禁用)。有关该主题的更多讨论内容,请参阅《小工具 API 开发人员指南》

function makeCachedRequest(url, callback, params, refreshInterval) {
  var ts = new Date().getTime();
  var sep = "?";
  if (refreshInterval && refreshInterval > 0) {
    ts = Math.floor(ts / (refreshInterval * 1000));
  }
  if (url.indexOf("?") > -1) {
    sep = "&";
  }
  url = [ url, sep, "nocache=", ts ].join("");
  gadgets.io.makeRequest(url, response, params);
}

更新 XML 实例

该实例显示了使用 DOM 内容类型处理 XML 数据的方式。当指定 DOM 内容类型后,makeRequest() 将作为 DOM 对象检索指定的 XML 文档。拥有该对象后,您可以使用标准 DOM JavaScript 函数对其进行操作。有关该主题的更多讨论内容,请参阅《小工具 API 开发人员指南》

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Fetch XML">
    <Require feature="opensocial-0.7"/>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[
    <div id="content_div"></div>
    <script type="text/javascript">

    function makeDOMRequest() {    
      var params = {};  
      params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;  
      var url = "http://doc.examples.googlepages.com/breakfast-data.xml";  
      gadgets.io.makeRequest(url, response, params);
    };

    function response(obj) { 
      // obj.data contains a Document DOM element corresponding to the
      // page that was requested
      var domdata = obj.data;
      var title = domdata.getElementsByTagName("menu").item(0).getAttribute("title");
      var html = "<h2>" + title + "</h2>";
      
      // Get a list of the <food> element nodes in the file
      var itemList = domdata.getElementsByTagName("food");
 
      // Loop through all <food> nodes
      for (var i = 0; i < itemList.length ; i++) { 
        // For each <food> node, get child nodes.
        var nodeList = itemList.item(i).childNodes;

        // Loop through child nodes. Extract data from the text nodes that are
        // the children of the associated name, price, and calories element nodes.
        for (var j = 0; j < nodeList.length ; j++) {
          var node = nodeList.item(j);
          if (node.nodeName == "name") {
            var name = node.firstChild.nodeValue;
          }
          if (node.nodeName == "price") {
            var price = node.firstChild.nodeValue;
          }
        }
        html += name + " - ";
        html += price + "<br />";
      }
      html += "</div>";
      document.getElementById('content_div').innerHTML = html;
    };
    makeDOMRequest();
    </script>
  ]]>
  </Content>
</Module>

新增!JSON 实例

您可以使用 JSON 内容类型作为 JavaScript 对象获取 JSON 编码的内容。

以下应用程序将从包含以下 JSON 编码的字符串的示例 PHP 页面中获取内容:

{"validated":"This request was spoofed","query":[],"url":"http:\/\/graargh.returnstrue.com\/buh\/fetchme.php","signature":"","signature_len":1}

从包含该字符串的 PHP 页面获取内容后,返回值是包含关键字值对(即,关联数组)的 JavaScript 对象。该示例会检索对象,然后打印出它所包含的关键字值对:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Fetch JSON 8">
    <Require feature="opensocial-0.7"/>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[
    <div id="content_div"></div>
    <script type="text/javascript">

    function makeJSONRequest() {    
      var params = {};
      params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
      // This URL returns a JSON-encoded string that represents a JavaScript object
      var url = "http://graargh.returnstrue.com/buh/fetchme.php";
      gadgets.io.makeRequest(url, response, params);
    };

    function response(obj) { 
      var jsondata = obj.data;
      var html = "<strong>Values: </strong><br /><br />";
      // Returned JS object can be processed as an associative array
      for (var key in jsondata) {    
        var item = jsondata[key];
        html += key + ": ";
        html += item + "<br />";
      }	   	    
      document.getElementById('content_div').innerHTML = html;
     };
     makeJSONRequest();
     </script>
  ]]>
  </Content>
</Module>

新增!有关 JSON 的更多信息

JSON(JavaScript 对象表示法)是数据交换格式,使您可以将某些对象类型(关键字值对的数组和集合)作为可以轻松传送的字符串进行编码。

小工具 API 提供了 gadgets.json.stringify() 方法用于将对象编码为 JSON 字符串,并提供 gadgets.json.parse() 方法用于将 JSON 字符串返回到对象。请注意,因为 OpenSocial 执行自动 HTML(对所有包括应用程序数据的返回数据进行编码),所以必须在解析它们之前对应用程序数据存储中字符串化的 JSON 对象进行解码,例如:gadgets.util.unescapeString(jsondata)

该实例创建了 JavaScript 数组,并将其编码为 JSON 字符串,然后将 JSON 字符串转换回数组对象:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="JSON Example">
    <Require feature="opensocial-0.7"/>
  </ModulePrefs>
  <Content type="html">
  <![CDATA[
     <div id="content_div"></div>
     <script type="text/javascript">
     var html = "";
     // Create Array object
     var myfriends = new Array();
     myfriends[0] = "Touki";
     myfriends[1] = "Rowan";
     myfriends[2] = "Trevor";

     // Encode array as JSON string
     var jsonString = toJSON(myfriends);
     html += "The JSON string is " + jsonString + "<br />";
     html += "The type of jsonString is " + typeof(jsonString) + "<br />";

     // Convert JSON string back to an object
     var arr_obj = toObject(jsonString);
     html += "The type of arr_obj is " + typeof(arr_obj);
     document.getElementById('content_div').innerHTML = html;

     // Encode object as JSON string
     function toJSON(obj) { 
       return gadgets.json.stringify(obj); 
     }

     // Convert JSON string into an object
     function toObject(str) {
       return gadgets.json.parse(str);
    }
    </script>
  ]]>
  </Content>
</Module>

该小工具的输出如下:

The JSON string is ["Touki","Rowan","Trevor"]
The type of jsonString is string
The type of arr_obj is object

更新使用 POST 方法

默认情况下,使用 GET 方法获取远程内容。您可以通过 POST_DATA 参数以改用 POST 方法来获取内容。例如:

function makePOSTRequest() {
  var params = {};
  var postdata = {
    data1 : "test",
    data2 : 1234566
  };
  params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
  params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(postdata);
  var url = "http://graargh.returnstrue.com/buh/makerequest.php";
  gadgets.io.makeRequest(url, response, params);
};

function response(obj) {
  // do something
};

makePOSTRequest();

更新设置授权类型

小工具 API 支持以下授权类型:

  • gadgets.io.AuthorizationType.AUTHENTICATED(容器使用完全验证)
  • gadgets.io.AuthorizationType.SIGNED(由容器注册请求)
  • gadgets.io.AuthorizationType.NONE(默认值)

如何使用这些方式取决于您的容器。以下是使用专用于 Orkut 的注册授权类型的一个实例

更新许可控制

OpenSocial API 支持应用程序中的许可控制。当应用程序使用数据请求从服务器获取查看者时,则只会在应用程序具有访问权限时返回。如果应用程序没有访问权限,则会返回其中一个标准错误代码 opensocial.ResponseItem.Error.UNAUTHORIZED。应用程序还可以通过使用新 opensocial.hasPermission 调用提前检查其访问权限。如果访问被拒绝,则可以使用 opensocial.requestPermission 向查看者要求指定的许可。当然,某些容器可能始终授予查看者访问权限,而某些则可能始终拒绝,但是该决定取决于容器。

该摘录说明了使用许可控制 API 的方式:

/**
 * Request the VIEWER and OWNER objects
 */
function requestData() {
  var req = opensocial.newDataRequest();
  req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER), "owner");
  
  // If we have permission to see the viewer's info, then add it to the request.
  if (opensocial.hasPermission(opensocial.Permission.VIEWER)) {
    req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER), "viewer");
  }
  req.send(showData);
}

function showData(data) {
  var viewer = data.get("viewer").getData();
  var owner = data.get("owner").getData();
  var ownerOutput = document.getElementById("owner-output");
  var viewerOutput = document.getElementById("viewer-output");

  showPerson(owner, ownerOutput);
  if (opensocial.hasPermission(opensocial.Permission.VIEWER)) {
    showPerson(viewer, viewerOutput);
  }
}

function requestPermission() {
  var reason = "To demonstrate permission capabilities";
  opensocial.requestPermission(opensocial.Permission.VIEWER, reason, requestData);
}

function showPerson(person, div) {
  var name = person.getDisplayName();
  var thumb = person.getField(opensocial.Person.Field.THUMBNAIL_URL);
  var html = '<img src="' + thumb + '"/>' + name; 
  div.innerHTML = html;
}

//Execute requestData when the page is done loading
gadgets.util.registerOnLoadHandler(requestData);

了解详情

要了解有关 OpenSocial API 的更多内容,以下是一些附加资源:

返回页首

修订历史记录

修订 更新 说明
OpenSocial 0.8.1 2008 年 9 月 大部分章节均已更新。Require 语句已更改为 0.8。访问示例现在使用 IdSpec。已添加了有关清除持久化数据的信息。已更新了权限示例。
OpenSocial 0.7 2008 年 4 月 新文档。