header

Conflicting form action element and property



Problem:
I recently came across an issue where an HTML input element named “action” was conflicting with the enclosing form’s action property. To clarify, there was a form setup thusly:

<form action="index.php" method="post" name="searchForm" id="searchForm">
...
<a onclick="changeAction();">Export File</a>
<input type="hidden" name="action" value="1" />
...
</form>

Where the changeAction function is defined as

<script>
function changeAction(){
 var x = document.getElementById("searchForm");
 alert("original action: "+x.action);
 x.action = 'export_csv.php';
 alert("new action: "+x.action);
 x.submit();
}
</script>

I found this function on w3schools, and I was trying to figure out why it wouldn’t work for me. It worked fine in Firefox, but not IE. It finally occurred to me that in IE, document.getElementById(“searchForm”).action was the same as document.getElementById(“action”) — that is to say the .action was not the form’s action property, it was actually pointing to the input HTML element instead. I would argue that this is a bug with IE, that any input named ‘action’ would overwrite any direct access to the action form property.

This made it seemingly impossible for me to dynamically change the action of a form with the conflicting named input item.

The obvious solution is to change the name of the input. For most that would probably work OK, but I didn’t like that solution. I HAD to get it ;).

Solutions:
The first thing I tried was removing the input, then submitting the form. This would work for most. So that involved:

  1. Enclosing the input with a span with an ID I could reference — ‘action_input’.
  2. Changing the changeAction function to clear the innerHTML of ‘action_input’, then submit.

This works fine for most. However, for me the new action I am setting retains the current page, it does not do a new page load. This means that I need to be able to reset the action value after submitting, and it appears as though setting the innerHTML after a submit() does not work so well cross browser.

I asked for help on efnet’s #javascript (IRC), and I was directed to the javascript function setAttribute. After some searching, I found that this doesn’t work; in IE the getAttribute(“action”)/setAttribute(“action”, “newVal”) functions STILL reference the HTML input element, not the action property of the form.

Upon more searching, I was directed to the changelog for AjaxAnywhere:

1.1.0.2 – evolution : form “action” attribute is accessed by DOM to prevent collision with <input name=”action” .. >

(Hey, at least someone else had this same issue!)

I perused their source code, and found this snippet (aa.js, line 130):

var actionAttrNode = form.attributes["action"];

So I tried that, and it worked beautifully in IE6, IE7 and Firefox 2. The adjusted javascript function:

function changeAction(){
 var x = document.getElementById("searchForm");
 x.attributes["action"].value = 'export_csv.php';
 x.submit();
 x.attributes["action"].value = 'index.php';
}

Update: makk on efnet #javascript says that this doesn’t work with Safari. There’s a workaround which makes it work, which I applied. Here’s the final version of the function:

function changeAction(){
 var x = document.getElementById("searchForm");
 x.attributes.getNamedItem('action').value = 'export_csv.php';
 x.submit();
 x.attributes.getNamedItem('action').value = 'index.php';
}

Problem solved!



1 Comment »

  1. gravatar

    Jeff Said,

    November 5, 2007 @ 8:31 am

    Good work with that fix. I hate tracking down variable name conflicts like that. Who wants to read online documentation? (I wish they had man pages for JavaScript!)

RSS feed for comments on this post · TrackBack URI

Leave a Comment

blogtimes