Link to home
Create AccountLog in
Avatar of Robert Granlund
Robert GranlundFlag for United States of America

asked on

PHP and jQuery

I have a form that when submitted, if it is successful I want to show a certain div and hide another div.  It works on success but then reverts back to the original once the page resets.  I'm not sure how to do this.  Where I am trying to implement the jQuery is on line: 43 - 51

 <?php
                if (isset($_POST['submitted'])) { // Handle the form.
                    // Trim all the incoming data:
                    $trimmed = array_map('trim', $_POST);


                    $errors = array(); // Initialize an error array.
                    // Check for a first name:
                    if (preg_match('/^[A-Z \'.-]{2,20}$/i', $trimmed['full_name'])) {
                        $fn = mysqli_real_escape_string($dbc, $trimmed['full_name']);
                    } else {
                        $errors[] = 'You forgot to enter your name.';
                    }

                    // Check for an email address:
                    if (preg_match('/^[\w.-]+@[\w.-]+\.[A-Za-z]{2,6}$/', $trimmed['email'])) {
                        $e = mysqli_real_escape_string($dbc, $trimmed['email']);
                    } else {
                        $errors[] = 'You forgot to enter a valid email address.';
                    }



                    if (empty($errors)) {
                        // Make sure the email address is available:
                        $q = "SELECT user_id FROM jmc_cal_users WHERE email='$e'";
                        $r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));

                        if (mysqli_num_rows($r) == 0) { // Available.
                            // Create the activation code:
                            $a = md5(uniqid(rand(), true));

                            // Add the user to the database:
                            $q = "INSERT INTO jmc_cal_users (email, full_name, active, registration_date) VALUES ('$e', '$fn', '$a', NOW() )";
                            $r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));

                            if (mysqli_affected_rows($dbc) == 1) { // If it ran OK.
                                // Send the email:
                                $body = "Thank you for registering your email  please click on this link:\n\n";
                                $body .= BASE_URL . 'activate.php?x=' . urlencode($e) . "&y=$a";
                                mail($trimmed['email'], 'Email Confirmation', $body, 'From: admin@sitename.com');
                                ?>
                                <script>
                                    $(function () {
                                        $("#calc_submit").click(function () {

                                            $(".submit-cont").hide("slow");
                                            $(".calculator-statement").show("slow");
                                        });
                                    });
                                </script>
                                <?php
                                
                            } else { // If it did not run OK.
                                echo '<p class="error">Your email could not be registered due to a system error. We apologize for any inconvenience.</p>';
                            }
                        } else { // The email address is not available.
                            echo '<p class="error">That email address has already been registered.</p>';
                        }
                    } else { // Report the errors.
                        echo '<h1>Error!</h1>
		<p class="error">The following error(s) occurred:<br />';
                        foreach ($errors as $msg) { // Print each error.
                            echo " - $msg<br />\n";
                        }
                        echo '</p><p>Please try again.</p><p><br /></p>';
                    } // End of if (empty($errors)) IF.
                    mysqli_close($dbc);
                } // End of the main Submit conditional.
                ?>


<html>
 <form action="?" method="post">
                    <div class="calculator-submit">
                        <p>
                            <input type="text" name="full_name" size="25" maxlength="120" value="<?php if (isset($trimmed['full_name'])) echo $trimmed['full_name']; ?>" placeholder="Name"/>
                            <br />
                            <input type="email" name="email" size="25" maxlength="65" value="<?php if (isset($trimmed['email'])) echo $trimmed['email']; ?>" placeholder="Email"/>
                        </p>
                        <p>

                        </p>
                    </div>
                    <div class="submit-cont">
                        <input type="submit" name="submit" id="calc_submit" value="Submit" />
                        <input type="hidden" name="submitted" value="TRUE" />
                    </div>
                </form>
                <div>

                    <!--  END Calculator Submit Form  -->

                    <div class="calculator-statement" style="display:none;">
                        <h2>Check your email</h2><br />
                    </div>

</html>

Open in new window

Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

reverts back to the original once the page resets
Pages don't "reset" but there must be another word that captures what you're going for.  Do you mean "after the client reloads the page?"  Or am I missing the point here?

Maybe the best design would be one that has both divs in the HTML.  The jQuery script could have a success function that changes the visibility.  So rather than sending some JavaScript after the PHP action script has taken control of the process, you could send just a signal from the PHP action script, and the jQuery success function could change the visibility of the divs based on the information gotten from the server-side script.  Just a thought.
Avatar of Robert Granlund

