0

In the code below I have two types of validation. I use a javascript validaton which displays the error message for when the user does not enter in anything in the course text input.

Then I have a php validation where that if it does not contain a row for the result from the query which checks to see if there are any assessments within the course the user has typed in the course text input, then it displays a message stating that no assessments are found.

The problem I am having though is that if the user does not enter in anything in the "Course" text input and they click on the submit button, it displays both the javascript validation and the php validation.

This is incorrect, what should happen is that :

  • if the user has not written anything in the course text input, then it should simply show only the javascript validation and NOT the php validation.

    • if the user has written something in the course text input and submits the form, but it then cannot find any results from the query, then it should display the php validation ONLY.

My question is what do I need to change in the code in order to be able to not show both validation messages at the same time and show only the correct validation messages when they should be shown?

In other words how do I stop the form from submitting if the javascript validation fails? And then obviously how do I make sure that if the javascript validation succeeds, then it does submit the form.

Javascript

function validation() {

    var isDataValid = true;

    var courseTextO = document.getElementById("coursesDrop");

    var errModuleMsgO = document.getElementById("moduleAlert");

    if (courseTextO.value == "") {
        $('#targetdiv').hide();
        $('#assessmentForm').hide();
        $('#updateForm').hide();
        $('#submitupdatebtn').hide();
        errModuleMsgO.innerHTML = "Please Select a Course";
        isDataValid = false;
    } else {
        errModuleMsgO.innerHTML = "";
    }
    return isDataValid;

}​

PHP/HTML

<?php

// connect to the database
include('connect.php');


/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    die();
}


$sql = "SELECT CourseId, CourseNo, CourseName FROM Course ORDER BY CourseId"; 

$sqlstmt=$mysqli->prepare($sql);

$sqlstmt->execute(); 

$sqlstmt->bind_result($dbCourseId, $dbCourseNo, $dbCourseName);

$courses = array(); // easier if you don't use generic names for data 

$courseHTML = "";  
$courseHTML .= '<input type="text" name="courses" id="coursesDrop" />' . PHP_EOL; 

?>

<form action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post" onsubmit="return validation();">
    <table>
        <tr>
            <th>Course: <?php echo $courseHTML; ?></th>
        </tr>
    </table>
    <p>
        <input id="moduleSubmit" type="submit" value="Submit Course and Module" name="moduleSubmit" />
    </p>
    <div id="moduleAlert"></div>
    <div id="targetdiv"></div>
</form>


<?php

if (isset($_POST['moduleSubmit'])) {    

    $sessionquery = "
    SELECT SessionId, SessionName, SessionDate, SessionTime, CourseId, SessionActive
    FROM Session
    WHERE (CourseId = ? AND SessionActive = ?)
    ORDER BY SessionName 
    ";

    $active = 1;

    $sessionqrystmt=$mysqli->prepare($sessionquery);
    // You only need to call bind_param once
    $sessionqrystmt->bind_param("si",$course, $active);
    // get result and assign variables (prefix with db)

    $sessionqrystmt->execute(); 

    $sessionqrystmt->bind_result($dbSessionId,$dbSessionName,$dbSessionDate,$dbSessionTime, $dbCourseId, $dbSessionActive);

    $sessionqrystmt->store_result();

    $sessionnum = $sessionqrystmt->num_rows();   

    if($sessionnum == 0) {
        echo "<p><span style='color: red'>Sorry, You have No Assessments under this Module</span></p>";
    } 
    else 
    { 
        echo "";
    }

    ...

}
?>
Cups
  • 6,901
  • 3
  • 26
  • 30
user1830984
  • 859
  • 3
  • 14
  • 26
  • Always assume the data isn't valid (`var isDataValid = false;`), then, if it passes all tests, set it to true. Can you check if the form still submits if you `return false;` from the `validation()` function? – Cerbrus Nov 28 '12 at 15:13
  • 1
    Your code appears to be correct. Take a look at this example: http://codepen.io/anon/pen/GpmjH. It appears to be working properly. Check your error console and see if you are getting a javascript error or something. – Travesty3 Nov 28 '12 at 15:21
  • @Travesty3 that makes sense. If there is a bug somewhere ELSE, in some unrelated function (i.e. jQuery lib related), then the JS won't fire properly but the FORM action still will. – Joshua Nov 28 '12 at 15:25
  • @Joshua I know it isn't a bug in jquery library – user1830984 Nov 28 '12 at 15:31
  • @Travesty3 Sorry I deleted my last comment because I am just losing it haha :) – user1830984 Nov 28 '12 at 15:42

