ajax callback display function closing too fast - javascript

I have a funcction in ajax callback that display a div with bootstrap alert inside. The problem is that it only stay for about half a second before it dissaspear. I'd like it to stay for 2 seconds. Async is set to false because I need form input to reload themself with the updated values and if it's set to true, I have to manually refresh the page with F5 to see the updated version.
function
$('#btnEnregistrerMembre').on('click', function (e) {
$.ajax({
async: false, type: 'POST', url: 'functionPHP.php', data: {
userID: document.getElementById('id').value, nomUtilisateur: document.getElementById('nomUtilisateur').value, estActif: +document.getElementById('actif').checked, estAdmin: +document.getElementById('admin').checked, updateMembre: 'updateMembre'
},
success: function (msg) {
ajouterMessage('messageArea', 'succes', 'Les modifications ont étés prises en compte.');
// alert('succes ajax');
},
error: function (err) {
ajouterMessage('messageArea', 'danger', 'Les modifications ont échouées.');
}
});
});
AjouterMessage
function ajouterMessage(locationID, type, message) {
var endroit = document.getElementById(locationID);
var element = document.createElement('div');
if (type == 'danger')
{
element.className = 'alert alert-danger';
element.innerHTML = '<strong>Erreur!</strong>' + ' ' + message;
}
else
{
element.className = 'alert alert-succes';
element.innerHTML = '<strong>Succès!</strong>' + ' ' + message;
}
endroit.appendChild(element);
}
Thank you for your help.

