27.7.12

UWA IFrame method [doc] - Netvibes

UWA IFrame method [doc]

Netvibes Developers Network » Universal Widget API » UWA HOWTOs » UWA IFrame method

UWA IFrame method

You can easily display UWA widgets within your own environment, thanks to our IFrame method. This document will show you how to build the correct URL to display a given widget within an IFrame on your platform. Relying on an IFrame has the advantage of both being simple and secure. There can be any number of IFrames on one page, as long as each IFrame has a unique ID (related to the widget's chosen ID).
What this method doesn't provide:
  • drag&dropping for your system

Building the IFrame's target URL

  • The base IFrame URL is:
http://nvmodules.netvibes.com/widget/frame/
Original widget URL:
http://www.netvibes.com/modules/alexa/alexa.html
URL-encoded widget URL:
http%3A%2F%2Fwww.netvibes.com%2Fmodules%2Falexa%2Falexa.html
Resulting URL:
http://nvmodules.netvibes.com/widget/frame/?uwaUrl=http%3A%2F%2Fwww.netvibes.com%2Fmodules%2Falexa%2Falexa.html
  • You must indicate a widget identifier, so that the communication script can work properly. It MUST be unique to the page, and generated by your system (or manually). In this example, the chosen id is “123456':
http://nvmodules.netvibes.com/widget/frame/?uwaUrl=http%3A%2F%2Fwww.netvibes.com%2Fmodules%2Falexa%2Falexa.html&id=123456
  • In order for the widget's height to be correctly resized when its content gets displayed (and other widget communication matters), you must add a reference to a local proxy file. This file must be hosted on the same domain as the page where the IFrame is set.
See further below to get more detail about that proxy file, and get a sample code that you should build upon.
The attribute is called ifproxyUrl (which stands for “IFrame proxy URL”).
For instance, if your widget is displayed here:
http://www.example.com/myWidgets/index.html
…then, the proxy file could reside here:
http://www.example.com/myWidgets/proxy.html
Once that URL is URL-encoded, the string for this example would be like so:
&ifproxyUrl=http%3A%2F%2Fwww.example.com%2FmyWidgets%2Fproxy.html
…which would result in this IFrame URL:
http://nvmodules.netvibes.com/widget/frame/?uwaUrl=http%3A%2F%2Fwww.netvibes.com%2Fmodules%2Falexa%2Falexa.html&id=123456&ifproxyUrl=http%3A%2F%2Fwww.example.com%2FmyWidgets%2Fproxy.html
  • Finally, just add the URL to an IFrame on your page. The IFrame should have the identifier as its id attribute, in the form of “frame_{ID}”, with {ID} being your widget's unique identifier:
<iframe id="frame_123456" scrolling="no" frameborder="0"
  height="200" width="400"
  src="http://nvmodules.netvibes.com/widget/frame/
  ?uwaUrl=http%3A%2F%2Fwww.netvibes.com%2Fmodules%2Falexa%2Falexa.html
  &id=123456
  &ifproxyUrl=http%3A%2F%2Fwww.example.com%2FmyWidgets%2Fproxy.html
  &alexaSite0=netvibes.com&alexaSite1=nytimes.com">
</iframe>
…and you are done with the IFrame itself!

Retrieving the widget's default title, favicon, meta-values and preferences

We have built a special script to return a simple JSON file containing the widget's informations:
http://nvmodules.netvibes.com/widget/json
Simply specify the needed widget URL with the uwaUrl parameter:
http://nvmodules.netvibes.com/widget/json?uwaUrl=http://www.netvibes.com/modules/digg/digg.html
This should sends back a nice JSON feed, that is yours to parse on your end.

Handling the widget's preferences (the Edit section)

Many UWA widget are not customizable, and just display some data or a Flash application, for instance. But the most useful widget are the ones that can be edit to fit the user's needs. This is done using preferences, which can be set through an 'Edit' section.
By default, the target URL that is built at the start of this tutorial only displays the widget's body - no Edit section is to be found, and thus preferences cannot be changed.
This is done so that you can build your own Edit section, one that would match the look-and-feel of the containing platform.

Displaying the default Edit section within the IFrame

For some reason, you might not want or need to go through the trouble of implement the proprer code to generate a form for the widget's preferences, along with handling the various needed events.
In this case, there is one very quick and painless to let UWA do all the work for you: simply add the &header=1 attribute to the IFrame's target URL. This will request the UWA server to send a fully-formed widget, with botht the body and a working Edit section.
While this might not match your platform's UI, it's a quick and painless way to get widgets fully working in your environment.

Building your own Edit section

For those times when the default Edit section will just not do, you can get all the information you need to build a complete custom form for any UWA widget, using a few tools of ours…

Gathering the widget's preferences names and default values

As indicated in the previous section, preferences are all available, along with metas, favicon and such, through the JSON tool:
http://nvmodules.netvibes.com/widget/json
In the case of the Digg widget, that URL would be:
http://nvmodules.netvibes.com/widget/json?uwaUrl=http://www.netvibes.com/api/uwa/examples/digg.html
…which returns a detailled JSON file. Sample JSON.
This gives you the names of the preferences for the widget, their type, value, and other useful data. Based on these, you are now able to generate a proper form, using which the user will be able to change the any widget's preferences.

Displaying the Edit section

The edit section depends on the displaying platform. Therefore, it is up to you to display the gathered preferences within a form that fits the context's UI, and to store these preferences.

Setting/updating the widget's preferences

In our example at the start of this page, the Alexa widget can take up to 5 sites, with variables names being “alexaSite0” to “alexaSite4” - you would have gathered these names thought the JSON tool above. We'll build an IFrame URL in order to compare two sites: alexaSite0 → netvibes.com & alexaSite1 → nytimes.com
Resulting IFrame URL:
http://nvmodules.netvibes.com/widget/frame/?uwaUrl=http%3A%2F%2Fwww.netvibes.com%2Fmodules%2Falexa%2Falexa.html&id=123456&ifproxyUrl=http%3A%2F%2Fwww.example.com%2FmyWidgets%2Fproxy.html&alexaSite0=netvibes.com&alexaSite1=nytimes.com
In order to properly set-up the widget's preferences, you have to know the preference variables used by the widget, and therefore use the JSON tool above. In its extract, you will find the variable names from the <widget:preference> element.

Handling the widget communications (resizing, preferences, title...)

The IFrame code can be placed anywhere within the body tag of a standard XHTML page. In order for the widget to properly communicate with your system/webpage, you not only need to place a proxy file on your host, as already advised, but you also need to place JavaScript code within the page itself. This code will let you completely handle the various messages sent by and to the widget, one of the most frequent being the resizing message.
Here is the basic code on which to build upon. As-is, it should handle resizing automatically.
<script type="text/javascript"
   src="http://www.netvibes.com/js/UWA/Utils/IFrameMessaging.js">
</script>
 
<script type="text/javascript">
msgHandler = function(message) {
  var id = message.id;
  switch (message.action) {
    case 'resizeHeight':
      var frame = document.getElementById('frame_' + id);
      if (frame) {
        frame.setAttribute('height', message.value);
      }
      break;
   default:
      console.log(message.action + ': not implemented - ' + message.name + ':' + message.value);
      break;
  }
};
 
UWA.MessageHandler = new UWA.iFrameMessaging;
UWA.MessageHandler.init({
    'eventHandler': msgHandler,
    'trustedOrigin' : 'nvmodules.netvibes.com'
});
</script>
This code creates a message-handler for all messages coming from the running widgets. The UWA.MessageHandler() method is called by the widget with a JSON object as a message. This message contains the following properties:
  • id: the widget's ID, as declared in the IFrame URL.
  • action: the name of the action. There are a handful, listed below.
  • value: the action's value.
  • name: if needed, the name of the target to which the value applies. If not used, its value is 'false'.
For instance, in the above sample code, we have built a handler for the resizeHeight action, which is triggered when the widget is first displayed, or when its content is updated. It asks for the container to resize itself according to the displayed content's height, which is given in the action's value. Once the widget's frame has been found (it's ID should be of the form frame_{ID}, as indicated before), the widget's height is reset to the required value.
In this sample code, only the resizeHeight action is fully described, in order for you to get the idea of the way it works. Other actions are redirected to the default behavior, which as you can see is simply to display a message in the console for this minimal example. In our own version of this code, you can make it do whatever is needed by your website to react consistently.
The full set of available actions is as follows:
action description
addStar can be used to indicate that the URL has been correctly sent to Netvibes
resizeHeight can be used to resize the widget's height according to its content's height
setIcon can be used update the widget's favicon
setSearchResultCount can be used indicate the number of results for a search with the widget's content. usually placed beside the title
setTitle can be used to change the widget's title, as displayed by your website
setUnreadCount can be used indicate the number of unread messages. usually place beside the title
setValue can be used to update the widget's preference value
The switch section of the above code can therefore be customized according to your needs and possibilities. For instance, here we set an aditionnal method for the setTitle action:
(...)
switch (message.action) {
   case 'resizeHeight':
      var frame = document.getElementById('frame_' + id);
      if (frame) {
        frame.setAttribute('height', message.value);
      }
      break;
   case 'setTitle':
      var chrome = document.getElementById('widget-' + id);
      var title = chrome.getElementsByClassName("title")[0];
      if (title) {
         title.innerHTML = message.value;
      }
      break; 
   default:
      console.log(message.action + ': not implemented - ' + message.name + ':' + message.value);
      break;
  }
