English | Site Directory

OpenSocial API Developer's Guide (v0.7)

This guide will help you build OpenSocial applications. It is meant for developers who have some general familiarity with the Gadgets API, and JavaScript, but provides links to other resources in places where you may need more information.

This document has been modified to reflect changes from the 0.7 update of the OpenSocial API. Sections are marked as being New! or Updated to help you identify coding practices that have changed since the last version.

Contents

  1. Writing a Social Application
  2. Importing the OpenSocial Library
  3. Accessing People and Profiles
    1. Getting Basic Information
    2. Complete Code for List Friends
  4. Working with Persistent Data
  5. Posting Activities
  6. Interacting with the Container
    1. Navigating from One View to Another
    2. Querying the Environment
    3. Including Multiple Content Sections
  7. Fetching Remote Content
    1. Caching
    2. XML Example
    3. JSON Example
    4. Using the POST Method
    5. Setting an Authorization Type
  8. Permission Control
  9. To Learn More

Writing a Social Application

A social application is simply a application that runs on a container that supports the OpenSocial JavaScript API.

To write a social application, you need the following:

The OpenSocial API focuses on people. It lets users share their activities with each other and access information about their friends. There are three primary areas of functionality in the OpenSocial API:

  • People and relationships
  • Persistence
  • Activities

Many API calls are asynchronous as they may require a server request to retrieve or update information. Because of this, you need to pass in a callback function that will be executed once the data is returned from the server.

For detailed information about the classes and method in the OpenSocial JavaScript API, see the API Reference.

Importing the OpenSocial Library

To use the OpenSocial API, add the following Requires section to your application:

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

For more information about the structure and contents of a gadgets XML specification, see the Gadgets API Developers Guide.

Accessing People and Profiles

Let's get started with a simple example that lists the names of your friends. But first, it's important to understand the roles defined by the OpenSocial API:

  • Viewer: the user logged into the browser. As a viewer you might be viewing your own page, or you might be viewing another user's profile.
  • Owner: the user who owns the profile or application in question.
  • Friends: users whom the owner or viewer has added as friends in the container.

The "List Friends" example discussed in this section fetches the viewer and the viewer's friends, and displays a list of the viewers friends. It illustrates how to fetch and operate on data in an OpenSocial application. The basic steps are as follows:

  1. Retrieve the data.
    • Create a DataRequest by calling opensocial.newDataRequest().
    • Call DataRequest.add(request) once for each type of data you would like to retrieve.
    • After you add all of the individual requests to your DataRequest object, call DataRequest.send(callback).
  2. Implement a callback function to process the retrieved data.
    • Once the server request has been processed, the callback function is executed. This function takes one DataResponse parameter that has the results of the request. In "List Friends", the DataResponse contains the viewer and the viewer's friends. The callback function processes the data in the DataResponse.

These steps are discussed in more detail below.

Retrieving the Data

