Thursday, July 3, 2008

Use multiple content sections

Take advantage of multiple content sections in your gadget spec to render more tailored views for
canvas and profile pages. This will help ensure that the container only loads the necessary components
for each view. In particular, focus on making your profile view as lean as possible.

Use appData as a cache for content

It's much faster to request data from the container than it is to hit your own server. There are
lots of ways you can cache your application data in the Persistence API and speed up page
loads. The profile view is a great place to do this because it gets a lot of page views
and there is less dynamic content.

Here's the slow way to load a profile page:

1.User opens profile page.
2.Your app uses makeRequest to get data from your server.
3.Once the data is returned, your app renders the profile page.

Here's a much faster way:

1.User opens profile page.
2.Your app uses a DataRequest to get data from the container.
3.Once the data is returned, your app renders the profile page.
4.Now, your app uses makeRequest to get data from your server.
5.Once the data is returned, your app updates the profile page.

An example
First, let's look at using multiple content sections. Here's the bare minimum:

;<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="users &lt;3 speed">
<Require feature="opensocial-0.7" />
</ModulePrefs>
<Content type="html" view="profile">
<![CDATA[
Hello, profile!
]]>
</Content>
<Content type="html" view="canvas">
<![CDATA[
Hello, canvas!
]]>
</Content>
</Module>

Now let's use the technique where we populate the profile view with HTML cached in appData:

<Content type="html" view="profile">
<![CDATA[
<script type="text/javascript">
function request() {
var req = opensocial.newDataRequest();
req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER), "owner");
req.add(req.newFetchPersonAppDataRequest(opensocial.DataRequest.PersonId.OWNER, "profile"), "usrdata");
req.send(response);
};
function response(data) {
console.log(data);
var usrdata = data.get("usrdata").getData(),
owner = data.get("owner").getData(),
profileHtml = 'No data';
if (usrdata[owner.getId()]) {
profileHtml = usrdata[owner.getId()].profile || 'Empty data';
}
document.write(profileHtml);
};
gadgets.util.registerOnLoadHandler(request);
</script>
]]>
</Content>
Finally, implement some functionality for the canvas view. When the user takes an action that
will update the data shown in their profile, update the 'profile' field in appData.
This app lets the user set a quote to be displayed on their profile.
When the 'save' link is clicked, the quote and the HTML to display in the profile view are updated in appData.
Here's the full application spec:


<?xml version="1.0" encoding="UTF-8" ?>

<Module>

<ModulePrefs title="users &lt;3 speed">

<Require feature="opensocial-0.7" />

</ModulePrefs>

<Content type="html" view="profile">

<![CDATA[

<script type="text/javascript">

function request() {

var req = opensocial.newDataRequest();

req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER), "owner");

req.add(req.newFetchPersonAppDataRequest(opensocial.DataRequest.PersonId.OWNER, "profile"), "usrdata");

req.send(response);

};



function response(data) {

console.log(data);

var usrdata = data.get("usrdata").getData(),

owner = data.get("owner").getData(),

profileHtml = 'No data';

if (usrdata[owner.getId()]) {

profileHtml = usrdata[owner.getId()].profile || 'Empty data';

}

document.write(profileHtml);

};



gadgets.util.registerOnLoadHandler(request);

</script>

]]>

</Content>

<Content type="html" view="canvas">

<![CDATA[

<script type="text/javascript">

function request() {

var req = opensocial.newDataRequest();

req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER), "owner");

req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER), "viewer");

req.add(req.newFetchPersonAppDataRequest(opensocial.DataRequest.PersonId.OWNER, "quote"), "appData");

req.send(response);

};



function response(data) {

var viewer = data.get("viewer") && data.get("viewer").getData(),

owner = data.get("owner") && data.get("owner").getData(),

appData = data.get("appData") && data.get("appData").getData(),

quote = '',

text = '';

if ((viewer.getId() || -1) == (owner.getId() || -2)) {

if (appData[owner.getId()]) {

quote = appData[owner.getId()];

}

text = ['Edit your quote: ',

'<input id="quote_input" type="text"/> ',

'<a href="javascript:void(0);" onclick="save();" value="',

quote,

'">save</a>'].join('');

document.getElementById('main').innerHTML = text;

}

};



function save() {

var quote = document.getElementById('quote_input').value,

profileHtml = '';

profileHtml = ['Latest quote: ', quote].join('');

req = opensocial.newDataRequest();

req.add(req.newUpdatePersonAppDataRequest(

opensocial.DataRequest.PersonId.VIEWER, "quote", quote), "updatequote");

req.add(req.newUpdatePersonAppDataRequest(

opensocial.DataRequest.PersonId.VIEWER, "profile", profileHtml), "updateprofile");

req.send(response2);

};



function response2(data) {

if (!data.hadError()) {

document.getElementById("status").innerHTML = "Saved quote at " + new Date();

} else {

document.getElementById("status").innerHTML = "There was a problem updating your profile";

}



/*

* Now that the page is loaded you can use makeRequest to

* see if you have fresher data on your server.

*/

};



function status(text) {

var dom =

dom.innerHTML = text;

};



gadgets.util.registerOnLoadHandler(request);

</script>

<div id="main"></div>

<div id="status"></div>

]]>

</Content>

</Module>

No comments: