A few tips on using jQuery with Drupal on IE6 (out of sweat and tears)
Introduction:
This post deals with several problems related to the combination of jQuery and IE6 and the lessons learned while working on a recent project. I just had to share those with you: so many hours have been put into the effort so I just can't let it all fade (even if also to have a reference to get back to
)
If you have comments on this post, feel free to post them. I'll be happy to update the post to make it better.
Lets get to the point(s):
1. Creating custom dynamic JS files from within PHP
Here's the scenario - you wan to be able to have a javascript file created dynamically on server side (where its being requested by the browser who follows the orders in a "script" tab. This script can be requested not only by your own site. The key thing is that you want to have the PHP script which generates this JS file given arguments. So, for example, you wish to have this sort of script tag:
| <script type="text/javascript" src="http://fqdn.my.site/js_stuff/JS_screator.php?param1=paramvalue1¶m2=paramvalue2... (etc) |
Cool.
Now, although this works fine on FF, on IE6 it sucks. IIRC, there was an unclear error message from IE6 which (took me a long time to debug and...) drills down to this - IE6 will know to include a JS file that's being produced by a php URL, that's fine. It fails when comes to putting GET arguments on this URI. Again, FF does very well with it - delivers the GET arguments and getting back the resulted JS code. Cool, but IE6 don't know ow to tackle this, and worse - it doesn't let you know exactly what's the problem.
The solution? Well, my solution was: you must avoid putting GET parameters on the URI. Instead, configure your Apache (did I mentioned this post is aimed at Apache users?... :-) to have rewrite rules that convert the URL into GET parameters, so for example-> http://fqdn.my.site/js_creating/param1_value/param2_value/.../js_creator.js is translated into http://fqdn.my.site/js_stuff/JS_screator.php?param1=paramvalue1¶m2=paramvalue2... . The rewrite syntax involved isn't too complicated.
Using this method fools a bit browsers to think this is a very standard JS file with some path to it, but it actually launches a PHP script with parameters that knows how to build the matching JS file a it output. This is a powerful thing to know and do.
2. Binding to "click" event on radio buttons prevents the buttons from actually being "selected" (IE6 only)
This is the scenario: you want to have some sexy form in which some of the form content is dependant on selections of a radio button in other part of the form and open dynamically, depending on that selection. Example - say you have a form for registering to your site, in either "regular" and "gold" account types. For each type, you want the registration form to show different fields and hide the unneeded ones.
You want it all to be AJAX'ed and sexy as you simply must have in the web2.0 world we live in (or so they say). Obviously, you are not going to write event handling code in pure javascript that will be cross browser. Why would you, if you know jQuery? 
So, you do something like this:
HTML:
|
<div id="account-type"> <!-- form continues here with other divs that should be shown or hide depending on the selection made above--> |
The matching client side jQuery code is therefore:
| $('.typeReg).each(function() { $(this).click(update_reg_form); }); |
The code above will attach a "click" event handling function to each matched element in the result set. In practice - to each of the radio buttons above. In other words, every time a click event will occur on each of the given buttons update_reg_form will be called.
If you, like me, uses a lot of "return false;" in the end of your JS functions to play safe when it comes to form redirection (in order NOT to redirect you need to return false), then you would set off the anti-developer mine and would see the problem in IE6 - the form is strangely updated when you click on the buttons but the click is not shown in the radio button (there's no middle black mark in the radio button indicating its selection). Instead, it will appear as if the group of radio buttons where not selected even once. "How come?" you would surely ask.
Well, it appears that in order to let those buttons to be "chosen", you simply need to remove that "return false;" statement at the end of update_reg_form. That's all! It appears that spreading those "return false" too much is not only playing safe, but also planting mines to later trip on...
.
3. Always check your code on IE6 (and 7).
This is a general warm recommendation - I found out the hard way that IE6 is very strict about the JS code its being fed and the resulting logic that needs to be run on the client side. It was much more pickier at what script it decides to run and what not and in reporting errors. FF is much more forgiving and will run many things that IE6 will fails upon. I must admit that this tendency of IE6 also contributes to cleaner code but never assumes that a piece of JS (jQuery) written and developed on FF will work on IE6. Always check it.
Boaz.

Considering the above using
Considering the above using Apache's mod_rewrite rewrite-rules is not a hack IMHO.
I agree, not a hack, but very specific to your case..
I think that the "change" event is not suitable
Right. Looking a bit more at radio buttons events (again, not specific to jquery) reveals that 'click' is the right event for this (but do let the button handle it).
Some more info about event handling and capturing:
http://www.quirksmode.org/js/events_order.html
http://docs.jquery.com/Events_(Guide)
Thanks for the informative
Thanks for the informative post.
Regarding issue #1, I would assume this is a "feature" of IE6, not a bug. Your hack to apache is quite controversial IMHO. I suggest to try and avoid such a thing alltogether - if you are creating the JS file yourself (which is the case you described, otherwise you wouldn't be able to edit apache settings), why not create it directly in the code that generates the page in the first place?
drupal_add_js('javascript code directly in here', 'inline');
?>
Regarding issue #2,
First, 'return false;' for event handlers tell the javascript parser - stop handling the event, as handling is finished here. otherwise, the event would bubble up to all the containing elements for handling. This is unrelated to jquery, but to javascript itself. This explains why you haven't seen the user selection.. It is unrelated to IE too..
Second, maybe 'click' is not the right event to detect radio button changes. 'change' on the option group seems much more appropriate here.
Hi Yuval, Regarding comment
Hi Yuval,
Regarding comment #1, I should put things in context and that'll explain better why does the suggested or described implementation diverted from using Drupal methods and methodology: well, the project I'm working on involves a requirement to put a registration form in affiliate sites. Since this form is customized per-affiliate, and is utilizing AJAX (and SOAP and more, and I learned a lot and still learning [yey!]), we chose to implement it this way and therefore drupal_add_js() is not relevant here. Considering the above using Apache's mod_rewrite rewrite-rules is not a hack IMHO.
Yep, this corner in this project is getting out of the Drupal realm altogether. I hope the comment clarifies it. I cannot go into all design considerations here but all I can say is that we carefully needed to find a solution for running Drupal-originating forms (but only originating and having life of their own later on) on other sites, and this involves in our case an iframe (not a must but simplifies things) and dynamically generated JS (that utilizes jQuery).
Regarding point #2, yes, you are probably right about return false and cessation of event bubbling. Interestingly, with return false I still had the selection "selected" in FF so this might be referred to as an IE-only issue after all (although in principal you are right - this is not an IE thing). Like I said in other words - life is full of ironic surprises and on this case - the fact that IE6 produced cleaner JS code from me.
Regarding the suggestion to use the "change" event I can say that I carefully examined all event types I could use for clicking of radio buttons and didn't find anything that matched better my needs (to tell the truth I don't remember all the gory details now). I think that the "change" event is not suitable - from jQuery documentation on the change event: "The change event usually fires when a control loses the input focus and its value has been modified since gaining focus" (http://docs.jquery.com/Events/change#fn). As you can see, the event fires when a radio button loses focus, not gaining focus (and IIRC I have tested and verified this).
Thanks for the feedback!
Boaz.
Post new comment