Tuesday, November 25, 2008

How to add user preferences to your Google Gadget

In the previous post, we saw how to create a simple Google Gadget that reads the CNN.com Top Stories feeds and display them. We make it by default to display only 10 stories and to display the summaries, but what about if I want to see some more stories or less? or if I don't want to the see the summary, only the story headline? Well, there is a way for the user to customize the gadget , we just need to use User Preferences.

With user preferences we can set information in the gadget that is specific to the user. To have user preferences you just need to specify them inside the Module tag of the gadget. See the following example:

<UserPref name="show_summ" display_name="Show Summaries?" datatype="bool" default_value="false" required="true"/>


As you can see what you need to specify is the name of the preference, the display name, the data type, the default value and if it is required or not. The data type, the default value and required attributes are optional. The default value for data type is string and the default value for required is false.

Let's see how our CNN.com Top Stories gadget would look with preferences that will allow the user to set how many stories wants to see and if he/she wants to see the summary or not.
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs
title="CNN.com Top Stories"
title_url="http://www.cnn.com/"
author="Your name"
author_email="youremail@domain.com"
description="Gadget to see the current CNN.com top stories."
width="450"
height="350"
scrolling="true">
<Require feature="dynamic-height"/>
</ModulePrefs>
<UserPref name="num_entries" display_name="Number of Entries:" default_value="5"/>
<UserPref name="show_summ" display_name="Show Summaries?" datatype="bool" default_value="false"/>

<Content type="html">
<![CDATA[
<style>
div#main_container {
font-size:12px;
font-family:Arial;
margin: 5px;
text-align: left;
text-decoration: none;
}

div#main_container h2 {
background: url(http://i2.cdn.turner.com/cnn/.element/img/1.0/logo/cnn.logo.rss.gif) no-repeat left top;
display: block;
height: 33px;
text-indent: -100000;
width: 144px;
}

</style>
<script type="text/javascript">

// Get userprefs
var prefs = new _IG_Prefs();
var summary = prefs.getBool("show_summ");
var entries = prefs.getInt("num_entries");

// Function to dipslay content retrieved from XML feed
function displayContent() {

// If user wants to display more than 50 entries, display an error
// and set the value to 50, the max allowed.
if (entries > 50)
{
alert("You cannot display more than 50 entries.");
entries = 50;
}

var url = "http://rss.cnn.com/rss/edition.rss";

// Use the _IG_FetchFeedAsJSON() function to retrieve core feed data from
// the specified URL. Then combine the data with HTML markup for display in
// the gadget.
_IG_FetchFeedAsJSON(url, processFeed, entries, summary);

}

// Function to process the feed
function processFeed(feed) {
var contentDiv = _gel("main_container");

if (feed == null) {
contentDiv.innerHTML = "Invalid data.";
return;
}

// Start building HTML string that will be displayed in gadget.
var html = "";

// Access the fields in the feed
html += "<h2>" + feed.Title + "</h2>";
html += "<div>" + feed.Description + "</div><br>";

// Access the data for a given entry
if (feed.Entry) {
for (var i = 0; i < feed.Entry.length; i++) {
html += "<div>" + "<a target='_blank' href='" + feed.Entry[i].Link + "'>" + feed.Entry[i].Title + "</a> ";
// The feed entry Date field contains the timestamp in seconds
// since Jan. 1, 1970. To convert it to the milliseconds needed
// to initialize the JavaScript Date object with the correct date,
// multiply by 1000.
var milliseconds = (feed.Entry[i].Date) * 1000;
var date = new Date(milliseconds);
html += date.toLocaleDateString();
html += " ";
html += date.toLocaleTimeString();
if (summary == true) {
html += "<br><i>" + feed.Entry[i].Summary + "</i>";
}

html += "</div>";
}
}

contentDiv.innerHTML = html;

// Adjust gadget height according to contents
_IG_AdjustIFrameHeight();

}

_IG_RegisterOnloadHandler(displayContent);


</script>

<div id="main_container"></div>

]]>
</Content>
</Module>

As you saw in the code we need the following code to retrieve the user preferences:

var prefs = new _IG_Prefs();
var summary = prefs.getBool("show_summ");
var entries = prefs.getInt("num_entries");


There is a "get" method for each data type available. To get more information about user preferences click here.

Allowing the user to set up its preferences is really simple and it adds a lot value to the gadget functionality!