Dojo and iFrames Tip

It’s funny you mention building rich UI’s in an environment that includes iframes and even the most harden of front end developer will shudder and then due to a defensive reflex go into a tirade about why iframes are evil (the word evil is always used for some reason) and how you should be ashamed for doing the work in the first place.

Well the unfortunate truth is that there are a huge number of iframes living happily across the internet and many corporate intranets. Any “portal” based system designed before 2005 probably has a huge smattering of iframes. So as much as we would all love to not have to deal with them, they’re out there and you’ll probably have to face your fear at some point.

Dojo is my library of choice when it comes to almost any JavaScript needs, so I’m always interested to see how it plays with iframes when I come across situations.

Today I had an interesting situation.

If you have a page with an iframe and that iframe is pulling in it’s own dojo.js and you’re using the Dojo pub/sub system, there is no way with a single publish to publish a topic across the entire UI.

If you’re publishing from the parent, the iframe won’t get it, if you publish from the iframe the parent won’t get it.

I pinged Alex Russell, who was as ever amazingly helpful (god knows how he has the time to answer unsolicited IM’s from people like me). He rattled off a series of ideas and options to get round the issue. The one that struck me as the “correct” solution was to not include dojo.js in the iframe but instead inherit the dojo object from the parent window.

  1.  
  2.  
  3. dojo = window.parent.dojo;
  4.  
  5.  

This, on face value is awesome. Loading Dojo.js and thus having a dojo object in every iframe just seems like madness and an object management nightmare. Having everyone sharing a singular dojo object that lives in the top document just seems so much better and most of the time it is.

However…

There’s always a however isn’t there. There are issues with sharing a top level none iframe document specific dojo object. That issue is that the top level dojo object has no Out of the Box knowledge of the iframes or their content. It means you run the risk of getting into hot water with some very simple core DOM traversing scripts.

  1.  
  2.  
  3. dojo.byId(‘foo’);
  4.  
  5. dijit.byId(‘foo’);
  6.  
  7. dojo.query(‘a.foo’);
  8.  
  9.  

All of these if run using a common shared Dojo object, even if the functions are called from “within” the iframe will not find what you are looking for if it lives in an iframe. They only traverse the parent document. If I’ve missed a config parameter or something else that makes Dojo work with iframes I’ll take back all of this and be very happy. I spent a few hours today trawling through the dojo forums and book, as well as drilling back through the source and nothing jumped out.

So in my original situation, we’ll actually probably keep each iframes own dojo.js and own dojo object. We’ll just be aware now that if we want to publish we have to publish within all the iframes.

  1.  
  2.  
  3. dojo.publish("foo", [obj]);
  4.  
  5. frames[‘iframeName’].window.dojo.publish("foo", [obj]);
  6.  
  7. // and/or
  8.  
  9. window.parent.dojo.publish("foo", [obj]);
  10.  
  11.  

I’m going to look at writing a little handler script that can be used to pass a function and it gets passed to every iframe and then also maybe look at a function that does the opposite, extends a function like byId and looks through all the iframes for all the results.

There are many other quirks that iframes have with JavaScript libraries. Positioning is a peach of an issue, but I’ll save that for another time.


About this entry