Hide

Gadget-to-Gadget Communication (Deprecated)

This document explains how to use the publish-subscribe ("pubsub") framework to pass messages from one gadget to another. This feature is deprecated and is unsupported.

Contents

  1. Overview
  2. How it Works
    1. Basic Example
  3. Bundling Updates
    1. Publisher Requirements
    2. Subscriber Requirements
    3. Example: Bundled Updates

Overview

The publish-subscribe framework allows publisher gadgets on iGoogle to communicate changes to subscriber gadgets that have declared interest in those changes.

Note: You can use the publish-subscribe framework for type="html" gadgets. This feature does not support type="url" gadgets. To use pubsub, your gadgets must be running on iGoogle. The pubsub feature won't work for syndicated gadgets.

Here are the major concepts involved in gadget-to-gadget communication:

  • Publisher. Publishers are gadgets that inform one or more subscribers that a particular userpref value has changed. A publisher gadget can have many subscriber gadgets. It does not need to know the number or identities of its subscriber gadgets.
  • Subscriber. Subscribers are gadgets that declare their interest in knowing when the value of a particular userpref has changed.
  • Message. A message is a string containing new userpref values that the publisher sends to subscribers.
  • Channel. A channel is a known, named place for publishing messages of a certain type.The pubsub framework enforces a set of predefined data policies to ensure that all messages published on a particular channel share the same type and have the same data structure. For example, the channel finance_symbol could be used for publishing Google Finance symbols, while the channels lat and long could be used for publishing geographic positioning information.

This table lists the channel names that are currently supported. As new channel names are added, they will be announced on the Developer Forum. If you want to propose new channel names, you can do so on the Developer Forum.

Channel Name Description
test000 - test100 Test channels to be used for development. You can use the test channel names test000 through test100.
rawquery Either the literal text of the user's query, or keywords used to match a context.
finance_portfolio Stock watchlist/portfolio.
finance_symbol Stock symbol.
finance_symbol_quote Stock market data for a symbol.
lat Latitude (in microdegrees) for geographical targeting.
long Longitude (in microdegrees) for geographical targeting.

How It Works

You implement gadget-to-gadget communication through "userprefs binding". With userprefs binding, the userprefs in the subscriber gadget map to the userprefs in the publisher gadget. You define this mapping in the XML portion of your gadget specs. For example:

// Publisher gadget userpref definition
<UserPref name="test000" 
  display_name="Message" 
  default_value="Bonjour Monde" 

  publish="true" />


// Subscriber gadget userpref definition
<UserPref name="test000" display_name="Message" default_value="Hello World" listen="true" on_change="updateMessage" />

The above snippet illustrates how to define userprefs for the pubsub feature:

  • The publisher gadget and the subscriber gadget must have at least one userpref with the same name. In this example, it is test000. This name is also used as the name of the channel that passes messages from the publisher to the subscriber.
  • The publisher gadget includes publish="true" in the userpref definition. This states that the userpref is published on a channel of the same name.
  • The subscriber gadget includes listen="true" in the userpref definition. This states that the subscriber gadget wishes to be notified when the userpref value changes in the publisher gadget.
  • The subscriber gadget includes on_change="updateMessage" in the userpref definition. This optional attribute specifies the name of a callback function that is invoked when the subscriber gadget receives notification that the userpref value has changed in the publisher gadget. Note that the callback function cannot take parameters.

The following example shows the publisher and subscriber gadgets that include these userpref definitions. This is the sequence of events in the running gadgets:

Step 1. The publisher and subscriber gadgets run in the container page for the first time.

Initially, each gadget displays its own default value for the userpref test000. For the publisher gadget, the value is "Bonjour Monde". For the subscriber gadget, the value is "Hello World".

Publisher and Subscriber Gadgets: Before

Step 2. The user enters a new value in the publisher gadget's Message text field, and clicks Update Message.

This invokes the publisher function updateValue(), which includes a call to prefs.set(). The prefs.set() call has the effect of publishing the new value to the channel.

As described in Saving State, the _IG_Prefs function set() causes userpref values to be saved persistently. If you navigate away from your browser window and return, the gadgets still have the last value you set. Another thing that might not be obvious is that if you change the value of the publisher's test000 userpref locally, in the userprefs edit box, the change does not get published to the channel, and the subscriber's test000 userpref is not updated. In other words, you must use the _IG_Prefs set() function to explicitly publish the change to the channel.

Step 3. The publisher tells subscribers that the value has changed.

Step 4. The subscriber responds by invoking its callback function updateMessage(), which causes the subscriber gadget to refresh its display to reflect test000's new value.

