removeChild - remove first or last node


removeChild - remove first or last node
I have a jQuery one-liner which I'm trying to convert to vanilla JavaScript.
$('#nav ul li:' + (dir == -1 ? 'last' : 'first')).remove();
This works. But do I need 5 lines to replace a single line of jQuery ?
var li = document.querySelectorAll('#nav ul li');
var first = li[0];
var last = li[li.length- 1];
theParent = document.querySelector("#nav ul");
theParent.removeChild(dir == -1 ? last : first);
can't you just use
document.querySelector('#nav ul li:' + (dir == -1 ? 'last' : 'first')).remove()
?– Steve
Jul 29 at 17:22
document.querySelector('#nav ul li:' + (dir == -1 ? 'last' : 'first')).remove()
jQuery helps for a reason. That's essentially what jQuery is doing behind the scenes. Also @Steve
.remove()
does not work in IE.– FrankerZ
Jul 29 at 17:23
.remove()
@Steve : We can't include :first and :last in querySelector. SyntaxError: '#nav ul li:first' is not a valid selector
– anjanesh
Jul 29 at 17:24
Thanks for the info; it does look like jQuery made a custom implementation for a reason. You might be able to use
:first-child
and :last-child
, depending on your structure.– Steve
Jul 29 at 17:35
:first-child
:last-child
2 Answers
2
The shortest way to write that in vanilla would be:
var nodes = document.querySelectorAll("#nav ul li"),
index = -1 == dir ? nodes.length-1 : 0;
nodes[index].parentElement.removeChild(nodes[index]);
...methinks. (obviously, nodes
and index
could be renamed to 1 letter var names and spaces could be removed, but that's not the point here).
nodes
index
By the way, as pointed out in the q comment, your version doesn't remove correct <li>
when there are two or more <ul>
s in #nav
<li>
<ul>
#nav
Testing:
// comment/uncomment this to test:
let dir = 1;
var nodes = document.querySelectorAll("#nav ul li"),
index = -1 == dir ? nodes.length-1 : 0;
nodes[index].parentElement.removeChild(nodes[index]);
<nav id="nav">
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
<ul>
<li>fourth</li>
<li>fifth</li>
<li><ul>
<li>sixth</li>
<li>seventh</li>
</ul></li>
</ul>
</nav>
Try this out
JS
// first or last
function remove(dir)
document
.querySelectorAll('#nav ul li:' + (dir < 0 ? 'last' : 'first') + '-child')
.forEach(function(element)
element.parentNode && element.parentNode.removeChild(element);
);
// by index
function removeByIndex(index)
document
.querySelectorAll('#nav ul li:nth-child(' + index + ')')
.forEach(function(element)
element.parentNode && element.parentNode.removeChild(element);
);
DEMO
Your version has same behavior with jQuery one liner only when there's only one
<ul>
in #nav
. It will always remove the last <li>
in the first <ul>
instead of removing the last <li>
in the last <ul>
. Not to mention nested <ul>
s.– Andrei Gheorghiu
2 days ago
<ul>
#nav
<li>
<ul>
<li>
<ul>
<ul>
okay, now it handles everything
– dysfunc
2 days ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You could wrap those lines in a function and then it would be one line, but what would you gain?
– Heretic Monkey
Jul 29 at 17:22