Login Register

dojo.publish & subscribe between windows? SOLVED

I am working on a map viewer that can be "undocked" from the browser window. I would like published events in the child window to be available to the opener. Is there any dojo mechanism for doing this or will I need to forward the messages by calling window.opener.dojo.publish?

simple solution ... I just wrapped dojo.publish

webmap.publish = function(event, args){
	dojo.publish(event, args);
	//if I am the child window publish to my opener too
	if (window.name == webmap.config.undocked) window.opener.dojo.publish(event, args);
	//if I am the parent window publish to my child too
	if (webmap.undockedWin) webmap.undockedWin.dojo.publish(event, args);
}

My solution is failing in IE!!!!! Help!

I am trying to force the opener window to publish the same events as its child window. The example code works beautifully in FireFox but results in an error in IE 6 and 7. Error 'JScript object expected' occurs in dojo._base.connect on line 257:

  1. dojo.publish = function(/*String*/ topic, /*Array*/ args){
  2.         //      summary:
  3.         //            Invoke all listener method subscribed to topic.
  4.         //      topic:
  5.         //            The name of the topic to publish.
  6.         //      args:
  7.         //            An array of arguments. The arguments will be applied
  8.         //            to each topic subscriber (as first class parameters, via apply).
  9.         //      example:
  10.         //      |     dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
  11.         //      |     dojo.publish("alerts", [ "read this", "hello world" ]);     
  12.  
  13.         // Note that args is an array, which is more efficient vs variable length
  14.         // argument list.  Ideally, var args would be implemented via Array
  15.         // throughout the APIs.
  16.         var f = dojo._topics[topic];
  17.         if(f){
  18.                 f.apply(this, args||[]);
  19.         }
  20. }

Below is a working example:

Html page:

<html>
        <head>
                <title>wtf?</title>     
            <script type="text/javascript" src="dojo/dojo/dojo.js"></script>
                <script type="text/javascript">
                        djConfig = {isDebug: true, parseOnLoad: true};
                        dojo.registerModulePath("webmap", "../../webmap");
                        dojo.require("webmap.foo");
                        dojo.subscribe("unDocking", function(){
                                alert(window.name+":unDocking");
                        });
                </script>
        </head>
        <body>
                <button onclick="webmap.undockWin()">call webmap.undockWin</button>
        </body>
<\/html>

foo module:

dojo.provide("webmap.foo");

window.undockedWin = null;
dojo.addOnLoad(function(){
        if (window.isUndocked) {
                webmap.publish("unDocking", []);
        }
});
webmap.publish = function(event, args){
        dojo.publish(event, args);
        if (window.isUndocked) {
                window.opener.dojo.publish(event, args);
        }
};
webmap.undockWin = function(){
        undockedWin = window.open(document.location, "webmapUndocked", "");
        undockedWin.isUndocked = true;
}

giving my post a bump...

Anyone interested in helping out? I really need to get this one figured out for a 1/2/08 deadline and I am supposed to be on vacation next week :(

Can't pass by ref between windows in IE.

You'll need to serialize and parse info between windows to make that work right. Probably the easiest thing to do would be to serialize to JSON in the publish window and pass that as a string to the subscribe one.

In the end this is my solution...

a little slow in IE but at least it works.

webmap.publish = function(evt, args){
  try{
    dojo.publish(evt, args);
    if (window.isUndocked) {
      webmap.publishSerialized(window.opener, evt, args);
      webmap.publishSerialized(window.opener.parent, evt, args);
    }
    if (undockedWin)
      webmap.publishSerialized(undockedWin, evt, args);
      if (!window.isUndocked)
        webmap.publishSerialized(window.parent, evt, args);
  }catch(ignore){
    //some window doesn't exist or doesn't have dojo
  }
}
webmap.publishSerialized = function(win, evt, args){
  dojo.isIE ? win.eval('dojo.publish("' + evt +
    '", dojo.fromJson(\'' + dojo.toJson(args) + '\'))') :
    win.dojo.publish(evt, args);
}

Serialize what? The args object for the publish function?

Serialize what? The args object for the publish function?