Unobtrusive IFrame shim – a half solution

In: JavaScript|Web development

1 Aug 2006

Something that really bugged me when using YUI Calendars and YUI AutoComplete widgets was how IFrame shims are currently being managed in libraries and home-brewed code (we use IFrame shims in many places as well). YUI Calendars doesn’t have a built-in IFrame shim, YUI AutoComplete has its own, and we use our own IFrame shim library.

For the uninitiated, IFrame shims are basically IFrames dynamically inserted (hence “shim”) under overlaying DOM elements so that any <select> elements do not show through in IE 5.5 and above. A common example would be dynamically generated divs that float on top of drop downs in forms, such as the Yahoo! Calendar widget example below.

An example of the select box see through problem in IE 5.5+


So anyway, the thing that’s bugging me is the awkwardness in inserting IFrame shims where they are needed and the duplication of unnecessary code to create, show, and hide the IFrame shims. Ideally, I’d like to do something like this to attach IFrame shims and forget about them:

var iframeShim = new net.codefront.IFrameShim(‘elementId’);

Or the conceptually nicer way of attaching IFrame shim “behavior”:

net.codefront.IFrameShim.attachShim($(‘elementId’));

No need for manually displaying and hiding the IFrame shim, polluting display logic and event handlers. I don’t care how all that shimming is done nor should I have to. I don’t want to have to call displayShim() whenever I display a floating div and hideShim() when I hide it. It should be smart enough to display the shim when the overlay is showing and to hide when the overlay is no longer visible.

As it is, I am seeing code duplicated in many places to manage these IFrame shims, and that’s a bad smell. Ahh ahh, before I go further, I am completely aware that I could be completely off-base and such a miraculous time-saver of a library already exists. If so, I want to know!

Trying to fix this problem, I came up with this bit of JavaScript, which you shouldn’t bother reading. The idea is to allow me to do this:

var shim = new com.bezurk.widget.IFrameShim(‘myFloatingCalendar’);
shim.manualShim = false;
shim.manualDeshim = false;

And I have a ‘myFloatingCalendar’ element that’s automagically shimmed whenever it’s displayed. (The shim.manualShim and shim.manualDeshim are defaulted to false, and are shown purely for explanatory purposes.)

There is one problem though – I can’t figure out an elegant way to “listen” to the display and hide events of the element that’s shimmed. The way I’ve done it is to rely on Prototype’s PeriodicalExecuter (extended to support a stop() method) to poll for the visibility of the element. Naturally this is an ugly hack and causes noticeable flicker.

I’ve looked at custom events (YUI and Dojo have very nice event handling libraries) but can’t see how to hook this up unobtrusively. If you have a suggestion or a solution, I want to hear it!

3 Responses to Unobtrusive IFrame shim – a half solution

Avatar

Zach Leatherman

November 21st, 2006 at 11pm

YUI Overlay’s automatically use a IFRAME shim.

http://developer.yahoo.com/yui/docs/YAHOO.widget.Overlay.html

Avatar

Rumble

May 18th, 2007 at 7pm

It’d be neat to use Object.watch to achieve this – set up a function to ‘watch’ the object you’re showing and hiding and show or hide the iframe shims when the display, or visibility changes. See here for a fuller explanation of how this would work: Mozilla Reference for Object.watch.

Alas, there is one slight problem, the one browser who needs the iframe work around doesn’t support Object.watch! D’oh!

Avatar

Milo

September 8th, 2007 at 1am

The magic word is “onpropertychange”. This is an IE-only event, but since it’s an IE-only problem, that should be fine.