I spent some time this evening thinking about ideas for progressing form validation code.
Specifically, I was trying to solve the conundrum: When the submit event for a form is triggered, how can you tell which user interface element triggered the event?
This problem typically arises when you have multiple submit buttons on a form, when any submit button is activated, the submit event is triggered, but the form element is passed as a property of the event object, not the element (in this case a button) that originally triggered the event.
To complicate matters further, pressing enter while focussed on any input element will also trigger the submit event in many user agents.
Finding a complete robust solution became a bit of an emotional roller-coaster, let me explain…
-
My initial investigation revealed that jQuery was returning a useful object
eventObj.originalEvent.explicitOriginalTarget
. 🙂For example:
$('form').submit(eventObj) { var iStartedIt = eventObj.originalEvent.explicitOriginalTarget; };
Unfortunately, it turned out that explicitOriginalTarget is a Mozilla-specific property, with no cross-browser alternative. 🙁
-
My next thought was that the currently focussed element would have to be the element that triggered the submit event! 🙂
Unfortunately, jQuery doesn’t have a
:focus
selector. 🙁 -
I found a proposed solution for extending jQuery with a :focus selector. 🙂
Unfortunately, it relies on
document.activeElement
, which is a property only supported in IE, and modern browsers that have implemented parts of the HTML5 draft specification. 🙁 -
Luckily, a good fellow proposed a way to support document.activeElement in older browsers that don’t implement it themselves. 🙂
And… even better, this seemed to work (well, mostly – see below).
All together now
So put all this together and we get:
// Add document.activeElement support to browsers that don't support it.
if (
typeof document.activeElement == 'undefined' &&
document.addEventListener
) {
document.addEventListener("focus", function(e){
if (e && e.target) {
document.activeElement = e.target == document
? null : e.target;
}
}, true);
}
// Extend jQuery to support :focus selector
jQuery.extend(jQuery.expr[':'], {'focus': function(e) {
return (document.activeElement)
? e == document.activeElement : false ;
}});
// Now on submit, we can find the element that triggered this event
$('form').submit(function(eventObj) {
// if a submit button triggered the submit event, find it
if ((focussedSubmit = $(this).find(':submit:focus')).size() > 0) {
var iStartedIt = focussedSubmit;
} else {
// otherwise find the first submit button
var iStartedIt = form.find(':submit').eq(0);
}
// The iStartedIt variable now contains a reference to the element
// that triggered the submit event!
};
Tested and working in Firefox 2, Firefox 3, Opera 9.5 but not working correctly in Chrome. IE versions were not tested at this time, but in theory IE6+ should be fine.