Javascript foreach loop calls ajax several times - javascript

So I am trying to create to do list with several boards. Each board have add item button. If I click add item button it opens modal where to insert task info. But if I click add item button several times and then insert info to modal and press save ajax fires as many times i clicked add item button. How can I prevent from that?
var addNewItems = document.querySelectorAll("#addNewItem");
var addNewSubmits = document.querySelectorAll("#listItemSave");
addNewItems.forEach(function(addNewItem) {
addNewItem.addEventListener("click", function(e) {
var newItemModal = this.nextElementSibling;
newItemModal.classList.toggle("hidden");
var addNewBtn = newItemModal.querySelector("#listItemSave");
//current board
var board = this.closest("div.list");
//current list
var list = board.querySelector(".todo--items");
addNewBtn.addEventListener ("click", function(e) {
//current board id
var boardId = board.dataset.boardid;
//current title
var title = newItemModal.querySelector("#listTitle");
var titleValue = title.value;
//current content
var content = newItemModal.querySelector("#listTextarea");
var contentValue = content.value;
$.ajax({
type: "POST",
url: "add.php",
data: { content: contentValue , title: titleValue , listid: boardId },
success: function(data, textStatus, jqXHR) {
$("#todoItems-" + id + "").append(data);
}
});
});
});
});

You could use a variable, lets say busy, to validate that an AJAX request isn't already on going.
You could set this variable in the beforeSend callback of AJAx and then updated it back to false in the finally callbac :
var addNewItems = document.querySelectorAll("#addNewItem");
var addNewSubmits = document.querySelectorAll("#listItemSave");
addNewItems.forEach(function (addNewItem) {
addNewItem.addEventListener("click", function (e) {
var newItemModal = this.nextElementSibling;
newItemModal.classList.toggle("hidden");
var addNewBtn = newItemModal.querySelector("#listItemSave");
//current board
var board = this.closest("div.list");
//current list
var list = board.querySelector(".todo--items");
var busy = false;
addNewBtn.addEventListener("click", function (e) {
//current board id
var boardId = board.dataset.boardid;
//current title
var title = newItemModal.querySelector("#listTitle");
var titleValue = title.value;
//current content
var content = newItemModal.querySelector("#listTextarea");
var contentValue = content.value;
if (!busy) {
$.ajax({
type: "POST",
url: "add.php",
beforeSend: () => {
busy = true;
}
data: {
content: contentValue,
title: titleValue,
listid: boardId
},
success: function (data, textStatus, jqXHR) {
$("#todoItems-" + id + "").append(data);
},
complete: () => {
busy = false;
}
});
}
});
});
});
This is a pretty simple solution but it works.

You can use addNewBtn.onclick = function () {} instead to overlap the previous listener in this case.
But it's not recommended to register listeners inside another listener. Try to move it out of there.

Related

trying to appendChild and removeChild at the same time

