Here is my example.
By clicking the add button, I add a user card. "Clear button" removes all cards. How to remove cards one by one clicking on the "close" icon in each card?
HTML file
<div class="header">
<button id="clear" class="button clear">Clear</button>
<button id="button" class="button add">Add user</button>
</div>
<div id="content">
</div>
JS file
var root = 'https://jsonplaceholder.typicode.com';
var index = 0;
$.ajax({
url: root + '/posts/1/comments',
method: 'GET'
}).then(function(data) {
$("#button").click(function() {
var notificationMessage = "Oops, there are no more user cards to display";
if (index >= data.length ) {
return alert(notificationMessage);
}
$("#content").append('<div id="card"><div class="title"><div class="image"></div><div id="name">'
+ data[index].name + '</div><span id="close"></span></div><div id="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
index++;
// remove all cards from a list and return index equally [0], to be able add user card again.
$("#clear").click(function() {
$("#card").remove();
index = 0;
});
});
});
//How to remove card by clicking on the close button?
have you try to use class in card element?
because id selector only get first matching element
$.ajax({
url: root + '/posts/1/comments',
method: 'GET'
}).then(function(data) {
$("#button").click(
function() {
var notificationMassage = "Oops, there are no more user cards to display";
if (index >= data.length ) {
return alert(notificationMassage);
}
$("#content").append('<div class="card"><div class="title"><div class="image"></div><div class="name">'
+ data[index].name + '</div><span class="close"></span></div><div class="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
index++;
// remove all cards from a list and return index equally [0], to be able add user card again.
$("#clear").click(function() {
$("#content").html('');
index = 0;
});
});
to remove one by one add this code
// remove one cards from a list.
$("#content").on("click", ".close", function() {
$(this).closest('div.card').remove();
});
First of all you need to change id to to class.
And here is solution:
codepen.io/ivanchuda/pen/xRjyJp
First of all, ids should be unique. I recommend changing yours into classes.
$("#content").append('<div class="card"><div class="title"><div class="image"></div><div class="name">'
+ data[index].name + '</div><span class="close"></span></div><div id="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
Now that we have all close icons with class close, we can add the following listener for all .close buttons to remove only the card which contains them.
$(document).on('click', '.close', function(){
$(this).closest('.card').remove(); // remove only closest '.card'
});
First off, I would change the ID on the divs to class instead since you are generating multiple cards. IDs should be unique. Then I would change the code to add one more line to your close-span:
<span class="close" onclick="$(this).parent().parent().remove()"></span>
Try like this
See the updated codeopen
Change the id to class .And match with parent() of parent()
on() more important
$(document).on("click",".close",function() {
$(this).parent().parent().remove()
});
You can use this code to implement what you want:
$("body").on("click", ".close", function(e) {
$(this).closest('.card').remove();
});
Note: Remember that use only single ID on a single page, instead use classes to make it work
See this CodePen
// jQuery on() method description
.on( events [, selector ] [, data ], handler )
See more about jQuery's on() method.
Hope this helps!
The short and not elegant answer is:
$("#content").on("click", "span[id=close]", function() {
$(this).closest("div[id=card]").remove();
});
This should work, but you need to do a better job than this. Your HTML is invalid, since id is expected to be unique and you use the very same id for different items. You could use classes instead, or make sure that the identifier is unique. Note that your SEO will instantly improve if you make your HTML valid. If you use classes instead of not-unique ids, then the script above will change to this one:
//content is unique, therefore it can remain an id
$("#content").on("click", "span.close", function() {
$(this).closest("div.card").remove();
});
Related
I know there are many of these types of questions already on here, but I can't find one that matches my specific case.
I just want to pass an id variable into a function from an onclick event, but there's something not right about the way I've got is set up
The goal is to be able to remove the rows that have been added when the X is clicked
$(document).ready(function () {
$("#subjectlist")
.change(function () {
console.log("hit");
$("select option:selected").each(function () {
console.log($("select option:selected"));
var id = 1;
$('#overview').append("<tr id='id'><td>" +
$(this).text() + "</td><td id='id'
onclick='removeItem(id)'>" + "X" + "</td></tr>");
id = id + 1;
});
})
.trigger("change");
$(".btn1").click(function () {
$("#subjectlist").toggle();
});
});
function removeItem(id) {
console.log(id.val);
console.log(id);
$('#overview').find('tr td').eq(id).remove();
}
If your goal is to remove the 'td' element that is clicked. Try this...
$(document).ready(function () {
var id = 1;
$("#subjectlist")
.change(function () {
console.log("hit");
$("select option:selected").each(function () {
console.log($("select option:selected"));
//var id = 1; moved this initialization up a scope level
//on the line below I corrected the concatenation to have unique id's, and removed inline click event.
$('#overview').append("<tr id='id'><td>" + $(this).text() + "</td><td id="+id+">" + "X" + "</td></tr>");
id = id + 1;
});
})
.trigger("change");
$(".btn1").click(function () {
$("#subjectlist").toggle();
});
// added click event to your dynamic element
$("#overview").on('click','td', function() {
$(this).parent().remove();
});
});
/* removed
function removeItem(id) {
console.log(id.val);
console.log(id);
$('#overview').find('tr td').eq(id).remove();
}*/
Your appending string is incorrectly formatted.
Drop the id attribute on the table column since your removeItem() function should be targeting the table row.
You can use back ticks to generate template literals like so...
$('#overview').append(`<tr id="${id}">
<td>${$(this).text()}</td>
<td onclick="removeItem(${id});"> X </td>
</tr>`);
The jQuery.eq() function is an index based filter, not an selector filter. You can then utilise the id selector...
function removeItem (id) {
$(`#${id}`).remove();
}
Try changing this
$('#overview').append("<tr id='id'><td>" + $(this).text() + "</td><td id='id' onclick='removeItem(id)'>" + "X" + "</td></tr>");
To this... should be less confusing, regarding the quote-nesting... notice the use of backticks (`) on the outermost quote level. Also restyled it to make it easier to read, and match html syntax more visually.
$('#overview').append(
`<tr id=x_id_`+id+`>` +
`<td>` +
$(this).html() +
`</td>` +
`<td onclick="$('#x_id_` +
id +
`').remove()">` +
`X` +
`</td>` +
`</tr>`
);
You can ditch the removeItem function entirely.
Since I don't have the rest of your code, not totally sure about the change to the $().html vs $().text, but this should produce a clickable element that will remove the whole row with that id label, which is coded into the rows id and the onclick function.
This will produce html like:
<tr id=x_ix_1><td>PREVIOUS STUFF HERE</td><td onclick='removeItem(`x_id_1`)'>X</td></tr>
Couple things:
First, keep in mind you can only have one element with a particular id at a time. Duplicates will cause errors (but you can remove an element with a particular id and make a new one with that same id, they just can't co-exist).
If you don't want the row removed, but just the td, move the bit about the elements id from the tr to the td-- can't have same id on both.
The quote-nesting was incorrect with the id variable, so was adding it as litteral text (just the string 'id', not the variable content)...
And html id's need to start with a letter. So I re-nested it so the id will parse as variable contents, and the html output will contain 'x_id_' prepended to the variable content... i.e. x_id_0 x_id_1 etc.
I got a question, what I have already solved, but it's just so annoying.
I have a js code, which is putting down some html code when a button is pushed with "append", and with that code I'm giving an id to an x button, and an id to the container element. I wanted to use these id-s to identify them with a click function, to remove the html code:
var num = 0;
$('.button').click(funcion(){
num++;
var code = '\
<div class="container" id="text' + num + '">\
<div id="x' + num + '">\
x\
</div>\
Some stuff\
</div>\
';
$('.puthere').append(code);
$('#x' + num).click(function(){
$('#text' + num).remove();
});
});
Now the annoying part is the click function on the x. What I would expect is, that this code would work somehow like this:
1st click on the "button" class element should give this code:
$('#x1').click(function(){
$('#text1').remove();
});
after 2nd click I should have this:
$('#x1').click(function(){
$('#text1').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
instead what I'm getting after the 2nd click is this:
$('#x1').click(function(){
$('#text2').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
so it's always the last element what the x buttons want to remove. My question is, why can my "num" variable stay "1" at the #x1, but not at the #text1?
My solution was to address the parent element instead:
$('#x' + num).click(function(){
$(this).parent('.container').remove();
});
I know, that there is the "live" function too, what I could use, and I wouldn't need to mess with id-s, but that just seems more heavy. Is that correct? Or I'm overcomplicating things too much without making it more efficent?
It's because num is global and you access it after you create second button. To fix this you can wrap your code with anonymouse self executing function:
(function(num) {
$('#x' + num).click(function(){
$('#text' + num).remove();
});
})(num);
or better use only one click
$('.parent').on('click', '.container > div', function() {
$(this).parent().remove();
});
I'm creating anchor tags dynamically and I want them to call a function that has a set parameter for each one.
Example:
<div class="AnchorHolder">
<a onclick="someFunction(1)">someText</a>
<a onclick="someFunction(2)">someText</a>
<a onclick="someFunction(3)">someText</a>
</div>
I've tried
$("#AnchorHolder").append("<a>" + someText + "</a>").click(function (e) {
someFunction(someIntVariable);
});
but instead connects all of the anchors to the IntVariables current value, whereas I wanted the previous ones.
How can I accomplish this?
Well, I would suggest you to try data attributes. As far I know they are made for that porpuse. See:
$("#AnchorHolder").append("<a href='#' data-myvar='" + someIntVariable + "'>" + someText + "</a>");
// Keep the event binding out of any loop, considering the code above will be called more than once...
$("#AnchorHolder").on('click', 'a', function (e) {
alert($(this).data("myvar"));
});
Fiddle
If you just want the click on the new element, tack it onto that element, and not on the #AnchorHolder element:
var newAnchor = $("<a>" + someText + "</a>").click(function (e) {
someFunction(someIntVariable);
});
$("#AnchorHolder").append(newAnchor);
Or, alternatively to get each <a> to call the someFunction with their postion-inside-the-div:
$("#AnchorHolder a").each(function(idx) {
var a = $(this);
a.click(function() { someFunction(idx); });
});
You can always create a html element as following
$('<a>').attr("onclick","fun('hi')").html('Some text').appendTo("#AnchorHolder");
Hope this helps
I have a form where I add inputs dynamically. When I add a new input I increment a global id variable and concatenate it to the input's id so it will be unique. I also create a delete button for each input that should remove that input and himself (through removing the container <div> they are in). I do the remove process by adding an anonymous function to the delete button's click event via JQuery:
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
The only problem with this solution that it isn't work in the way I excepted it. When I click any of the delete buttons it will delete the last input container because when I click, it executes the anonymous function and evaluate the id variable at that time, so the selected id will be the last input's id. So always the last input container will be deleted.
Is there a way to rewrite this function so when I add it to the click event, than it will evaluate the id, inject it and handle the selection as if it had been written like #inputcontainer1, #inputcontainer2, etc.
I can make this by adding the function's body to the button's onclick() event:
var newbutton = '<button id="deletebutton' + id + '" type="button" onclick="javascript:$(\'#inputcontainer' + id + '\').remove();">x</button>';
But is there a way doing this with the JQuery click() way?
To answer the specific question, you'd have to dig the id out of the DOM:
$('#deletebutton' + id).click(function(){
var id = $(this).attr("id").replace('deletebutton','');
$('#inputcontainer' + id).remove();
});
You could also store it as data when you create the delete button:
<button data-id="1" id="deletebutton1">
$('#deletebutton' + id).click(function(){
var id = $(this).data("id");
$('#inputcontainer' + id).remove();
});
Note that in both of these cases, id is a string, not an integer.
When I click any of the delete buttons it will delete the last input container [...]
If your 1st snippet is inside a loop, id probably isn't being scoped to each iteration. So, by the time one of the click() events is triggered and it's trying to use .remove(), id will have already been set to the last value given while looping.
You can use an IIFE to create an additional function scope for keeping a different id for each iteration (ref: closure).
/* loop */ {
var id = ...;
(function (id) {
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
})(id);
}
Though, for future reference, ECMAScript 6 is adding block scoping which should allow for:
/* loop */ {
let id = ...;
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
}
$('#deletebutton' + id).click(function(){
$(this).parent().remove();
});
If the container isn't a direct parent and doesn't have a class you could do:
$('#deletebutton' + id).click(function(){
var idNum = $(this).attr("id").replace('deletebutton','');
$("#inputcontainer"+idNum).remove();
});
If you've got appropriate classes (or can add them), this would be best:
$(document).on("click",".deleteButton",function() {
$(this).parents(".inputContainer").remove();
});
I am reading contents from JSON file and adding to div with unique IDs. I need to call jquery slide down effects to each div. Lets us consider the case, on clicking (div id=A1) it should slide down and show (div id=B1), in that way I have div with IDs A(1..N) and B(1..N).
var i=1;
$.each(items, function (index, item) {
$(document).ready(function(){
$("#A"+i).click(function(){
$("#B"+i).slideToggle();
});
});
$("#allContents").append('<div id="A'+i+'">' + item.Name + '</div>');
$("#allContents").append('<div id="B'+i+'">' + item.Details + '</div>');
i++;
});
This is the closest code I could derive to, but it is not working. If anyone could help me fix or suggest a better way to get this thing working it would be great. Thanks a lot!
$('#allContents').on('click', 'div[id^=A]', function() {
$('div#B' + this.id.replace('A','')).slideToggle();
});
A little explain
div[id^=A] point out those div whose id start with A.
this.id retrieve the id of clicked element.
this.id.replace('A','') replace A form the id and get the numeric index which equal to index of B.
$('div#B' + this.id.replace('A','')) point to element id=B1, id=B2 and so on.
Full code
// you can bind event handler outside ot loop
$('#allContents').on('click', 'div[id^=A]', function() {
$('div#B' + this.id.replace('A','')).slideToggle();
});
$.each(items, function(index, item) {
$("#allContents").append('<div id="A' + i + '">' + item.name + '</div>');
$("#allContents").append('<div id="B' + i + '">' + item.Details + '</div>');
i++;
});
Working Sample
Note
As you're creating div from A(1..N) and B(1..N) dynamically so you need delegate event handler (aka live event).
Syntax of jQuery .on() for delegate event is like following:
$(container).on(eventName, target, handlerFunction)