Back to my page

Developer Blog



Converting a MiniAPI module to a UWA widget (part 3)

We’ve seen a lot already: now you should be familiar with the differences between a MiniAPI file and a UWA one, and you should know how to convert a MiniAPI configuration form into a UWA preferences form. Now is the time to dive into a more advanced feature, one that will be of use to those who built truly advanced MiniAPI modules: Ajax requests, as done using the Universal Widget API.

Ajax is obviously one of the foundations of Netvibes, and therefore of its widgets/modules API. But between the release of MiniAPI (2006) and that of UWA (2007), its support and understanding has increased so much that we felt it was time to urge developers to use Ajax as the main (if not sole) way of retrieving and setting external data.

Previously, the MiniAPI let developers use dynamic files (.php, .jsp, .whatever…), and link multiple files between them if this was needed. Thankfully, with the advent of Ajax-support in browsers, they can entirely rely on Ajax, CSS and the DOM to update both their widget’s displayed content and their widget’s external data, and make it all fit in one clean file. Furthermore, now that UWA works on multiple platforms, it becomes a requirement to code a widget using only one file and Ajax - otherwise, who knows how a given platform will handle your lovingly-crafted POST forms, or your relative URLs…

Hence, UWA’s advice: a single, static file (.htm, .html, .xhtml, .xml…), with a companion dynamic file (.php, .jsp, .whatever…). The static file then uses JavaScript/Ajax to retrieve server data through the dynamic file and display it using JavaScript/DOM, or to save data through another dynamic file. Thus separated, it’s easier for the developer to see what does what, and debug accordingly.

Let’s see how we can adapt MiniAPI sample Ajax code into a working UWA one…

An Ajax request, as seen from the MiniAPI angle

Here’s how it is explained in step 8 of the now-deprecated MiniAPI tutorial:

  • the <body> section of the file is basically devoid of content, save for a <p>Loading...</p> line that will eventually be dealt with using JavaScript. That line is only here to help the user be patient while your Ajax request loads the content.
  • the <script> section is where the real meat is - the widget’s behavior itself. Through JavaScript, you would launch an Ajax request using MiniAPI’s methods (at the time a direct copy of prototype.js’s), and would then update the <body> section using wildly-supported DOM methods like .innerHTML.
<script type="text/javascript">
NV_ONLOAD = function() {
  var url = 'http://www.fkdl.com/rss.php';
  function AjaxShow(xhr) {
    var dom = xhr.responseXML.documentElement;
    var mainTitle =
      dom.getElementsByTagName("title")[0].firstChild.nodeValue;
    var firstTitle =
      dom.getElementsByTagName("title")[2].firstChild.nodeValue;
    var firstContent =
      dom.getElementsByTagName("description")[1]
        .firstChild.nodeValue;

    NV_TITLE.innerHTML = mainTitle + ' : ' + firstTitle + '';
    NV_CONTENT.innerHTML = '<div style="text-align:center">'
      + firstContent + '</div>';
    }
  var request = new Ajax.Request(NV_XML_REQUEST_URL + '?url='
    + escape(url), { method: 'get', onSuccess: AjaxShow });
  }
</script>

The sample MiniAPI module’s code differs slightly from what is documented, but not enough to contradict the tutorial. - it mostly adds more tests. See for yourself.

The same Ajax request, in a UWA perspective

UWA uses the same code-repartition philosophy as MiniAPI: empty <body> section, behavior in <script> section. From there on, the MiniAPI developer should know the UWA equivalents to MiniAPI’s methods and variables.

The code below is an UWA adaptation of the above MiniAPI code:

<script type="text/javascript">
var MyAjaxWidget = {};

MyAjaxWidget.onLoad = function() {
  var theurl = 'http://www.fkdl.com/rss.php';
  UWA.Data.getXml(theurl, MyAjaxWidget.AjaxShow);
  }

MyAjaxWidget.AjaxShow(xhr) {
  var dom = xhr.responseXML.documentElement;
  var mainTitle =
    dom.getElementsByTagName("title")[0].firstChild.nodeValue;
  var firstTitle =
    dom.getElementsByTagName("title")[2].firstChild.nodeValue;
  var firstContent =
    dom.getElementsByTagName("description")[1]
      .firstChild.nodeValue;

  widget.setTitle(mainTitle + ' : ' + firstTitle + '');
  widget.setBody('<div style="text-align:center">'
    + firstContent + '</div>');
  }

widget.onLoad = MyAjaxWidget.onLoad;
</script>

