1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Using JavaScript to conditionally submit a form

Discussion in 'JavaScript' started by Rwthwyn, Apr 3, 2013.

  1. #1
    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
     
    Solved! View solution.
    Rwthwyn, Apr 3, 2013 IP
  2. #2
    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.
     
    deathshadow, Apr 5, 2013 IP
  3. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #3
    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):
     
    deathshadow, Apr 5, 2013 IP
  4. Rwthwyn

    Rwthwyn Greenhorn

    Messages:
    4
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    11
    #4
    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
     
    Rwthwyn, Apr 6, 2013 IP
  5. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #5
    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.
     
    Last edited: Apr 6, 2013
    deathshadow, Apr 6, 2013 IP
  6. udores

    udores Member

    Messages:
    25
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    38
    #6
    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):
     
    udores, Apr 17, 2013 IP
  7. Rwthwyn

    Rwthwyn Greenhorn

    Messages:
    4
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    11
    #7
    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!
     
    Rwthwyn, Apr 26, 2013 IP
  8. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #8
    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.
     
    Last edited: Apr 26, 2013
    deathshadow, Apr 26, 2013 IP
  9. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #9
    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.
     
    deathshadow, Apr 26, 2013 IP
  10. Rwthwyn

    Rwthwyn Greenhorn

    Messages:
    4
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    11
    #10
    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.
     
    Rwthwyn, Apr 27, 2013 IP