$('#submit').on('click', function(){
$.ajax({
type:'GET',
url:'http://www.boredapi.com/api/activity/',
success: function(data){// my data
console.log(data);
console.log(data.activity);
var body = document.getElementById('add');
var newDiv = document.createElement('div');
newDiv.innerText = data.activity;
console.log(newDiv); //my data
console.log(body);
var num = 0;
body.appendChild(newDiv);
$('#submit').on('click', function(){
body.removeChild(newDiv);
})
}
})
})
I am trying to add one div with one click, and with a second click remove the first div and add a new div in its place. Right now, I figured out a way to have another eventListner to make a second 'click' remove the first div and add a second but the third click it'll go right back to storing every div with each click. I thing a loop between both eventListner will work but not sure how to make that work logically. I hope I've explained this well enough. Thank you in advance for your help.
$('#submit').on('click', function(){
$.ajax({
type:'GET',
url:'http://www.boredapi.com/api/activity/',
success: function(data){// my data
console.log(data);
console.log(data.activity);
var body = document.getElementById('add');
var newDiv = document.createElement('div');
newDiv.innerText = data.activity;
console.log(newDiv); //my data
console.log(body);
$("#add").empty()
body.appendChild(newDiv);
}
You can use replaceWith() in this case:
Like:
var body = document.getElementById('add');
var newDiv = document.createElement('div');
var old_div = document.querySelectorAll('#add>div') !== null;
if(!old_div){
body.appendChild(newDiv);
} else {
old_div.replaceWith(newDiv);
}
If third line is not understandable, see here.
Overall, your code will look sthg like this:
$.ajax({
type:'GET',
url:'http://www.boredapi.com/api/activity/',
success: function(data){// my data
console.log(data);
console.log(data.activity);
var body = document.getElementById('add');
var newDiv = document.createElement('div');
var old_div = document.querySelectorAll('#add>div') !== null;
newDiv.innerText = data.activity;
if(!old_div){
body.appendChild(newDiv);
} else {
old_div.replaceWith(newDiv);
}
})
}
})
*Note:- success, error, complete are depreciated are removed from version 3.0. Refs
You need to check if the div exists before removing it. The first time the form is submitted there is no div, so it's going to be created and then the new click event will be binded. Then when you click again that div already exists, so you are creating it again, before removing the previous one. I suggest you to add an id to the div in the moment you create it
I would do:
$('#submit').on('click', function () {
$.ajax({
type: 'GET',
url: 'http://www.boredapi.com/api/activity/',
success: function (data) {
var body = $('#add');
if($('#NewDiv')){
body.removeChild($('#NewDiv'))
}
// my data
console.log(data);
console.log(data.activity);
var newDiv = $(document.createElement('div'));
newDiv.attr('id', 'NewDiv');
newDiv.innerText = data.activity;
console.log(newDiv); //my data
console.log(body);
var num = 0;
body.appendChild(newDiv);
}
})
})
This solution stores newDiv and ensures that it's not null before it's removed:
<script>
var newDiv = null;
var body = document.getElementById('add');
$('#submit').on('click', function () {
if (newDiv) {
body.removeChild(newDiv);
}
$.ajax({
type: 'GET',
url: 'http://www.boredapi.com/api/activity/',
success: function (data) {// my data
console.log(data);
console.log(data.activity);
newDiv = document.createElement('div');
newDiv.innerText = data.activity;
console.log(newDiv); //my data
console.log(body);
var num = 0;
body.appendChild(newDiv);
}
})
});
</script>
Here is a solution on how you can remove and append divs using clicks, I have added a counter to demonstrate the change, you can accustom this solution to fit your need
let body = document.getElementById('add');
let olddiv = document.getElementById('olddiv');
let divs=document.getElementsByClassName("div");
flag = false
counter = 0
$('#submit').on('click', function() {
if (!flag) {
addiv(counter)
console.log("divadded ",divs)
counter++
flag = true
} else {
addNewDiv(counter)
counter++
flag = false
}
})
function addiv(counter) {
while (body.hasChildNodes()) {
body.removeChild(body.firstChild);
}
var newDiv = document.createElement('div');
newDiv.id = `olddiv${counter}`
newDiv.className = "div"
newDiv.innerText = counter;
body.appendChild(newDiv);
}
function addNewDiv(counter) {
while (body.hasChildNodes()) {
body.removeChild(body.firstChild);
}
addiv(counter)
console.log("removed",divs)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="add"></div>
<button id="submit">changeDiv</button>

Launch modal in modal

I want to launch a modal in a modal. It's actually working, but if I open the 2nd modal in the 1st modal, the 2nd modal appears, but behind the 1st modal and the scroll bar disappear, when I close the 1st modal: modal
The JavaScript is in my modal PHP file.
How can I solve this problem?
Javascript
$(document).ready(function() {
$('.relations').click(function(e) {
var checkBoxes = $("input[name=case]");
var checkedBoxes = checkBoxes.filter(":checked");
if (checkedBoxes.length === 0) {
return false;
}
e.preventDefault();
var insert = [];
$('.checkboxes').each(function() {
if ($(this).is(":checked")) {
insert.push($(this).val());
}
});
insert = insert.toString();
var data_id = $(this).attr("id");
$.ajax({
url: "nodes.php",
method: "post",
dataType: "json",
data: {
data_id: data_id,
insert: insert
},
success: function(data) {
$('#moreInfo').html(data);
$('#dataModal').modal("show");
var nodeDatas = new vis.DataSet();
nodeDatas = data;
$.ajax({
method: "post",
dataType: "json",
url: "edges.php",
data: {
data_id: data_id
},
success: function(data) {
var edgeDatas = new vis.DataSet();
edgeDatas = data;
var myDiv = document.getElementById("moreInfo");
data = {
nodes: nodeDatas,
edges: edgeDatas
};
var options = {
};
var network = new vis.Network(myDiv, data, options);
}
});
}
});
});
});
I'm assuming that the second modal is moreInfo div, if that's correct, you need to make few css changes for that element to appear on top of the first modal, using z-index:99999; maybe more, and also for the scrollbar to appear you need another css property overflow:scoll;
I hope this helps!

JQuery data is not "bind" with click submit

i have a tip game where are many games on a list. If you click on a game´s quote, a modal opens with the data and you can set your amount and then with submit you can submit it via ajax. I don´t know whats going wrong, but since 2 days i have a binding problem.
When i click on some quotes and then I take an amount.. then it submits not only one, it submits all i have clicked before...
that´s crazy.. here is my js code
$('.ui.buttons').on('click', 'a.quote.button', function (e) {
e.preventDefault();
// FOR DESKTOP
// $('#bet').fadeIn(300);
var id = $(this).data('id');
var tip = $(this).data('tip');
var game = $(this).data('game');
var team = $(this).data('team');
var quote = $(this).data('quote');
var earnings = 0;
var amount = $('#stake').val();
console.log(game);
$('#game').text(game);
$('#team').text(team);
$('#tip').text(tip);
$('#quote').text(quote);
bet.modal('show');
//bet.on('change', '#submit', function(){
// console.log(2);
$("#submit").bind('click', function (ev) {
ev.preventDefault();
$(this).unbind(ev);
var game = {};
game.id = id;
game.tip = tip;
game.quote = quote;
game.amount = $('#stake').val();
//SEND TIP
$.ajax({
type: 'POST',
url: url + '/bet',
data: {game_id: game.id, tip: game.tip, quote: game.quote, stake: game.amount}, .....
});
I solved it. I have closed it before the #submit binds.
$('body').on('click', 'a.quote.button', function (e) {
// e.stopPropagation();
$('a.button.active').removeClass('active');
$(this).addClass('active');
// FOR DESKTOP
// $('#bet').fadeIn(300);
id = $(this).data('id');
tip = $(this).data('tip');
game = $(this).data('game');
team = $(this).data('team');
quote = $(this).data('quote');
earnings = 0;
amount = $('#stake').val();
console.log(game);
$('#game').text(game);
$('#team').text(team);
$('#tip').text(tip);
$('#quote').text(quote);
bet.modal('show');
earnings = quote * amount;
return false;
});
$("#submit").on('click', function () {
....
});

Adding event handler to non-existent class?

I've seen questions that relate to non-existent elements, but not non-existent classes. Here's what I want to do. When a button of class "see_answer" is clicked, I want to remove the class and replace it with "see_question". However, my click function for a button, once its class is "see_question", is not running. I have tried $(document).on("click", ".see_question", function(event ) and I have tried $(".see_question").on("click", function(event) {etc.... Thanks for the help! My code is below:
$(document).ready(function() {
// initialize variables
var lang = "javascript";
var qno = 1;
var prevText; // holds question/answer
var language = lang + ".html";
// set up tabs, and keep track of which one is clicked
$("#myTabs").tabs({
activate: function (event, ui) {
var active = $("#myTabs").tabs("option", "active");
lang = $("#myTabs ul > li a").eq(active).attr("href");
lang = lang.replace("#", "");
}
});
/* REMINDERS
actual qa part: blah_language
*/
// set up question
$.ajax({
url: language,
dataType: "html",
success: function(data) {
$("#blah_"+lang)
.text($(data).find("#1").text());
},
error: function(r) {
alert("whoops, error in initialization");
}
});
$(".next_question").on("click", function(event) {
event.preventDefault();
var id = $(this).attr("id").replace("next_question_", "");
var language = id + ".html";
var doc = "#blah_" + id;
$.ajax({
url: language,
dataType: "html",
success: function(data) {
var num = "#" + qno;
$(doc)
.text($(data).find(num).text());
qno = qno + 1;
},
error: function(r) {
alert("whoops");
}
});
prevText = "";
});
// SHOW ANSWER
$(".see_answer").on("click", function(event) {
event.preventDefault();
var id = $(this).attr("id").replace("see_answer_", "");
var prev = "#blah_" + id;
var answers = id + "_answers.html";
// Save the question
prevText = $(prev).text();
var obj = $(this);
$.ajax({
url: answers,
dataType: "html",
success: function(data) {
var num = "#" + 3;
$(prev)
.text($(data).find(num).text());
},
error: function(r) {
alert("whoops");
}
});
obj.val("See Question");
obj.removeClass("see_answer");
obj.addClass("see_question");
event.stopPropagation();
});
$(document).on("click",".see_question", function(event) {
event.preventDefault();
obj = $(this);
event.preventDefault();
var id = $(this).attr("id").replace("see_answer_", "");
var prev = "#blah_" + id;
$(prev).text(prevText);
obj.val("See Answer");
obj.removeClass("see_question");
obj.addClass("see_answer");
});
})
Click handling for .see_question elements is delegated to document. For .see_answer elements, a click handler is attached directly. Therefore, swapping the class names will have an undesirable effect.
when see_answer is in force, a click will trigger the "see_answer" handler.
when see_question is in force, a click will trigger the "see_question" handler AND the "see_answer" handler, which is still attached.
There's a number of ways to do this properly. From where you currently are, the simplest solution is to delegate click handling of .see_question and .see_answer elements to document.
$(document).on("click", ".see_answer", function(event) {
...
});
$(document).on("click", ".see_question", function(event) {
...
});
Combine the 2 handlers and figure out which version it is by hasClass() before you change the classes around
$(document).on("click", ".see_question, .see-answer", function(event ){
var $btn =$(this), isAnswer = $btn.hasClass('see_answer');
// we know which one it is so can switch classes now
$btn.toggleClass('see_answer see_question');
if(isAnswer){
/* run code for answer version */
}else{
/* run code for question version */
}
});

How to achieve recursive call - jquery

I have a custom created dialog module.
I am passing a mvc view called Cart to this module.
The cart view has a link called 'Create New Contat' clicking on which the view(Cart) will be replaced with another view(Contact) using an ajax call. The contact view has a button called cancel. When the user clicks on Cancel the old view(Cart) will replace the existing view(contact).
The problem I am facing is after replacing the view none of the links or buttons work on the view.
Can some body pls directed me towards a better way of doing this.
Pasted below is the code.
$(document).on('click', '.ddlCart li', function(e) {
var ddlselectedVal = $(this).attr('id');
var selectedListinsCount = selected_Listings.length;
var SelectedMlsnums = selected_Listings.join();
var agentId = $("#AgentId").val();
var Action;
var EnvironmentURL = $("#EnvironmentURL").val();
var postData = { AgentId: agentId, Mlsnums: SelectedMlsnums, ActionTypeValue: “PreAddToCart” };
var close = function (event, ui) {
$('#dvModalDialog').dialog("close");
}
var open = function (event, ui) {
var url = EnvironmentURL + "MLSReports/Stats/SearchContacts";
$("#btncart_cancel").on("click", function () {
$('#dvModalDialog').dialog("close");
});
$("#btncart_submit").on("click", function () {
var url = EnvironmentURL + "MLSReports/Stats/Cart";
//Send the data using post and put the results in a div
$.post(url, {
AgentId: agentId, Mlsnums: SelectedMlsnums, ActionTypeValue: "AddToCart"
},
function (data) {
// Replace current data with data from the ajax call to the div.
$("#dvModalDialog").empty().append(data);
});
});
$("#lnkCreateNewcart").on("click", function () {
var url = EnvironmentURL + "MLSReports/Stats/Cart";
//Send the data using post and put the results in a div
$.post(url, {
ActionTypeValue: "preAddorEditContact"
},
function (data) {
//debugger;
// Replace current data with data from the ajax call to the div.
$("#dvModalDialog").empty().append(data);
$("#btnCancelContact").on("click", function () {
////********** replace the view (Contact) with the view (Cart).
// In the cancel event I am loading the previous page.I am having problem here. after post none of the controls work.
$.post(url, {
ActionTypeValue: "PreAddToCart"
},
function (data) {
//debugger;
// Replace current data with data from the ajax call to the div.
$("#dvModalDialog").empty().append(data);
})
});
});
});
};
if (ddlselectedVal == "AddtoCart") {
var rd = Mod.ReportsDialog({ title: 'Add To Cart', close: close, open: open });
rd.url = EnvironmentURL + "/MLSReports/Stats/Cart";
rd.targetElement = '#dvModalDialog'// '#dvSendEmail'
rd.formName = '#frmCart'
rd.postData = postData
rd.open();
}
});

Categories

Resources