Redirecting When Submitting in Internet Explorer
How to redirect in IE(7) when submitting a form
Introduction
The goal of the code is to redirect to a specific URL when submitting a form in Internet Explorer.
That sounds straightforward, doesn't it? But there's a catch. Actually, a few catches. The solution is simple and can be written in 5 statements, but the time it would take to get these 5 statements might take a bit longer than just writing those lines.
Background
I was asked to create a search form that redirects when it's submitted. The first version just had an onclick
event on the button but that kind of only solves half the problem.
If the user presses 'enter', the form gets submitted but the onclick
is never called (which is fair since the button was never clicked), so I thought I'd just move the eventhandler
to the forms onsubmit
.
(Those of you not coding .NET, skip the next paragraph)
Then I encountered my first problem. The JScript code I needed to call is specific to a page but the form is declared in a master page so setting the onsubmit
handler is not straightforward, but I'll show one possible solution.
After figuring out how to get the eventhandler in place, I encountered the second problem.
When you're submitting and redirecting at the "same time" in Internet Explorer, the post action wins so you end up in the action location (note: changing the action and method was not an option for us).
One might consider just cancelling the submission but that turned out to be not so straightforward.
The Code
The first part for the master page is only needed if you actually have a master page in play, otherwise only the submit
function is needed. First, let's look at the onsubmit
attribute of the form:
if(formSubmit){
var shouldPost = new referenceBoolean();
formSubmit(shouldPost);
return shouldPost.value;
}
A few things happen here: first, we test if the method formSubmit
is actually declared taking advantage of null
being treated as false
. This ensures that the method will only be invoked on a child page if it's actually defined (omitting will give the user a warning that an error occurred if the method is not declared). Next, we instantiate a new object. The implementation of the 'type' looks like this:
function referenceBoolean(){
this.value = true;
}
This just holds a boolean value. Why we need it is explained later, for now just know it's just the type of object that formSubmit
expects. After instantiating the object, we pass it to formSubmit
and after the call, we return the value of our shouldPost
.
If shouldPost.value
is true
, the form is submitted, if the value is false
it's not submitted. Why go this long way of instantiating an object and passing that instead of just returning the value from the method? I'll tell you.
The first attempt at the submit handler I made looked like this:
function formSubmit(){
window.location.href = "redirect url";
}
This actually works in FF but not in IE. If there's a redirect in the onsubmit
in FF that effectively short circuits the post back which then never happens. But in IE things are different. The post back actually short circuits the redirect, so from the user's perspective, the redirect never happens.
Second attempt:
function formSubmit(){
window.location.href = "redirect url";
return false;
}
Well, you would think this solved the problem, right? I know I did, but actually the result of this code in IE is the same as what I used in my first attempt. The problem is that the redirect for some reason implicitly returns from the method with true (I'm not talking about what might actually happen but how the system acts). Calling the above still submits the form and hence the redirect never happens (from the user's point of view).
That then led to my third attempt:
function formSubmit(shouldPost){
shouldPost.value = false;
window.location.href = "redirect url";
return shouldPost.value;
}
The thing to notice here is that the value of shouldPost
is set before the redirect and is only returned for completeness.
The reason why this works is also the reason why we're passing an object to the method. Objects are passed by reference so that all changes made to them in the method is reflected anywhere else the same object is used. Basically, we're setting our return value before calling the redirect code.
With the third version in place, all we need to do is test shouldPost.value
instead of the return value and if you take a look in the declaration of the eventhandle, that's exactly what happens.
Points of Interest
The part used in the master page can be used as an example on a general way of "inheriting" abstract JavaScript methods from master pages in child pages.