4 Answers4

2

Try stopping the submit event thoroughly (you're suffering from jQuery-itis, causing you to abuse return false):

method="post" onsubmit="return validation(event);">

And in JS:

function validation(e)
{
    //your checks
    if (isDataValid === false)
    {
        if (e.preventDefault)
        {
            e.preventDefault();
            e.stopPropagation();//VERY important
        }
        e.returnValue = false;
        e.cancelBubble = true;
    }
    return isDataValid;
}

To find out what both methods do, have a look at what MDN has to say
To find out what you're stopping when calling stopPropagation (or setting cancelBubble to true) I'd recommend quirksmode: events order very easy to follow, reasonably comprehensive description, and, in case you need it: their introduction to JS events, too.

Update
In response to your comments:

<?php

// connect to the database
include('connect.php');


/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    die();
}


$sql = "SELECT CourseId, CourseNo, CourseName FROM Course ORDER BY CourseId"; 

$sqlstmt=$mysqli->prepare($sql);

$sqlstmt->execute(); 

$sqlstmt->bind_result($dbCourseId, $dbCourseNo, $dbCourseName);

$courses = array(); // easier if you don't use generic names for data 

$courseHTML = "";  
$courseHTML .= '<input type="text" name="courses" id="coursesDrop" />' . PHP_EOL; 
$pHTML = '&nbsp;';//default paragraph inner
if (isset($_POST['moduleSubmit'])) {    
        $sessionquery = "
    SELECT SessionId, SessionName, SessionDate, SessionTime, CourseId, SessionActive
    FROM Session
    WHERE (CourseId = ? AND SessionActive = ?)
    ORDER BY SessionName 
    ";
    $active = 1;
    $sessionqrystmt=$mysqli->prepare($sessionquery);
    // You only need to call bind_param once
    $sessionqrystmt->bind_param("si",$course, $active);
    // get result and assign variables (prefix with db)
    $sessionqrystmt->execute(); 
    $sessionqrystmt->bind_result($dbSessionId,$dbSessionName,$dbSessionDate,$dbSessionTime, $dbCourseId, $dbSessionActive);

    $sessionqrystmt->store_result();

    $sessionnum = $sessionqrystmt->num_rows();   

    if($sessionnum == 0) {//error msg?
        $pHTML =  "<span style='color: red'>Sorry, You have No Assessments under this Module</span>";
    } 
}

?>
    <p id="warnings"><?php echo $pHTML;?></p><!-- echo the innerHTML created server-side -->
<form id="myForm" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post" onsubmit="return validation(event);">
    <table>
        <tr>
            <th>Course: <?php echo $courseHTML; ?></th>
        </tr>
    </table>
    <p>
        <input id="moduleSubmit" type="submit" value="Submit Course and Module" name="moduleSubmit" />
    </p>
    <div id="moduleAlert"></div>
    <div id="targetdiv"></div>
</form>

Tweaked JS - since you're using jQuery, I'll use that as delegating a change event in IE is a pain:

$('#myForm').delegate('change','select',function()
{
    $('#warnings').html('');//clears current warnings
});

Or, a more efficient but somewhat more complex take:

$('#myForm').delegate('change','select',(function(warnings)
{
    return function()
    {
        warnings.html('');
    };
}($('#warnings'))));

