Reputation: 1
Ok so I have a script that layers data throughout the process (an online test, data is kept for up to 50 questions). I have recently found that my Ajax and jquery code is not stopping all users from getting a secondary page that is meant to be reloaded in place of a DIV currently on the page. All information is passed through the jquery and ajax and works great, but sometimes on a users very first visit and first question it loads the page that is just meant to replace the DIV information currently and is not meant to be visible.
Here is my Ajax & jquery code:
<script>
$("#quizForm").submit(function(event){
event.preventDefault(); //prevent default action
var post_url = $(this).attr("action"); //get form action url
var form_data = $(this).serialize(); //Encode form elements for submission
$.post( post_url, form_data, function( response ) {
$("#prntqst").html( response );
dataLayer.push({"event" : "formSubmitted", "formName" : "'.$this->quizID.'"});
});
});
</script>
Here is the HTML:
<div id="prntqst"> <!-- this is DIV set to be reloaded -->
<font class="prntqst-text">Question Goes Here</font>
<form id="quizForm" action="ajax.php" method="post"> <!-- Script setup to handle submitted data -->
<input type="hidden" id="next_question" name="next_question" value="2">
<input type="hidden" id="quiz_type" name="quiz_type" value="learning">
<input type="hidden" id="quiz_name" name="quiz_name" value="knowledge-1">
<label class="container" for="a">Ans A
<input type="radio" name="answers[1]" id="a" value="a">
<span class="checkmark"></span>
</label>
<label class="container" for="b">Ans B
<input type="radio" name="answers[1]" id="b" value="b">
<span class="checkmark"></span>
</label>
<label class="container" for="c">Ans C
<input type="radio" name="answers[1]" id="c" value="c">
<span class="checkmark"></span>
</label>
<div class="subbtn_contain">
<div class="submitbtn">
<input id="submit" type="submit" class="button" value="Next Question">
</div>
</div></div>
</form>
<!-- currently this is the location of Ajax and jquery script -->
<div>
So when the form is submitted it processes the data through the ajax.php page, and then page reloads the next question into the "prntqst" DIV, after the first page load every request is sent to the ajax.php location, and all subsequent reloads carry all of the data needed for the test to work properly. However I find that if I use a new computer, or clear the cache the very first request can sometimes result in the user be pushed to the location of the ajax.php instead of them staying at the current URL with a DIV reload.
I have verified this issue through my analytics account, 99% of the time a user still shows at the correct URL as if the ajax is properly reloading the DIV, however sometimes it does show a user directly at the ajax.php script.
Any ideas or comments would be appreciated,
Thanks again!
Upvotes: 0
Views: 86
Reputation: 33933
Okay, I see now.
If you can have "some garbage" inside a code block and, as you say
works with or without that line...
That's because that code block is not even running at all.
The processData: false
is a value assignation to an object property. It is ouside any object, in the code you provided. Then it seems like you tried to comment it like this: <!-- removed from code processData: false; -->
, which also should throw an error. That is the HTML way to comment lines. in JS, it would be // removed from code processData: false;
.
So... It seems that the form submits anyway. That just can the the "normal" form submit where the whole page reloads. As a test. Please try your page with that script completely removed. You should see no difference.
There is something else to explain here. You are playing with "dynamic" elements. Those are elements that didn't exist on page load and were added after... Or element that were there and were removed/replaced.
You have to write the script in such that this situation is handled.
In $("#quizForm").submit(function(event){
an event handler is attached to the element #quizForm
. If there is no such element in the page when the page first load... Or there is a parsing error... The function won't run. So the event.preventDefault()
won't be called either.
Then, assuming you fixed all errors in that code block and it runs. It squarely replaces all the HTML inside #prntqst
. So for the second submit, the element on which the event handler was attached is not there anymore and the function won't run again.
The solution for that is to use event delegation to attach the event handler to the document
and "delegate" it to the #quizForm
(if exist when the handler is called).
That is $(document).on("event", "delegated_element_selector", function(){
So when the "event" fires within the "document", a lookup is made to find the "delegated_element_selector" and if found, the handler is executed.
That way is the way to have some event handler for the dynamic elements in a page.
Additionnally, about your question where to place the code, I added a $(document).ready()
handler, which ensures the initial page load is complete before trying any jQuery lookup on some elements. So you can place that script where you want.
$(document).ready(function () {
$(document).on("submit", "#quizForm", function (event) {
console.log("Custom submit")
event.preventDefault(); //prevent default action
var post_url = $(this).attr("action"); //get form action url
var form_data = $(this).serialize(); //Encode form elements for submission
$.post(post_url, form_data, function (response) {
console.log(response)
$("#prntqst").html(response);
dataLayer.push({ event: "formSubmitted", formName: "'.$this->quizID.'" });
});
});
});
Now you should see "Custom submit" in the console on each form submit. And you should see what is the response too.
About post_url
, I didn't any action
attribute to the <form>
... Maybe you just did not post it here on SO. Make sure there is one. Also make sure that the response
$.post()
should receive only is the necessary HTML and not a whole page (with <head>
, <body>
, etc...).
Upvotes: 1