Remove dynamically created elements (with separate delete button) using jquery - javascript

I'm trying to delete dynamically created elements each with their own delete button. This is the element that gets added with every button click. When the delete button of an element gets clicked I want that specific element to be deleted.
I use the following code to append the element:
$("#addsitem").click(function () {
$("#holdsitems").append('myFunction');
});
This is how I try to remove it:
$("#item").on("click", "#deleteitem", function() {
$("#item").remove();
});
I can only delete the elements that haven't been added.
This is all the relevant HTML code (myFunction) of the element:
<div id="item" class="itemdiv">
<form>
<div>
<div id="deleteitem">
<input type="button" name="Delete Button" value="Delete">
</div>
</div>
</form>
</div>
I'm rather new to jQuery and this is giving me headaches. Would appreciate it lots if someone could help me out!

You can use classes and the command .closest("selector") where this moves up the DOM tree until it finds the first element that matches that selector, you can then remove this.
You shouldn't be adding an id dynamically, unless you are adding an indices so that they are unique.
Demo
// Add new item on click of add button
$("#addsItem").click(function(event) {
// Stop submission of form - this is not necessary if you take it out of the form
event.preventDefault();
// Append new form item
$("#holdsitems").append('<div class="item-wrapper"><button type="button" class="deleteItem" >Delete</button></div>');
});
// Add DYNAMIC click event to class .deleteItem
$(document).on("click", ".deleteItem", function() {
// Move up DOM tree until first incidence of .item-wrapper and remove
$(this).closest(".item-wrapper").remove();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="item" class="itemdiv">
<form>
<div id="holdsitems">
<button id="addsItem">Add Item</button>
<div class="item-wrapper">
<button type="button" class="deleteItem">Delete</button>
</div>
</div>
</form>
</div>

Related

Closest() in jQuery doesn't work when at the same level

Problem:
I want (after clicking on a button - this part is OK) to select the closest element with a class .my-textarea, but the using of prev() is not always possible, because the code is dynamic. Could you help?
Details:
I have this HTML code:
<div class="row">
<div class="label">Description:</div>
<textarea class="my-textarea" name="my-textarea" rows="8" cols="40"></textarea>
<button type="button" class="my-submit" name="my-submit">Save</button>
</div>
And my JS code (in on button with class "my-submit" click event) is:
var text = $(this).closest('.my-textarea').val();
But it's not working. I am getting undefined.
If I tried:-
var text = $(this).prev().val();
I will get the text of the text-area, but as I've mentioned, my code is dynamic and the order and number of elements will change. So, prev() is out of option.
Any idea how to make closest() work?
I always select parent and than search for child with class. That way your element can be placed virtually anywhere in parent.
$(this).parent().find('.my-textarea').val();
Need to Use siblings() instead of closest():-
$('.my-submit').click(function(e){
e.preventDefault();
var text = $(this).siblings('textarea').val();
console.log(text);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="label">Description:</div>
<textarea class="my-textarea" name="my-textarea" rows="8" cols="40"></textarea>
<button type="button" class="my-submit" name="my-submit">Save</button>
</div>
You need to refer it using class
closest will traverse up the DOM tree to look for the element, while in this case textarea is sibling of the button.
$('.my-submit').click(function(){
var text = $(this).siblings('.my-textarea').val();
alert(text)
})
DEMO

toggle class on ul to change font

I'm very new to javascript & jQuery and I'm having trouble with toggling a class when a button is clicked. The desired output is to have the user add items as they click a button. That works fine. However when they want to check an item off their list, I can't get the font to change to be strike-through when the user clicks the button that is inside the <li>.
I think I'm close but there's something amiss.
Any help is appreciated.
CODE:
function checkItem(element) {
// toggles the class shopping-item__checked when button inside the parent <li> is clicked
element.parent('li').toggleClass('.shopping-item__checked');
console.log(element);
}
// Event listeners
$(document).ready(function () {
console.log("ready!");
$('#js-shopping-list-form').submit(function (event) {
event.preventDefault();
addItem(state, $('#shopping-list-entry').val());
renderList(state, $('.shopping-list'));
});
$('ul.shopping-list > li').click(checkItem($(this).closest('shopping-item')));
});
HTML:
<div class="container">
<h1>Shopping List</h1>
<form id="js-shopping-list-form">
<label for="shopping-list-entry">Add an item</label>
<input type="text" name="shopping-list-entry" id="shopping-list-entry" placeholder="e.g., broccoli">
<button type="submit">Add item</button>
</form>
<ul class="shopping-list">
<li>
<span class="shopping-item">apples</span>
<div class="shopping-item-controls">
<button class="shopping-item-toggle">
<span class="button-label">check</span>
</button>
<button class="shopping-item-delete">
<span class="button-label">delete</span>
</button>
</div>
</li>
remove the '.' from the toggleclass,
function checkItem(element) {
// toggles the class shopping-item__checked when button inside the parent <li> is clicked
element.parent('li').toggleClass('shopping-item__checked');
console.log(element);
}
also u can try the following as alternative
function checkItem(element) {
// toggles the class shopping-item__checked when button inside the parent <li> is clicked
if(element.parent('li').hasClass('shopping-item__checked')){
element.parent('li').removeClass('shopping-item__checked');
}else{
element.parent('li').addClass('shopping-item__checked');
}
console.log(element);
}
You are binding event handlers the wrong way.
$('ul.shopping-list > li').click(checkItem($(this).closest('shopping-item')));
You need to pass the event information in the following manner.
function checkItem(event) {
//event information is passed. target contains the target element on which the event was fired. in this case the check button
var element = $(event.target);
// toggles the class shopping-item__checked when button inside the parent <li> is clicked
//element.parent('li').toggleClass('.shopping-item__checked');
element.closest('li').find('span.shopping-item').css('text-decoration','line-through');
console.log(element);
}
// Event listeners
$(document).ready(function () {
console.log("ready!");
$('#js-shopping-list-form').submit(function (event) {
event.preventDefault();
addItem(state, $('#shopping-list-entry').val());
renderList(state, $('.shopping-list'));
});
//bind each check button with the check item function
$('ul.shopping-list > li > div.shopping-item-controls > button.shopping-item-toggle').on('click', {event_data:this}, checkItem);
});
and modify your html to remove the span inside the button, coz it it's unecessary.
<div class="container">
<h1>Shopping List</h1>
<form id="js-shopping-list-form">
<label for="shopping-list-entry">Add an item</label>
<input type="text" name="shopping-list-entry" id="shopping-list-entry" placeholder="e.g., broccoli">
<button type="submit">Add item</button>
</form>
<ul class="shopping-list">
<li>
<span class="shopping-item">apples</span>
<div class="shopping-item-controls">
<button class="shopping-item-toggle">
<!--<span class="button-label">check</span>-->
<!-- recommend not to use the span, since you will not be able to capture click event of button -->
check
</button>
<button class="shopping-item-delete">
<span class="button-label">delete</span>
</button>
</div>
</li>
the .closest() method finds the closest matching ancestor, while the .find() method finds the closest matching child.
https://coderwall.com/p/wxjljq/jquery-find-and-closest-are-your-best-friends
First things first you are adding the callback function wrong for the jQuery click event.
$('ul.shopping-list > li').click(checkItem($(this).closest('shopping-item')));
You are actually passing in undefined as a callback function because you are calling checkItem() right away and that function returns nothing. So everytime you click on the li elements they do nothing.
Lets fix that by just adding in the function name without any paranthesis. So we are not calling it we are just passing it through as a parameter.
$('ul.shopping-list > li .shopping-item-toggle').click(checkItem);
I have also targeted the check button for the click in this example. Now everytime the button is clicked it will call checkItem and pass in an event object like so: checkItem(event);
Looking at your checkItem function it is expecting an element to be passed through, well lets change that part:
function checkItem(event) {
// toggles the class shopping-item__checked when button inside the parent <li> is clicked
$(this).closest('li').toggleClass('shopping-item__checked');
console.log(this);
}
I changed a few things here. I changed the parameter name from element to event and I changed element.parent('li').blah.blah to $(this).closest('li').blah.blah
this is going to represent the element clicked and I wrap it in a jquery selector so I can chain some stuff to it like the closest and toggleClass methods.
Now I noticed that this is going to work for the first element but its not going to work for elements that you add later. This is because you would have to add a click event to the new list item everytime you call addItem. There is an easier way to do that and it would require us to modify how we add the click event in the first place.
$('ul.shopping-list').on('click', 'li .shopping-item-toggle', checkItem);
This technique that we are using now is called Event Delagation. Now I am actually adding the click event on the entire shopping list and its going fire on all li .shopping-item-toggle items that were clicked inside the shopping list. This means the elements don't yet need to be added at this point for them to have a click event work on it. They can be added later and it will still work. Now when you add new items you can click on them and they will have the click event fire.

Jquery 1.10 combination of live() and clone() - weird behaviour

i want to clone a element and insert on another position in the DOM. (So actually i just want to 'move' it).
On document ready some events get binded in a Plugin (which i don't want to edit) to a child element of the element i want to clone.
When i clone the element like this:
$('.FSGD-logo-slider-element-info').each(function(){
$number = $(this).attr('data-trigger');
$element = $(this).clone(true, true);
$('.FSGD-logo-slider-element[data-index="'+$number+'"]').after($element);
$(this).remove();
});
The element is cloned, but they don't react on any Events.
When i do it like this (Have a look on the third line with the live-method):
$('.FSGD-logo-slider-element-info').each(function(){
$number = $(this).attr('data-trigger');
$element = $(this).live().clone(true, true);
$('.FSGD-logo-slider-element[data-index="'+$number+'"]').after($element);
$(this).remove();
});
It is working. But the live method is removed since jquery 1.9, because of that i also get an error output.
I can't explain why that code is working and i don't have any idea to get it working without the live method.
I hope someone is able to help. That would be awesome.
i want to clone a element and insert on another position in the DOM. (So actually i just want to 'move' it).
Then just move it:
$('.FSGD-logo-slider-element-info').each(function(){
var $number = $(this).attr('data-trigger');
$('.FSGD-logo-slider-element[data-index="'+$number+'"]').after(this);
});
Example:
// Hook an event on a child of the info elements
$(".FSGD-logo-slider-element-info input").on("click", function() {
alert($(this).parent().attr("data-trigger"));
});
// Move the elements
setTimeout(function() {
$('.FSGD-logo-slider-element-info').each(function(){
var $number = $(this).attr('data-trigger');
$('.FSGD-logo-slider-element[data-index="'+$number+'"]').after(this);
});
$("p").remove();
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="FSGD-logo-slider-element-info" data-trigger="1">
Info One <input type="button" value="Click me">
</div>
<div class="FSGD-logo-slider-element-info" data-trigger="2">
Info Two <input type="button" value="Click me">
</div>
<div class="FSGD-logo-slider-element-info" data-trigger="3">
Info Three <input type="button" value="Click me">
</div>
<div class="FSGD-logo-slider-element-info" data-trigger="4">
Info Four <input type="button" value="Click me">
</div>
<div class="FSGD-logo-slider-element" data-index="1">
Element One
</div>
<div class="FSGD-logo-slider-element" data-index="2">
Element Two
</div>
<div class="FSGD-logo-slider-element" data-index="3">
Element Three
</div>
<div class="FSGD-logo-slider-element" data-index="4">
Element Four
</div>
<p>Elements will move after a second</p>
Side note: I added var in front of $number = ... above. Without it, your code was falling prey to The Horror of Implicit Globals (unless of course it was declared in a parent scope, but this is clearly used as a local, so that wouldn't make much sense).

Remove items one at a time using JQuery

I am trying to create a to-do list using HTML/CSS, Javascript and JQuery. The problem I have occurs when I try to delete an item off the list. Here is the Javascript.
$(document).ready(function(){
$('#add').click(function(){
if($('#input').val() != '')
$('.container').append('<p class="todo">'+$('#input').val()+'</p><span class="del">&times</span><br/>');
});
$(document).on('click','.del',function(){
$(this).click(function(){
$('.todo').hide();
});
});
});
The HTML
<body>
<h1 class="header">To-Do List</h1>
<hr/>
<br/>
<input type="text" id="input"/>
<button id="add">Add</button>
<br/>
<br/>
<div class="container">
</div>
</body>
What the above does is it removes all of the dynamically generated todo [paragraph] elements when a single del element [an x] is clicked. I am asking how to change the code so clicking the del element removes the todo element that it was generated with. I understand I can use ids but I feel that is too cumbersome. Thanks for the help.
You can use .prev() to hide only the immediate previous sibling .todo paragraph of clicked .del:
$('.container').on('click','.del',function(){
$(this).prev().hide();
});
Also take note that you don't need to use .click() event for .del any more since you've already using event delegation to attach the click event to them as well as using closest static parent for delegated event instead of $(document).
Try this jQuery, this also hides the 'x':
$(document).on('click','.del',function(){
$(this).hide();
$(this).prev().hide();
});

javascript - remove element

My question is rather elementary, but I do not understand why, in the following code, on button click only button dissapears, instead of the whole div:
<script>
function remove(id) {
//get the element node
element = document.getElementById(id);
//remove the element from the document
document.removeChild(element);
}
</script>
<div id="intro" class="jumbotron">
<h1>Your Offline Web Dictionary!</h1>
<p class="lead">
<div class="controls">
<input class="span7 " type="text" placeholder=" " name="key">
</div>
<div>
<button class="btn btn-large btn-success" onclick="remove(intro)">
Dictionary Search
</button>
</div>
</div>
JSFiddle
The problem is that the button element has a remove property so that is called instead of your remove function. And also the string thing.
<button class="btn btn-large btn-success" onclick="window.remove('intro');console.log(this.remove);">
Search
</button>
http://jsfiddle.net/HMEVd/76/
Two problems. Firstly, intro should be a string, not an identifier, so use remove('intro') in your onclick.
Second, document.rwmoveChild is incorrect. removeChild should be called on the parent of the element you are removing. It is common to use:
element.parentNode.removeChild(element);
intro should be sent to the function as a string rather than a variable, i.e, 'intro'
Also, you must rename your function, for example, removeById instead of remove. Then it works perfectly.
The function remove actually does something completely different. (Your function is not even invoked when it is named remove as you can see by putting an alert message into it.)
function removeById(id) {
//get the element node
element = document.getElementById(id);
//remove the element from the document
document.removeChild(element);
}
...
<button class="btn btn-large btn-success" onclick="removeById('intro')">

Categories