Your problem is that async is set to false. I know you want the page reload effect, but you are trying to set a value in the old page before the reload.
What is happening:
You send a request synchronously
receive the response from the server
You handle the response message and show and appropriate message
The web browser also handles the response from the server (remember, it's synchronous!)
The page reloads because the request was synchronous and not asynchronous and your message is lost
You have a few options here...
Option 1 (recommended):
You can send the request asynchronously and return whatever relevant data you need to be refreshed in the response.
Option 2:
Set a cookie with a flag to indicate what message should be set upon refresh of your page. Remember to clear the flag after reading it.
Si c'est plus facile pour toi, je peux traduire ma réponse en français.
Edit: It should be noted that synchronous AJAX is altogether not that useful. It stands for Asynchronous Javascript And XML. If you want to send a synchronous request, a simple form submission or link with some GET parameters would probably be far more simple.

Thank you for this very clear answer. However, i have a return value in the function that update the database, but how can I get the values in the modifierUtilisapeur.php page? Here is some code on the function if it can help:
update
function updateMembre($id,$nomUtilisateur,$status,$admin){
$caught = false;
$connexion = Connexion(NOM, PASSE, BASE, SERVEUR);
$requete = "update utilisateur set nomUtilisateur = '".addslashes($nomUtilisateur)."', estActif = '".$status."',estAdmin = '".$admin."' where id ='".$id."' ;";
try{
ExecRequete($requete, $connexion);}
catch (Exception $e){
$caught = true;
echo '<div class="alert alert-danger">
<strong>Erreur!</strong> Le nom d\'utilisateur existe déjà.
</div>';
}
finally{
if (!$caught){
echo '<div class="alert alert-success">
<strong>Succès!</strong> Les modifications ont étés prises en compte.
</div>';
}
}
return getMembre($id);
}
getMembre
function getMembre($nomUtilisateur){
$connexion = Connexion(NOM, PASSE, BASE, SERVEUR);
$requete = "SELECT * FROM utilisateur where nomUtilisateur = '".$nomUtilisateur."';";
$resultat = ExecRequete($requete, $connexion);
$resultat->data_seek(0);
$row = $resultat->fetch_assoc();
return $row;
}

Related

How to avoid double login in PHP?

I am creating a system where the objective is that only one person per user can access the system, for this I have in my DB two tables called: users and accesses What I am doing is that when person 1 logs in, it is saved in my DB the id of the session in the two tables, if person 2 with the same user tries to access then the first person to log in takes it out of the system. I do this with help with AJAX, comparing if the last user who started has the same session id then he can navigate without problem, if he does not close session.
The problem is that I make this ajax request every 10s, but I would have problems if 10,000 people or more log in, then the request will be sent to the server every 10 seconds and this could saturate the server.
Try an active field if the session is equal to 1 and if the session is equal to 0, then discard this since if the user closes the browser then I never close session and the person will not be able to access, I also tried using a ajax method to detect if you close the browser but it is not very reliable. Has anyone had the same problem? I would thank you a lot.
I leave my php and js code to display as I do:
Code JS:
$(function() {
cron(); // Lanzo cron la primera vez
function cron() {
$.ajax({
method: "POST",
url: "closeuser.php",
data: { action: 1 }
})
.done(function(msg) {
var trimmedString = msg.trim();
console.log(trimmedString)
if( trimmedString == 'success' ) { // Valida si el server devolvió 'success'
location.href='logoutuser.php';
}
});
}
setInterval(function() {
cron();
}, 10000); // cada 10 segundos
});
Code PHP:
<?php
require_once 'Connections/sesionunica.php';
$connection_s = new sesionunica();
if(!isset($_SESSION["id_user"])){
echo"<script>location.href='index.php';</script>";
}
if(isset($_POST["action"])) { // Se pasa una acción
switch(sprintf("%d", $_POST["action"])) { // ¿Qué acción?
case 1:
cerrar();
break;
default:
echo "default";
}
}
function cerrar(){
$ses = session_id();
$connection_s = new sesionunica();
$userById = $connection_s->getUsers($_SESSION["id_user"]);
if ($userById["id_sesion"] <> $ses) {
echo "success";
}
}
?>
In the same way, I cannot use websockets since there are accessibility problems with the server.
I think you could create an "access filter" that would check if the "access token" is valid or not in every request the users would make.
If the "access token" is expired, then return an HTTP status 401 (unauthorized), and, in client-side, redirect the user to login page.
Request filter is a very common resource that many REST frameworks have.

Output PHP Form Validation Error Messages When Using JavaScript Fetch API

I have a page with multiple forms on, where each form is processed with PHP in the backend that sends data to a MySQL database, but on the front end it uses Javascript's fetchAPI to prevent the page refreshing when an instance of the form is completed and data is sent to the database.
I have some PHP server side validations that take place that still work in terms of not sending the data to the database, although on submission the instance of the form completed does disappear from the page (due to javascript shown below), but re-appears when refreshed if it failed the validations.
The main code example below includes this code block that would normally output the error message:
<?php
// echo form validation error messages
if(isset($error)) {
foreach($error as $msg) {
echo "<p>** {$msg}</p>";
}
}
?>
In terms of outputting these error messages is it possible to still use this PHP code (currently not working), or now I'm using the javascript fetchAPI in conjunction with PHP, will I have to also write validations in JavaScript to output the errors on the front end, in addition to the PHP ones which securely prevent the form failing the validations? It should be noted there are multiple instances of the form on the page which are outputted with a while loop, each one is in relation to a specific post.
<?php
if(isset($_POST['upload-submit'])) {
// note $imageTitle is a variable given to the title of a post submitted via an HTML form
if(!preg_match('/^[a-zA-Z0-9\s]+$/', $imageTitle)) {
$error[] = "Post Title can be letters and numbers only";
}
if(empty(trim($imageTitle))){
$error[] = "Image Title cannot be blank";
}
// if no errors process submission
if (!isset($error)) {
try {
// PDO prepared statements that update the database
} catch (PDOException $e) {
echo "There is an error: " . $e->getMessage();
}
}
}
?>
Also here is the javascript fetchAPI code that works on the page.
var forms = document.querySelectorAll('.image-upload-details-form'),
forms.forEach(item => {
item.querySelectorAll('[type="submit"], button').forEach(button => {
button.addEventListener("click", e => item._button = button); //store this button in the form element
})
item.addEventListener("submit", function(evt, btn) {
evt.preventDefault();
const formData = new FormData(this);
if (this._button) //submitted by a button?
{
formData.set(this._button.name, this._button.value);
}
fetch("upload-details.php", {
method: 'post',
body: formData
}).then(function(response){
return response.text();
}).then(function(text){
console.log(text);
}).catch(function (error){
console.error(error);
})
// removes form when submitted
item.remove();
})
})
Many thanks in advance for any help / advice.
My understanding is after making the fetch request you want to show the error message.
Your php code is incomplete. On pdo execption, you are outputting a string. On your validation, you are storing in an array.
Not clear about the output, if the validation fails.
(Recommended is output a string with html tags, so you can overcome the complexity of running a loop and creating dom nodes at js end)
While communicating with backend, best way is to use JSON format, to identify whether the response success or error
<?php
// echo form validation error messages // from php
if(isset($error)) {
foreach($error as $msg) {
echo "<p>** {$msg}</p>";
}
}
<div class="error-messages"></div> // for fetch error messages. leave it blank
?>
const errorElement = document.querySelector(".error-messages"); // capture error element
errorElement.innerHTML =''; // clean previous errors
fetch("upload-details.php", {
method: 'post',
body: formData
}).then(function(response){
const echoed = response.text(); // assuming you are captuing the text
if(echoed.includes("There is an error: ")){ // it is an error
errorElement.innerHTML = echoed; // insert the error message into the div
return;
}
return response.text();
}).then(function(text){
console.log(text);
}).catch(function (error){
errorElement.innerHTML = "Error communicating with server.Contact administrator"
console.error(error);
})
First you have not give full php function code post method.
you have to write proper code in php which will give proper response of ajax call like below
<?php
if (isset($_POST['username'])) {
// do user authentication as per your requirements
// ...
// ...
// based on successful authentication
echo json_encode(array('success' => 1));
} else {
echo json_encode(array('success' => 0));
}
after that you have to add code in javascript for handle error and success based on your php reponse.
function(response)
{
var jsonData = JSON.parse(response);
// user is logged in successfully in the back-end
// let's redirect
if (jsonData.success == "1")
{
location.href = 'my_profile.php';
}
else
{
alert('Invalid Credentials!');
}
}
This is proper way for ajax call request. Use proper code for that and your problem will solve
You need to echo you error(s) all in one time, otherwise you'll get the 1st echo only... ;
<?php
// echo form validation error messages
$echo = [];
if(isset($error)) {
foreach($error as $msg) {
$echo[] = "<p>** {$msg}</p>";
}
echo implode(PHP_EOL, $echo);
}
?>
And for you other block :
<?php
if(isset($_POST['upload-submit'])) {
// note $imageTitle is a variable given to the title of a post submitted via an HTML form
if(!preg_match('/^[a-zA-Z0-9\s]+$/', $imageTitle)) {
$error[] = "Post Title can be letters and numbers only";
}
if(empty(trim($imageTitle))){
$error[] = "Image Title cannot be blank";
}
// if no errors process submission
if (!isset($error)) {
try {
$success = false;
// PDO prepared statements that update the database => success = true ?
echo $success;
} catch (PDOException $e) {
echo "There is an error: " . $e->getMessage();
}
}
echo $errors; // form 'user' errors
}
?>
or smthg like that
When you catch PDOException you make echo (but not throw new Exeption).
So in JS it goes to then(function(response), not to catch(function (error).
You should check response in then(function(response).
Example:
.then(function(response){
if (response.includes('Error:') {
// do something
}

Jquery ajax code in .done(function()) after $.when() not being executed

Here is the jquery code that is the problem. I wanted for the ajax to send json data to the server and then submit the form. If I don't have the when and done clause then it's possible for submission to be done before the ajax and will not be able to retrieve success or error in time.
function deleteImage(button)
{
//There is only one image that is a sibling of the delete button
var image = $(button).siblings(".MultiFile-image")[0];
var groupId = $(image).data("modelId");
var imgId = $(image).data("id");
var imgSrc = $(image).attr("src");
//Delete the image view after the removed button is clicked but the data to be sent to the server for deletion is already stored
$(button).parent(".MultiFile-label").remove();
var imageToDelete = {imgId:imgId, imgSrc:imgSrc, groupId:groupId};
var imageJSON = '{"imageToDelete":' + JSON.stringify(imageToDelete) + "}";
//This is needed to check whether ajax has been executed before submission
var sentImageData = false;
$("form").submit(function(e) {
//Stop submission, need to send data through ajax first, will submit after ajax is executed later.
if(!sentImageData)
{
e.preventDefault();
//Send the images for deletion only when the form has been submitted
//For some reason this code is never executed and go immediately to the end of this method
$.when(sendImageData(imageJSON)).done(function(jqXHR) {
if(jqXHR.readyState == 4 && jqXHR.status == 200)
{
sentImageData = true;
$("form").submit();
}
else
{
console.log(jqXHR);
sentImageData = false;
}
}); //For some reason the debugger skips to here and return is undefined
}
//If executed is true, send the form as normal
});
}
/**
* #var imageJSON the image json data that will be sent to the server to delete the image
* #returns {#exp;$#call;ajax} return XMLHttpRequest of the ajax
*/
function sendImageData(imageJSON)
{
return $.ajax({
type: 'POST',
data: imageJSON,
dataType: 'JSON',
url: "index.php?r=artworkGroup/deleteArtwork",
});
}
Thank you, I would much appreciate the help from the community on this problem :)
EDIT: Here is the action that handles this ajax code. an example of json is: "{"imageToDelete":{"imgId":2,"imgSrc":"upload_file/artwork/1-New_Artwork_Group/12861274.jpg","groupId":2}}"
public function actionDeleteArtwork() {
$noError = false;
if(isset($_POST["imageToDelete"]))
{
$imageArray = $_POST["imageToDelete"];
//Delete every image retrieved by post
foreach($imageArray as $image)
{
$transaction = Yii::app()->db->beginTransaction();
try{
$imageToDelete = json_decode($image);
$model = $this->loadModel($imageToDelete->groupId);
$artworkToDelete = $model->artworks->loadModel($imageToDelete->id);
if($imageToDelete->imgSrc == $artworkToDelete->imgSrc)
{
$artworkToDelete->delete();
if(file_exists($imageToDelete->imgSrc))
{
unlink($imgToDelete->imgSrc);
}
}
else
{
$hasError = true;
}
$transaction->commit();
}
catch(Exception $e)
{
$transaction->rollback();
$hasError = true;
}
//Delete the image files if there are no errors and that the file exists, otherwise just ignore
if(file_exists($imageToDelete->imgSrc) && $noError)
{
unlink($imageToDelete->imgSrc);
}
}
}
}
You have omitted url from your ajax request. that means it is going to hit your current page url. That may be triggering timeout.
and Timeout is kind of error in $.ajax. thats why your
sendImageData(imageJSON)
is returning you false. and by consequence of it your .done() is not getting executed.

Passing a JavaScript value to PHP on completion of quiz

I have a web page that allows users to complete quizzes. These quizzes use JavaScript to populate original questions each time it is run.
Disclaimer: JS Noob alert.
After the questions are completed, the user is given a final score via this function:
function CheckFinished(){
var FB = '';
var AllDone = true;
for (var QNum=0; QNum<State.length; QNum++){
if (State[QNum] != null){
if (State[QNum][0] < 0){
AllDone = false;
}
}
}
if (AllDone == true){
//Report final score and submit if necessary
NewScore();
CalculateOverallScore();
CalculateGrade();
FB = YourScoreIs + ' ' + RealScore + '%. (' + Grade + ')';
if (ShowCorrectFirstTime == true){
var CFT = 0;
for (QNum=0; QNum<State.length; QNum++){
if (State[QNum] != null){
if (State[QNum][0] >= 1){
CFT++;
}
}
}
FB += '<br />' + CorrectFirstTime + ' ' + CFT + '/' + QsToShow;
}
All the Javascript here is pre-coded so I am trying my best to hack it. I am however struggling to work out how to pass the variable RealScore to a MySql database via PHP.
There are similar questions here on stackoverflow but none seem to help me.
By the looks of it AJAX seems to hold the answer, but how do I implement this into my JS code?
RealScore is only given a value after the quiz is complete, so my question is how do I go about posting this value to php, and beyond to update a field for a particular user in my database on completion of the quiz?
Thank you in advance for any help, and if you require any more info just let me know!
Storing data using AJAX (without JQuery)
What you are trying to do can pose a series of security vulnerabilities, it is important that you research ways to control and catch these if you care about your web application's security. These security flaws are outside the scope of this tutorial.
Requirements:
You will need your MySQL database table to have the fields "username" and "score"
What we are doing is writing two scripts, one in PHP and one in JavaScript (JS). The JS script will define a function that you can use to call the PHP script dynamically, and then react according to it's response.
The PHP script simply attempts to insert data into the database via $_POST.
To send the data to the database via AJAX, you need to call the Ajax() function, and the following is the usage of the funciton:
// JavaScript variable declarations
myUsername = "ReeceComo123";
myScriptLocation = "scripts/ajax.php";
myOutputLocation = getElementById("htmlObject");
// Call the function
Ajax(myOutputLocation, myScriptLocation, myUsername, RealScore);
So, without further ado...
JavaScript file:
/**
* outputLocation - any HTML object that can hold innerHTML (span, div, p)
* PHPScript - the URL of the PHP Ajax script
* username & score - the respective variables
*/
function Ajax(outputLocation, PHPScript, username, score) {
// Define AJAX Request
var ajaxReq = new XMLHttpRequest();
// Define how AJAX handles the response
ajaxReq.onreadystatechange=function(){
if (ajaxReq.readyState==4 && xml.status==200) {
// Send the response to the object outputLocation
document.getElementById(outputLocation).innerHTML = ajaxReq.responseText;
}
};
// Send Data to PHP script
ajaxReq.open("POST",PHPScript,true);
ajaxReq.setRequestHeader("Content-type","application/x-www-form-urlencoded");
ajaxReq.send("username="username);
ajaxReq.send("score="score);
}
PHP file (you will need to fill in the MYSQL login data):
<?php
// MYSQL login data
DEFINE(MYSQL_host, 'localhost');
DEFINE(MYSQL_db, 'myDatabase');
DEFINE(MYSQL_user, 'mySQLuser');
DEFINE(MYSQL_pass, 'password123');
// If data in ajax request exists
if(isset($_POST["username"]) && isset($_POST["score"])) {
// Set data
$myUsername = $_POST["username"];
$myScore = intval($_POST["score"]);
} else
// Or else kill the script
die('Invalid AJAX request.');
// Set up the MySQL connection
$con = mysqli_connect(MYSQL_host,MYSQL_user,MYSQL_pass,MYSQL_db);
// Kill the page if no connection could be made
if (!$con) die('Could not connect: ' . mysqli_error($con));
// Prepare the SQL Query
$sql_query="INSERT INTO ".TABLE_NAME." (username, score)";
$sql_query.="VALUES ($myUsername, $myScore);";
// Run the Query
if(mysqli_query($con,$sql))
echo "Score Saved!"; // Return 0 if true
else
echo "Error Saving Score!"; // Return 1 if false
mysqli_close($con);
?>
I use these function for ajax without JQuery its just a javascript function doesnt work in IE6 or below. call this function with the right parameters and it should work.
//div = the div id where feedback will be displayed via echo.
//url = the location of your php script
//score = your score.
function Ajax(div, URL, score){
var xml = new XMLHttpRequest(); //sets xmlrequest
xml.onreadystatechange=function(){
if (xml.readyState==4 && xml.status==200){
document.getElementById(div).innerHTML=xml.responseText;//sets div
}
};
xml.open("POST",URL,true); //sets php url
xml.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xml.send("score="score); //sends data via post
}
//Your PHP-script needs this.
$score = $_POST["score"]; //obtains score from POST.
//save your score here
echo "score saved"; //this will be displayed in the div set for feedback.
so call the javascript function with the right inputs, a div id, the url to your php script and the score. Then it will send the data to the back end, and you can send back some feedback to the user via echo.
Call simple a Script with the parameter score.
"savescore.php?score=" + RealScore
in PHP Side you save it
$score = isset ($_GET['score']) ? (int)$_GET['score'] : 0;
$db->Query('INSERT INTO ... ' . $score . ' ...');
You could call the URL via Ajax or hidden Iframe.
Example for Ajax
var request = $.ajax({
url: "/savescore.php?score=" + RealScore,
type: "GET"
});
request.done(function(msg) {
alert("Save successfull");
});
request.fail(function(jqXHR, textStatus) {
alert("Error on Saving");
});

ajax, jquery and Iframe (creating a message box system)

I'm trying to create a sort of mail on my site.
So I have a table that contains three columns, let's say (for simplicity , but in reality) , with the two int fields ( from, to ) and a timestamp (date of sending )
a part of my page , I display a list of messages with a group by to to group all messages that are destined for the same person .
Eventually I want to display the entire conversation when clicking on the message but it is not obvious.
I tried jquery ajax and then an iframe but it is not great , because on one hand it does not return me anything (white pages) and secondly the reload each second is not great .
At first I would like to display the result of my request.
I have not set callback because I do not know what to do with an application in a jquery callback . I thought the easiest way was to do my processing in php and run my loop then displays everything in the iframe .
So I put it in jquery
$( ".load_message" ).click(function() {
//On marque uniquement l'id de l'expediteur et du destinataire
// pour chercher les messages expédiés par A vers B ou inversement
var from = $(this).closest('tr').find('span.from').text();
var to = $(this).closest('tr').find('span.to').text();
$.ajax({
type: 'POST',
url: 'pages_ajax/fetch-messages.php',
data: { from: from, to: to},
dataType: "json"
});
});
setInterval(refreshIframe1, 1000);
function refreshIframe1() {
$("#messages")[0].src = $("#messages")[0].src;
}
and the php page I have this:
<?php
session_start();
require_once("../../lib_php/librairie.php");
require_once("../../config/connexion.php");
//header('Content-Type: application/json; charset=utf8');
/**
* Fonction qui retourne une liste de messages
* #return int
*/
function fetchMessages() {
if (isset($_POST['from'])) {
$from = mysql_real_escape_string($_POST['from']);
$to = mysql_real_escape_string($_POST['to']);
$query = "SELECT `id`, `from`, `to`, `message`, `sent`, `read`, `direction`
FROM `cometchat`
WHERE `from` = {$from} || `from` = {$to} || `to` = {$to} || `to` = {$from}";
return $query;
} else {
return null;
}
}
if (isset($_POST['from'])) {
$liste_messages = fetchMessages();
if (!is_null($liste_messages)) {
$result_message = mysql_query($liste_messages);
while ($mess = mysql_fetch_assoc($result_message)):
?>
ici
<?php
endwhile;
}
}
?>
But for now nothing works I do not even have my messages while running the echo of my query in phpMyAdmin return me something. I guess I'm loosing context when reloading ($_POST are loosing themselves)
I would initially display the entire conversation in an iframe or a div, then after whatever it is automatically updated if ever there's new posts in the meantime a bit like the messaging system on Facebook with no reloading of the page.
Any help will be greatly appreciated.
it's been a while you asked the question hope u solved it. Anyway is what i can tell from your code and what you try to do:
Your jquery function have no callback (success, complete)
Your php code don't return anything, you just do a loop like you want to manipulate each record, and reading your post you want to have your ajax to read all value in a success callback... So don't need a loop except you want to parse it, just expose them with json_encode($mess);
setInterval 1s? argh!!! Will your server handle it? Use something like 10 à 30s or 4:
go for websocket solution like racket in php or use nodejs plateform (nodejs + socket.io + redis)
Hope it helped you out or someone else

Categories