The callback function updateMessage()is specified by the on_change attribute in the subscriber's test000 userpref definition. Using the on_change attribute to specify a callback function is optional. However, if you want the subscriber to immediately respond (typically by refreshing its display) when a value changes, using on_change to specify a callback function is the way to do it.

After the user enters a new value in the publisher's Message field and clicks Update Message, the publisher and subscriber gadgets display the same message:

Publisher and Subscriber Gadgets: After

Basic Example

This section shows the gadget specs for the publisher and subscriber gadgets described above. You may notice that the gadget specs don't include the statements <Require feature="pubsub" /> or <Require feature="setprefs" /> to load the pubsub and setprefs libraries, even though the gadgets use them. This is because for the pubsub feature, iGoogle automatically includes these libraries in the gadget context.

Here is the publisher gadget spec:

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="Publisher Gadget 01" height="150" /> 
  <UserPref name="test000" 
    display_name="Message" 
    default_value="Bonjour Monde" 
    publish="true" />  
  <Content type="html">

  <![CDATA[ 
    <br/>
    My Message
    <br/><br/>
    <table>
      <tr>
        <td>

         Message:
        </td>
        <td>
          <input type="text" id="msg" name="msg" value="">

        </td>
        <td>
          <input type="button" name="butUpdateMsg" name="butUpdateMsg" value="Update Message" onclick="updateValue()">

        </td>
      </tr>
    </table>

    <script type="text/javascript">
    // This publisher gadget updates the value for the test000 userpref when users click the "Update Message"

    // button.
    function updateValue() {   
      var newMsg = _gel("msg").value;
      prefs.set("test000", newMsg);  
    }

    // Gets and displays the publisher gadget's local test000 userpref. New userpref value is not published
    // unless user invokes updateMsg() by clicking button.
    var prefs = new _IG_Prefs(__MODULE_ID__);
    var str = prefs.getString("test000");
    _gel("msg").value = str;
    </script>

  ]]> 
  </Content> 
</Module>

Here is the subscriber gadget spec:

<?xml version="1.0" encoding="UTF-8" ?> 

<Module>
  <ModulePrefs title="Subscriber Gadget 01" height="150" scrolling="true"/> 
  <UserPref name="test000" 
    display_name="Message" 
    default_value="Hello World" 
    listen="true" 
    on_change="updateMessage"  /> 
  <Content type="html">

  <![CDATA[ 
  <div id="mydiv"></div>   
  
  <script type="text/javascript">
  
  // When the message value is updated in the publishing gadget, 
  // the test000 userpref is updated. Refresh the message in the
  // div to display the new value.
  function updateMessage() {  
    div.innerHTML = "<h1>" + prefs.getString("test000") + "</h1>";
  }
  
  // Gets and displays the subscriber gadget's local test000 userpref value.
  var prefs = new _IG_Prefs(__MODULE_ID__);  
  var div = _gel("mydiv");
  div.innerHTML = "<h1>" + prefs.getString("test000") + "</h1>";

  </script>

  ]]> 
  </Content>
</Module>

Bundling Updates

"Bundling" allows you to group a set of changes into a single transaction. It allows the publisher gadget to pass updated values as a unit to subscribers.

The following sections describe the publisher and subscriber requirements for bundling updates.

Publisher Requirements

In the most common case, you publish bundled userprefs by specifying the group attribute for all userprefs in the same bundle, and giving the attribute the same value for all userprefs. You then call the _IG_Prefs set() function.

The publisher gadget call to the set() function typically includes all userprefs of the bundle, but it does not have to. If a subset of userprefs in a group are specified in the call to the set() function, all userprefs with the same group get published as a bundle. Any userprefs that are not specified in the set() call are published with old values, whereas the userprefs specified in the set() call are published with new values.

For example:

<UserPref name="lat" display_name="Latitude:"
     publish="true" 
     group="geoinfo" />
<UserPref name="long" display_name="Longitude:" publish="true" group="geoinfo" /> ... var prefs = new _IG_Prefs(__MODULE_ID__); prefs.set("lat", "45.8");

In this example, both the lat and long userprefs get published as a bundle, with lat having the new value ("45.8.") and long having the old value.

There is a second way of publishing bundled userprefs. Userpref updates are published as a bundle if the userprefs are marked with publish="true" and they get updated in a single call to _IG_Prefs set() function. For example:

<UserPref name="lat" display_name="Latitude:"

     publish="true" />
<UserPref name="long" display_name="Longitude:"
     publish="true" />

     ...
     var prefs = new _IG_Prefs(__MODULE_ID__);
     prefs.set("lat", 45.8, "long", 16);