To get information about a viewer and a list of the viewer's friends, you create a new DataRequest object and add a request to it for each type of data you want to retrieve:

 /**
  * 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);
  };

The last parameter in the newFetch*Request() calls is a string key used to retrieve the data in the response.

Using a Callback Function to Process the Data

Let's suppose you did the example in the previous section. Now you want to do something with the returned data, which is of the type opensocial.DataResponse. The onLoadFriends() callback function below parses the DataResponse it takes as a parameter, and displays the names of the viewer and the viewer's friends:

 /**
  * 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;
  };

Calling DataResponse.get(key) with the string key you passed in to the newFetch*Request() returns a ResponseItem containing the results of the request.

Calling dataResponse.get(key).getData() returns the actual response data for a successful request. Here are response data types associated with common requests:

  • When you request the viewer or owner, you get an opensocial.Person object back.
  • When you request a group of friends, you get an opensocial.Collection of opensocial.Person objects.

DataResponse.get(key).hasError() returns true if a given request was unsuccessful.

Complete Code for List Friends

This section lists the complete code for the "List Friends" application discussed above.

Within an application, usually the very first thing you want to do is request the data your application needs. Note that the code includes this line:

gadgets.util.registerOnLoadHandler(getData);

This registers getData() as the application's onload handler, which means that the first thing the application does (through getData()) is to fetch the viewer and viewer friends data.

Here is the complete example. It writes its output to a <div> that has the id "message".

<?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>

Updated Working with Persistent Data

The OpenSocial API supports saving and retrieving per-user, per-application data. In OpenSocial v0.5 and v0.6, per-application instance and global application data were also supported, but this is removed for v0.7.

This code snippet shows how to save data to the shared store:

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);
};

You could retrieve the data stored in the code snippet above as follows:

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);

Here is the complete code for the application. It sets some values for the viewer and then retrieves them:

<?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>

Note: The data stored in an OpenSocial application is always a string. For most purposes, it is practical to make this a JSON-encoded string. Because OpenSocial performs automatic HTML escaping of all returned data including application data, you must unescape stringified JSON objects in the appdata store before parsing them. For example:

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

Activities

The OpenSocial API lets you share activities with your friends through an activity stream. An activity stream is a feed in which each entry represents an action performed by the user. An activity could be anything from modifying an application's state to writing an online review for a movie.

If you request HIGH activity priority, the app will ask the user for permission to post activities on behalf of the user if it doesn't already have permission. If you request LOW priority, then the call will do nothing if the app doesn't have permission to post.

This simple example illustrates how to create an activity:

<?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>

Updated Interacting with the Container

The OpenSocial API gives applications the ability to interact with their container in the following ways:

  • Applications can navigate from one view in the container to another (for example, from a profile view to a canvas view).
  • Applications can query the container for information about their environment and tailor their behavior accordingly. For example, applications can get information about the following:
    • The container's domain.
    • Whether the container supports a particular method.
    • What fields the container supports for particular objects. For example, for a Person object, a container might support "hobbies".

Updated Navigating from One View to Another

You can use gadgets.views.requestNavigateTo to take your application from one page of a container to another (for example, to link the profile to the canvas page).

This example shows how to use the API to navigate from one view to another. It displays a list of links that the user can click to navigate to the container's available views.

<?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>

Note this function in the above example:

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

It uses a technique known as a closure. In this context, it means that a function invoked from within another function has access to the local variables of the outer function. The use of a closure here allows the name of the selected view to be passed into the requestNavigateTo() method when the user clicks the link for that view.

Updated Querying the Environment

The Environment class includes a getDomain method, which tells you which site you are in (such as orkut.com or myspace.com). This allows your application to respond in different ways to different environments. The getDomain method can be helpful in building absolute URLs in cases where the API only returns a relative URL. In general, however, we recommend that you use another method, hasCapability, for all functional changes. The hasCapability method takes a function name and tells you if that function is available in your current container. This lets a container add its own extensions to OpenSocial while still giving developers one common mechanism for accessing them. This container-specific extensibility also shows up in the supportsField method. A container provider can add its own person or activity field. To remain compliant with the OpenSocial spec, this field needs to be documented somewhere outside of the opensocial namespace.

This sample application changes its display depending on whether the user is in the profile or the canvas:


<?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>

New! Including Multiple Content Sections

You can include more than one <Content> section in a gadget XML file, where each <Content> section declares the views it should be rendered on. All <Content> sections should be siblings in the document tree, and may use the optional parameter view= to define the views in which they should render.

Two content sections

Here is a simple example that shows a gadget with two content sections:

<?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>

The output is as follows:

Profile view

<h1>Profile</h1>

Canvas view

<h1>Canvas</h1>

Any other views that are not canvas or profile

no content is displayed

Content sections with multiple views specified

Content sections can specify multiple views, separated by commas:

<?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>

The output is as follows:

Profile view

<h1>Canvas and Profile</h1>

Canvas view

<h1>Canvas and Profile</h1>

Any other views that are not canvas or profile

no content is displayed

Content section with view specified and no default content section

If you specify a content section with a view parameter, that content section is only shown on that view. If you don't specify a default content section, other views will not display any content.

<?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>

The output is as follows:

Profile view

<h1>Profile</h1>

Canvas view

no content is displayed

Any other views that are not canvas or profile

no content is displayed

Content section with view specified and a default content section

To specify a default content section, simply define a content section with no view parameter:

<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>

The output is as follows:

Profile view

<h1>Profile</h1>

Canvas view

<h1>Default</h1>

Any other views that are not canvas or profile

<h1>Default</h1>

Complete Example

You can use all of these techniques in one gadget:

<?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>

The output is as follows:

Profile view

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

Canvas view

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

Any other views that are not canvas or profile

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

Updated Fetching Remote Content

You can use the gadgets.io.makeRequest() method to remotely fetch content from other web servers and web pages. In an enhancement to the old gadget API IG_Fetch... methods, gadgets.io.makeRequest() allows for POSTs as well as GETs, and you can specify whether you want your request to be signed or even authenticated.

The gadgets.io.makeRequest() method takes these parameters:

  • The URL from which to fetch remote content.
  • A callback function that processes the fetched content.
  • Parameters that specify additional information about how the content is being fetched, what type of content it is, how the content should be displayed, and so on.

By default, makeRequest() uses the GET method to fetch data, and the default type for content is TEXT (where a web page's content is fetched as raw text).

This example shows a very simple use of the API. It fetches the first 400 characters on www.google.com and outputs them to a <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>

New! Caching

Calls to makeRequest are cached by default. In the example below, the wrapper function takes the same parameters as the makeRequest call, but accepts another parameter named refreshInterval, which allows you to specify the cache duration. However, caching serves a useful purpose, and you should be careful not to refresh the cache so often that you degrade performance. Caching makes fetching data faster. It also reduces the load on third-party servers hosting the remote content. You should try to avoid disabling the cache completely, which you would do by specifying 0. For more discussion of this topic, see the Gadgets API Developers Guide.

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);
}

Updated XML Example

This example shows how to use the DOM content type to process XML data. When you specify the DOM content type, makeRequest() retrieves the specified XML document as a DOM object. Once you have the object, you can operate on it using standard DOM JavaScript functions. For more discussion of this topic, see the Gadgets API Developers Guide.

<?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>

New! JSON Example

You can use the JSON content type to fetch JSON-encoded content as a JavaScript object.

The application below fetches content from a sample PHP page that contains the following JSON-encoded string:

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

When you fetch content from the PHP page that contains this string, the return value is a JavaScript object containing key-value pairs (that is, an associative array). This sample retrieves the object and then prints out the key-value pairs it contains:

<?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>

New! More about JSON

JSON (JavaScript Object Notation) is a data interchange format lets you encode certain types of objects (arrays and collections of key-value pairs) as strings that can easily be passed around.

The Gadgets API provides the gadgets.json.stringify() method for encoding object as JSON strings, and the gadgets.json.parse() method for turning a JSON string into an object. Note that because OpenSocial performs automatic HTML escaping of all returned data including application data, you must unescape stringified JSON objects in the appdata store before parsing them, for example: gadgets.util.unescapeString(jsondata).

This example creates a JavaScript array, encodes it as a JSON string, and then converts the JSON string back into an Array object:

<?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 output from this gadget is as follows:

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

Updated Using the POST Method

By default, remote content is fetched using the GET method. You can use the POST_DATA parameter to use the POST method to fetch content instead. For example:

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();

Updated Setting an Authorization Type

The Gadgets API supports the following authorization types:

  • gadgets.io.AuthorizationType.AUTHENTICATED (container uses full authentication)
  • gadgets.io.AuthorizationType.SIGNED (request is signed by the container)
  • gadgets.io.AuthorizationType.NONE (the default)

How you use these methods depends on your container. Here is one example of using a signed authorization type that is specific to Orkut.

Updated Permission Control

The OpenSocial API supports permission control in applications. When an application uses a data request to fetch a viewer from the server, it is only returned if that application has access. If the application does not have access, one of the standard error codes, opensocial.ResponseItem.Error.UNAUTHORIZED, is returned instead. An application can also check ahead of time for its access by using the new opensocial.hasPermission call. If access is denied, you can use opensocial.requestPermission to ask the viewer for the specified permission. Of course, some containers may always grant viewer access, and some may always deny, but this decision is up to the container.

This excerpt illustrates how to use the permission control 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);

To Learn More

To learn more about the OpenSocial API, here are some additional resources:

Back to top