I use this code to delete the last item of an <ul> list, but only on the second, fourth, sixth, ... every second click on the button the item gets removed, but every click the message appears. What can I do that the element gets deleted on every click.
document.getElementsByTagName('input')[0].onclick = function () {
'use strict';
var list = document.getElementById('list'), item = list.lastChild;
list.removeChild(item);
window.alert("Removed");
};
<ul id="list">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li id="child">List item 4</li>
<li>List item 5</li>
</ul>
<input type="button" value="Delete last">
This is because .lastChild returns all nodes, including empty text nodes which exist in your <ul>. Use .lastElementChild instead to target your <li> nodes
The difference between this property and lastElementChild, is that
lastChild returns the last child node as an element node, a text node
or a comment node (depending on which one's last), while
lastElementChild returns the last child node as an element node
(ignores text and comment nodes).
See HTML DOM lastChild Property and HTML DOM lastElementChild Property for more information
document.getElementsByTagName('input')[0].onclick = function () {
var list = document.getElementById('list'), item = list.lastElementChild;
list.removeChild(item);
};
<ul id="list">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li id="child">List item 4</li>
<li>List item 5</li>
</ul>
<input type="button" value="Delete last">
Some more details on why this is happening... When you format your markup with clean spacing, what I think of as "phantom" text nodes silently exist within your <ul>. If you minify this markup to the following, your first example would indeed work fine
<ul id="list"><li>List item 1</li><li>List item 2</li><li>List item 3</li><li id="child">List item 4</li><li>List item 5</li></ul>
Plunker Link - minifed markup example using .lastChild
Change:
item = list.lastChild;
to
item = list.lastElementChild;
Related
This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 2 years ago.
I'm quite a beginner so apology for my question if it's dumb.
I have an unordered list and a button in HTML and I want to make the button show or hide the list via javascript, but I am trying to avoid giving the onclick attribute to the button in the HTML code.
var btn = document.getElementById("button");
btn.onclick = function(){
var ul = document.getElementById("ul");
if(ul.style.display=='none'){
ul.style.display='block'}
else{ul.style.display='none'}
}
<ul id=ul>
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li>List item 4</li>
<li>List item 5</li>
<li>List item 6</li>
</ul>
<input id="button" type="button" name="button" value="press me!" >
What am I missing here, can't make it work? Could only do it when I included the onclick attribute in HTML and made a showhide() function for its onclick event, but that seems impractical in the long run.
Yes, you use addEventListener
var btn = document.getElementById("button");
btn.addEventListener('click',function(){
var ul = document.getElementById("ul");
if(ul.style.display=='none') ul.style.display='block'
else ul.style.display='none'
});
<ul id="ul">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li>List item 4</li>
<li>List item 5</li>
<li>List item 6</li>
</ul>
<input id="button" type="button" name="button" value="press me!" >
You can define event handler using addEventListener on JavaScript.
var btn = document.getElementById("button");
btn.addEventListener('click', function(){
var ul = document.getElementById("ul");
if(ul.style.display=='none'){
ul.style.display='block'}
else{ul.style.display='none'}
});
<ul id="ul">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li>List item 4</li>
<li>List item 5</li>
<li>List item 6</li>
</ul>
<input id="button" type="button" name="button" value="press me!" >
I need to reorder some children elements with defined class and maintain the old order of the others that doesn't have the class. I have other sub elements
Code - html
<ul class="menu_dinamico">
<li class="reverseMenu">Item 1</li>
<li class="reverseMenu">Item 2</li>
<ul>
<li>item 2.1</li>
<li>item 2.2</li>
</ul>
<li class="reverseMenu">Item 3</li>
<li class="reverseMenu">Item 4</li>
<li>Item 4.5</li>
<li>Item 5</li> </ul>
Code - javascript
$.fn.reverse = [].reverse;
var list = $('.menu_dinamico');
var listItems = list.children('.reverseMenu');
list.prepend(listItems.get().reverse());
The result
item 4
item 3
item 2
item 1
item 2.1
item 2.2
item 4.5
item 5
The result wanted
item 4
item 3
item 2
item 2.1
item 2.2
item 1
item 4.5
item 5
P.s: I have to maintain the html structure like links, attributes etc.
Any clues? Thanks!
Edit:
After #bubicsaszar response I realized that my question was incomplete because my list can have infinite sub lists and their structure must be preserved.
try this, if the constant items always in the end of the list:
$.fn.reverse = [].reverse;
var list = $('.menu_dinamico');
var listItems = list.children('.reverseMenu');
list.prepend(listItems.get().reverse());
var rightSide=document.getElementById("rightSide");
var leftsidecopy = leftSide.cloneNode(true);
document.getElementById("leftsidecopy").removeChild();
document.getElementById("rightSide").appendChild(leftsidecopy);
I have a original copy of data in leftside.I make a copy of leftside .I remove the lastchild of leftside and initialise to rightside.This code doesnt work!
Try this type of thing. I try on ol if you need on other tag you can try.
<ol id="myTestList">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li>List item 4</li>
<li>List item 5</li>
<li>List item 6</li>
<li>List item 7</li>
</ol>
$('ol#myTestList li:last-child').remove();
I'm trying to add <li>s to an existing <ul> with AJAX. It is a very simple test.
HTML:
<ul id="full_list">
<li>Existing item 1</li>
<li>Existing item 2</li>
<li>Existing item 3</li>
<li>Existing item 4</li>
<li>Existing item 5</li>
</ul>
<button type="button" onclick="addMoreItems()"></button>
JS:
function addMoreItems () {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("full_list").appendChild = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "filler.txt", true);
xmlhttp.send();
}
filler.txt:
<li>New item 6</li>
<li>New item 7</li>
<li>New item 8</li>
<li>New item 9</li>
<li>New item 10</li>
Desired result:
<ul id="full_list">
<li>Existing item 1</li>
<li>Existing item 2</li>
<li>Existing item 3</li>
<li>Existing item 4</li>
<li>Existing item 5</li>
<li>New item 6</li>
<li>New item 7</li>
<li>New item 8</li>
<li>New item 9</li>
<li>New item 10</li>
</ul>
<button type="button" onclick="addMoreItems()"></button>
I have no problems populating the <ul> with filler.txt's <li>s if I use innerHTML. I have spent time searching this and other sites, and have seen it said that unlike innerHTML which replaces all of an element node's contents, appendChild expects an object as opposed to a string, and so can't be added to the DOM after the page has loaded.
Unfortunately I'm still not able to figure out how to append a text string with a lot of <li>s back-to-back to the existing <ul>. Thoughts?
(The filler.txt document in xmlhttp.open()'s second parameter is something I'm only using for testing purposes. Once I figure out how to append more <li>s into the <ul> with AJAX, I'll use a PHP page instead which generates the <li>s with information from my MySQL db.)
This will give you the output:
var newItems = "
New item 6
New item 7
New item 8
New item 9
New item 10";
document.getElementById("full_list").innerHTML += newItems;
For simplicity, I used a variable already with html and added in innerHTML property.
If you really want to use appendChild(), rather than .innerHtml += ... try it like this:
var element = document.createElement("li");
var elementContent = document.createTextNode(xmlhttp.responseText);
element.appendChild(elementContent);
document.getElementById("full_list").appendChild(element);
I am beginner in javascript. I have this list:
<p class="lead">parent item1</p>
<ul class="list bot-2">
<li>child item 1
</li>
<li>child item 2
</li>
<li>child item 3
</li>
</ul>
<p class="lead">parent item2</p>
<ul class="list bot-2">
<li>child item 1
</li>
<li>child item 2
</li>
<li>child item 3
</li>
</ul>
<p class="lead">parent item3</p>
<ul class="list">
<li>child item 1
</li>
<li>child item 2
</li>
<li>child item 3
</li>
</ul>
I need to display the matching div when one child item clicked, and hide other divs, the matching items is in this html structure:
<ul class="list-services">
<li class="clearfix"></li>
<li class="clearfix"></li>
<li class="clearfix"></li>
</ul>
How I can do this, I see similar posts in stackoverflow, but it didn't have the similar structure.
Well, you could use this:
$(".list a").click(function(){
var x = $(this).parents(".list").children().get();
var find = $(this).parent().get(0);
var nth = x.indexOf(find) + 1;
$(".list-services .clearfix:not(:nth-child(" + nth + "))").hide();
});
http://jsfiddle.net/wumm/v7Ks7/1/
var x = $(this).parents(".list").children().get(); gets the current .list children.
Then var find = $(this).parent().get(0); find is set to the liin which this a was.
And now nth is set to the index of this li in the current .list. (1 is added because CSS has a 1 based index)
Last thing: hiding anything else then the nth link in .list-services
This can be done with plain javascript as well, here's the jQuery solution:
$('a').on('click', function (event) {
$('.clearfix').hide();
$('.clearfix').eq($(this).closest('li').prevAll('li').length).show();
});
The $(this).closest('li').prevAll('li').length bit gives the index of the clicked child item by finding the immediate li parent and counting the number of previous li tags inside the parent ul tag. Then we just show the .clearfix item with that index using eq and show
DEMO