ASKER

How would I send a "signal" to the jQuery upon success?
jQuery has HTTP request methods that invoke success or failure functions.  But that aside, it might be simpler to just work with the server-side response, as shown in this article.
https://www.experts-exchange.com/articles/10712/The-Hello-World-Exercise-with-jQuery-and-PHP.html

Your jQuery code could look for information in the AJAX response and decide what to do.  A good response format is JSON because it's a nearly universal language in information processing today.
Avatar of Rob
This is typically what you use ajax for.  So instead of submitting the page the traditional way, you submit behind the scenes asynchronously.

This is untested but demonstrates the use of ajax:

 <?php
                if (isset($_POST['submitted'])) { // Handle the form.
                    // Trim all the incoming data:
                    $trimmed = array_map('trim', $_POST);


                    $errors = array(); // Initialize an error array.
                    // Check for a first name:
                    if (preg_match('/^[A-Z \'.-]{2,20}$/i', $trimmed['full_name'])) {
                        $fn = mysqli_real_escape_string($dbc, $trimmed['full_name']);
                    } else {
                        $errors[] = 'You forgot to enter your name.';
                    }

                    // Check for an email address:
                    if (preg_match('/^[\w.-]+@[\w.-]+\.[A-Za-z]{2,6}$/', $trimmed['email'])) {
                        $e = mysqli_real_escape_string($dbc, $trimmed['email']);
                    } else {
                        $errors[] = 'You forgot to enter a valid email address.';
                    }



                    if (empty($errors)) {
                        // Make sure the email address is available:
                        $q = "SELECT user_id FROM jmc_cal_users WHERE email='$e'";
                        $r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));

                        if (mysqli_num_rows($r) == 0) { // Available.
                            // Create the activation code:
                            $a = md5(uniqid(rand(), true));

                            // Add the user to the database:
                            $q = "INSERT INTO jmc_cal_users (email, full_name, active, registration_date) VALUES ('$e', '$fn', '$a', NOW() )";
                            $r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));

                            if (mysqli_affected_rows($dbc) == 1) { // If it ran OK.
                                // Send the email:
                                $body = "Thank you for registering your email  please click on this link:\n\n";
                                $body .= BASE_URL . 'activate.php?x=' . urlencode($e) . "&y=$a";
                                mail($trimmed['email'], 'Email Confirmation', $body, 'From: admin@sitename.com')                                
                            } else { // If it did not run OK.
                                $errors[] = 'Your email could not be registered due to a system error. We apologize for any inconvenience.';
                            }
                        } else { // The email address is not available.
                            $errors[]= 'That email address has already been registered.';
                        }
                    } else { // Report the errors.
                        echo json_encode($errors);
                    } // End of if (empty($errors)) IF.
                    mysqli_close($dbc);
                } // End of the main Submit conditional.
                ?>


<html>
<body>
 <form action="?" method="post" id="calc" on>
                    <div class="calculator-submit">
                        <p>
                            <input type="text" name="full_name" size="25" maxlength="120" value="<?php if (isset($trimmed['full_name'])) echo $trimmed['full_name']; ?>" placeholder="Name"/>
                            <br />
                            <input type="email" name="email" size="25" maxlength="65" value="<?php if (isset($trimmed['email'])) echo $trimmed['email']; ?>" placeholder="Email"/>
                        </p>
                        <p>

                        </p>
                    </div>
                    <div class="submit-cont">
                        <input type="submit" name="submit" id="calc_submit" value="Submit" />
                        <input type="hidden" name="submitted" value="TRUE" />
                    </div>
                </form>
                <div>

                    <!--  END Calculator Submit Form  -->

                    <div class="calculator-statement" style="display:none;">
                        <h2>Check your email</h2><br />
                    </div>
                                <script>
                                    $(function () {
                                    	$("#calc").on('submit', function(e) {
                                    		e.preventDefault();
                                    	});
                                        $("#calc_submit").click(function () {
											$.ajax({
												url: '',
												data: $("#calc").serialize(),
												method: 'post',
												success: function(d) {
													// d will hold the json representation of $errors
													if (d.length) {
													    // there are errors
														console.dir(d);// output to he console to see what they are
													}
													else {
														// success!
														$(".submit-cont").hide("slow");
														$(".calculator-statement").show("slow");
													}
												}
											});
                                        });
                                    });
                                </script>
</body>
</html>

Open in new window

