Why do the ajax requests fire multiple times - javascript

I have a form inside a modal that either saves a memo when one button is clicked or deletes it when another is clicked. The items get saved/deleted but the request count multiplies with each click. I'm getting 4 of the same request etc. How do i stop this. do i have to unbind something?
$('#modal').on('show.bs.modal', function (e) {
var origin = $(e.relatedTarget);
var memoId = origin.attr('data-id');
$('#modal').click(function(event){
if($(event.target).hasClass('memo-save')) {
event.preventDefault();
var memoText = $(event.target).parent().parent().find('textarea').val();
var memo = {
memo: memoText,
id: memoId
}
$.ajax({
type: "POST",
url: '/memos/add-memo?memo=' +memo+'&id=' + memoId,
data: memo,
success: function (result) {
$(event.target).toggleClass('active').html('Memo Saved');
}
});
} else if($(event.target).hasClass('memo-delete')) {
event.preventDefault();
var memoText = "";
var memo = {
id: memoId
}
$.ajax({
type: "POST",
url: '/memos/remove-memo?id=' + itemId,
data: memo,
success: function (result) {
$(event.target).toggleClass('active').html('Memo Deleted');
}
});
}
});
});

you can move the $('#modal').click outside the $('#modal').on('show.bs.modal' that way it will not re-add the listener each time the modal is shown

Related

How to change default selected option in bootstrap select2 in nested modal dialog programmatically with ajax?

I have a bootstrap modal dialog with a select2 option selector. when user clicks on edit button an ajax request calls and gets record info from server, then bootstrap modal dialog appears and initiates record data in a modal form.
But when a modal form appears select2 doesn't show true data. it shows default.
When user clicks on edit button the showEditModal() function gets call.
function showEditModal(getUrl) {
$('#modalCreate').on('show.bs.modal', function (event) {
initSelect2();
});
$.ajax({
url: getUrl,
type: "GET",
}).then(function (data) {
$('#pid').val(data.detail.pid);
$('#name').val(data.detail.title);
$('#number').val(data.detail.number);
$('#letterNumber').val(data.detail.letterNumber).trigger('change');
$('#abstract_desc').val(data.detail.abstractDesc);
$('#tags').val(tags);
$('#tags').trigger('change');
$('#modalUpdateArticle').modal('show');
});
}
function initSelect2() {
var getTagsUrl = "/tags";
$('#tags').remove();
var newOption = new Option("<...>", -1, false, false);
$("#tags").append(newOption).trigger('change');
$.ajax({
url: getTagsUrl,
type: "GET",
}).then(function (data) {
var tag = [];
for (i in data.detail) {
var tag = {id: data.detail[i].pid, name: data.detail[i].name};
var newOption = new Option(tag.name, tag.id, false, false);
$("#tags").append(newOption);
}
$("#tags").select2().trigger('change');
});
var getLetterUrl = "/letters";
$('#letterNumber').remove();
var newOption = new Option("<...>", -1, false, false);
$("#letterNumber").append(newOption).trigger('change');
$.ajax({
url: getLetterUrl,
type: "GET",
}).then(function (data) {
var letters = [];
for (i in data.detail) {
var letter = {id: data.detail[i].pid, name: data.detail[i].name};
var newOption = new Option(letter.name, letter.id, false, false);
$("#letterNumber").append(newOption);
}
$("#letterNumber").select2().trigger('change');
});
}
I see some mistake on your code. Based on your code, user click an edit button, and a modal dialog appears. you can call ajax when modal dialog shows. like this:
function showEditModal(getUrl) {
$('#modalCreate').on('show.bs.modal', function (event) {
initSelect2();
});
$('#modalUpdateArticle').modal('show');
}
$('#modalUpdateArticle').on('show.bs.modal', function (event) {
$.ajax({
url: getUrl,``
type: "GET",
}).then(function (data) {
$('#pid').val(data.detail.pid);
$('#name').val(data.detail.title);
$('#number').val(data.detail.number);
$('#letterNumber').val(data.detail.letterNumber).trigger('change');
$('#abstract_desc').val(data.detail.abstractDesc);
$('#tags').val(tags);
$('#tags').trigger('change');
$('#modalUpdateArticle').modal('show');
});
});

scroll div down on specific event

I have a simple chat application using Ajax and HTML.
Whenever I load new messages, I want to scroll the div to show the most recent message, so I'm doing the following:
jQuery:
function SendMessage()
{
var clientmsg = $("#comment").val();
var email = $("#email").val();
event.preventDefault();
if (clientmsg != '')
{
$.ajax(
{
type: 'POST',
url: url,
data:
{
email: email,
message: clientmsg
},
success: function (data)
{
// Success means the message was saved
// Call the function that updates the div with the new messages
UpdateChat();
$("#conversation").scrollTop($("#conversation").outerHeight() * 1000);
}
});
}
}
I use this line to scroll the div down to the maximum:
$("#conversation").scrollTop($("#conversation").outerHeight()*1000);
My problem is, it scrolls down to the maximum WITHOUT showing the new messages. It scrolls down till the last message before the new one. Which is weird, because I'm calling it after updating the chat. Here's the function that updates the chat:
function UpdateChat(){
$.ajax({
// URL that gives a JSON of all new messages:
url: "url",
success: function(result)
{
var objects = JSON.parse(result);
$("#conversation").html("");
objects.forEach(function(key, index){
//append the messages to the div
$("#conversation").append("html here");
});
}
});
};
As mentioned in comments, you can use a setTimeout() to let the dom update add give some time before scrolling. See code below:
function SendMessage()
{
var clientmsg = $("#comment").val();
var email = $("#email").val();
event.preventDefault();
if (clientmsg != '')
{
$.ajax(
{
type: 'POST',
url: url,
data:
{
email: email,
message: clientmsg
},
success: function (data)
{
// Success means the message was saved
// Call the function that updates the div with the new messages
UpdateChat();
setTimeout(function() {
$("#conversation").scrollTop($("#conversation").outerHeight() * 1000);
}, 500);
}
});
}
}
Assuming you insert a new element at the bottom, you could use scrollIntoView to make sure the new element is visible:
$.ajax({
// ...
success: function(data) {
var lastElement = $('#conversation :last-child');
lastElement[0].scrollIntoView();
}
});
Try putting the scroll line inside a setTimeout() method to allow about 500ms for things to update before scrolling down.
jQuery:
function SendMessage(){
var clientmsg = $("#comment").val();
var email = $("#email").val();
event.preventDefault();
if (clientmsg != '') {
$.ajax({
type: 'POST',
url: url,
data: {
email: email,
message: clientmsg
},
success: function (data) {
// Success means the message was saved
// Call the function that updates the div with the new messages
UpdateChat();
setTimeout(performScroll, 500);
}
});
}
}
and the scroll function
function performScroll() {
$("#conversation").scrollTop($("#conversation").outerHeight()*1000);
}

jQuery wait for .each to finish and run ajax call

I have the following code:
var allChecks = [];
$('input[type=text]').each(function () {
var key = $(this).attr("id");
allChecks[key] = [];
}).promise()
.done(function () {
$('input[type=checkbox]').each(function () {
if (this.checked) {
var ref = $(this).attr('id');
$('.' + ref).each(function () {
allChecks[ref].push({
amount: $("#" + ref).text()
});
});
} else {
allChecks[ref].push({
amount: 0.00
});
}
}).promise()
.done(function () {
$.ajax({
cache: false,
type: 'POST',
data: {
allChecks: allChecks
},
url: '/process',
beforeSend: function () {
console.log("Processing your checks please wait...");
},
success: function (response) {
console.log(response);
},
error: function () {
console.log("Error");
}
});
});
});
My Ajax call runs but I see no data passed as parameters, like if the array allChecks is empty. As JavaScript runs synchronously, I'm expecting that whatever I place after each() will not run until each() is complete, so the Ajax call should run fine and nor give me no data passed as if the array allChecks is empty. Any help or solution on this would be appreciated. Thanks.

stopping a function after first click, to prevent more executions

I have this function
function display() {
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
}
});
}
and it serves its purpose, the only problem is, a user can click on for as many times as possible, and it will send just as many requests to new.php.
What I want is to restrict this to just 1 click and maybe till the next page refresh or cache clear.
Simple example would be :
<script>
var exec=true;
function display() {
if(exec){
alert("test");
exec=false;
}
}
</script>
<button onclick="javascript:display();">Click</button>
In your case it would be :
var exec=true;
function display() {
if(exec){
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
exec=false;
}
});
}
}
This should do what you want:
Set a global var, that stores if the function already was called/executed.
onceClicked=false;
function display() {
if(!onceClicked) {
onceClicked=true;
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
}
});
}
}
During onclick, set a boolean flag to true to indicate that user clicked the link before invoking the display() function. Inside the display() function, check the boolean flag and continue only if it is true. Reset the flag to false after the AJAX completed processing (successful or failed).
You can use Lock variable like below.
var lock = false;
function display() {
if (lock == true) {
return;
}
lock = true;
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function (data) {
$('.daily').html(data);
lock = false;
}
});
}
you can implement this with that way too
$(function() {
$('#link').one('click', function() {
alert('your execution one occured');
$(this).removeAttr('onclick');
$(this).removeAttr('href');
});
});
function display(){
alert('your execution two occured');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" onclick="display();" id='link'>Have you only one chance</a>

Change class and text of button based on post result

I'm trying to change the class and text of the button that was clicked based on the result from an ajax post. The page has many buttons, none have IDs (although I could add them if it's for sure needed). I have the following javascript:
$('.ph-button').click(function () {
var selected = [];
$(this).closest('tr').each(function () {
$(this).find('td').each(function() {
selected.push($(this).html));
})
})
console.log(selected);
$.ajax({
type: "POST",
url: "/ClassSearch/watchClasses",
data: { arrayOfClasses: selected },
traditional: true,
success: function (data) {
//need the if statements here I think
console.log(data);
}
});
});
It works and gives me a 0 or 1 as data. I need to change the class to class='ph-button ph-btn-blue and the text to Watched if data is 0 and change the class to class='ph-button ph-btn-grey and the text to Watch if data is 1.
I tried using $(".ph-button").toggleClass("ph-button ph-btn-blue"); but it changed the class of all the buttons on the page and didn't seem to do it like I need.
I'm guessing toggleClass isn't what I need and i'm not sure how to address the button that was clicked instead of all of them. Here are the two possible buttons:
<td><button class='ph-button ph-btn-blue'>Watched</button></td>
<td><button class='ph-button ph-btn-grey'>Watch</button></td>
SOLUTION:
$('.ph-button').click(function () {
var selected = [];
var btn = $(this);
$(this).closest('tr').each(function () {
$(this).find('td').each(function(){
selected.push($(this).html());
})
})
console.log(selected);
$.ajax({
type: "POST",
url: "/ClassSearch/watchClasses",
data: { arrayOfClasses: selected },
traditional: true,
success: function (data) {
console.log(data);
if (data == 1) {
btn.toggleClass("ph-btn-grey ph-btn-blue").text('Watched');
}
if (data == 0) {
btn.toggleClass("ph-btn-blue ph-btn-grey").text('Watch');
}
}
});
});
set a temporary variable referencing the button, so you can use it later on in your AJAX success callback:
$('.ph-button').click(function () {
var selected = [];
var btn = $(this);
$(this).closest('tr').each(function () {
$(this).find('td').each(function(){
selected.push($(this).html());
})
})
$.ajax({
type: "POST",
url: "/ClassSearch/watchClasses",
data: { arrayOfClasses: selected },
traditional: true,
success: function (data) {
if(data == "0"){
btn.toggleClass("ph-button ph-btn-blue").text('Watched');
}
}
});
});

Categories

Resources