views:

532

answers:

6

I'm working on a large web application with a lot of AJAX whose event handling has gotten out of control. I'm trying to set up an event delegation system to manage all of it, but am wondering if there's a workaround for IE's non-bubbling form submits (there are a lot of forms that get inserted/updated via AJAX). The best thing I've come up with is executing a bit of javascript to reload submit handlers every time I get a response from an AJAX call, but this seems ugly. Any ideas?

Also, does anyone have a good reference for which events don't correctly propagate in different versions of IE? I've had trouble finding good information (though this other question has a bit).


A real example from the site: there is in-place editing of some user content. Doing event delegation, I would have the body listen for submit events and then see what element triggered the event and handle it accordingly. Since submits don't bubble in IE, this won't work. The $5 solution would be to do event delegation for all other events and handle submits using something like this in Prototype:

// call this onload:
$$('form').invoke('observe', 'submit', function(event) { /*delegate*/ });

But this won't work for forms that are created dynamically (I'd have to re-instantiate the handler every time as mentioned above), and the whole thing would just be nicer if I could "make" form submits bubble in IE and just do plain delegation everywhere (no special cases, etc).

A: 

Options I've considered thus far:

  • The crappy solution that I posted in the question itself.
  • The Inline Cop-out - Always guaranteed to work, and has relatively low overhead, but is incredibly obtrusive. I'd have to adapt this idea to work with Prototype (which wouldn't really be hard, I'd probably just write an Event.fix(event) function that stops the event then re-fires it to propagate on its merry way).
  • NWEvents - I didn't get a chance to fiddle with this too much, but supposedly this forces all events to bubble. Looking at the source, I'm not sure that this actually works for dynamically created elements. I'll have to play with it some more.
Matt Kantor
+1  A: 

One technique you can try is to have only two forms: a "working" form and a hidden "submitting" form and only have these two forms on the page.

The "working" form is what is displayed to the user - it's just a container and can contain elements from various forms. Various buttons on the form don't actually submit, but call a form handler/validation routine in JavaScript.

The handler/validation routine dynamically sets the action of the "submitting" form and adds the required elements to that form dynamically so it can be submitted.

This way you are never adding and removing from tags themselves, you're just changing the appearance and behavior of the two main ones, thus avoiding all the nasty event manipulation.

Diodeus
+2  A: 

Can you make the forms return false and just look for the CLICK event on the submit buttons instead of the form submit event? Then submit the forms programatically via your AJAX calls.

sanchothefat
I'd do something more like this:<form onsubmit="$(this).fire('form:submit'); return false;">I was looking for a completely unobtrusive solution, but if I can't find one then this is probably what I'll do.
Matt Kantor
You could do it unobtrusively still,$("#form-id").submit(function(){ return false; });$("#form-submit-button").click(function(){ $(this).parents("form").submit(); // fires the submit event return false;});Look into using the jquery form plugin: http://malsup.com/jquery/form/
sanchothefat
Woops, code got wrapped but you get the idea
sanchothefat
This won't work for dynamically created elements though, which is one of the main reasons I'm doing this. Also, what about submitting the form by pressing enter or with javascript? This needs to be regression-less.
Matt Kantor
Also, I'm pretty sure that the event fired by $(this).parents("form").submit(); won't bubble either (unless jQuery works around this internally).
Matt Kantor
+1  A: 

Another option to consider may be reglib.

Latest trunk version has an implementation that allows delegation of submit

Ryan Watkins
+1  A: 

Rails 3 rails.js has solved this issue by detecting if the browser supports submit event bubbling, if not then bind the onSubmit method to the handler on the first focus event of the form. Pretty neat.

Check out

http://github.com/rails/rails/commit/f61d923d284062b4e4864d81c603157020198d06

Alex Le