Build a DevX RSS Feed-Reader Gadget
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:
- 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
description="Aggregate 1-10 entries of DevX Feeds.
You can choose the feed to read by editing settings"
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:
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:
|Figure 3. Preferences: The figure shows how the the DevX gadget renders preferences.|
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.
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:
display_name="Open Link In New Page"
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.
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:
The contents of this div element will contain the entire gadget bodynamely, the DevX RSS feeds.
, and parseFeed
plus 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:
// Display loading message before fetching feed.
// Fetch feed and return it as a JSON object.
// parseFeed is the callback function.
_IG_FetchFeedAsJSON(feedUrl, parseFeed, numOfEntries);
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
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
- 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
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
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
"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