Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Will Your Next Web Application Be a Google Gadget? : Page 4

Learn how to leverage the Google Gadget API to make your web applications more reachable. As an example, you'll see how to build a real-world gadget that fetches and displays the DevX feeds.


advertisement
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 gadget—author 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 instead—which 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 page—that is in their Google Homepage—or 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 body—namely, the DevX RSS feeds.

That leaves the JavaScript section, which is formed by three functions: fillGlobals, init, 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:

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 object—representing the feeds—to 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 article—the 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 HTML—declared 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.



Alessandro Lacava is a software developer and technical writer based in Italy. He is mainly interested in Java and .NET technologies, Web applications and telecommunication systems. Alessandro holds a degree in telecommunications engineering. You can reach him via his Web site.
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap