Can't figure out why this ajax request fires two times - javascript

I am working on this snippet of code, but I can't figure out why the ajax request is firing up twice when I click the selected button:
$('#passwd-nuova').blur(function() {
var response = $('#passwd-nuova').validate({
'classeform': 'form-utenti',
'empty': 'passwd-nuova'
});
if (!response.empty) {
$('#reset').addClass('btn-disabled');
} else {
$('#reset').removeClass('btn-disabled');
/*
* RESET PASSWORD PANNELLO
*/
$('#reset').on('click', function() {
var new_passwd = $('input[name=passwd-nuova]').val();
var selezionato = $(this).loadID({
'nometabella': 'utenti',
'abbr': 'utenti'
});
var send_email = $('#cb-email').prop('checked');
$.ajax({
cache: false,
type: "POST",
url: "/gutenti/",
dataType: "json",
data: {
'mod-passwd': true,
'idu': selezionato,
'new-passwd': new_passwd,
'send-email': send_email
},
success: function(response) {
var tab = $("#datatable_utenti").dataTable();
$('#modal-reset').modal('hide');
tab.fnDraw();
$(window).scrollTop(0);
$(document).genAlert({
tipo: 'success',
msg: 'modifica completata con successo',
time: 800
});
$('input').each(function() {
$(this).val('');
});
$("#datatable_utenti tbody").compileForm({
'abbr': 'utenti',
'nometabellaDB': 'admin_utenti',
'nometabella': 'utenti'
});
$(document).stato(profile, 'base');
return;
},
error: function() {
console.log("errore async");
$('#modal-reset').modal('hide');
$(window).scrollTop(0);
$(document).genAlert({
tipo: 'error',
msg: 'qualcosa è andato storto, riprova',
time: 800
});
}
});
return;
});
}
});
I've tried to disable the button after the call, and also to return nothing to exit from the function, but nothing has worked.

Your $('#passwd-nuova').blur handler binds the $('#reset').click' handler multiple times.
I'm glad my comment helped you out ;)

I have called the function inside the blur funciton. However; The function is going to be called also when you click the #reset button. I hope it works.
$('#passwd-nuova').blur(function() {
var response = $('#passwd-nuova').validate({
'classeform': 'form-utenti',
'empty': 'passwd-nuova'
});
if (!response.empty) {
$('#reset').addClass('btn-disabled');
} else {
$('#reset').removeClass('btn-disabled');
/*
* RESET PASSWORD PANNELLO
*/
$('#reset').click();
}
});
$('#reset').on('click', function() {
var new_passwd = $('input[name=passwd-nuova]').val();
var selezionato = $(this).loadID({
'nometabella': 'utenti',
'abbr': 'utenti'
});
var send_email = $('#cb-email').prop('checked');
$.ajax({
cache: false,
type: "POST",
url: "/gutenti/",
dataType: "json",
data: {
'mod-passwd': true,
'idu': selezionato,
'new-passwd': new_passwd,
'send-email': send_email
},
success: function(response) {
var tab = $("#datatable_utenti").dataTable();
$('#modal-reset').modal('hide');
tab.fnDraw();
$(window).scrollTop(0);
$(document).genAlert({
tipo: 'success',
msg: 'modifica completata con successo',
time: 800
});
$('input').each(function() {
$(this).val('');
});
$("#datatable_utenti tbody").compileForm({
'abbr': 'utenti',
'nometabellaDB': 'admin_utenti',
'nometabella': 'utenti'
});
$(document).stato(profile, 'base');
return;
},
error: function() {
console.log("errore async");
$('#modal-reset').modal('hide');
$(window).scrollTop(0);
$(document).genAlert({
tipo: 'error',
msg: 'qualcosa è andato storto, riprova',
time: 800
});
}
});
return;
});

