Jump to content
Larry Ullman's Book Forums

Redirect Browser Using Onchange Method


Recommended Posts

Although this issue is not PHP specific, I am using PHP to generate a form in HTML. My script generates the following page:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml: lang="en" lang="en">

<head>

<meta http-equiv="content-type" content="text/html; charset=utf-8" />

<title>SDFSC Scrip</title>

<style type="text/css" media="all">@import "includes/style.css";</style>

</head>

<body>

<div id="wrapper">

<div id="banner">

<span><img id='logo_z1' src='images/TdS.png' /></span>

<span id='logo_z2'>Team del S l </span>

<span id='head'>Scrip Program</span>

<span id='greeting'>Hi Anderson Family!</span>

<span id='logout'><a href='login.php?logout=true'>logout</a></span>

</div> <!-- end banner -->

<div id='menu'>

<span id='selnav'> Reports </span>

<span id='nav'><a href='help.php'>   Help   </a></span>

<form method='post' action='reporthandler.php'>

<span id='season'><label>Season: </label>

<select name='seasonid' onchange="window.location.href=reports.php?season=this.form.seasonid.options[this.form.seasonid.selectedIndex].value">

<option value=2>2011-2012</option>

<option value=1>2010-2011</option>

</select></span></div> <!-- end menu -->

<div id='main'>

</form> <!-- end form -->

</div> <!-- end main -->

</div> <!-- end wrapper -->

</body>

</html>

 

On line 22, the expected behavior of the SELECT is:

When the option is changed by the user, the page will redirect to itself, with a query string identifying the options selected.

 

The actual behavior is: nothing happens

 

If I hardcode the onchange method with:

<select name='seasonid' onchange="window.location.'href=reports.php?season=1'">

then then page redirects

 

I have researced many forums and tutorials, and cannot find an suitable answer. Has anyone solved a similar problem?

 

Thank you.

Link to comment
Share on other sites

Well, the difference between the code that does work and the code that doesn't is the wrapping of the destination URL in quotes (although I expect the single quote comes before "reports" not "href"). I would use quotes in the other code, too.

Link to comment
Share on other sites

Thank you for your reply Larry. You are corret, I did misplace the single open quote. Unfortunately, when I attempt to wrap the entire redirect target in single quotes, the bit of code meant to determine the chosen option is sent as a literal string, so I get a URL of:

 

"http://www.redfalconmarketing.com/SDFSCScrip/reports.php?season=this.form.seasonid.options[this.form.seasonid.selectedIndex].value"

 

I've tried every workaround that is obvious to me, including creating a JavaScript function to build the redirect on the fly, but so far no joy.

 

What I am attempting to do here is refresh a report patameters page based on a sporting season.

Link to comment
Share on other sites

Ron, there are a few things to consider here.

 

First and foremost though, it's important to understand what this is referring to in the following line:

 

<select name='seasonid' onchange="window.location.href=reports.php?season=this.form.seasonid.options[this.form.seasonid.selectedIndex].value">

 

Before I tell you what it's referring to, I want you to think about it a bit. Maybe even do a little research if necessary.

 

You got it? this is referring to the select HTML element that the JS is being invoked in. As such, this does not have a form property, a seasonid property, etc., etc. Basically, I'm surprised your browser is not spitting out JS errors left and right. You might want to try loading your page with a JS debugger and seeing what kind of error messages you get.

 

Anyway, to make a long story short, because this refers to the select HTML element (essentially, the select tag), to get the value of the selected option, you need only use this.value.

 

Using your code as a base, I've created the following simple script to illustrate my point. Feel free to copy and paste it into a blank HTML file and run it in your browser. Select a drop-down list item, and see the results.

 

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">

 <head>

   <title>onchange event test</title>

   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

 </head>

 <body>

   <form method='post' action='reporthandler.php'>

     <select name='seasonid'>

       <option value=2>2011-2012</option>

       <option value=1>2010-2011</option>

     </select>

   </form>

   <script type="text/javascript">

     document.getElementById('seasonid').onchange = function() { alert(this.value); };

     //document.forms[0].seasonid.onchange = function() { alert(this.value); }; This is also valid, and returns the same thing.

   </script>

 </body>

</html>

 

The main thing to note is that by simply using this.value (and the JS alert function to report that value to the screen), we can very easily see that we have access to the values.

 

The other thing I want to note is the separation of code. Really, you should not mix JavaScript with HTML by placing JS in inline tags. Instead, do what I'm doing and access the HTML element you want via the DOM, attach the onchange event to it, and then do what you have to do within the anonymous function. You could also call another function from here, if need be.

 

The last thing I want to mention is that even if you use your method, you're still going to have to reload the page after the user makes a selection. Instead (if you want to make things smooth), I highly recommend using Ajax to make an asynchronous call to a PHP script/database and return the data without having to reload the page.

 

Anyway, I'm curious to hear your thoughts. Hope this helps.

  • Upvote 1
Link to comment
Share on other sites

Domo HartleySan!

 

First off, I would like to recognize your willingness to share your knowledge in a way that assists others in growing their knowledge as well.

 

My first inclination was to separate the script from HTML as you suggested, but was unclear on how to accomplish this. I believe that your example got me moving in the right direction. Here are some observations that I made during testing:

 

1. Both of the following anonymous function calls accomplish the same thing in IE8 without JS errors:

document.getElementById('seasonid').onchange = function() {window.location.href="reports.php?season=" + this.value};

document.getElementById('seasonid').onchange = function() {window.location.href="reports.php?season=" + this.form.seasonid.options[this.form.seasonid.selectedIndex].value};

 

I speculate that 'this' conditionally references different objects based on how the object is being qualified (at least in IE8).

 