What we did was:

  • created the MyAjaxWidget namespace, in order to store values and methods under a coherent umbrella. Note that MyAjaxWidget is just an example, any valid name is okay…
  • turned NV_ONLOAD into widget.onLoad and make it call the MyAjaxWidget.onLoad method instead of declaring a function right away
  • took the AjaxShow method out of widget.onLoad, and put it into the MyAjaxWidget namespace, which gives us the MyAjaxWidget.AjaxShow method
  • discarded the whole old-style Ajax request code, and used one of UWA’s Ajax methods. See after this list to understand which one we used.
  • turned two MiniAPI values into the equivalent UWA methods: NV_TITLE.innerHTML into widget.setTitle() and NV_CONTENT.innerHTML into widget.setBody().

All in all, UWA is not only a portable version of MiniAPI, but also a much cleaner API altogether.

Which of the five UWA Ajax methods to use?

The choice of Ajax method is tricky in this case: the MiniAPI code used a request that retrieves XML data, but the target URL is a RSS 1.0 feed. Logically a feed should be loaded using the UWA.Data.getFeed method, in order to profit from JSON integration ; but since the rest of the JavaScript code (the beginning of the AjaxShow method) uses XML-related methods to extract content out of the data, and we don’t want to change too much code for now, we decided to use the classic UWA.Data.getXml method.

Should you rather want to use the more adequate UWA.Data.getFeed method, here’s how the UWA version of onLoad and AjaxShow would be like:

MyAjaxWidget.onLoad = function() {
  var theurl = 'http://www.fkdl.com/rss.php';
  UWA.Data.getFeed(theurl, MyAjaxWidget.AjaxShow);
  }

MyAjaxWidget.AjaxShow(json) {
  var mainTitle = json.title;
  var firstTitle = json.items[0].title;
  var firstContent = json.items[0].content;

  widget.setTitle(mainTitle + ' : ' + firstTitle + '');
  widget.setBody('<div style="text-align:center">'
    + firstContent + '</div>');
  }

The data is made available using our JSON Feed format, which is always the same for any type of feed (RSS, Atom). You can see how using UWA.Data.getFeed (or JSON data in general, using UWA.Data.getJson) can make data extraction that much easier than using XML-related methods…

Focusing on the request itself

The ease of use of UWA’s Ajax method jumps to the eyes! Here is comparison of the equivalent code in the two APIs:

MiniAPI (deprecated):

var request = new Ajax.Request(NV_XML_REQUEST_URL + '?url='
  + escape(url), { method: 'get', onSuccess: AjaxShow });

UWA:

UWA.Data.getXml(theurl, MyAjaxWidget.AjaxShow);

What can be said of their differences:

  • the UWA version is obviously much shorter and thus simpler to use
  • in UWA, no need to set it to a variable in order to make it work nicely
  • the hard to read NV_XML_REQUEST_URL + '?url=' + escape(url) is a thing of the past, UWA simply needs you to give the target URL
  • UWA.Data.getXml is a shorthand method to the more advanced UWA.Data.request, and therefore method:'get' and the onSuccess declaration are implied, making it even more readable

What’s not to like? :)

As long as all you need is retrieve data (and therefore, use only HTTP GET methods), UWA’s 4 quick’n'easy Ajax methods will handle it all for you nicely, you just have to give them the target URL and the callback method (that is, the method that will be triggered in case of success of the request). These method are all placed in the UWA.Data object, and are handily named:

  • UWA.Data.getText(url, callback): gets the content of an external XML data source, in plain text format
  • UWA.Data.getXml(url, callback): gets the content of an external XML data source. It can be used to retrieve the content of a feed in XML format
  • UWA.Data.getJsonl(url, callback): gets the content of an external JSON data source
  • UWA.Data.getFeed(url, callback): gets the content of a feed, and makes it available using our JSON Feed format

What about HTTP POST requests?

That is all fine and dandy, you might say, but you might also wonder about when you need to send data to the server. Surely you mustn’t use HTTP GET requests for these occasions, so how to deal HTTP POST? Or, more to the point, how to handle a form in UWA, now that MiniAPI’s classic forms are no longer recommended?

This, my friends, will be the subject of the next part in this series… Until then, you can still read up on UWA.Data.request and have a try at it…

Tags: , , , , , , , ,

Leave a Reply


Business

Click here if you want to know more about how netvibes can help you widgetize your brand and connect to your audience.

Developers

Click here to learn about netvibes open widget platform and how you can create cool widgets for your service or your application that run everywhere.

Community

Click here to know how to join the netvibes community, get involved and help us translate and create a global directory of widgets for netvibes

Media

Click here to access informations about the company, our latest press release, our logos and media kit