Google Code offered in: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
This tutorial will walk you through the steps required to build a simple social gadget where you can give gifts to your friends. You can find the complete sample code in the opensocial-resources project on Google Code.
This demo uses the SocialNorms utilities, also part of the opensocial-resources project. These utilities encapsulate some common OpenSocial idioms, making it easier to write social gadgets. Use of SocialNorms for your own gadgets is entirely optional -- if you want more control over the data exchanged, feel free to use the APIs directly.
Feel free to copy the sample gadget source code and make changes as you go along. Your gadget will need to be hosted publicly, and you can use the Google Gadget Editor, Google Page Creator, Project Hosting on Google Code, or any other webhosting service to host your gadget.
The sample code has two main parts: the Gadget XML specification and the JavaScript code called by the Gadget XML. Each version of the gadget will use a similar XML specification to call different functions in a JavaScript file. For example, the first gadget calls the hello method from the common.js file:
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Gifts - 1 - hello">
<Require feature="opensocial-0.6"/>
</ModulePrefs>
<Content type="html">
<![CDATA[
<script src="http://opensocial-resources.googlecode.com/svn/samples/tutorial/trunk/json.js"></script>
<script src="http://opensocial-resources.googlecode.com/svn/samples/tutorial/trunk/SocialNorms.js"></script>
<style>
@import url(http://opensocial-resources.googlecode.com/svn/samples/tutorial/trunk/styles.css);
</style>
<div id='main'>
</div>
<script>
var gadgetToLoad = "hello";
</script>
<script src="http://opensocial-resources.googlecode.com/svn/samples/tutorial/trunk/common.js"></script>
]]>
</Content>
</Module>
To use the SocialNorms sample utility code, you need to create an object with a "render" method and register this app to be started on application load:
SocialNorms.createSocialAppOnLoad(MyApp, mode, ["gifts"]);
The render method is called once the gadget has loaded. For our sample code, our render code just calls one of the methods on the Gadgets object.
The first version uses the function Gadgets.hello. It simply sets innerHTML on the main div (which is specified in the Gadget XML file) to some text that welcomes the viewer (that's you) by name. In the following code snippet, the getViewer method returns a Person object, and the getDisplayName returns the name of the person.
byId("main").innerHTML = "Welcome, " + data.getViewer().getDisplayName();
The next step runs the Gadgets.friends method to list the names of your friends. The SocialNorms utility method data.getViewerFriends().asArray() returns a JavaScript array of Person objects corresponding to the friends of the viewer. The following code iterates over the viewer's friends and adds each friend to a table (encapsulated as a SimpleTable object).
var html = "Welcome, " + data.getViewer().getDisplayName();
var table = new SimpleTable();
var friends = data.getViewerFriends().asArray();
for (var i=0; i<friends.length; i++) {
table.addPersonRow(friends[i], "hi there");
}
html += table.getHtml();
byId("main").innerHTML = html;
In the next method, Gadgets.gifts, you can actually give your friends a gift. You store the gifts that you (the viewer) are giving to your friends in a single field of the shared data store named "gifts". Gifts are represented as a JavaScript associative array whose keys are the ids of our friends (obtained from the Person.getId method) and whose values are the gifts you're giving. This array is collapsed into a single key by encoding it as JSON, so the following code parses the JSON and displays the gifts you've given.
var html = "Welcome, " + data.getViewer().getDisplayName();
var table = new SimpleTable();
var friends = data.getViewerFriends().asArray();
globalGiftsGiven = safeParseJSON(data.getDataFor(opensocial.DataRequest.PersonId.VIEWER)['gifts']);
for (var i=0; i<friends.length; i++) {
var person = friends[i];
var row = "You gave: " + makeOptions(person, globalGiftsGiven[person.getId()], 'handleChange1');
table.addPersonRow(person, row);
}
html += table.getHtml();
byId("main").innerHTML = html;
When the user changes their selection, the callback function handleChange1 is invoked. This method updates the associative array, re-encodes it as JSON, and saves it back to the server. This write operation is performed by creating a new DataRequest object and adding a request to update the app data using the special id opensocial.DataRequest.PersonId.VIEWER.
function handleChange1(id, name, sel) {
var item = sel.options[sel.selectedIndex].value;
globalGiftsGiven[id] = item;
var json = globalGiftsGiven.toJSONString();
var req = opensocial.newDataRequest();
req.add(req.newUpdatePersonAppDataRequest(opensocial.DataRequest.PersonId.VIEWER, 'gifts', json));
console.log("setting: " + json);
req.send();
}
Once you've given a gift, you'd like to let your other friends know. The Gadgets.activities is the same as the previous
step, except for the callback that is invoked when the user changes their gift selection. The following code is added to post an activity to the user's stream.
var activity = opensocial.newActivity(
theApp.data.getViewer().getDisplayName() + " gave a " + item + " to " + name
);
opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH);
The title of our activity should say something like "Alice gave a peanut to Bob", so get the viewer's name, the name of the item (passed into the handler function) and the name of the recipient (also passed into the handler function). Once you've created the activity, you pass it into the requestCreateActivity function. When the activity has been posted, it will be shown in the user's activity stream (which shows up on their home page in Orkut).
Note: Passing in a priority of opensocial.CreateActivityPriority.HIGH means that the gadget will pop up a message asking the user's permission about whether or not the gadget is allowed to post the activity -- this is a one-time message and the gadget will remember the user's preference later. Passing in a priority of "LOW" means that the gadget will drop the activity (without notification) if the user has not already granted permission.
So far this tutorial focused on the "canvas" view of the application, where the application gets to take over the entire page. You can also view your application on a user's profile. You can tell which page you're on by checking the URL parameters in document.location. In the Gadgets.profile method, a different view is shown depending on the mode of the page:
function getSurface() {
return opensocial.Environment.getSurface();
}
if (getSurface() == "canvas") {
// show the canvas view from the previous example
Gadgets.activities(data);
} else {
// show the profile view
var html = "Gifts you're receiving:";
....
}
The next steps are up to you! You could add pictures for the gifts (use the application storage to store the URLs), or let users send a custom message with their gift. There are many ways to use OpenSocial to build cool new applications that will spread virally across the web. How will your apps socialize?
For your convenience, here is the full listing of common.js, where all the OpenSocial API calls are made:
function byId(x) {
return document.getElementById(x);
}
function SimpleTable() {
var html = "<div>";
this.addRow = function(row) {
html += "<div class='listitemchk'>" +
row +
"</div><div class='listdivi'></div>";
};
this.addPersonRow = function(person, row) {
this.addRow(
"<img class='listimg' src='" + person.getField(opensocial.Person.Field.THUMBNAIL_URL) + "'/>" +
"<h3 class='smller'>" + person.getDisplayName() + "</h3>" +
"<div class='para'>" +
row +
"</div>"
);
};
this.getHtml = function() {
return html + "</div>";
};
}
function getSurface() {
return opensocial.Environment.getSurface();
}
var MyApp = {};
MyApp.render = function(data) {
Gadgets[gadgetToLoad](data);
}
function myInit() {
var mode = (gadgetToLoad == "profile") ? opensocial.DataRequest.PersonId.OWNER : opensocial.DataRequest.PersonId.VIEWER ;
SocialNorms.createSocialAppOnLoad(MyApp, mode, ["gifts"]);
}
myInit();
Gadgets = {};
Gadgets.hello = function(data) {
byId("main").innerHTML =
"Welcome, " + data.getViewer().getDisplayName();
}
Gadgets.friends = function(data) {
var html = "Welcome, " + data.getViewer().getDisplayName();
var table = new SimpleTable();
var friends = data.getViewerFriends().asArray();
for (var i=0; i<friends.length; i++) {
table.addPersonRow(friends[i], "hi there");
}
html += table.getHtml();
byId("main").innerHTML = html;
}
function makeOptions(person, val, fname) {
var options = [["cashew_nut", "a cashew nut"],
["peanut", "a peanut"],
["hazelnut", "a hazelnut"],
["red_pistachio", "a red pistachio nut"]];
var html = "<select onchange='" + fname + "(\"" + person.getId() + "\", \"" + person.getDisplayName() + "\", this)'>";
for (var i=0; i<options.length; i++) {
html += "<option value='" + options[i][0] + "'";
if (val == options[i][0]) {
html += " selected='selected'";
}
html += ">" + options[i][1] + "</option>";
}
html += "</select>";
return html;
}
var globalGiftsGiven = {};
function handleChange1(id, name, sel) {
var item = sel.options[sel.selectedIndex].value;
globalGiftsGiven[id] = item;
var json = globalGiftsGiven.toJSONString();
var req = opensocial.newDataRequest();
req.add(req.newUpdatePersonAppDataRequest(opensocial.DataRequest.PersonId.VIEWER , 'gifts', json));
console.log("setting: " + json);
req.send();
}
function safeParseJSON(str) {
if (!str) {
return {};
}
try {
return str.parseJSON();
} catch (e) {
console.log("error parsing JSON: " + e);
return {};
}
}
Gadgets.gifts = function(data) {
var html = "Welcome, " + data.getViewer().getDisplayName();
var table = new SimpleTable();
var friends = data.getViewerFriends().asArray();
globalGiftsGiven = safeParseJSON(data.getDataFor(opensocial.DataRequest.PersonId.VIEWER )['gifts']);
for (var i=0; i<friends.length; i++) {
var person = friends[i];
var row = "You gave: " + makeOptions(person, globalGiftsGiven[person.getId()], 'handleChange1');
table.addPersonRow(person, row);
}
html += table.getHtml();
byId("main").innerHTML = html;
}
function handleChange2(id, name, sel) {
handleChange1(id, name, sel);
var item = sel.options[sel.selectedIndex].value;
var activity = opensocial.newActivity(
theApp.data.getViewer().getDisplayName() + " gave a " + item + " to " + name
);
opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH);
}
Gadgets.activities = function(data) {
var html = "Welcome, " + data.getViewer().getDisplayName();
var table = new SimpleTable();
var friends = data.getViewerFriends().asArray();
globalGiftsGiven = safeParseJSON(data.getDataFor(opensocial.DataRequest.PersonId.VIEWER )['gifts']);
for (var i=0; i<friends.length; i++) {
var person = friends[i];
var row = "You gave: " + makeOptions(person, globalGiftsGiven[person.getId()], 'handleChange2');
table.addPersonRow(person, row);
}
html += table.getHtml();
byId("main").innerHTML = html;
}
Gadgets.profile = function(data) {
if (getSurface() == "canvas") {
Gadgets.activities(data);
} else {
var html = "Gifts you're receiving:";
var table = new SimpleTable();
var friends = data.getOwnerFriends().asArray();
for (var i=0; i<friends.length; i++) {
var person = friends[i];
console.log(person.getDisplayName() + " => " + data.getDataFor(person).toJSONString());
var friendGiftsGiven = safeParseJSON(data.getDataFor(person)['gifts']);
var giftToOwner = friendGiftsGiven[data.getOwner().getId()];
if (!giftToOwner) {
continue;
}
var row = person.getDisplayName() + " gave you a " + giftToOwner;
table.addPersonRow(person, row);
}
html += table.getHtml();
byId("main").innerHTML = html;
}
}
| Revision | Updated | Description |
|---|---|---|
| OpenSocial 0.8 | August 2008 | Updated for 0.8 and added three additional steps. |
| OpenSocial 0.7 | February 2008 | Major content update and rewrite for OpenSocial 0.7. |
| OpenSocial 0.6 | January 2008 | Updated for OpenSocial 0.6. |
| OpenSocial 0.5 | November 2007 | Created article. |