I am trying to add a listener to a form so that when the user leaves it, an ajax call is made but nothing seems to be happening. Don't see any errors in firefox and nothing gets console logged when I leave the page which tells me the code is incorrect. Fairly new to jquery (and ajax), hoping someone can show me what I'm doing wrong here.
html: home/folder/index.php
<script>
var rowid = "<?php echo $_SESSION['rowid'] ?>";
var user = "<?php echo $_SESSION['user'] ?>";
</script>
...
<form id="update" method="post" action="index.php?update=1" autocomplete="off">
Jquery: home/scripts/main.js
var end_lock = 0;
$('#update').on('unload', function(){
end_lock = 1;
console.log('error');
});
window.onunload = callAjaxRecordLock;
function callAjaxRecordLock(){
if (end_lock === 1){
$.ajax({
url: 'home/includes/ajax.php',
type: 'POST',
data: {
method: 'ajax_record_lock',
rowid: rowid,
user: user,
endlock: 1
}
});
}
}
php: home/includes/ajax.php
<?php
if (isset($_POST['method'])) {
$_POST['method']();
}
function ajax_record_lock(){
$ajax_rowid = $_POST['rowid'];
$ajax_user = $_POST['user'];
$ajax_endlock = $_POST['endlock'];
if (isset($ajax_rowid) && isset($ajax_user) && isset($ajax_endlock)) {
sp_record_lock($ajax_rowid, $ajax_user, $ajax_endlock);
}
}
Edit:
Found this link https://api.jquery.com/category/events/form-events/ where it appears that beforeunload is not a valid event for a form element. Is there another way to achieve what I need?
You need to make the AJAX call synchronous. If it’s async, it will never execute because the website will, well, unload. With a synchronous request you lock the browser until its made:
async: false
However, I think it’s not a good thing to do. Don’t mess with default client behavior, it’s bad user experience.
Related
I am facing issue, i f i am using ajax call, the return false not working..
and form submitted sucessfully.. I want that when i get response 1 form don't submit.. but on ajax request response form still submitting please help me..
here is code:
<form action="<?php echo base_url(); ?>do/add/review" method="post" name="dologin" id="dologinsubmitreview" onSubmit="return showpopupbox();">
function showpopupbox(){
var strs = $("form").serialize();
var autocompleteURL = "<?php echo base_url(); ?>grahak/save_record_session?rnd=" + Math.random() +"&sessiondata="+ $("form").serialize();
$.ajax({
url : autocompleteURL,
async: false,
cache: false,
method : "POST",
success : function(respd)
{
if(respd == 1){
$("#classiconpopupbx").show();
return false;
}
else {
return true;
}
}
});
}
You need to redesign your flow. Javascript is asynchronous, which means that the form is submitted LONG before the AJAX call is complete.
Instead, use jQuery on to bind to the event, capture the event in the function, and run event.preventDefault() immediately which will stop the form from submitting. THEN run your AJAX call.
In your AJAX success function, you'll need to decide what to do when it comes back "truthy". Without knowing more about your desired outcome, it's impossible to advise how to handle that piece.
<!-- remove the inline onsubmit script handler -->
<form action="<?php echo base_url(); ?>do/add/review" method="post" name="dologin" id="dologinsubmitreview">
// no-conflict safe document ready
jQuery(function($) {
// Bind to the form submit here, and call event.preventDefault immediately
$('#dologinsubmitreview').on('submit', function(event) {
event.preventDefault();
showPopUpBox(event);
}
function showpopupbox() {
var strs = $("form").serialize();
var autocompleteURL = "<?php echo base_url(); ?>grahak/save_record_session?rnd=" + Math.random() +"&sessiondata="+ $("form").serialize();
$.ajax({
url : autocompleteURL,
async: false,
cache: false,
method : "POST",
success : function(respd) {
if(respd == 1){
$("#classiconpopupbx").show();
} else {
// Do what you need to do here if the AJAX is true
}
}
});
}
});
One way you can do this is to prevent the submit, always, then if your Ajax call returns true, post the form (and tell the code to allow it this time):
For starters, don't mix inline event handlers with jQuery. The jQuery way is better:
// Start by not allowing submit
var allowSubmit = false;
$('form').submit(function(){
var $form = $(this);
// Only run the ajax if this is not a "real" submit
if (!allowSubmit){
// do the ajax call
$.ajax({
url: ...
success: function(respd){
if(respd == 1){
$("#classiconpopupbx").show();
}
else {
allowSubmit = true;
$form[0].submit(); // important - bypass jQuery event handler
}
}
});
}
// Conditionally allow the form to submit
return allowSubmit;
});
I have a PHP quiz page which posts answer data on clicking the answer by a function called answer() via ajax then loads the question and answer contents if the answer is correct by loadQuestion() function also via ajax. Here is a part of my code:
<ul class="choices">
<li><span id="a0"><?php echo $questionDetail['a'.$answerOrder[0]]; ?></span></li>
<li><span id="a1"><?php echo $questionDetail['a'.$answerOrder[1]]; ?></span></li>
</ul>
<div id="countdown"><div class="saniyeLoading" style="display: none;"></div></div>
<ul>
<li><span id="a2"><?php echo $questionDetail['a'.$answerOrder[2]]; ?></span></li>
<li><span id="a3"><?php echo $questionDetail['a'.$answerOrder[3]]; ?></span></li>
</ul>
<script type="text/javascript">
function answer(elm){
countdown.stop();
var answer = $(elm).text();
$.ajax({
type: 'POST',
url: "/soru",
data: {act: 'soru', answer: answer},
success:function (data) {
if(data == "success"){
setTimeout(loadQuestion, 300);
} else {
location.href = "/yanlis";
}
}
});
}
function loadQuestion() {
$.ajax({
type: 'POST',
url: "/",
data: {act: 'ysoru'},
success: function (data) {
try {
data = $.parseJSON(data);
$("#questionDetailQuestion").text(data.questionDetail['question']);
$("#a0").text(data.questionDetail['a0']);
$("#a1").text(data.questionDetail['a1']);
$("#a2").text(data.questionDetail['a2']);
$("#a3").text(data.questionDetail['a3']);
$('.saniyeLoading').hide();
countdown.start();
} catch (e) {
}
}
});
}
</script>
My problem here is that people can manipulate the answer() function by writing a simple for loop in the browser developer console. Something like this:
for(i = 1 ; i <= 4; i ++ ) {
$.ajax({
type: 'POST',
url: "/soru",
data: {act: 'soru', answer: $('#a' + i).text()},
success:function (data) {
if(data == "success"){
loadQuestion();
}
}
});
}
I have found a temporary solution by removing onclick="answer(this);" and replacing answer() function with $('.choices a').click(). Then I'm validating if there is a click event in my PHP page by sending the event via my ajax page.
Would there be a better solution to this problem? I've tried tokens but the problem is as I'm loading questions via ajax, I will have to save the token in an hidden input etc, they can get also get the token and send it.
While there is no way you can stop user from using console to manipulate your code. I can suggest following:
You can put server side limit on number of Ajax requests accepted from single user.
Adding captcha code, if you see unusual activity
Obfuscate your code and AJAX call format, so it requires more effort from user to analyze code and will stop most of people
Use dynamically generated image with answers "radio buttons" located at random locations and submitting back x and y position of user click event and use server-side logic to match click position with answer option
Use sessions on the server-side to track each user's correct and incorrect guesses, and enforce the rules.
As long as you rely on the client side to "play nice", you're exposing your application to the will of the end user.
I am developing a website for practice, and I would like to know how to use JS to notify the user that the username he picked is already in use, all works fine, if my function(check_username) returns false, the user succesfully registers himself into the site, otherwise the register won't happen.
When the user can't register I would like to know how can I notify the user with a js script.
<?php
//database includes
include_once('../config/init.php');
include_once('../database/users.php');
if(!check_username($_POST['username'])) {
insertUser($_POST['name'], $_POST['username'], $_POST['email'], $_POST['pass']);
}
else header('Location: ../index.php');
?>
One way would be to change your redirect on failure to a javascript message
else
{
echo "<script>alert('Username already exists');</script>";
}
That's a very trivial example to get you started since you mentioned you're learning JS. You can build a lot of improvements on that.
You can set the returns into a javascript variable and use it to display message if the user is not registered.
var x = <?php echo check_username($_POST['username']); ?>;
if(x) {
alert("You are not registered");
}
You can use php ajax for a live notification to users.
<script>
$(document).ready(function() {
$("#InputFieldID").keyup(function (e) {
//removes spaces from username
$(this).val($(this).val().replace(/\s/g, ''));
//Getting value of input field.
var username = $(this).val();
//Check only if the username characters are above 4
if(username.length >= 4){
$("#IndicatorDivID").html('<p style="color:#ffbf25;">Checking..!</p>');
$.ajax({
type: 'POST',
url: 'check_username.php',
data: {"username": username},
dataType: 'json',
success: function (data) {
if(data.response=='true')
alert("Already Exist");
}
});
}
});
});
//Username Checker
</script>
The result fo check_username.php must be in json format.
eg: {"response":"false"}
Okay, so I am trying to use ajax. I've tried several ways of doing this but nothing is working for me. I believe the main problem I have is that ajax won't add to my database, the rest is managable for me.
Here is the relevant ajax-code:
$(document).ready(function(){
console.log($("going to attach submit to:","form[name='threadForm']"));
$("form[name='threadForm']").on("submit",function(e){
e.preventDefault();
var message = $("#message").val();
//assumming validate_post returns true of false(y)
if(!validatepost(message)){
console.log("invalid, do not post");
return;
}
console.log("submitting threadForm");
update_post(message);
});
});
function update_post(message){
var dataString = "message=" + message;
alert(dataString);
$.ajax({
url: 'post_process.php',
async: true,
data: dataString ,
type: 'post',
success: function() {
posts();
}
});
}
function posts(){
console.log("getting url:",sessionStorage.page);
$.get(sessionStorage.page,function(data){
$("#threads").html(data);
});
}
function validatepost(text){
$(document).ready(function(){
var y = $.trim(text);
if (y==null || y=="") {
alert("String is empty");
return false;
} else {
return true;
}
});
}
Here is the post_process.php:
<?php
// Contains sessionStart and the db-connection
require_once "include/bootstrap.php";
$message = $con->real_escape_string($_POST["message"]);
if (validateEmpty($message)){
send();
}
function send(){
global $con, $message;
$con->create_post($_SESSION['username'], $_SESSION['category'], $_SESSION("subject"), $message);
}
//header("Location: index.php");
?>
And lastly, here is the html-form:
<div id="post_div">
<form name="threadForm" method="POST" action="">
<label for="message">Meddelande</label><br>
<textarea id="message" name="message" id="message" maxlength="500">
</textarea><br>
<input type="submit" value="Skicka!" name="post_btn" id="post_btn"><br>
</form>
create_post is a function I've written, it and everything else worked fine until I introduced ajax.
As it is now, none of the console.log:S are getting reached.
Ajax works when jumping between pages on the website but the code above literally does nothing right now. And also, it works if I put post_process.php as the form action and don't comment out the header in post_process-php.
I apologize for forgetting some info. I am tired and just want this to work.
I would first test the update_post by removing the button.submit.onclick and making the form.onsubmit=return update_post. If that is successful place the validate_post in the update_post as a condition, if( !validate_post(this) ){ return false;}
If it's not successful then the problem is in the php.
You also call posts() to do what looks like what $.get would do. You could simply call $.get in the ajax return. I'm not clear what you are trying to accomplish in the "posts" function.
First you can just submit the form to PHP and see if PHP does what it's supposed to do. If so then try to submit using JavaScript:
$("form[name='threadForm']").on("submit",function(e){
e.preventDefault();
//assumming validate_post returns true of false(y)
if(!validate_post()){
console.log("invalid, do not post");
return;
}
console.log("submitting threadForm");
update_post();
});
Press F12 in Chrome or firefox with the firebug plugin installed and see if there are any errors. The POST should show in the console as well so you can inspect what's posted. Note that console.log causes an error in IE when you don't have the console opened (press F12 to open), you should remove the logs if you want to support IE.
Your function posts could use jQuery as well as it makes the code shorter:
function posts(){
console.log("getting url:",sessionStorage.page);
$.get(sessionStorage.page,function(data){
$("#threads").html(data);
});
}
UPDATE
Can you console log if the form is found when you attach the event listener to it?
console.log($("going to attach submit to:","form[name='threadForm']"));
$("form[name='threadForm']").on("submit",function(e){
....
Then set the action of the form to google.com or something to see if the form gets submitted (it should not if the code works). Then check out the console to see the xhr request and see if there are any errors in the request/responses.
Looking at your code it seems you got the post ajax request wrong.
function update_post(message){
console.log(message);
$.ajax({
url: 'post_process.php',
async: true,
//data could be a string but I guess it has to
// be a valid POST or GET string (escape message)
// easier to just let jQuery handle this one
data: {message:message} ,
type: 'post',
success: function() {
posts();
}
});
UPDATE
Something is wrong with your binding to the submit event. Here is an example how it can be done:
<!DOCTYPE html>
<html>
<head>
<script src="the jquery library"></script>
</head>
<body>
<form name="threadForm" method="POST" action="http://www.google.com">
<label for="message">Meddelande</label><br>
<textarea id="message" name="message" id="message" maxlength="500">
</textarea><br>
<input type="submit" value="Skicka!" name="post_btn" id="post_btn"><br>
</form>
<script>
$("form[name='threadForm']").on("submit",function(e){
e.preventDefault();
console.log("message is:",$("#message").val());
});
</script>
</body>
</html>
Even with message having 2 id properties (you should remove one) it works fine, the form is not submitted. Maybe your html is invalid or you are not attaching the event handler but looking at your updated question I think you got how to use document.ready wrong, in my example I don't need to use document.ready because the script accesses the form after the html is loaded, if the script was before the html code that defines the form you should use document ready.
What's the best way to trigger errors on elements for server-side validation errors that come back after the form passes the initial client-side validation?
$("#contact_form").validate({
submitHandler: function(form) {
$.ajax({
type: 'POST',
dataType: 'json',
url: '/contact/send',
data: $(form).serialize(),
success: function(response) {
if(response.error) { //server came back with validation issues
var fields = response.fields;
for(var i=0, var len = fields.length; i < len; i++) {
var field_name = fields[i].name;
var field_error = fields[i].error;
// TRIGGER ERROR ON AFFECTED ELEMENT
}
return false;
}
//everything went ok, so let's show a thanks message
showThanks();
}
}
});
I'm thinking something like:
$(form).find("[name='" + field_name + "']").triggerError(field_error);
But I didn't see any api methods for manually triggering errors in that manner.
I think I figured it out from the documentation of Validator/showErrors
var validator = $("#contact_form").validate();
validator.showErrors({"state": "Bad state."});
Make it. Write a plugin that will do whatever you want.
Or if you get to complicated, simply write a javascript function to do it and call that.
I would write a plugin that would create a div, fill it with the error text and animate it nicely.
On submit of the form, I would make the target of the form an invisible iframe on the page which would then call a function in the topWindow with it's result.
<iframe id="subject_frame" name="submit_frame" src="#" style="width:0;height:0;border:0px solid #fff;"></iframe>
then in the page in the iframe call a javascript method in the top window that either redirects on success or displays the errors.
In the iframe
<script language="javascript" type="text/javascript">
window.top.window.submitComplete("<?php echo $response; ?>");
</script>
In the top window (as an example)
function uploadComplete( result ){
$.unblockUI();
if(result == "OK"){
$.blockUI({ message: "<span style='color:green;'>File upload successful, request submitted.</span><br/><br/>Redirecting..." });
setTimeout(function() {
$.unblockUI({
onUnblock: function(){ window.location='thankyou.php'; }
});
}, 2000);
} else {
$.blockUI({ message: "<span style='color:red;'>Failed.</span><br/><br/>"+result });
$('.blockOverlay').attr('title','Click to remove').click($.unblockUI);
}
}