I guess that this line:
$('#reset').on('click', function() {
........
runs more than once(on each blur).
You can bind an event more than once with no problem.
Check if this solves your problem:
$('#reset').off('click').on('click',function(){ .....
If it does, then try to move the "event attachment" to a different place.
Jquery - 'on' and 'off'

Try unbind / bind the click callback:
var callback = function () { ... }
$('#reset').unbind('click', callback);
$('#reset').bind('click', callback);
If you attach the click event twice, it will get called two times.

Related

Click event listener on elements with the class stops working after first click

I have an anchor element with a class called .trigger. I have a listener for that class which opens a modal using the iziModal framework. On first click the function works as expected. On second click the listener does not work. Instead i get in console "$(...).iziModal is not a function". What am i doing wrong? Any help would be greatly appreciated. I am bot of a newbie with JS.
** Jquery ver **
3.6.3
Ajax Example 8
$(document).on('click', '.trigger', function(event) {
event.preventDefault();
var url = $(this).attr('href');
var wtitle = $(this).data('title');
$('#my-modal').iziModal({
title: wtitle,
bodyOverflow: true,
width: 600,
headerColor: '#000',
fullscreen: false,
openFullscreen: false,
transitionIn: 'fadeInDown',
transitionOut: 'fadeOutUp',
onOpening: function(modal) {
modal.startLoading();
$.ajax({
url: url,
type: 'GET',
success: function(data) {
modal.stopLoading();
modal.setContent(data);
},
error: function() {
alert('Error loading content.');
}
});
}
});
$('#my-modal').iziModal('open');
});
I have tried initialising the izi modal outside of the trigger event (suggested by ChatGPT).
I think this would work but I am not sure how to pass the URL from the onClick event to $('#my-modal').iziModal(). If someone could suggest that then i could try.
// Initialize the iziModal
$('#my-modal').iziModal({
title: '',
bodyOverflow: true,
width: 600,
headerColor: '#000',
fullscreen: false,
openFullscreen: false,
transitionIn: 'fadeInDown',
transitionOut: 'fadeOutUp',
onOpening: function(modal) {
modal.startLoading();
$.ajax({
url: '',
type: 'GET',
success: function(data) {
modal.stopLoading();
modal.setContent(data);
},
error: function() {
alert('Error loading content.');
}
});
}
});
// Bind the click event to the trigger element
$(document).on('click', '.trigger', function(event) {
event.preventDefault();
event.stopPropagation();
var url = $(this).attr('href');
var wtitle = $(this).data('title');
// Set the modal title
$('#my-modal').iziModal('setTitle', wtitle);
// Set the modal content
$('#my-modal').iziModal('setContent', '');
$('#my-modal').iziModal('startLoading');
$.ajax({
url: url,
type: 'GET',
success: function(data) {
$('#my-modal').iziModal('stopLoading');
$('#my-modal').iziModal('setContent', data);
},
error: function() {
$('#my-modal').iziModal('stopLoading');
alert('Error loading content.');
}
});
// Open the modal
$('#my-modal').iziModal('open');
});

Triggering event after preventDefault() doesn't work as expected

$(document).on('click', '[data-toggle="if-exist"]', function (e, options) {
options = options || {};
if (options.fileExist) {
return true;
}
var target = e.currentTarget;
var fileId = $(this).data('file');
e.preventDefault();
$.ajax({
url: Routing.generate('checkFile', {file: fileId }),
type: 'HEAD',
statusCode: {
404: function () {
alert('File does not exist');
},
200: function () {
$(target).trigger('click', { 'fileExist': true });
}
}
});
});
When clicking the button the HEAD request is send and when I've got 200 response than the click event is triggered again but this time with fileExist option. Listener is called again (I checked this) but nothing happens, it's like e.preventDefault() would still working. Any ideas?
Solution
trigger() method will trigger jQuery event, but will not trigger default behaviour for a browser, which in my case is redirecting to another page. This code works:
$(document).on('click', '[data-toggle="if-exist"]', function (e) {
var target = this;
var fileId = $(this).data('file');
e.preventDefault();
$.ajax({
url: Routing.generate('checkFile', { file: fileId }),
type: 'HEAD',
statusCode: {
404: function () {
alert('File does not exist');
},
200: function () {
var event = document.createEvent('MouseEvents');
event.initEvent('click', false, false);
target.dispatchEvent(event);
}
}
});
});
use e.stopImmediatePropagation(); to stop multiple calls of ajax.

Jquery close popup on click

I use this jquery to show my popup,
//ResetPassword Popup display
$(document).ready(function () {
var passwordExpiredVal = $("#isPasswordExpired").html();
if (passwordExpiredVal == "True") {
$("#ResetPasswordModal").modal({
show: 'true'
});
};
});
I use this jquery to pass the new typed password to controller action ON CLICK, once the save button is clicked I want the popup to close
//Reset Password submit
$(document).ready(function () {
$("#submitSave").on("click", function () {
var confirmPassword = $("#txtLgnPasswordConfirmReset").val();
var passwordReset = {
UserName: $("#txtLgnUsername").val(),
Password: $("#hdnOldPassword").val(),
NewPassword: $("#txtLgnPasswordReset").val()
}
if (passwordReset.NewPassword != confirmPassword) {
notifyMessage.showNotifyMessage('error', 'The passwords entered should match', false);
$("#txtLgnPasswordReset").val("");
$("#txtLgnPasswordConfirmReset").val("");
}
else {
$.ajax({
type: "POST",
url: "/Account/PasswordReset",
data: passwordReset,
success: function () {
$("#ResetPasswordModal").modal({
show: 'false'
});
},
error: function () {
alert('failure');
}
});
}
});
});
My jquery function is not helping...
success: function () {
$("#ResetPasswordModal").modal({
show: 'false'
});
},
Any ideas??
Thanks in advance...
The code you are using is unnecessarily initializing the modal again on that element.
Use modal('hide') : Docs,
success: function () {
$('#ResetPasswordModal').modal('hide');
},
If you further wish to use this again, 'toggle' would be a better option.
$('#ResetPasswordModal').modal('toggle')

Jquery $(this).closest('form'); not working after button click

I have the following js code:
$("#add_station").on('click', function () {
$(this).closest('form').submit(function () {
alert("working!");
$.ajax({
url: advoke.base_url + "/new-vendor-user/station/ajax",
method: 'post',
processData: false,
contentType: false,
cache: false,
dataType: 'json',
data: new FormData(this),
beforeSend: function () {
$('.info').hide().find('ul').empty();
$('.success_message').hide().find('ul').empty();
$('.db_error').hide().find('ul').empty();
},
success: function (data) {
if (!data.success) {
$.each(data.error, function (index, val) {
$('.info').find('ul').append('<li>' + val + '</li>');
});
$('.info').slideDown();
setTimeout(function () {
$(".info").hide();
}, 5000);
} else {
$('.success_message').slideDown();
$('#add_station').remove();
$("#station").append(data.new_station);
setTimeout(function () {
$(".success_message").hide();
}, 5000);
} //success
},
error: function () {
//db error
$('.db_error').append('<li>Something went wrong, please try again!</li>');
$('.db_error').slideDown();
//Hide error message after 5 seconds
setTimeout(function () {
$(".db_error").hide();
}, 5000);
} //error
});
});
return false;
});
When I click the button with the id add_station it alerts on click function after $($this).closest('form').submit(function(){...) it doesn't work as you can see I've put an alert 'works' after submit function.I get no errors on the console and I can't figure what the problem is. Also, the button that is clicked is inside a form.
I need to use $($this).closest('form').submit(function(){...) inside because after ajax success a new form will be generated with add station button that will use this code.
You should block the default submit trigger by using
e.preventDefault();
$(this).closest('form').submit(function (e) {
e.preventDefault();
<!--rest of the code-->
})
add a separately submit handler
$("#add_station").on('click', function () {
$(this).closest('form').submit();
});
$("form").on("submit", function (e) {
e.preventDefault();
alert("working!");
$.ajax({
url: advoke.base_url + "/new-vendor-user/station/ajax",
method: 'post',
processData: false,
contentType: false,
cache: false,
dataType: 'json',
data: new FormData(this),
beforeSend: function () {
$('.info').hide().find('ul').empty();
$('.success_message').hide().find('ul').empty();
$('.db_error').hide().find('ul').empty();
},
success: function (data) {
if (!data.success) {
$.each(data.error, function (index, val) {
$('.info').find('ul').append('<li>' + val + '</li>');
});
$('.info').slideDown();
setTimeout(function () {
$(".info").hide();
}, 5000);
} else {
$('.success_message').slideDown();
$('#add_station').remove();
$("#station").append(data.new_station);
setTimeout(function () {
$(".success_message").hide();
}, 5000);
} //success
},
error: function () {
//db error
$('.db_error').append('<li>Something went wrong, please try again!</li>');
$('.db_error').slideDown();
//Hide error message after 5 seconds
setTimeout(function () {
$(".db_error").hide();
}, 5000);
} //error
});
});
after ajax success a new form will be generated with add station
button that will use this code
If you generate a new button you have to bind the click again after it is placed to the dom.

Ajax, prevent multiple request on click

I'm trying to prevent multiple requests when user click on login or register button. This is my code, but it doesn't work. Just the first time works fine, then return false..
$('#do-login').click(function(e) {
e.preventDefault();
if ( $(this).data('requestRunning') ) {
return;
}
$(this).data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
});
Any ideas? Thanks!
The problem is here:
complete: function() {
$(this).data('requestRunning', false);
}
this no longer points to the button.
$('#do-login').click(function(e) {
var me = $(this);
e.preventDefault();
if ( me.data('requestRunning') ) {
return;
}
me.data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
me.data('requestRunning', false);
}
});
});
Use on() and off(), that's what they are there for :
$('#do-login').on('click', login);
function login(e) {
e.preventDefault();
var that = $(this);
that.off('click'); // remove handler
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize()
}).done(function(msg) {
// do stuff
}).always(function() {
that.on('click', login); // add handler back after ajax
});
});
In your ajax callbacks the context (this) changes from the outer function, you can set it to be the same by using the context property in $.ajax
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this, //<-----
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
You can disable the button.
$(this).prop('disabled', true);
I have also faced a similar problem.
Just adding $('#do-login').attr("disabled", true); gives me the solution.
$('#do-login').click(function(e) {
e.preventDefault();
$('#do-login').attr("disabled", true);
.........
.........
Here do-login is button id.
I've tried this and worked very fine for me, I was having trouble that $.ajax send more request until results return,
var settings = {
"url": "/php/auth/login.php",
"method": "POST",
"timeout": 0,
"async": false,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"data": jsondata, //data pass here is in JSON format
};
$.ajax(settings).done(function (ress) {
try{
console.log(ress, "Result from Ajax here");
}
catch(error){
alert(error);
console.log(ress);
}
});
async : false worked for me.
Thanks.
Or you can do it by $(this).addClass("disabled"); to you button or link and after click is performed, you can $(this).removeClass("disabled");.
// CSS
.disabled{
cursor: not-allowed;
}
// JQUERY
$('#do-login').click(function(e) {
e.preventDefault();
$(this).addClass("disabled");
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this,
success: function(msg) {
//do more here
$(this).removeClass("disabled");
},
});
});
P.S. If you use bootstrap css, you do not need the css part.
I found the approach useful. I've implemented it as a general purpose function for jQuery with ES6.
export default function (button, promise) {
const $button = $(button);
const semaphore = 'requestRunning';
if ($button.data(semaphore)) return null;
$button.data(semaphore, true);
return promise().always(() => {
$button.data(semaphore, false);
});
}
Because $.ajax() returns a promise, you simply pass in the promise and the function takes care of the rest.
Roughly speaking, here's the usage.
import preventDoubleClick from './preventdoubleclick';
...
button.click(() => {
preventDoubleClick(this, () => $.ajax()
.done(() => { console.log("success") }));
});
This function can help you with control multi Ajax requests and it's has timeout function which can return flag status to 0 after ex. 10sec (In case the server took more than 10 seconds to respond)
var Request_Controller = function(Request_Name = '', Reactivate_Timeout = 10000)
{
var a = this;
a.Start_Request = function(){
if(window.Requests == undefined){
window.Requests = {};
}
window.Requests[Request_Name] = {'Status' : 1, 'Time': + new Date()};
}
a.End_Request = function(){
if(window.Requests == undefined){
window.Requests = [];
}
window.Requests[Request_Name] = undefined;
}
a.Is_Request_Running = function(){
if(window.Requests == undefined || window.Requests[Request_Name] == undefined){
return 0;
}else{
var Time = + new Date();
// Reactivate the request flag if server take more than 10 sec to respond
if(window.Requests[Request_Name]['Time'] < (Time - Reactivate_Timeout))
{
return 0;
}else{
return 1
}
}
}
}
To use it:
var Request_Flag = new Request_Controller('Your_Request_Name');
if(!Request_Flag.Is_Request_Running()){
Request_Flag.Start_Request();
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
Request_Flag.End_Request();
}
});
}
for prevent multiple ajax request in whole site. For example: If use ajax request in other ajax page, Using ajax in php loop, etc, Give you multiple ajax request with one result. I have solution:
Use window.onload = function() { ... }
instead of
$(document).ready(function(){ ... });
on the main index.php page. Its will be prevent all multi request. :)

Categories