2. While the 'seasonid' element may be referenced as document.getElementById('seasonid') in IE8, Firefox 4 returns a 'null' value for this reference. However, your second solution 'document.forms[0].seasonid' works well in both browsers.

 

3. If I attempt to create a second select element named 'purch' and append its value in the query string '&purch=purch.value' works without error in IE8, but 'purch' is not recognized as an object in Firefox 4.

 

So I'm already running into browser incompatabilities, and I haven't even tested in Safari or Opera yet!

 

This brings us to your final point. My ultimate strategy is to add an AJAX layer to the application. However, the reading that I have done so far suggests that it is preferable to have a working solution that functions without AJAX so that users whose browsers are incompatible with the required technology can still use the application. Then and only then should AJAX technology be added. For me, this begs the question: will my compatibility issues be compounded by adding an AJAX layer?

 

I do understand the issue your raise regarding the current strategy, and the need to reload the page every time the select option is changed. However, I don't anticipate that users will be using this functionality regularly. I simply wanted to make it available in the off chance that users wanted to review previous seasons' data.

 

Thank you again for taking the time to share your thoughts and to guide me. I look forward to your thoughts on the above.

Link to comment
Share on other sites

Yes, I recommend getting it working in a non-JavaScript method, then applying JavaScript. If you go the "unobtrusive JavaScript" route, as HartleySan suggested, you'll not only have cleaner code but have a more reliable always works/always fails scenario (as opposed to working-ish in some browsers and not working-ish in others). Although I'm comfortable handcoding JavaScript, I find that a framework such as jQuery helps a lot in terms of providing consistent browser behavior.

Link to comment
Share on other sites

Thanks for replying, Ron. I'm at work and stuck on IE6 at the moment, so when I get home, I'll play around with my recommended code a bit more in different browsers, and then report back with answers to your questions.

 

Initially, just reading your post though, I suspect there are things other than browser incompatibilities causing the issues, which I'll explain when I get home later.

Link to comment
Share on other sites

Ron, now that I have more time, I will try to better reply to your questions. There are a few things going on. First off, in regards to your first question:

 

1. Both of the following anonymous function calls accomplish the same thing in IE8 without JS errors:

document.getElementById('seasonid').onchange = function() {window.location.href="reports.php?season=" + this.value};

document.getElementById('seasonid').onchange = function() {window.location.href="reports.php?season=" + this.form.seasonid.options[this.form.seasonid.selectedIndex].value};

 

I speculate that 'this' conditionally references different objects based on how the object is being qualified (at least in IE8).

 

I did some research, and amazingly, you're right. The second one returns the same value. The fact of the matter is, this is always referring to the select HTML element. That's not debatable. What I didn't know is that if this refers to an element within a form, then this.form refers to the parent form. Similar to how this.parentNode would (in most cases) refer to the parent form. I did not know this, and learned something new.

 

With that said, this.form.seasonid is the same thing as this. Kinda the whole "This man's father is my father's son." Anyway, from this.form.seasonid, you can access options just fine. And again, this.form.seasonid in the brackets means the same thing as before, after which you add the index value of the selected element, and then the value of that. Basically, the second method is super, super inefficient, but in the end, you get the same thing. That was a bit of a brain teaser.

 

For practical uses though, stick with the first one.

 

As for your second question:

 

2. While the 'seasonid' element may be referenced as document.getElementById('seasonid') in IE8, Firefox 4 returns a 'null' value for this reference. However, your second solution 'document.forms[0].seasonid' works well in both browsers.

 

This issue is a result of me being a newb. When I posted my original code, I did a couple of things wrong. One, I used single quotes to surround the HTML attribute values, when I should have used double quotes. More importantly though, there was no ID attached to the select element, so getElementById won't work. Duh! Obviously, there was a name attached, but no ID. Basically, if you give the select element the same ID as the name, it'll work. My bad!

 

As for question #3:

 

3. If I attempt to create a second select element named 'purch' and append its value in the query string '&purch=purch.value' works without error in IE8, but 'purch' is not recognized as an object in Firefox 4.

 

This I can't really comment on without seeing your code. My only assumption is that you've made a mistake somewhere. If you don't mind posting your code, then maybe I can better help.

 

So, with all that said, what it adds up to is mistakes on my part, not browser incompatibilities. If you fix the things I mentioned, then I guarantee it'll work in all browsers that support JS.

 

And on that note, in regards to Ajax, in this day and age, you should be fine using Ajax. The truth is, yes, if someone is using a browser that does not support JS and the XMLHttpRequest object (i.e., pre-IE5 browsers), or if a user has intentionally disabled JS, then Ajax will not work. However, that type of user is very rare these days.

 

So yes, the truth is that you could potentially deny service to some people, but in all cases, I can't imagine the user not being able to upgrade to an able browser, if they really wanted to. And really, if you start assuming that users can't use JS, etc. these days, you're really denying all users a lot of great features you could add to your website.

 

In conclusion, don't shy away from Ajax because a super small, and ever-decreasing number of people's browsers don't support it. Also, the "browser incompatibilities" you mentioned were merely human error on my end. Sorry. I'll try and double check my code next time before posting. Anyway, here's a revised version of the code, which *should* work in all browsers that support JS:

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">

 <head>

   <title>onchange event test</title>

   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

 </head>

 <body>

   <form method="post" action="reporthandler.php">

     <select name="seasonid" id="seasonid">

       <option value=2>2011-2012</option>

       <option value=1>2010-2011</option>

     </select>

   </form>

   <script type="text/javascript">

     document.getElementById('seasonid').onchange = function() { alert(this.value); };

   </script>

 </body>

</html>

 

Also, feel free to ask any other questions and post your code regarding the purch issue.

  • Upvote 1
Link to comment
Share on other sites

 Share

×
×
  • Create New...