i have a data which were parsed from json, i display the data in a box like facebook's friends suggestion box. i want when the user click on any of the suggested users the request to be added to DB via ajax and its corresponding button disappears,everything is working just fine except the last thing(button disappears) instead the very first button in the list gets disappear, while im searching for a solution to my problem i came across something called closure but i reaaly couldn't know how to implement it in my code, another problem appeared when i tried to declare the listener anonymous function inside the loop was the data get inserted in the DB multiple times (because its inside a loop), i know it might seems duplicated question but i just need someone pointing me the right place to declare my inner function,
my code looks like this
$(document).ready(function() {
var suggest = new XMLHttpRequest();
suggest.onreadystatechange = function() {
if (suggest.readyState === 4 && suggest.status === 200) {
var susers = JSON.parse(suggest.responseText);
for (var i = 0; i < susers.length; i += 1) {
var sphoto = '<div class="col-md-4 text-left "> <div id="fimage">';
sphoto += '<img width="50" height="50" src="user/';
sphoto += susers[i].activation + '/' + susers[i].pic + '"> </div> </div>';
var sname = '<div id="fname">' + susers[i].name + '</div>';
// here is the form im targetting to pull informtion from
var hidden = '<form id="fform"><input id="fnameh" name="name" type="hidden" value="' + susers[i].name + '" >';
hidden += '<input name="id" type="hidden" value="' + susers[i].id + '" >';
var fbutton = '<button id="addfriend"class="btn btn-info btn-xs pull-right text-center" type="submit" >Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button></form';
var display = document.getElementById('fsuggest');
display.innerHTML += '<div class="scroller"><div id="fspace" > <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' + sphoto + sname + hidden + fbutton +'</div></div>'
$('#addfriend').live('click', function(arg) {
return function() {
arg.preventDefault();
var data = $('#fform').serialize();
$.ajax({
data: data,
type: "post",
url: "addnew.php",
success: function(data) {
//make the text area empty
$('#addfriend').css("display", "none");
console.log(data);
}
}); // end of $.ajax
}(i); // end of inner function
}); // end of click listner
} //end of for loop
}
};
suggest.open('GET', 'box.php');
suggest.send();
}); // end of JQUERY ready
I am not sure why exactly you need closure
here. The problem seems to be with the multiple form & button with same id
.
All these buttons have same id
so the forms
. So
$('#addfriend').live('click', function(arg) {..}) has no reference to the particular button
Hope this change will help
Con-cat the value of i
with the id of the form & add an attribute data-id=i
the button.
Beside instead of id add class addfriend
to the button. So when this button will be clicked take the data-id
value. Use this value to get the relevant form with id , & serialize that
var hidden = '<form id="fform_' + i + '"><input id="fnameh" name="name" type="hidden" value="' + susers[i].name + '" >';
hidden += '<input name="id" type="hidden" value="' + susers[i].id + '" >';
var fbutton = '<button data-id="' + i + '" id=""class=" addfriend btn btn-info btn-xs pull-right text-center" type="submit" >Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button>';
Make below change to the click function.
Also reason of adding the event handler inside loop is not clear.
$('.addfriend').live('click', function(arg) {
arg.preventDefault();
var getDataId = $(this).attr('data-id') // get the data-id
var data = $('#fform_'+getDataId).serialize(); // get relevant form
$.ajax({
// rest of code
}); // end of $.ajax
})
Try to use jquery version above 1.9 to use the on
method for event delegation
I made a few changes to your code.
With the new javascript, I believe most browsers support string interpolation natively (without any extra plugins or pre-compiling with babel for example) so you can just interpolate your variables within backticks ``.
Also, you seemed to be creating a form with the id of #fform
and a button with the id of #addfriend
for each iteration. The problem is that calling $('#fform')
or $('#addfriend')
will return an array with as many elements as you have users.
So I added an extra data-suser-id
attribute with unique id
's on those. I am not sure the code will work because I can't actually try it and changed quite a few things but let me know if you are getting closer to your solution.
$(document).ready(function() {
var suggest = new XMLHttpRequest();
suggest.onreadystatechange = function() {
if (suggest.readyState === 4 && suggest.status === 200) {
var susers = JSON.parse(suggest.responseText);
var limit = susers.length;
for (var i = 0; i < limit; i += 1) {
var sphoto = `<div class="col-md-4 text-left ">
<div id="fimage">
<img width="50" height="50" src="user/${susers[i].activation}/${susers[i].pic}">
</div>
</div>`
var sname = `<div id="fname">${susers[i].name}</div>`
// here is the form im targetting to pull informtion from
var hidden = `<form id="fform" data-suser-id='${susers[i].id}'>
<input id="fnameh" name="name" type="hidden" value="${susers[i].name}" >
<input name="id" type="hidden" value="${susers[i].id}">`
var mutalusers = `</form><div id="mutal" class="text-left">
<h6>
<div id="fmutal">
<?php echo $c = mutal(${susers[i].id}, $me, $db) ?>
</div>
</h6>
</div>`
var fbutton = `<button id="addfriend" class="btn btn-info btn-xs pull-right text-center" type="submit" data-suser-id='${susers[i].id}'>Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button>`;
var display = document.getElementById('fsuggest');
display.innerHTML += `<div class="scroller">
<div id="fspace">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
${sphoto}
${sname}
${hidden}
${fbutton}
${mutalusers}
</div>
</div>`
// #live method is deprecated : http://api.jquery.com/live/
var addfriend_button = $(`#addfriend[data-suser-id=${susers[i].id}]`)
addfriend_button.on('click', function(arg) {
// return function(){
arg.preventDefault();
// the selector `#fform` doesn't seem to be unique to the current user's form data, so I added an data-attribute to make sure we are getting the correct form data
var data = $(`#fform[data-suser-id=${susers[i].id}]`).serialize();
$.ajax({
data: data,
type: "post",
url: "addnew.php",
success: function(data) {
//make the text area empty for the current user's `#addfriend` button
addfriend_button.html('done');
console.log(data);
}
}); // end of $.ajax
// }(i); // end of inner function : not sure why this inner function is necessary
}); // end of click listner
} //end of for loop
console.log(susers);
}
};
var suugestFile = 'box.php';
suggest.open('GET', suugestFile);
suggest.send();
}); // end of JQUERY ready