views:

412

answers:

3

How can I use addEventListener() to assign a handler to an HTML form's Submit button, similar to assignment to the button's 'onclick' attribute, without triggering the form's default submit() behavior?

I have no trouble assigning a custom function to the 'onclick' attribute of the "Submit" button. The custom function executes a variety of steps, then creates an Ajax request object and uses this to send the data to the server. The default submit() behavior isn't triggered.

submitButton.onclick = function() {
    mySubmit();
    return false;
};

function mySubmit() {
   //do stuff
   notTheDefaultUrl = generateNonStandardUrl();
   request = GetStandardAjaxRequestThingamabob();
   request.open("POST", notTheDefaultUrl, true);
   request.onreadystatechange = myHandler;
   request.send(formData);
   return false;
}

But with addEventListener(), the browser submit the request twice -- once under the Ajax request object, and again with the default HTML form submit() behavior. (I can tell b/c the mySubmit function sends the data to a different URL than the default -- but both the default and the Ajax url are appearing in the server logs.)

var func = window['mySubmit'];
submitButton.addEventListener('click', func, false);

I'm aware that the function assigned to the button must return 'false' to prevent triggering the default submit() behavior. I thought mySubmit() did that, and I've tried to write the function passed in via addEventListener to return false more explicitly (instead of 'func', 'function() {mySubmit(); return false}') but these dosn't work either.

So how do I do this?

UPDATE

Comments to Peter's raised some browser compatability issues; also, IE doesn't support addEventListener(). This code addresses these. I've tested it in Firefox and IE 8.

function func( event ) {
    if ( event.preventDefault ) { event.preventDefault()};  
    event.returnValue = false;  
    // do whatever
}

if (submitButton.addEventListener) {
    submitButton.addEventListener('click', func, false);
}
else {
    submitButton.attachEvent('onclick', func);
}

Apologies for the messy newbie formatting.

+2  A: 

Shouldn't the handler be added as event listner for "submit" event?

It makes sense the "click" event handler returning false does not prevent default submit behavior, I think. It makes sense, kind of, that the form gets submitted to both targets.

edit: added second paragraph.

comment: And as Ken says the event listener should be added to the form and not the button.

edit 2: So I was wrong. You shouldn't use "return false;" but something like...

event.preventDefault ? event.preventDefault() : event.returnValue = false;
EMPraptor
Yes, and it should be on the form, not the button.
Ken
+6  A: 

You need to receive the event in your handler function, and prevent the event from executing its default behavior. This applies to click events, submit events - really any event that's cancelable.

// using your example
submitButton.addEventListener('click', func, false);

// here's what func should look like    
function func( event )
{
  if ( event.preventDefault ) event.preventDefault();
  event.returnValue = false;
  // do whatever
}
Peter Bailey
I like it, I posted the html alternative to this, but I prefer the way you posted better, much more cleaner
Zoidberg
good solution! and not to split hairs, but just as a note, this is not a cross-browser solution. In theory it is, but for IE browsers, you will need to use their alternative methods to achieve the same behavior :)
jaywon
I know YUI provides this functionality and takes care of the cross browser issues. My form validator that I built for YUI prevents exactly this behaviour if neededhttp://yuilibrary.com/gallery/show/formvalidator
Zoidberg
Apparently IE will spit out an error if you try to call preventDefault? http://stackoverflow.com/questions/1000597/event-preventdefault-function-not-working-in-ie-any-help
EMPraptor
@empraptor - Thanks! Absored answer into this example.
Peter Bailey
Trying this in IE revealed that IE doesn't support addEventListener() -- so I had to provide for attachEvent(), which has some differences in its arguments. See code in update, which worked in IE and Firefox.
chernevik
A: 

EASY WAY: Set the forms onsubmit attribute to return false

<form onsubmit="return false;">

Now if it MUST be done through assigning of an event listener through javascript, then the answer given by Peter Bailey is ideal.

My form validator does exactly what your trying to do. Check out this example

http://murdog05.github.com/yui3-gallery/examples/json/beforeSubmitExample.html

And the code base

http://yuilibrary.com/gallery/show/formvalidator

You might find it handy.

Zoidberg