Mixing the two techniques of publishing bundled userprefs is not recommended. However, for the purpose of explanation, suppose you have an _IG_Prefs set() call that includes userprefs with group attributes and userprefs without group attributes. In that "mixed" scenario, the set of userprefs that would get published as a bundle would include:

  • Any userprefs without group attributes that are included in the set() call.
  • Any userprefs that belong to a group in which at least one group member is included in the set() call.

For example:

<UserPref name="lat" display_name="Latitude:"

     publish="true" 
     group="geoinfo" />
<UserPref name="long" display_name="Longitude:"
     publish="true" 
     group="geoinfo" />

<UserPref name="test003" display_name="Locaccuracy:"
     publish="true" />
     ...
     var prefs = new _IG_Prefs(__MODULE_ID__);
     prefs.set("lat", "45.8", "test003", "0.89");

In this example, all the userprefs get published as a bundle:

  • test003 is published even though it does not have a group attribute, because it is specified in the set() call.
  • lat is published with a new value since it is specified in the set() call.
  • long is published (with the old value) since it's in the same group as lat.

Subscriber Requirements

In the subscriber gadget, all userprefs that have a group attributed specified must also have the on_change attribute specified. Also, all userprefs that have the same group attribute specified must have the same on_change attribute value (that is, the same callback function must be invoked for each userpref). For example:

<UserPref name="lat" display_name="Latitude:"
     listen="true" 
     on_change="locationChange"
     group="geoinfo" />

<UserPref name="long" display_name="Longitude:"
     listen="true" 
     on_change="locationChange"
     group="geoinfo" />

The locationChange() function specified by the on_change attribute gets invoked only when one or more of the bundled userprefs get updated.

Example: Bundled Updates

In this example, the publisher gadget has text fields where users can specify a latitude and longitude. When users specify a new value and click Update, the subscriber gadget updates its display to show a map that matches the specified longitude and latitude.

Publisher gadget:

<?xml version="1.0" encoding="UTF-8" ?> 

<Module>
  <ModulePrefs title="Map Controller" height="150" /> 
  <UserPref name="lat" 
    default_value="37441900" 
    publish="true" 
    group="geoinfo" /> 
  <UserPref name="long" 
    default_value="-122141900" 
    publish="true"

    group="geoinfo" /> 
 <Content type="html">
 <![CDATA[     
    <br/><br/>
    <table>

      <tr>
        <td>
          Latitude:
        </td>
        <td>
          <input type="text" id="txtLat" name="txtLat" value="">

        </td>
      </tr>
      <tr>
        <td>
          Longitude:
        </td>
        <td>

          <input type="text" id="txtLong" name="txtLong" value="">
        </td>
        <td>

          <input type="button" name="butUpdateLoc" name="butUpdateLoc" value="Update" onclick="updateLoc()">
        </td>

      </tr>
    </table>

    <script type="text/javascript">
      function updateLoc() {
        var newLat = parseFloat(_gel("txtLat").value) * 1000000;
        var newLong = parseFloat(_gel("txtLong").value) * 1000000;
        prefs.set("lat", newLat.toString(), "long", newLong.toString());

      }

      var prefs = new _IG_Prefs(__MODULE_ID__);
      var lat = prefs.getInt("lat") / 1000000;
      var long = prefs.getInt("long") / 1000000;
      _gel("txtLat").value = lat;
      _gel("txtLong").value = long;
  
    </script>
  ]]> 
  </Content>

</Module>

Subscriber gadget:

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="Listening Map" height="500" /> 
  <UserPref 
    name="lat" 
    default_value="37441900" 
    listen="true" 
    on_change="updateLocation" 
    group="geoinfo" /> 
  <UserPref name="long" 
    default_value="-122141900" 
    listen="true" 
    on_change="updateLocation" 
    group="geoinfo" /> 
 <Content type="html">

 <![CDATA[ 
    <script src="http://maps.google.com/maps?file=api&amp;v=2.x" type="text/javascript"></script>
    <div id="map" style="width:100%;height:100%"></div>

    <script type="text/javascript">
      function updateLocation() {
        var newLat = prefs.getInt("lat") / 1000000;
        var newLong = prefs.getInt("long") / 1000000;
        map.panTo(new GLatLng(newLat, newLong), 13);
      }

      var prefs = new _IG_Prefs(__MODULE_ID__);
      var lat = prefs.getInt("lat") / 1000000;
      var long = prefs.getInt("long") / 1000000;
      var map = new GMap2(_gel("map"));
      map.setCenter(new GLatLng(lat, long), 13);
    </script>

  ]]> 
  </Content>
</Module>

Back to top