Build a DevX RSS Feed-Reader Gadget
Listing 1 contains the complete code to build the DevX feed reader. Although at first glance, that might look like a lot of code, it's not that much when you consider that it contains both the presentation and the business logic.
Again, if you don't have a server, you can test this gadget at the URL
http://www.alessandrolacava.com/google/gadgets/devx-feeds.xml.
Although
Listing 1 is considerably larger than the examples you've seen so far, it is composed of the same elements you've already seen, starting with the
Module root element, which contains the following child elements:
- ModulePrefs
- A set of UserPref elements.
- A Content element.
However it's worth explaining some new aspects you haven't seen yet. Here's the
ModulePrefs element:
<ModulePrefs title="__UP_title__"
directory_title="DevX Feeds"
description="Aggregate 1-10 entries of DevX Feeds.
You can choose the feed to read by editing settings"
author="Alessandro Lacava"
author_email="alessandrolacava+devxgadget@gmail.com"
author_affiliation="DevX"
author_location="Milan, ITALY"
height="250"
scrolling="true"
singleton="false"
author_link="http://www.alessandrolacava.com">
</ModulePrefs>
As you can see, the
ModulePrefs element contains general infoormation about the gadgetauthor info, the gadget's height and so on. Because the content may exceed the height, the gadget supports scrolling via the
scrolling="true" attribute. Notice how I wrote my e-mail address:
alessandrolacava+devxgadget@gmail.com
I've done that because of spam. Gmail drops everything after the plus sign (+).
I told you earlier that you can specify other datatypes for a
UserPref section. The control rendered for the preference strongly depends on the datatype you choose. If you don't specify a datatype it defaults to string, which gets rendered as a simple textbox. The
title preference relies on that default rendering:
<UserPref name="title"
display_name="Gadget Title"
default_value="DevX Feeds"/>
 | |
Figure 3. Preferences: The figure shows how the the DevX gadget renders preferences. |
Figure 3 shows how the sample gadget renders the title and other preference options.
The DevX gadget uses
bool and enum preference datatypes as well as the default string type. As you can see from
Figure 3, the gadget renders
bool preferences as a checkbox, while the
enum preference becomes a combobox (a drop-down list). For example, here's the
feedUrl enum preference definition that lets the user choose which of several DevX feeds to fetch.
<UserPref name="feedUrl"
display_name="Feed" datatype="enum"
default_value="http://services.devx.com/outgoing/devxfeed.xml">
<EnumValue value="http://services.devx.com/outgoing/devxfeed.xml"
display_value="Latest Articles"/>
<EnumValue value="http://services.devx.com/outgoing/javafeed.xml"
display_value="Java"/>
...
</UserPref>
Note that you can indicate a default value through the
default_value attribute of the
UserPref element, and that the displayed value can differ from the item's
value. You specify a different display value using the
display_value attribute. If you don't indicate a specific display value the control displays the
value attribute value insteadwhich wouldn't be as convenient for end users in this case. For completeness, here's a more detailed examination of one of the
bool preferences used in the DevX gadget:
<UserPref name="newPageTarget"
display_name="Open Link In New Page"
datatype="bool"
default_value="true"/>
The previous preference definition lets users choose whether to open feed links in the same pagethat is in their Google Homepageor in a different page. I chose
true as the default for this preference, which means that the checkbox will be checked by default and all the feed links will load in a fresh browser instance.
As you have probably guessed, the most important part of a gadget lies in the Content element, which is where you define the presentation (CSS and HTML) and business logic (JavaScript) for the gadget application.
I won't delve into the CSS section because it's just styling, like any other CSS. The HTML part is delimited by the following line of code:
<div id="feedContainer"></div>
The contents of this div element will contain the entire gadget bodynamely, the DevX RSS feeds.
That leaves the JavaScript section, which is formed by three functions:
fillGlobals,
init, and
parseFeedplus a call to the
_IG_RegisterOnloadHandler discussed earlier, which registers the init function as the page load handler. Here's the code for the init function:
function init()
{
fillGlobals();
// Display loading message before fetching feed.
container.innerHTML =
'<div class="loadingLabel">Loading...</div>';
// Fetch feed and return it as a JSON object.
// parseFeed is the callback function.
_IG_FetchFeedAsJSON(feedUrl, parseFeed, numOfEntries);
}
The
init function calls
fillGlobals, which simply assigns values to some variables used throughout the application. It does this by retrieving the user preferences and getting a handle to the
feedContainer div tag that contains the feeds. Here's the code for the
fillGlobals function:
function fillGlobals()
{
var prefs = new _IG_Prefs(__MODULE_ID__);
feedUrl = prefs.getString("feedUrl");
numOfEntries = prefs.getInt("numOfEntries");
container = _gel("feedContainer");
showFeedDate = prefs.getBool("showFeedDate");
openInNewPage = prefs.getBool("newPageTarget");
}
After calling
fillGlobals, init displays a "Loading..." message in the main container and then calls the
_IG_FetchFeedAsJSON built-in function used to retrieve the RSS feed as a JSON object (see
this JSON article for more information. The three parameters passed to
_IG_FetchFeedAsJSON are:
- feedUrl: The URL of the RSS feed to fetch. The fillGlobals method retrieves the specific preferred feed value from the user preferences.
- parseFeed: This is a callback function fired when the feed has been retrieved. Remember, _IG_FetchFeedAsJSON fetches feeds asynchronously and, when done, passes the JSON objectrepresenting the feedsto the specified callback function, namely parseFeed.
- numOfEntries: the maximum number of entries to retrieve. This variable is also initialized in fillGlobals from the user's preferences.
That's all the basic information you need to know to build brilliant Google gadgets.
Figure 4 shows a screenshot of the completed gadget in my Google homepage.
 | |
Figure 4. The DevX Tab in My Google Homepage: Here's my homepage showing both the sample gadgets developed for this articlethe HelloWorld gadget and the DevX feed reader gadget. |
I won't delve into the details of the
parseFeed function because it's just basic JavaScript code that loops through the retrieved feed entries and adds them to the gadget's main container (the
feedContainer div). The only thing you might need to know more about is the structure of the JSON object passed to
parseFeed. For more information on that you can explore the
official documentation.
Security Concerns
Finally, I wish to spend some words about security. In fact, you might wonder: "What impedes my gadget from accessing data that belongs to another gadget on the page?"
From gadgets whose content type is HTMLdeclared such through the line
<Content type="html">—you cannot access other gadgets' data. The reason for this is that each HTML-type gadget is rendered into an
iframe. The following is an excerpt from the Google Gadget
Development Fundamentals page:
"Gadget content is wrapped in an
iframe. An
iframe is effectively a separate page running within the parent page. The
iframe has no knowledge of and no ability to interact with the parent page. This isolation helps protect users from malicious gadgets that might try, for example, to steal or modify cookies. However,
iframes do impose certain restrictions by denying gadgets to interact with each other and other components on the page."
You can bypass these restrictions by declaring your gadget as an HTML-inline gadget, which you do by changing its
content type setting to
<Content type="html-inline">. Of course, this type of gadget has other limitations; for example, you can't use HTML-inline gadgets with other Google properties, and HTML-inline gadgets can't be included in the content directory. There are other major drawbacks to inlining, but they are beyond the scope of this article. For more information about inline gadgets I strongly suggest you download and study the
related documentation.