-
Chad Granum
OpenSourcery Alumnus
I have been working on a Drupal project here at OpenSourcery that involves a dynamic form which updates via ajax whenever a radio button or checkbox is modified. Drupal has built-in ajax/ahah, making this task much simpler. It lets you specify which type of event you want to trigger the ajax, as well as many other options.
For this specifically the requirement was that it occur with the 'OnChange' event. This works great in firefox, but not so great in IE. IE does not register an 'OnChange' event until the mouse is clicked somewhere else on the page after having changed your radio/checkbox selection. This is of course not the desired behavior.
Drupal offers other choices for events that trigger the ajax. The next obvious candidate was 'click'. Click provided consistant behavior between IE and FF. When you click the new button the form would update. However, it resulted in some undesirable behavior in both browsers. The radio button selection would not update. The correct option was sent to post for ajax, but the actual radio button selection did not change.
At this point it became obvious that I was going to need to hand-code some javascript to work around this issue. At first I attempted to write javascript that would update the radio selection after the ajax fired. This was an exercise in futility. I encountered many difficulties, most of which were probably due to inexperience.
Before pounding my head too long on my first attempted solution, a better solution reached my brain. Instead of using 'Click' and trying to re-write default radio and checkbox functionality, I would use 'OnChange' and work around IE's problem. The solution was simple, if the browser is IE, add an 'OnClick' event to all the ajax elements that triggers the 'OnChange' event.
This solution worked perfectly, and was very easy to write, even for someone with little js experience. My first time through I failed to follow proper Drupal convention, and as such I had to implement my own logic to update all the element triggers whenever ajax was used. Fortunately Jonathan reviewed my JS and pointed out the proper way to achieve this (see note 2).
Here is the final version of the javascript
Drupal.behaviors.nexusForm = function (context) { if (jQuery.browser.msie) { trig_bind() } //Hide the botton we only want to see if the browser does not support js $("#edit-continue").hide() } //IE waits until another event to send the 'change' events on radios and checkboxes //This bind a trigger for those events on click. function trig_bind() { //unbind old events $("input[type='checkbox']").unbind( 'click' ) $("input[type='radio']").unbind( 'click' ) //bind the events $("input[type='checkbox']").bind( 'click', function() { $(this).trigger( 'change' ) }) $("input[type='radio']").bind( 'click', function() { $(this).trigger( 'change' ) }) }
Notes:
ahah.js bug
The reason you can't use checkbox onclick with #ahah isn't because of some browser bug, but because ahah.js always returns false when its event handler is triggered. This is meant to block normal form submissions, but it fires regardless of whether a button was clicked. In this case, it blocks the checkbox value from being changed, exactly as the DOM event model specifies.
Don't forget accessibility.
Don't forget accessibility. If you are using OnClick, that excludes keyboard navigation.
Only on IE6?
When you refer to IE you mean IE 6?.
On IE7 happens the same. I didn't tried on IE8, but y supose it still happens. Microsoft is very lazy fixing bugs, don't you think the same?
onchange vs onclick
I am stuck with the onchange vs onclick conflict. Do you have any idea about the following issue:
When you have onchange event on a textbox and also onclick on a button, what should be done if we want that the click event should also fire on button when we change value in textbox and immediately click on the button?
hmmz, I solved this issue by
hmmz, I solved this issue by simply using
$(selector).bind('change click keypress', function() { ... });instead of just
$(selector).bind('change', function() { ... });this should catch all non-programmatic ways of marking a checkbox/radio button, even when 1 option of a radio group is selected and then altered with the arrow keys or something
also, this seems to be normalized in jQuery 1.4, so the change event fires properly if ur using this version
(sry for double-posting like
(sry for double-posting like this)
@Naresh: avoid binding click handlers to buttons, there's a million other ways to get the form to submit, for instance: most browsers will submit the form a textfield resides in when the user presses enter while focussed on that field
I therefore use:
$('form').bind('submit', function() { // do work });instead of
$('form input[type=submit]').bind('click', function() { // do work });that should catch all ways to submit the form, including a click on the submit button
thanks
Hi
Thanks for this tip !
I implemented in a very little module and i post the tar on the issue post about this problem. I hope you will not be angry about it.
Chers !
Tim
amazing
This solution worked perfectly, and was very easy to write, even for someone with little js experience. My first time through I failed to follow proper Drupal convention brmaswn , and as such I had to implement my own logic to update all the element triggers whenever ajax was used.
great solution
Thanks for the tip.
@seutje
Nice one, worked for me!
Thanks.
I bow to your greatness
I'm fairly new to Javascript and just had my first go with the ahah helper module but unfortunately came across this problem too. The above fix worked for me, and I've bookmarked this page for future reference. Just out of interest, would you put the above in a conditional comment for IE? Thanks Catherine
thanks
worked like a charm! thanks!!!
Gracias!
Me ahorraste horas de trabajo ;D