Friday, December 12, 2008

how to build a Google Gadget with data fetched from an APEX Application Process

Last week, I release a Google Gadget to publish the weekly release of Insum's Web 2.0 Demos.
I'll explain how I did it.

Google Gadget... what's that?!
It's an XML file defining every aspect of your gadget(module). The words "gadget" and "module" can both be used to describe a Google Gadget.

The gadget definition contains 3 sections:

1)Module Preferences
The general information of my gadget is defined in this section. Here is the list of attributes for which I set values.
title
title_url
description
author
author_email
author_location
author_affiliation
author_link
author_photo
author_quote
height
width


I put a default value for the height. Users can update this value using the gadget's settings (build using the "users preferences"). It's also possible to auto-adjust the gadget height.

2)Users Preferences
The settings of my gadget are defined in this section. Here's the list of settings available to the users.
itemCount
fHeight
nHeight


The "itemCount" defines how many items to display. This can be useful if my gadget displays many demos and you don't want the gadget to take too much space on your web page.

The "fHeight" is a flag to set the auto-adjust height to "true" or "false".

The "nHeight" defines the height of the gadget if the auto-adjust height is set to "false".

3)Content
The HTML/JavaScript code is written in this section.

Load the required APIs:

<script src="http://www.google.com/jsapi"></script>
<script>
// Load jQuery
google.load("jquery", "1.2.6", {uncompressed:true});

// Load Google Visualization API
google.load('visualization', '1', {packages: ['table']});
</script>

I use Google Visualization API to display the data in a data grid.

Instantiate an "_IG_Prefs" object:
var prefs = new _IG_Prefs(__MODULE_ID__);

We can access the values of the users preferences using the "getInt" and "getString" functions.
prefs.getInt('fHeight');
prefs.getInt('nHeight');
prefs.getString('itemCount');

Declare the setHeight function

function setHeight() {
_IG_AdjustIFrameHeight(prefs.getInt('fHeight') ? -1 : prefs.getInt('nHeight'));
}
This function will be called each time the data is refreshed.


Declare the draw function

function draw() {
var url = "http://apex.oracle.com/pls/otn/f?p=987654321:204:0:APPLICATION_PROCESS=GET_WEEKLY_RELEASE:::P_REQUEST_ITEM_COUNT:"+prefs.getString('itemCount')+"";

_IG_FetchContent(url, function(data) {
data = eval(data);
if ((nb_demo = data.length) > 0) {
var table_data = new google.visualization.DataTable();
table_data.addColumn('string', 'Title');
table_data.addRows(nb_demo);

for (i = 0; i < nb_demo; i++) {
table_data.setCell(i, 0, data[i].url, data[i].title);
}

table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(table_data, {showRowNumber: true});

// Add our selection handler.
google.visualization.events.addListener(table, 'select', function() {
var row = table.getSelection()[0].row;
window.open(table_data.getValue(row, 0));
});

setHeight();
}
},
{refreshInterval: 0});
}

The "_IG_FetchContent" function will call the GET_WEEKLY_RELEASE Application Process. The callback function handle the data returned by the Application Process. I am using JSON to format the data and I use jQuery to parse it. I set the "refreshInterval option" to 0 because I don't want the results to be cached. This is not recommended!!!... I'll put it to 360(6hrs) when I am done modifying my gadget.


To build my first gadget, I was using an iframe to display the page 204 of my application. Because I didn't like the look and feel, I decided to build it using the Google Visualization API and use an APEX Application Process to feed the data.

I hope I'll see other Google Gadget using APEX Application Processes or MOD_PLSQL.