How do I remove the parent element and all the respective nodes using plain JavaScript? I'm not using jQuery or any other library.
In other words, I have an element and when user clicks on it, I want to remove the parent of the parent element (as well as the respective children nodes).
<table id='table'>
<tr id='id'>
<td>
Mohit
</td>
<td>
23
</td>
<td >
<span onClick="edit(this)">Edit</span>/<span onClick="delete_row(this)">Delete</span>
</td>
<td style="display:none;">
<span onClick="save(this)">Save</span>
</td>
</tr>
</table>
Now,
function delete_row(e)
{
e.parentNode.parentNode.removeChild(e.parentNode);
}
Will remove only last <td>.
How do I remove the <tr> directly>?
e.parentNode.parentNode.getAttribute('id')
returns the id of the row...
Is there any function like remove() or delete() ?
Change your function like this:
function delete_row(e)
{
e.parentNode.parentNode.parentNode.removeChild(e.parentNode.parentNode);
}
You can now use node.remove() to remove the whole element
so in your case you'd do
function delete_row(e) {
e.parentElement.remove();
}
You can read more on it here
https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
node.parentNode.parentNode.removeChild(node.parentNode)
Edit: You need to to delete parent of parent, so add one more .parentNode
node.parentNode.parentNode.parentNode.removeChild(node.parentNode.parentNode)
Or for those who like a one-liner
<button onClick="this.parentNode.parentNode.removeChild(this.parentNode);">Delete me</button>
Change this:
onClick="delete_row(this)"
To this:
onClick="removeParents(this, document.getElementById('id'))"
function removeParents(e, root) {
root = root ? root : document.body;
var p = e.parentNode;
while(root != p){
e = p;
p = e.parentNode;
}
root.removeChild(e);
}
http://jsfiddle.net/emg0xcre/
You can specify it even more. Instead of parentElement.parentElement you can do something like this:
static delete_row(element) {
element.closest("tr").remove();
}
The other preferred way of handling such scenario would be event propagation instead of adding onclick to html element:
document.querySelector("#id").addEventListener("click", (e) => {
UI.handleEvents(e.target);
});
static handleEvents(el){
if (el.classList.contains("delete")) {
el.closest("tr").remove();
}
if (el.classList.contains("edit")) {
// do something else
}
if (el.classList.contains("save")){
// save records
}
}
<tr id='id'>
<td>Mohit</td>
<td>23</td>
<td >
<span class="edit">Edit</span> |
<span class="delete">Delete</span>
</td>
<td style="display:none;"><span class="save">Save</span></td>
</tr>
Simple function to do this with ES6:
const removeImgWrap = () => {
const wrappedImgs = [...document.querySelectorAll('p img')];
wrappedImgs.forEach(w => w.parentElement.style.marginBottom = 0);
};
I know it's a little too late, but someone else might find it useful.
e.target.parentElement.parentElement.parentElement.remove()
<div>
<span>1<button onclick="removeParents(this);">X</button></span>
<span>2<button onclick="removeParents(this);">X</button></span>
<span>3<button onclick="removeParents(this);">X</button></span>
<span>4<button onclick="removeParents(this);">X</button></span>
</div>
<script>
function removeParents(e) {
var root = e.parentNode;
root.parentNode.removeChild(root);
console.log(root);
}
</script>
working sample
If you want to delete whatever is inside the <tr> tags, by clicking on the "Delete", give that span a class name (whatever you want).
Then, in JS code: you basically select the element people will click with the document.querySelector(), add an Event Listener to it & on clicking on that span with that .whatever class, the element with the ID name "id" will be removed.
document.querySelector('.wtvr').addEventListener('click', function () {
document.getElementById('id').remove();
});
<table id="table">
<tr id="id">
<td>Mohit</td>
<td>23</td>
<td><span>Edit</span>/<span class="wtvr">Delete</span></td>
<td style="display: none">
<span>Save</span>
</td>
</tr>
</table>
I took the onclick away because you can delete a DOM element just using CSS class and a bit of JS.
Related
I am trying to use a button inside a table division to set a variable as the same value as another division in the same row, but whenever I run my code (below), it returns the value of all the table divisions concatenated together. I am unsure why this was happening, so I replaced '.children()' with 'childnodes[0]' to try and get only the first name, but this just doesn't work and I don't why.
My html looks like this:
<table>
<tr>
<td>John</td>
<td>Doe</td>
<td><button>Get First Name</button></td>
</tr>
</table>
And my Javascript is this:
$(document).ready(function(){
$("button").click(function(){
var first = $(this).closest("tr").childNodes[0].text();
alert(first)
})
});
set a variable as the same value as another division in the same row
there are lots of possibilities for this, here are some (with the most useful first (opinion based))
$("button").click(function() {
var first = $(this).closest("tr").find("td:first").text();
var first = $(this).closest("tr").find("td").first().text();
var first = $(this).closest("tr").find("td").eq(0).text();
var first = $(this).closest("tr").children().first().text();
var first = $(this).closest("tr").children().eq(0).text();
var first = $(this).closest("td").siblings().first().text();
});
it returns the value of all the table cells concatenated together
https://api.jquery.com/text
Get the combined text contents of each element in the set of matched elements, including their descendants, or set the text contents of the matched elements.
because you're passing the "tr" to text() it gets the text of all the cells (tds) and their content etc and combines them as one, so you need to limit to the first as you've attempted.
however .childNodes[0] can only be applied to a DOM element/node, while $(this).closest("tr") gives you a jquery object/collection, which doesn't have .childNodes property.
So the jquery equivalent would be to use .children().eq(0).
You could use class identifiers to get information you need as well.
<table>
<tr>
<td><span class="first-name">John</span></td>
<td><span class="last-name">Doe</span></td>
<td>
<button class="btn-get-data" data-class="first-name">Get First Name</button>
<button class="btn-get-data" data-class="last-name">Get Last Name</button>
</td>
</tr>
</table>
$(document).ready(function() {
$(".btn-get-data").click(function() {
$btn = $(this);
$tr = $btn.closest('tr');
var first = $tr.find('.' + $btn.attr('data-class')).html();
alert(first);
})
});
If you make the button click generic like so, you can add additional buttons on the page and use that to get the class within that row.
Here is a working fiddle example: https://jsfiddle.net/b1r0nucq/
you could find the :first child and get his html(), as below:
$(document).ready(function() {
$("button").click(function() {
var first = $(this).closest("tr").children(":first").html();
alert(first)
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>John</td>
<td>Doe</td>
<td><button>Get First Name</button></td>
</tr>
</table>
I am trying to make an interactive periodic table of elements. I need to change the background color of more <td> with the classname "nemetale" when a button is clicked. It's not working, I don't know what I am doing wrong.
There is the button
<button onclick="document.getElementsByClassName('.nemetale').style.backgroundColor = 'red';">Nemetale</button>
There is one of the <td>s.
<table class="tabel_periodic">
<!--Randul 1-->
<tr>
<td class="nemetale">
<strong>1</strong><br>
<acronym>H</acronym><br>
<em>Hidrogen</em><br>
<i>1,008</i>
</td>
...
Working fiddle.
getElementsByClassName() : Returns an array-like object of all child elements which have all of the given class names.
The function .getElementsByClassmame() doesn't exist you should use .getElementsByClassName().
Since the .getElementsByClassName() return a list of elements you should return the first element instead using [0] like :
document.getElementsByClassName('nemetale')[0].style.backgroundColor = 'red';
var trs = document.getElementsByClassName('nemetale');
document.getElementById('change_color').addEventListener('click', function() {
for (var i = 0; i < trs.length; i++) {
changeColor(trs[i]);
}
});
function changeColor(tr) {
tr.style.backgroundColor = 'red';
}
<button id="change_color">Nemetale</button>
<table class="tabel_periodic">
<tr>
<td class="nemetale">
<strong>1</strong><br>
<acronym>H</acronym><br>
<em>Hidrogen</em><br>
<i>1,008</i>
</td>
</tr>
<tr>
<td class="nemetale">
<strong>2</strong><br>
<acronym>H</acronym><br>
<em>Hidrogen</em><br>
<i>2,008</i>
</td>
</tr>
<tr>
<td class="nemetale">
<strong>3</strong><br>
<acronym>H</acronym><br>
<em>Hidrogen</em><br>
<i>3,008</i>
</td>
</tr>
</table>
Two things:
Firstly, there is a typo in the function you call. It should be getElementsByClassName().
Secondly, getElementsByClassName() returns a NodeList. This is “like” an Array, but it means you have to select each item from the NodeList.
If there is only one element, you can do
document.getElementsByClassName('nemetale')[0].style.backgroundColor = 'red';
If there is more than one element you will have to loop through the items. I recommend making it a function.
<button onclick="highlight">Nemetale</button>
function highlight() {
var items = document.getElementsByClassName('nemetale');
Array.from(items).forEach(function(item) {
item.style.backgroundColor = 'red';
});
}
If you are using ES6, you can make it a bit shorter as well:
function highlight() {
const items = document.getElementsByClassName('nemetale');
Array.from(items).forEach(item => item.style.backgroundColor = 'red');
}
You have a typo: getElementsByClassmame, this isn't a valid JS method.
Use .querySelector instead:
document.querySelector('.nemetale')
https://jsfiddle.net/d5dg0uw4/
Make it like below by adding function:
<button onclick="changeBackgroundColor()">Nemetale</button>
put this into
<script>
function changeBackgroundColor(){
document.getElementsByClassName('nemetale')[0].style.backgroundColor = 'red';
}
</script>
I'm trying to make a Div on the page Appear if a word exists later on the page? , what i'd actually like it to do is display if any words in a list of 10 appear on the page? The only place I want to look for them is inside of that TD class "sku nobr" after that span class "td-title"
I'm a total rookie at this, I got it to work for a H1 value with this code but I don't know how to do it with the 4523 where it is now??
THANKS!!!!!
<script type="text/javascript">
$(document).ready(function(){
if ($(".sku nobr:contains('4523')").length) {
$("#thingtohide").removeAttr("style").none();
}
});
</script>
<div id="thingtohide" style="display: none;">COOL TEXT TO DISPLAY</div>
<tr class="cart-item-row">
<td class="sku nobr">
<span class="td-title">SKU:</span>
4523
</td>
</tr>
First, your HTML is not valid. You're missing the <table></table> tags.
<div id="thingtohide" style="display: none;">COOL TEXT TO DISPLAY</div>
<table>
<tbody>
<tr class="cart-item-row">
<td class="sku nobr">
<span class="td-title">SKU:</span>4523
</td>
</tr>
</tbody>
</table>
Second, your selector is wrong. Replace .sku nobr:contains('4523') with .sku:contains('4523')
$(document).ready(function(){
if ($(".sku:contains('4523')").length) {
$("#thingtohide").show();
}
});
Edit If you are looking for any number (which can include commas), you have to be more creative. You can use the filter method. Here's another demo.
$(document).ready(function(){
// find TD with class 'sku' containing numbers
var $sku = $("td.sku").filter(function () {
// assuming the number is 4523,8563,9997,7757
// text = $.trim($(this).text()); => SKU:4523,8563,9997,7757
// text = text.replace(/SKU:|,/g, ''); => 4523856399977757
var text = $.trim($(this).text().replace(/SKU:|,/g, ''));
// check that it is a number
return text && !isNaN(text);
});
// check if there are any matches
if ($sku.length) {
$("#thingtohide").show();
}
});
It looks like you've got a minor typo.
$(".sku nobr:contains('4523')")
Change to:
$(".sku.nobr:contains('4523')")
Multiple classes need to be separated by a ., not a space.
for checking if a cel contains multiple pieces of text I did this:
<script>
$(document).ready(function(){
if ($(".sku:contains('4523'),.sku:contains('5678')").length) {
$("#thingtohide").show();
}
});
</script>
I need some help for doing a menu built automatically with jQuery.
I have the following HTML structure
<table width="99%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td height="20">Descripción</td>
</tr>
<tr>
<td height="20">Preguntas Frecuentes</td>
</tr>
<tr>
<td height="20">Incompatibilidades</td>
</tr>
</tbody>
</table>
...
<a name="descripcion"></a>
<h1>Descripcion</h1>
...
<a name="preguntas"></a>
<h1>Preguntas</h1>
In this case the anchor "incompatibilidades" doesn't exist, so what I need is to create a jQuery script which look for any "a" tag which has its corresponding link.
The result I expect is the following:
<table width="99%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td height="20">Descripción</td>
</tr>
<tr>
<td height="20">Preguntas Frecuentes</td>
</tr>
</tbody>
</table>
I'll appreciate your help!
If I understood correctly, you could do something like this:
var menu = $("#menu");
$("a").each(function() {
var $this = $(this);
var name = $this.attr("name");
if (typeof(name) !== 'undefined') {
var links = $("a[href='#"+name+"']");
var link;
if (links) {
link = links.eq(0);
}
if (link && typeof(link) !== 'undefined') {
menu.append("<tr><td><a href='#"+name+"'>"+link.text()+"</a></td></tr>");
}
}
});
You have to add "menu" id in a new table to create what you expect.
If you would like to remove the the table row which contains the mentioned anchor tag which does not exist, you could use:
$(document).ready(function() {
$('a[href="#incompatibilidades"]').closest('tr').remove(); // Or detach, possibly
});
If you would like to add in an h1 + a and append it to your DOM, you could use:
$(document).ready(function() {
var anchor = $('<a></a>', { 'name' : 'incompatibilidades' });
var h1 = $('<h1></h1>', { text: 'incompatibilidades' });
// Append these to the DOM here.
});
First, you shouldn't be using named anchors, but ids instead (the "name attribute on the a element is obsolete1"), to give:
<h1 id="descripcion">Descripcion</h1>
...
<h1 id="preguntas">Preguntas</h1>
Also, using a <table> element to present a list is a little non-semantic, since it's non-tabular information; instead use an ordered list, <ol>. So, with that in mind, I'd suggest the following jQuery:
$('h1[id]').each(function() {
var target = this.id;
$('#toc').append(function() {
return '<li>' + target + '</li>';
});
});
#toc {
text-transform: capitalize;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ol id="toc"></ol>
<h1 id="descripcion">Descripcion</h1>
...
<h1 id="preguntas">Preguntas</h1>
This approach is based on an assumption that you want to build a table of contents to link to those elements that are on the page.
Notes:
http://www.w3.org/TR/html-markup/a.html#a-constraints.
Without testing, and if I get your question correct - you are looking for something like this:
$().ready(function() {
// scan all links in your menu
$('table').find('a').each(function() {
// grep href attribute
var target = $(this).attr('href');
// element does not exist?
if(! $(target).length) {
// remove parent row
$(this).closest('tr').remove();
}
});
});
And - as #David Thomas mentioned correctly, you shouldn't be using named anchors, but ids instead - if you do so, you can use the anchor ('#xyz') directly as id selector as I did in the function above.
I'm building a jQuery sortable list where the user can add items from a table, drag and sort and/or remove them. I can add and sort no problem, but I can't work out how to remove an item element after it has been added. I'm relatively new to js / jQuery, so I have a feeling there's something new to learn here about how it works!
I'll leave out the ui.sortable stuff here as I'm only concerned with removing items..
<table>
<tr>
<td><a class="addrelease" href="#" cat_id="1">add</a></td>
<td>Item 1</td>
</tr>
<tr>
<td><a class="addrelease" href="#" cat_id="2">add</a></td>
<td>Item 2</td>
</tr>
</table>
<div id="list"></div>
<script>
$("a.addrelease").click(function (e) {
e.preventDefault();
cat_id = $(this).attr('cat_id');
remove_str = " remove";
str = cat_id + remove_str;
$(str).appendTo("#list").hide().fadeIn();
});
$("a.remove").click(function (e) {
alert("This function doesn't seem to be called");
$(this).parent().remove(); //Doesn't happen..
});
</script>
I'm guessing that javascript doesn't recognize the new generated items - but I'm not sure, so I'm not sure where to start fixing it
Cheers
You should use live function to attach events to dynamically added elements.
Try this to bind click event to a.remove elements:
$("a.remove").live("click", function (e) {
alert("This function doesn't seem to be called");
$(this).parent().remove(); //Doesn't happen..
});
You're absolutely right, javascript won't recognise new items.
jQuery selectors will normally only match against elements currently in the document. When you use $("a.remove").function(), jQuery builds a list of nodes matching "a.remove", then calls function() on each of them.
The .live() function is special, and doesn't attach events directly to elements - instead, events bubbling up to the top of the DOM are evaluated to see if they match the selector.
IMHO, the best approach is to bind the remove handler when you create the new list entry:
str = cat_id + remove_str;
var remove = $(str);
remove.appendTo("#list").hide().fadeIn();
remove.click(function(e) { .... })
Disclaimer: Typed late at night & not tested!
Here is my answer of how I think you should modify your code:
http://jsfiddle.net/RY5CP/
<table>
<tr>
<td><a class="addrelease" href="#" rel="1">add</a></td>
<td>Item 1</td>
</tr>
<tr>
<td><a class="addrelease" href="#" rel="2">add</a></td>
<td>Item 2</td>
</tr>
</table>
<div id="list"></div>
<script type="text/javascript">
$("a.addrelease").click(function(e) {
e.preventDefault();
var catId = $(this).attr('rel');
var itemName = $(this).closest('td').next('td').text();
var newItem = '<p>' + catId + ' ' + itemName + ' remove';
$(newItem).appendTo('#list').hide().fadeIn();
});
$("a.remove").live('click', function(e) {
$(this).parent('p').remove();
});
</script>
It's not valid to use cat_1, cat_2 as HTML attributes. You can use the rel attribute if you need to have a specific value to be associated to your items
Use the live() method to have the click event handler automatically attached to items dynamically created