Read the bug fix announcement. Upgrade! This was causing extremely puzzling crashes in Safari on Macs (pre-Safari 3 beta) on one of our applications and I’m glad (in some ways) that the problem lay with the Prototype library. (2)

Essential Firebug video for web developers

If you’re doing web development or design of any sort, you have to check out Joe Hewitt’s talk on Firebug at Yahoo! - download the movie or watch it online, just make sure you watch it.

If you aren’t already using Firebug, this will convince you. If you are, you’ll probably find some gems in there that you didn’t know before. I didn’t know that you could log events to elements on the fly, or press the up and down arrow keys to adjust numerical values (such as margins and paddings), or edit the values in the box model layout diagram, or hover over variable names to see a tooltip of their values in the JavaScript debugger, or conditional breakpoints.

Now if only it were able to detect JavaScript syntax errors that cause an entire JS file to be ignored by the browser.

Beware of form parameters named ’submit’

Well, that is if you are ever going to be submitting the form via Javascript. We had to generate forms on the fly and POST them behind the scenes (i.e. in hidden <iframe>s), and got a decent script going, until a particular case failed for no apparent reason. I finally found that the problem was due to a form parameter named “submit” that overwrote the submit() function of the <form>. That’s, of course, after looking at all the wrong places.

So this doesn’t work:

<form id="ninjaForm" action="/come/get/some" method="post">
  <input id="someParam" name="someParam"
    type="hidden" value="Some value" />
  <input id="submit" name="submit"
    type="hidden" value="Start search" />
</form>
<script type="text/javascript">
  setTimeout("document.ninjaForm.submit()", 200);
</script>

When the browser tries to execute “document.ninjaForm.submit()”, it sees the “submit” form field (which overwrote the submit() function) instead and complains that “submit is not a function”.

Do this instead:

<form id="ninjaForm" action="/come/get/some" method="post">
  <script type="text/javascript">
    // Alias the submit function in case there is a 'submit' param.
    ninjaForm = document.getElementById('ninjaForm');
    ninjaForm.__submit = ninjaForm.submit;
  </script>
  <input id="someParam" name="someParam"
    type="hidden" value="Some value" />
  <input id="submit" name="submit"
    type="hidden" value="Start search" />
</form>
<script type="text/javascript">
  setTimeout("ninjaForm.__submit();", 200);
</script>

That’s one way to workaround, of course, and we can get away with the “ninjaForm” global in this case.

Unobtrusive IFrame shim - a half solution

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!