Ray, sorry I hadn't seen your post when I submitted mine.  AJAX definitely the way to go here :)
@rob, thanks for this example.  This is the way to go.  Thanks to you and Ray.  Two final questions from the example you sent,
1.  how do I get the error messages to do a for each?
2. The error message returned is in brackets.  How do I remove them?  It looks like this when returned:
["You forgot to enter your name.","You forgot to enter a valid email address."]
 $("#calc_submit").click(function () {
                                $.ajax({
                                    url: 'http://jaymillerconsulting.com/ltv_email_ajax.php',
                                    data: $("#calc").serialize(),
                                    method: 'post',
                                    success: function (d) {
                                        // d will hold the json representation of $errors
                                        if (d.length) {
                                            // there are errors

                                            $( "div.errors").html(function() {
  var errormessage = d;
  return errormessage;
});
                                        } else {
                                            // success!
                                            $(".submit-cont").hide("slow");
                                            $(".calculator-statement").show("slow");
                                        }
                                    }

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Note that AJAX is never needed.  It's purely for improving the user experience (by not reloading the page) as you could always post all the data to the server and recreate the page.

I'm inclined to agree with Slick on this after chewing on it for a bit if I'm correct in saying that the "state" of your page can be recreated easily from the PHP.  By "state", I mean the logic behind why you are showing a form and what the user can or should do next and also the way the page looks because of the previous user interactions.

AJAX is useful when you want to stay on the same page and retain the visual state of that page (e.g. scroll position).  This can get quite complex to do via PHP when you have a lot going on in your front end.   This forms part of the methodology of Model, Views and Controllers.  Separating your elements makes for easier coding, readability, SEO and performance.

With the example of a simple contact form, the user is only going to fill it out once and submit so it doesn't really make sense to use AJAX in that case.

On the other hand, take this question thread, if it didn't use AJAX and the page refreshed it wouldn't retain the simple scroll position (state) and you'd have to navigate back to where you were when you posted the comment; not a good user experience.

Another example is filling out a form and halfway through due to the user selecting say a category, you need to show them the contents of that category (from your database) then using AJAX will not affect the selections they've already made on the page.  The flipside is refreshing the page gives you the opportunity to save the selections they've already made in their session.

There's a lot to consider and I would think about how important it is to separate the way your front end works from your backend.  Too much front end control from PHP (controlling classes or showing/hiding elements) IMO isn't going to do you any favours.

Side note: Remember that all validation needs to happen in your PHP.  Some basic parsing can happen in JavaScript but the validation MUST happen server side.
As for getting the errors, they're all in a simple array so assuming you have an element you want to show the errors:

success: function(d) {
	// d will hold the json representation of $errors
	if (d.length) {
		// there are errors
		for (err in d) {
			$("#errors").append("<p class='error'>"+err+"</p>");
		}
	}
	else {
		// success!
		$(".submit-cont").hide("slow");
		$(".calculator-statement").show("slow");
	}
}

Open in new window

2. The error message returned is in brackets.  How do I remove them?  It looks like this when returned:
["You forgot to enter your name.","You forgot to enter a valid email address."]

This looks like a JSON return - you can simply add the

dataType: "JSON"

To your AJAX request and the return in your success - should then be a javascript array.

In other words
$("#calc_submit").click(function () {
  $.ajax({
    url: 'http://jaymillerconsulting.com/ltv_email_ajax.php',
    data: $("#calc").serialize(),
    method: 'post',
    dataType: 'JSON', /ADD THIS
    success: function (d) {
      // d will hold the json representation of $errors
      if (d.length) {
        // there are errors
        $.each(d, function(index, item) {
          // DO SOMETHING WITH ERROR MESSAGE HERE
        });
      } else {
        // success!
        $(".submit-cont").hide("slow");
        $(".calculator-statement").show("slow");
      }
    }
  });
});

Open in new window

Also take a look at the docs for JQuery .ajax . The success call back is being deprecated in favour of then
Yeah it was only showing brackets because I had you outputting it to the console. JQuery's Ajax function will automatically recognise the returned data as json so it's not needed but probably good practice as an error is thrown if json format isn't returned.  The way I had it, a string, xml etc could be returned and it wouldn't throw an error. Not something you want, I suspect.
@rgranlund    ? ? , you still here?

In my view, It takes time and effort to learn to Correctly use any server-browser Exchange as AJAX processes, especially for someone that is not familiar with using JavaScript and-or Jquery, it is not easy to understand, even if you just copy and paste code as you did here, and hope that the code works for you.