このガイドでは、OpenSocial アプリケーションの構築について解説します。Gadgets API や JavaScript についてある程度の知識をお持ちのデベロッパーを対象としていますが、詳しい情報が必要な箇所では他の資料へのリンクを示します。
このドキュメントには、OpenSocial API の 0.7 更新時の変更点が反映されています。Newや更新とマークされている項は、コーディング方法が前のバージョンから変更されたことを示します。
ソーシャル アプリケーションとは、簡単に言えば、OpenSocial JavaScript API をサポートするコンテナ上で実行されるアプリケーションです。
ソーシャル アプリケーションを記述するには以下が必要です。
OpenSocial API は、人に焦点を当てた API です。ユーザー間でアクティビティを共有したり、友人に関する情報にアクセスしたりできます。OpenSocial API の機能は、以下の 3 つの領域に分けることができます。
API 呼び出しの多くは非同期です。これは、情報を取得したり更新したりする上で、サーバー要求が必要になることがあるためです。したがって、サーバーからデータが返されたときに実行されるコールバック関数を渡す必要があります。
OpenSocial JavaScript API のクラスやメソッドの詳細については、API リファレンスをご覧ください。
OpenSocial API を使用するには、アプリケーションに次のような Requires セクションを追加します。
<ModulePrefs title="Title of Your Application"> <Require feature="opensocial-0.7"/> </ModulePrefs>
ガジェット XML 仕様の構造とコンテンツの詳細については、Gadgets API デベロッパー ガイド をご覧ください。
ここでは、友人の名前を一覧表示する簡単な例について説明します。まずは、OpenSocial API で定義されている以下の役割について理解する必要があります。
この項で説明する「友人リスト」サンプルでは、ビューアとビューアの友人をフェッチし、ビューアの友人の一覧を表示します。このサンプルに沿って、OpenSocial アプリケーションでデータをフェッチして操作する方法を説明します。基本的な手順は次のとおりです。
opensocial.newDataRequest() を呼び出して DataRequest を作成します。 DataRequest.add(request) を呼び出します。DataRequest オブジェクトに個別の要求をすべて追加したら、DataRequest.send(callback) を呼び出します。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 では、アプリケーションごとのインスタンスやグローバル アプリケーション データもサポートされていましたが、これらは 0.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 エスケープが実行されるため、解析前に appdata ストア内の文字列化された JSON オブジェクトをアンエスケープする必要があります。次に例を示します。
var unescapedString = gadgets.util.unescapeString(jsondata); var obj = gadgets.json.parse(unescapedString);
OpenSocial API を使用すると、アクティビティ ストリームを介してアクティビティを友人と共有できます。アクティビティ ストリームとは、ユーザーのアクションを個別のエントリで表現したフィードです。アクティビティには、アプリケーションの状態の変更から映画のオンライン レビューの書き込みまで、ユーザーのあらゆるアクションが含まれます。
アクティビティの優先度を HIGH にするよう要求すると、アプリケーションがユーザーに対して、ユーザーの代わりにアクティビティを登録する許可を求めます (まだ許可を得ていない場合のみ)。アプリケーションによる登録が許可されていない場合、優先度を LOW にするよう要求しても、その呼び出しでは何も行われません。
次に、アクティビティを作成する簡単な例を示します。
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Activities" >
<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);
};
function callback(data) {
var title = data.getField(opensocial.Activity.Field.TITLE);
title = gadgets.util.unescapeString(title);
div.innerHTML = title;
};
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.com や myspace.com) がわかります。これにより、アプリケーションから、別の環境に別の方法で応答することが可能になります。getDomain メソッドは、API から相対 URL のみが返される場合に、絶対 URL を作成するために使用します。ただし、機能面で何らかの変更を行う場合は、通常は hasCapability, という別のメソッドを使用することをお勧めします。hasCapability メソッドは関数名を取り、その関数が現在のコンテナで使用できるかどうかを返します。これにより、デベロッパーは、コンテナ固有の拡張を常に同じ仕組みで OpenSocial に追加できます。supportsField メソッドも、このようなコンテナ固有の拡張性を備えています。コンテナ プロバイダでこのメソッドを使用すると、プロバイダ固有の Person フィールドや Activity フィールドを追加できます。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>
1 つのガジェット XML ファイルには、複数の <Content> セクションを含めることができます。各 <Content> セクションは、それぞれがレンダリングするビューを宣言します。ドキュメント内のすべての <Content> セクションは兄弟関係にあり、レンダリングするビューをオプション パラメータ view= を使用して定義することもできます。
ここでは、2 つのコンテンツ セクションからなるガジェットを表示する単純な例を示します。
<?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>
これらすべての手法を 1 つのガジェットにまとめると次のようになります。
<?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() メソッドを使用すると、他のウェブ サーバーやウェブ ページから、コンテンツをリモートにフェッチできます。gadgets.io.makeRequest() は、以前のガジェット API の IG_Fetch... メソッドの拡張で、GET だけでなく POST にも使用できます。また、要求の署名や認証を行うかどうかを指定することもできます。
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 と同じパラメータを取りますが、もう 1 つ別に refreshInterval というパラメータを取ります。このパラメータを使用することで、キャッシュの期間を指定できます。キャッシュは便利な機能ですが、あまり頻繁に更新するとパフォーマンスが低下するおそれがありますので注意してください。キャッシュを行うことで、データをすばやくフェッチできるようになります。また、リモート コンテンツをホストするサードパーティ サーバーへの負荷を軽減することもできます。0 を指定すると、キャッシュが完全に無効になってしまいます。このような設定は、できる限り避けてください。このトピックについて詳しくは、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);
}
この例では、DOM コンテンツ タイプを使用して XML データを処理する方法を示します。DOM をコンテンツ タイプを指定すると、指定した XML ドキュメントが makeRequest() によって DOM オブジェクトとして取得されます。取得した DOM オブジェクトは、標準の DOM JavaScript 関数を使用して操作できます。このトピックについて詳しくは、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>
JSON コンテンツ タイプを使用すると、JSON エンコードのコンテンツを JavaScript オブジェクトとしてフェッチできます。
下に示すアプリケーションでは、次の 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 (JavaScript Object Notation) は、特定のタイプのオブジェクト (キー/値ペアの配列およびコレクション) を交換しやすいデータにエンコードするためのデータ交換形式です。
ガジェット API には、オブジェクトを JSON 文字列にエンコードするための gadgets.json.stringify() メソッドと、JSON 文字列をオブジェクトに変換するための gadgets.json.parse() メソッドが用意されています。OpenSocial では、アプリケーション データを含め、返されるすべてのデータに対して自動的に HTML エスケープが実行されるため、解析前に appdata ストア内の文字列化された JSON オブジェクトをアンエスケープする必要があります。たとえば、gadgets.util.unescapeString(jsondata) のようにします。
この例では、まず JavaScript 配列を作成し、これを JSON 文字列としてエンコードしてから Array オブジェクトに変換し直しています。
<?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
リモート コンテンツは、デフォルトでは GET メソッドでフェッチされます。コンテンツを POST メソッドでフェッチしたい場合は、POST_DATA パラメータを使用します。次に例を示します。
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 については、以下の資料も参考にしてください。