Don't forget to wrap this in a $(document).ready(function(){[here]});

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • Ok this has worked but just got one little issue. If I select a course and and module from drop down menu and submit, if that module does not contain any assessments, then it does the php validation which displays the message `Sorry, You have No Assessments under this Module`. This is fine. But if I then straight away do not select a Course from the drop down menu, it displays both the javascript message `Please Select a Course from the course drop down menu` BUT it also still displays the php message. It should remove that php message. – user1830984 Nov 28 '12 at 15:51
  • I have an app [here](http://helios.hud.ac.uk/u0867587/Mobile_app/editsessionadmin.php), on the app please select course `INFO101....` and Module `CHT2220....` then submit, you will see the php validation message in red, now the Course and Module drop down menu goes back to saying `Please Select` so straight away click on the same Submitbutton again, then you will see both validation messages appear in red, it should only display the javascript error message `Please select a Course and Module from the Drop down menus above` – user1830984 Nov 28 '12 at 15:53
  • @user1830984: change `echo "

    Sorry,...` to `echo "

    Sorry,..` and create an event listener that listens for a `change` event, the handler should look lik `function(e){ if (document.getElementById('invalid')){ document.getElementById('invalid').innerHTML = "";}};`, this clears the warning once an element is changed

    – Elias Van Ootegem Nov 28 '12 at 15:55
  • _OR_ you could have an element that's always on your page: `

     

    ` and have your JS submit handler set the innerHTML of that element, to display the warnings. And in your PHP, have the script either output ` ` if no $_POST vars were sent, or an error msg if the query failed
    – Elias Van Ootegem Nov 28 '12 at 15:57
1

I believe action and onsubmit will both fire, even if there is a return false in the onsubmit function. I suggest removing the action and moving the form POST to a Javascript function, to be called upon successful front end validation.

Joshua
  • 3,615
  • 1
  • 26
  • 32
  • Nope, returning false to the onsubmit event should stop the form from submitting. – Travesty3 Nov 28 '12 at 15:15
  • 1
    @Travesty3: Nope, only true if the handler is a jQuery function. To prevent the the submit `event.preventDefault(); event.stopPropagation()` in most browsers, `event.returnValue = false; event.cancelBubble = true;` in IE – Elias Van Ootegem Nov 28 '12 at 15:32
  • @EliasVanOotegem: What exactly is a jQuery function? How is it different than a javascript function? Take a look at my sample, it's pure javascript: http://codepen.io/anon/pen/GpmjH. It does exactly what the OP wants. I have used this technique for years in pure javascript, without the jQuery library included on the page. – Travesty3 Nov 28 '12 at 15:38
  • By jQuery function, I mean a callback function passed to a jQ event binding: `$('#foo').on('click',function jQFunction()`<-- return false here equals `preventDefault` + `stopPropagation`. The difference is that the callback is called in one of jQ's internal function objects. If the function returns `false`, the aforementioned methods are invoked on the event object for you. That's the difference [Check this blog/article](http://fuelyourcoding.com/jquery-events-stop-misusing-return-false/) for a full explanation of what I'm on about – Elias Van Ootegem Nov 28 '12 at 15:44
0

I think it is because you are missing .value

var courseTextO = document.getElementById("coursesDrop").value;
// add line of debug
alert(courseText0);
Cups
  • 6,901
  • 3
  • 26
  • 30
  • Further down he is referencing courseText0.value, in the `if` statement. – Joshua Nov 28 '12 at 15:15
  • 1
    Oh, yeah, scrub that then. But alert()ing some of the values out should figure out why the form is submitting when it shouldn't, that is the nub of the problem. – Cups Nov 28 '12 at 15:19
  • 1
    var isDataValid = true; I always set this type of flag var as false and then only alter it if the opposite is proven. When you read the code properly (well, unlike me in this case.. ) it seems to be true by default. It is offputting, just a personal thing. – Cups Nov 28 '12 at 15:22
  • @Cups Im trying to say that there is no validation error first but then when I submit, it will go through the validation() function to see if there are any errors, if so then display the error message associated with the error. If I change it to `var isDataValid = false;`, then what do I replace `return isDataValid` to and do I need to change the `onsubmit=" return validation();"` line? – user1830984 Nov 28 '12 at 15:35
0

It must return both, because your action is to call the php validation and you have also a onsubmit that calls the javascript validation.

What happens is, that your code executes at first the javascript and then the php.

The best way to solve your problem is setting no action at all in the from-tag and setting the action of the form in your javascript validation function depending on the outcome.

Sven Bieder
  • 5,515
  • 2
  • 21
  • 27
  • Returning `false` to the `onsubmit` event should stop the form from submitting. That's where the OP is having trouble. – Travesty3 Nov 28 '12 at 15:15
  • So do I need to change `onsubmit=" return validation();"` to `onsubmit="validation() return false;"`? or something like that? – user1830984 Nov 28 '12 at 15:36