Hi there, I am looking for some help with JavaScript that I am only just beginning to learn a little about. I have coded a form that I am trying to, onsubmit, take a user to a relevant page on a shop website, depending on the selections they make within a form so that they can order a photobook. What I have so far can be seen below. Here is the code, html first: <form name="frm1" method="post" onSubmit="javascript:decide_action();" action=""> <br> <input type="radio" name="group1" value="portrait"> Portrait<br> <input type="radio" name="group1" value="landscape" checked> Landscape<br> <hr> <input type="radio" name="group2" value="layout1"> Layout 1<br> <input type="radio" name="group2" value="layout2"> Layout 2<br> <input type="radio" name="group2" value="layout3" checked> Layout 3<br> <input type="radio" name="group2" value="layout4"> Layout 4 <hr> <input type="radio" name="group3" value="pagenos"> Page numbers<br> <input type="radio" name="group3" value="nopagenos" checked> No page numbers<br> <input type="submit" name="s1" value="Submit" /> </form> Code (markup): Now for the JavaScript: <script language="javascript"> function decide_action() { if(check_buttons()==true) { if(document.frm1.group1[0].checked==true && document.frm1.group2[0].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="one.php"; } else if(document.frm1.group1[0].checked==true && document.frm1.group2[0].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="two.php"; } else if(document.frm1.group1[0].checked==true && document.frm1.group2[1].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="three.php"; } else if(document.frm1.group1[0].checked==true && document.frm1.group2[1].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="four.php"; } else if(document.frm1.group1[0].checked==true && document.frm1.group2[2].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="five.php"; } else if(document.frm1.group1[0].checked==true && document.frm1.group2[2].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="six.php"; } else if(document.frm1.group1[0].checked==true && document.frm1.group2[3].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="seven.php"; } else if(document.frm1.group1[0].checked==true && document.frm1.group2[3].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="eight.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[0].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="nine.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[0].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="ten.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[1].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="eleven.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[1].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="twelve.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[2].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="thirteen.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[2].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="fourteen.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[3].checked==true && document.frm1.group3[0].checked==true) { document.frm1.action="fifteen.php"; } else if(document.frm1.group1[1].checked==true && document.frm1.group2[3].checked==true && document.frm1.group3[1].checked==true) { document.frm1.action="sixteen.php"; } } function check_buttons() { var ok=false; for(i=0; i<3; i++) { if(document.frm1.ch[i].checked==true) { ok=true; } } if(ok==false) { alert("Select at least one option."); } return ok; } </script> Code (markup): As I said, I am VERY new to this JavaScript lark, so if you can let me know in small words how to fix this, I would be very grateful. With kind regards, Rwthwyn
To be brutally frank, this is a case of "JS for nothing and your scripts for free" -- You are sending it to PHP files, so have a PHP file SERVER SIDE that routes it to the correct page... You should have that ANYWAYS for when scripting is disabled! Again as I've said several dozen times on these forums, you should make the page work without javascript FIRST, then enhance it with scripting if needed -- since you're sending it to PHP in the first place, it's not needed. Also, if your VALUE attributes contained "real" values, you could add them together to build your name... You should probably have LABELS on your form, the radio buttons are basically sets of fields -- we have a tag for that called fieldset which I'd use instead of the HR. (border-bottom, put the submit in a 'submits and hiddens' div since that's not a field, it's a control). etc, etc... So first, let's clean up your markup - excuse the XHTML, it's how I roll: <form id="layoutSelector" method="get" action="layoutSelector.php" > <fieldset> <input type="radio" name="aspect" id="layoutAspectPortrait" value="portrait" /> <label for="layoutAspectPortrait">Portrait</label> <br /> <input type="radio" name="aspect" id="layoutAspectPortrait" value="landscape" checked="checked" /> <label for="layoutAspectPortrait">Landscape</label> </fieldset> <fieldset> <input type="radio" name="layout" id="layoutNumber1" value="layout1" /> <label for="layoutNumber1">Layout 1</label> <br /> <input type="radio" name="layout" id="layoutNumber2" value="layout2" /> <label for="layoutNumber2">Layout 2</label> <br /> <input type="radio" name="layout" id="layoutNumber3" value="layout3" checked="checked" /> <label for="layoutNumber3">Layout 3</label> <br /> <input type="radio" name="layout" id="layoutNumber4" value="layout4" /> <label for="layoutNumber4">Layout 4</label> </fieldset> <fieldset> <input type="radio" name="pageNums" id="layoutPageNums" value="pageNums" /> <label for="layoutPageNums">Page Numbers</label> <br /> <input type="radio" name="pageNums" id="layoutNoPageNums" value="" checked="checked" /> <label for="layoutNoPageNums">No page numbers</label> <br /> </fieldset> <div class="submitsAndHiddens"> <input type="submit" value="Submit" /> </div> </form> Code (markup): The advantages of properly using labels is many -- for example it gives people a larger area to click on to hit the radio buttons since you can click on the label too! Then, since you seemed to be sending to PHP, just make a PHP file to handle which content to send -- either via a redirect, or 'include'. If going for include (simpler of the two) I'd send it via GET instead of POST so that people can hotlink to the results. For example: <?php /* safeName function strips out characters that could be used to hack the results. Use only 'word' characters in your 'value' attributes in the markup! */ function safeName($name) { return preg_replace('/[^\w]/','',$name); } // safeName function formError($description) { echo ' <h1>Form Error</h1> <p>',$description,'</p>'; } if ( isset($_GET['aspect']) && isset($_GET['layout']) && isset($_GET['pageNums']) ) { $result = array(); if (!empty($_GET['aspect'])) $result[]=safeName($_GET['aspect']); if (!empty($_GET['layout'])) $result[]=safeName($_GET['layout']); if (!empty($_GET['pageNums'])) $result[]=safeName($_GET['pageNums']); if (empty($result)) { formError(' All form elements had empty values, unable to create a valid include filename! '); echo '<h1>Form Error</h1> } else include(implode('_',$result).'.php'); } else formError(' Some of the radio buttons were not selected -- which should be impossible! Hacking attempt perhaps? '); ?> Code (markup): The default "checked" from that form for example would try to run/include "landscape_layout3.php" using this code... if you left the first two as is and added "Page Numbers" it would try to include "landscape_layout3_pageNums.php" By making your values meaningful and your filenames meaningful, you can use a lot less logic in figuring out what file to show/run. I'd also suggest having a list of valid values in the PHP to make sure a hacker doesn't try to BS the PHP handler. Make it work without scripting FIRST. THEN you can add scripting if desired. If I were to add scripting (I wouldn't) it would probably be something like this: document.getElementById('layoutSelector').onsubmit = function(e) { e = e || window.event; var target = e.target || e.srcElement, inputList = target.getElementsByTagName('input'), result = new Array(); for (var t=0; t<inputList.length; t++) { if ( (inputList[t].type == 'radio') && (inputList[t].checked) && (inputList[t].value.length > 0) ) result.push(inputList[t].value); } target.action=result.join('_')+'.php'; } // method #layoutSelector.onsubmit Code (markup): let the script attach itself instead of using onsubmit in the markup, let the script determine what element triggered the event (the e=e||window.event and target=e.target||e.srcElement is for simple cross browser support), iterate through all it's input checking if they are radio buttons -- if they are and are checked and have a value, put that value on an array, then implode the array with underscores just like the PHP would. Functionally identical to the PHP, skips the extra code server side, though I'm really not sure it's even worth the effort of bloating out what's sent to your visitors. Hope all this helps, I know it's a lot to go through. -- edit -- oh, some simple CSS to make that form 'purty'. /* null margins and padding to give good cross-browser baseline */ html,body,address,blockquote,div, form,fieldset,caption, h1,h2,h3,h4,h5,h6, hr,ul,li,ol,ul,dl,dd,dt, table,tr,td,th,p,img { margin:0; padding:0; } img,fieldset { border:none; } #layoutSelector { max-width:12em; padding:1em; } #layoutSelector fieldset { padding:1em; border-bottom:2px solid #000; } #layoutSelector .submitsAndHiddens { padding:1em; } Code (markup): Included the reset I use with that just for consistency.
Oh, and to make the PHP version be a redirect instead of an include, just swap this line: } else include(implode('_',$result).'.php'); Code (markup): For this: } else header('Location: '.implode('_',$result).'.php'); Code (markup):
Hi Deathshadow, Thank you VERY much for your help. You have really put a lot of effort into your answer. Tis most appreciated. I'm on holiday just now so won't be able to put your suggestion into practice for a week or so. Do I take it that the php you have written is layoutselector.php? Sorry I'm a bit of a dunce when it comes to php as well! Thanks again, Rwthwyn
That's the general idea. We all start somewhere. We are all born in ignorance, only through the struggle of learning can one gain wisdom.
Thumbs up man for your elaborate code. What really caught my interest here was your php redirect code, cause i've been using javascript ever since. I would like to know if the location used within the header should be internal or external to your server or can be both. Would have tested it my self, but am on a mobile device presently. Thanks Example: //internal header('Location: section/page1.php'); //external header('Location: http://www.google.com'); Code (markup):
Hi Deathshadow, Right, back from holiday now and have had a chance to test the code you submitted. Unfortunately, I couldn't get the php to work. However, the html worked a treat, and submitting to another forum, I was able to get help with the php. Somebody suggested the following and it works perfectly. Just thought you'd like to know, so here goes: <?php die(header('Location: http://piciscanshop.co.uk/'. $_GET['aspect'] .'-'. $_GET['layout'] .'-'. $_GET['pageNums'] .'-photobook')); ?> Code (markup): Thanks VERY much for your help. You put me on the right track!
I would NOT be blindly and stupidly plugging in $_GET with no processing. on a redirect that's dangerous/stupid. Could you elaborate on 'couldn't get it to work'? I'll set up a local test case and see if I can figure out what's wonky with it, then toss a .rar of a working version up on my server.
Duh, I see the problem: echo '<h1>Form Error</h1> right before the include, that line shouldn't be there. Would also help if the form was set to GET and not POST.... or the script was set to use $_POST and not $_GET <?php /* safeName function strips out characters that could be used to hack the results. Use only 'word' characters in your 'value' attributes in the markup! */ function safeName($name) { return preg_replace('/[^\w]/','',$name); } // safeName function formError($description) { echo ' <h1>Form Error</h1> <p>',$description,'</p>'; } if ( isset($_POST['aspect']) && isset($_POST['layout']) && isset($_POST['pageNums']) ) { $result = array(); if (!empty($_POST['aspect'])) $result[]=safeName($_POST['aspect']); if (!empty($_POST['layout'])) $result[]=safeName($_POST['layout']); if (!empty($_POST['pageNums'])) $result[]=safeName($_POST['pageNums']); if (empty($result)) { formError(' All form elements had empty values, unable to create a valid include filename! '); } else header('Location: '.implode('_',$result).'.php'); } else formError(' Some of the radio buttons were not selected -- which should be impossible! Hacking attempt perhaps? '); ?> Code (markup): That's a working copy using redirect. There's a copy live here showing it working: http://www.cutcodedown.com/for_others/Rwthwyn/template.html and a .rar of the complete working demo http://www.cutcodedown.com/for_others/Rwthwyn/layoutSelect.rar Hope this helps.
Hi Deathshadow, Thanks for your renewed answer. I'm probably going to make use of it, as it allows the user the possibility of confirming their selection before clicking a link to take them through to the shop website. Looking back, it seems I wasn't clear to start with about what I was after: I have a website, piciscan.co.uk, wherein my business' services are advertised and a separate shop website, piciscanshop.co.uk, through which customers make their orders. And, I was looking for a script that would take the user from one to the other, based on the selections made in the order form. The redirect solution from the other forum solves that. BUT, I do think your solution may provide the better solution as it gives me the possibility of providing the customer with a more obvious point at which they can press the browser back button and change their mind before proceeding with their order: It would be very easy to, for example, modify landscape_layout3.php to show the customer what they had selected, with an order now button below the picture and text.