views:

83

answers:

2

Hello,

I have a Dojo SubmitButton with jsId="saveParamButtonWidget". I overrided its onClick method by putting:

saveParamButtonWidget.onClick = editParam

I defined the editParam() function like this:

function editParam(eventObj) {
    dojo.stopEvent(eventObj);
    // ...
}

dojo.stopEvent() is supposed to stop event bubbling and default processing. However, the browser will submit the form anyway. I also tried with the following:

function editParam(eventObj) {
    eventObj.stopPropagation();
    eventObj.preventDefault();
    // ...
}

Same thing. The only way I've managed to prevent form submission is by returning "false" from the event handler:

function editParam(eventObj) {
    // ...
    return false;
}

Can someone tell me why the first two ways did not work? Thanks.

+1  A: 
S.Jones
Technically nothing bad will happen from setting the onClick method directly, since it's just a stub in `dijit._Widget` meant to be hooked anyway. In fact, using dojo.connect (or perhaps better, yourwidget.connect) will actually do *worse* because then `return false` won't work either.
Ken
+3  A: 

Okay, after doing some digging through the source, I believe I can answer your question definitively.

The reason dojo.stopEvent() doesn't work, but return false does, is entirely due to how dijit.form.Button is coded. If you're interested, it's time for a little field trip. Keep your hard hats on.

When a dijit.form.Button is clicked...

  1. The button's _onButtonClick method is invoked. (This is hooked up in the template, to the special ondijitclick event which captures not only mouse click but also certain keypresses, for a11y purposes.)
  2. The _onButtonClick method first invokes the _onClick method, which, presuming the button is not disabled (which it's not in this case), invokes and returns the result of the onClick method. This is of particular interest since it's the method you're overriding!
  3. Coming back to _onButtonClick, if _onClick returned precisely false (e.g. if your onClick handler returned false), _onButtonClick immediately bails out. This is why returning false makes your code work as desired. But what happens if it doesn't bail out there? Let's follow the trail further...
  4. Next, _onButtonClick checks whether this button not a descendant of an actual HTML form, but is a descendant of a widget with an _onSubmit method (duck-typing). I'm assuming that in your case it is inside a real form (dijit.form.Form counts), so we'll skip over this. (I am under the impression that this code path wouldn't actually end up submitting, whereas yours apparently does.)
  5. One final condition is checked: if the button has a valueNode defined (it does), the click method of this node is invoked. Unfortunately, this produces an entirely new event object on an invisible input type="submit" node under your form, and thus anything you tried to tell the original event is rendered immaterial, and the form goes on to submit! This is why dojo.stopEvent did not work - this code in dijit.form.Button pays it absolutely no heed.

I cooked this up as a somewhat-limited proof of concept (be sure to open firebug/etc. to get the logs): http://jsfiddle.net/Bf5H8/

Perhaps this is something that should be logged as a bug, but I suppose the initial thought may have been that supporting the well-known return false mechanism would be enough.

All this being said, it's quite possible that overriding onSubmit of the form is more in-line with your interests than overriding the button's onClick anyway (as S.Jones suggested), but at least this should solve the mystery.

Ken
Thanks a lot for your effort, Ken.
Dario