Who started it?

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…

  1. 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. 🙁

  2. 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. 🙁

  3. 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. 🙁

  4. 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("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.

Posted in

Leave a reply