Liferay 6.0, OpenSocial and Gadgets (Part 2)

This is the second part in a series of working with Gadgets on Liferay 6.0 (Part 2)#


Let's take a look at a gadget. Most of the details about gadgets can be found at various places on the Internet. You can look at the following resources:

+Google's Getting Started with Gadgets
+OpenSocial.org

I'm calling a web service from GeoNames which gets location information based on a Postal Code and Country.
I'll explain the sections of the gadgets.
Just like an HTML page, you can reference local and remote files. You'll see I reference an external javascript file and a local css file.

This is the Module definition. The "Require" tells the gadget container that the module will need the features listed.

<?xml version="1.0" encoding="UTF-8"?>
<Module>
  <ModulePrefs
    title="Postal Code Lookup"
    directory_title="Postal Code Lookup">
    
    <Require feature="setprefs"/>
    <Require feature="opensocial-0.8"/>
    <Require feature="dynamic-height"/>

</ModulePrefs>


The UserPref will allow user configuration by the gadget container. In the previous article, this was shown by using a Default Zip Code for the weather. In this example it will allow the user to set the max number of results to be returned.

<UserPref name="maxRows" display_name="Max Rows To Return" default_value="10"  datatype="string"/>


This starts the content, it's essentially an HTML page, but without the HTML, HEAD and BODY sections. Don't worry, the gadget container will assemble the content for you.
Here you can see the included external javascript file and the css file (in the same directory as the gadget)

<Content type="html"><![CDATA[

<link rel="stylesheet" type="text/css" href="PostalCodeLookup.css">
<script type="text/javascript" src="http://ws.geonames.org/export/geonamesData.js"></script>

<script language="Javascript">


This tells the gadget to get the defined UserPref value for maxRows and make it available in a javascript variable.

var prefs = new _IG_Prefs();
var maxRows = prefs.getString("maxRows");


The function getLocationsForPostalCode makes the call to the web service. The call is not made directly as that may be a cross site scripting issue. Instead it calls the gadget container which acts as a proxy. Here we're using a simple HTTP GET to call the web service.
The gadgets.io.makeRequest function's parameters are the URL to call, the function to call when the call is complete (the callback function) and any parameters. Since the return from the web service is in the JSON format, we set the CONTENT_TYPE to the JSON type.

function getLocationsForPostalCode() {

  var postalCode = document.getElementById('postalCode').value;
  var countryCodeSelect =  document.getElementById('countryCodeSelect');
  var country = countryCodeSelect.options[countryCodeSelect.selectedIndex].value

  var geonamesUrl = "http://ws.geonames.org/postalCodeLookupJSON?";
  geonamesUrl += "postalcode=" + postalCode;
  geonamesUrl += "&country=" + country;
  geonamesUrl += "&maxRows=" + maxRows;

  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;

  gadgets.io.makeRequest(geonamesUrl, loadLocationsForPostalCode, params);

};


loadLocationsForPostalCode is the callback function that is called when the web service request is complete. It will do the parsing of the JSON return data, and build HTML that will be displayed. The web service actually returns more information than we are using, and you can read more about that at the GeoNames web site.
the obj is the data returned from the web service and is passed into the callback function. We're interested in the data in the obj. The obj can be used to get different types of data and handle errors, but we're going to keep it simple for now.

    
function loadLocationsForPostalCode(obj) {

var postalCodeLocations = obj.data; var locationResults = "";

if (postalCodeLocations.postalcodes.length == 0) { locationResults += "Sorry, your request returned no location(s)"; } else { locationResults += "<table>"; locationResults += "<tr class='tableHeading'><td>Place</td><td>State/<br/>Provence</td><td>Country</td><td>Postal Code</td></tr>";

for (i = 0; i < postalCodeLocations.postalcodes.length; i++) { locationResults += "<tr>"; locationResults += "<td>" + postalCodeLocations.postalcodes[i].placeName + "</td>"; if (postalCodeLocations.postalcodes[i].adminCode1 != undefined) { locationResults += "<td>" + postalCodeLocations.postalcodes[i].adminCode1 + "</td>"; } else { locationResults += "<td>&nbsp;</td>" } locationResults += "<td>" + postalCodeLocations.postalcodes[i].countryCode + "</td>"; locationResults += "<td>" + postalCodeLocations.postalcodes[i].postalcode + "</td>";

locationResults += "</tr>"; }

locationResults += "</table>"; locationResults += "<p class='note'>NOTE: Will only return up to " + maxRows + " results.</p>"; }

document.getElementById('locationResultsDiv').innerHTML = locationResults; }}}
The gadgets.window.adjustHeight() is important, as it resizes your gadget based on the new HTML you have inserted. It should be called whenever you do something to to DOM (like the .innerHTML replacement)

  gadgets.window.adjustHeight();
};

</script>


Everything here is the initial HTML the user see in the gadget. The external javascript from GeoNames set the user's country code based on their IP address. So I used it here just to show working external javascript.

<!-- HTML -->

<div id="postalCodeLookupHtml">
    
  <p id="yourCountry">
    It appears you are in the country: 
      <script type="text/javascript">document.write(geonamesUserIpCountryCode)</script>
  </p>

  <form name="postalCodeForm" action="#" method="GET">
    <fieldset>
	
      <label for="county">Country</label>
      <!-- I've included only a few countries to keep this short, you may add more -->
      <select id="countryCodeSelect" name="countryCodeSelect">
        <option value="CA"> Canada</option>
        <option value="DE"> Germany</option>
        <option value="ES"> Spain</option>
        <option value="US"> United States</option>
      </select>
      <br/>
    
      <label for="postalCode">Postal Code</label>
      <input type="test" name="postalCode" id="postalCode"  value="" />

      <label for="getLocations"></label>
      <input type="button" name="getLocations" 
	    value="Get Locations" onclick="getLocationsForPostalCode()"/>
   
    </fieldset>
  </form>
    
  <p>
    <div id="locationResultsDiv"></div>  
  </p>

</div>

  ]]></Content>
</Module>


I've attached the PostalCodeLookup.xml and PostalCodeLookup.css used so you can download and try it yourself. Have fun!


2 Attachments
7210 Views
Average (1 Vote)
The average rating is 4.0 stars out of 5.
Comments