(...)

IFrame proxy

The proxy.html file should be present anywhere in your domain, and passed as a parameter in your IFrame. This file is a very basic HTML file, the purpose of which is to trigger specific JavaScript code. That code can be called from Netvibes' domain, or from within the proxy.html file itself.
Note that the JavaScript code is released by Netvibes under LGPL license.
The following example links Netvibes' own ifproxy.js:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="http://www.netvibes.com/js/UWA/Utils/ifproxy.js"></script>
<title>UWA Container Proxy</title>
</head>
<body>
</body>
</html>
If needed, you can host yourself. Just remember that the Netvibes-hosted version is always the latest. Here's what the current JS code would look like in the proxy file:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
var map = {};
var hash = location.hash.substr(1);
var pairs = hash.split('&');
for (var i = 0; i < pairs.length; i++) {
    var pair = pairs[i].split('=');
    if (pair.length == 2 && pair[0].length > 0) {
        map[pair[0]] = unescape(pair[1]);
    }
}
 
if (typeof map.target !== 'undefined' && typeof map.message !== 'undefined' &&
    typeof map.origin !== 'undefined' && typeof map.uri !== 'undefined') {
 
    if (map.target != 'parent') {
        throw new Error('The communication system works with the parent window.');
    }
 
    if (parent.parent.UWA.MessageHandler) {
        var message = null;
        if (typeof map.message === 'string' && map.message.length) {
            parent.parent.UWA.MessageHandler.dispatch(map.message, map.origin, 'ifproxy');
        }
    }
}
</script>
<title>UWA Container Proxy</title>
</head>
<body>
</body>
</html>
The location of the JS code is not important, as long as it is triggered from the proxy.html file. What is important is that the proxy.html file MUST be stored on the same domain as the widget.

Quick FAQ

Q: Where should I put the “proxy.html” file you provide us with?
A: It should be uploaded on your own domain.
Q: You mention a unique ID for each widget. Who provides it? The user? Your system? Our system?
A: The widget ID has to be unique to the current page, and handled/generated by your system. All you will need from us is the widget's URL, provided by Ecosystem (or from a list of selected widgets).
Q: How can I implement drag&dropping on UWA widgets?
A: It all depends on your own system. Widgets are hosted in an IFrame, so you will need to build a drag&drop functionality for your system if you don't have one already, and make it work with iframed UWA widgets.