how to get last li element using javascript? - javascript

I am trying to get last li element of list . but it is not giving correct output. here is my markup
<div class="abc">
<ul>
<li>1</li>
<ul><li>1.1</li><li>1.2</li></ul>
<li>2</li>
<ul><li>2.1</li><li>2.2</li></ul>
<li>3</li>
<ul><li>3.1</li><li>3.2</li></ul>
</ul>
</div>
trying like this
console.log(document.querySelector('.abc ul li:last-child').innerHTML)
output Element
<li>1.2</li>
Expected output
<li>3</li>

There are 2 problems
Your HTML Is invalid as ul is not a valid child of ul so the nested ones need to be actually inside a li
Use the > modifier to find direct descendents only in the selector
console.log(document.querySelector('.abc>ul>li:last-child').innerHTML)
<div class="abc">
<ul>
<li>
1
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>
2
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
3
<ul>
<li>3.1</li>
<li>3.2</li>
</ul>
</li>
</ul>
</div>
If you do just want the text (and not the nested ul) you could put that text in a span and select that only
console.log(document.querySelector('.abc>ul>li:last-child span').innerHTML)
<div class="abc">
<ul>
<li>
<span>1</span>
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>
<span>2</span>
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
<span>3</span>
<ul>
<li>3.1</li>
<li>3.2</li>
</ul>
</li>
</ul>
</div>
If you do just want the text (and not the nested ul) you could put that text in a span and select that only

You can just go for the javascript way like this.
li = document.querySelectorAll('.abc>ul>li');
console.log(li[li.length-1].innerText);

console.log(document.querySelector('.abc ul li:last-child').innerHTML)
This syntax of giving white space instead of adjacent selectors like ">" is used when we want to apply common styles to multiple class.
So replacing your whitespace with adjacent selectors like > will work in your case to select all its descendent childs.
console.log(document.querySelector('.abc>ul>li:last-child').innerHTML)
<div class="abc">
<ul>
<li>
1
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>
2
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
3
<ul>
<li>3.1</li>
<li>3.2</li>
</ul>
</li>
</ul>
</div>

Related

Remove link from parent menu if it has sub menu

How to remove link from parent menu anchor if it has submenus
<ul class="sitemap-ul">
<li> Home</li>
<li> about Us <!-- Remove link-->
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li> Media <!-- Remove link-->
<ul>
<li>news</li>
</ul>
</li>
<li> Contact</li>
</ul>
You can use jQuery :has() pseudo-class selector.
$('.sitemap-ul > li:has(ul) > a').remove()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="sitemap-ul">
<li> Home</li>
<li> about Us <!-- Remove link-->
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li> Media <!-- Remove link-->
<ul>
<li>news</li>
</ul>
</li>
<li> Contact</li>
</ul>
UPDATE : In case you just want to replace a tag with text then use contents() method with unwrap() method.
$('.sitemap-ul > li:has(ul) > a')
// get children element
.contents()
// unwrap them
.unwrap()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="sitemap-ul">
<li> Home</li>
<li> about Us
<!-- Remove link-->
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li> Media
<!-- Remove link-->
<ul>
<li>news</li>
</ul>
</li>
<li> Contact</li>
</ul>
Assuming you want to remove the <a> elements themselves but leave behind their text content you can use :has() to get the relevant li with submenus, then replaceWith() on the child a elements, like this:
$('.sitemap-ul > li:has(ul) > a').replaceWith(function() {
return $(this).text();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="sitemap-ul">
<li>Home</li>
<li>
About Us
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li>
Media
<ul>
<li>news</li>
</ul>
</li>
<li>Contact</li>
</ul>
$('.sitemap-ul > li').each(function(){
if($('ul', this).length > 0){
$(this).closest("a").click(function(e){
e.preventDefault();
});
}
});
I have a solution by using vanilla js for you.
var elements = document.querySelectorAll(".sitemap-ul li")
Array.from(elements).forEach(function(el) {
if (el.children.length > 1) {
el.removeChild(el.children[0])
}
});

Using jQuery(this).next() to show/hide the next nested UL in a menu

Whenever "section" is clicked, I would like for the next UL (sub-menu) to disappear (or reappear). I can get a simple P tag to disappear outside of this tree, but I am trying to use the jQuery next(); function. How can I select this element with jQuery. I thought that:
$(".section").click(function() {
$(this).next('ul').hide();
});
Would work, but it doesn't... here is the HTML:
<div class="menu">
<ul class="main-menu">
<li class="section">
Section 1
<ul class="sub-menu" style="z-index: 3;">
<li>
Section 1A
</li>
<li>
Section 1B
</li>
<li>
Section 1C
</li>
<li>
Back
</li>
</ul>
</li>
<li class="section">
Section 2
<ul class="sub-menu" style="z-index: 2;">
<li>
Section 2A
</li>
<li>
Section 2B
</li>
<li>
Section 2C
</li>
<li>
Back
</li>
</ul>
</li>
</ul>
</div>
Update
Find() worked fine. But now I am wondering how I can use the li element with the text "Back" in it to toggle the sub-menu off. I have added a class "back" to the last LI element on each sub-menu list, but jQuery can't seem to find it and apply the CSS. Here is what I have:
//this code works
$(".section").click(function() {
$(this).find('ul').css( "left", "0" );
});
//this code doesn't locate the previous UL (i also tried (".sub-menu").css()
$('.back').click(function() {
$('.back').prev('ul').css( "left", "485" );
});
//html:
<li class="section">
Section 1
<ul class="sub-menu" style="z-index: 3;">
<li>
Section 1A
</li>
<li>
Section 1B
</li>
<li>
Section 1C
</li>
<li class="back">
Back
</li>
</ul>
</li>
next affects the tag's siblings, i.e. the other .section tags, while the <li> tags you want to operate on are in reality its descendants. Thus you should use
$(".section").click(function() {
$(this).find('ul').toggle();
});
The find and toggle method are the ones you need.
In your code you use next() which looks at the next sibling, where you instead want to look at the children. To target them, you can use the find(filter) function. By finding the ul, you can use toggle() or slideToggle to toggle it's visibility.
I've also added an extra click function on the children. That prevents that clicking the child closes the sub-menu.
$(function() {
$('.section').click( function() {
$(this).find('ul').slideToggle();
}).children().click( function() {
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
<ul class="main-menu">
<li class="section">
Section 1
<ul class="sub-menu" style="z-index: 3;">
<li>Section 1A</li>
<li>Section 1B</li>
<li>Section 1C</li>
<li>Back</li>
</ul>
</li>
<li class="section">
Section 2
<ul class="sub-menu" style="z-index: 2;">
<li>Section 2A</li>
<li>Section 2B</li>
<li>Section 2C</li>
<li>Back</li>
</ul>
</li>
</ul>
</div>

How to use jQuery to hide/show certain divs on hover?

I've got a list of links embedded in a <ul> as so
<ul class="list">
<li id="1">Result 1</li>
<li id="2">Result 2</li>
<li id="3">Result 3</li>
<li id="4">Result 4</li>
</ul>
And I have another <ul> that displays information that goes with the results list:
<ul class="summary">
<li id="1"><p>Result 1 Info</p></li>
<li id="2"><p>Result 2 Info</p></li>
<li id="3"><p>Result 3 Info</p></li>
<li id="4"><p>Result 4 Info</p></li>
</ul>
How do I make it to where I can hover over a li in list and it only displays the li in summary that goes with the respective li hover? This is my jQuery code:
$("ul.summary li").hide();
$("ul.summary li:first-child").show();
$("ul.lsit li").hover(function(){
var id = $(this).attr("id");
$("ul.summary li#"+id).show();
})
id should be unique. Instead you can do something like this with help of eq() , index() and siblings()
$("ul.summary li").hide();
$("ul.summary li:first-child").show();
$('ul.list li').hover(function() {
$('ul.summary li').eq($(this).index())
// using eq() you can select element using index
// index() returns index based on it's siblings
.show()
//show element using show()
.siblings().hide();
// use siblings() to get all siblings and hide them using hide()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="list">
<li>Result 1
</li>
<li>Result 2
</li>
<li>Result 3
</li>
<li>Result 4
</li>
</ul>
<ul class="summary">
<li>
<p>Result 1 Info</p>
</li>
<li>
<p>Result 2 Info</p>
</li>
<li>
<p>Result 3 Info</p>
</li>
<li>
<p>Result 4 Info</p>
</li>
</ul>
UPDATE : If you want to change the order then you can set some custom attribute and do something like
$("ul.summary li").hide();
$("ul.summary li:first-child").show();
$('ul.list li').hover(function() {
$('ul.summary li').eq($(this).data('target'))
// using eq() you can select element using index
// get custom attribute value using data()
.show()
//show element using show()
.siblings().hide();
// use siblings() to get all siblings and hide them using hide()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="list">
<li data-target=3>Result 1
</li>
<li data-target=2>Result 2
</li>
<li data-target=1>Result 3
</li>
<li data-target=0>Result 4
</li>
</ul>
<ul class="summary">
<li>
<p>Result 1 Info</p>
</li>
<li>
<p>Result 2 Info</p>
</li>
<li>
<p>Result 3 Info</p>
</li>
<li>
<p>Result 4 Info</p>
</li>
</ul>

Javascript toggle menu with multiple levels

I'm working on a navigation with 3 levels and want use toggle to expand and close those levels. I got it to work with the second level but am struggling with the third level.
I want the third level(purpose1,purpose2) to open when the second level(Purpose) is clicked.
<ul>
<li class="dropdown">About Us
<ul>
<li>Services</li>
<li>History</li>
</ul>
</li>
<li class="dropdown">Products
<ul class="products">
<li>Series</li>
<li>Purpose</li>
</ul>
<ul>
<li>purpose1</li>
<li>purpose2/li>
</ul>
</li>
</ul>
Javascript:
$('li.dropdown').click(function(){
$('li.dropdown').not(this).find('ul').hide();
$(this).find('ul').toggle();
});
$('ul.products').click(function() {
$('ul.products').not(this).find('ul').hide();
$(this).find('ul').toggle();
});
I've created a fiddle to illustrate the issue. The actual navigation is much more complex but this should do the job. Any suggestiones are really appreciated!
Your html is wrong. If the third lvl is to be displayed by clicking "purpose" it shoudl look like this:
<li class="dropdown">Products
<ul class="products">
<li>Series</li>
<li >Purpose
<ul >
<li>Series123</li>
<li>Series456</li>
</ul>
</li>
</ul>
</li>
Then just add a class to this thrid lvl list parent and add the jquery fucntion.
clicking in the product li is propagating up to the top level, which is causing the close.
$('ul.products').click(function(e) {
$('ul.products').not(this).find('ul').hide();
$(this).find('ul').toggle();
e.stopPropagation();
});
.
<ul>
<li class="dropdown">About Us
<ul>
<li>Services</li>
<li>History</li>
</ul>
</li>
<li class="dropdown">Products
<ul class="products">
<li>Series
<ul>
<li>Series123</li>
<li>Series456</li>
</ul>
</li>
<li>Purpose
<ul>
<li>purpose1</li>
<li>purpose2</li>
</ul>
</li>
</ul>
</li>
</ul>
here is the simplified working version, first move you 3rd level ul inside the li
<ul>
<li class="dropdown">About Us
<ul>
<li>Services</li>
<li>History</li>
</ul>
</li>
<li class="dropdown">Products
<ul class="products">
<li>Series
<ul>
<li>Series123</li>
<li>Series456</li>
</ul>
</li>
<li>Purpose</li>
</ul>
</li>
</ul>
and here goes the jQuery snippet -
$('li.dropdown a').click(function(){
$('li.dropdown').not(this).find('ul').hide();
$(this).parent('li').find('ul').toggle();
});
$('li.dropdown ul li').click(function() {
$(this).find('ul').toggle();
});
Check the working fiddle

jquery - Add html content within a selected div like a plugin

I would like to add some html content within a selected div like most of the plugins are.
Eg:
<div id="selected-div">
</div>
$('#selected-div').foo();
When the div (selected-div) is passed to the function, I would like to add the below html content inside that div (selected-div).
<div id="lorem-ipsum-wrapper">
<ul id="lorem-ipsum-main">
<li id="btn-header-wrapper" class="main-btn">
T
<ul>
<li>
T1
</li>
<li>
T2
</li>
<li>
T3
</li>
<li>
T4
</li>
</ul>
</li>
<li class="main-btn">
<b>E</b>
</li>
<li id="btn-justify-wrapper" class="main-btn">
Gender
<ul>
<li>
M
</li>
<li>
F
</li>
<li>
other
</li>
</ul>
</li>
<li class="main-btn" id="btn-list-wrapper">
List
<ul>
<li>
List 1
</li>
<li>
List 2
</li>
</ul>
</li>
<span class="clear_both"></span>
</ul>
</div>
Demo at codepen.
Which after execution should become like this
<div id="selected-div">
<div id="lorem-ipsum-wrapper">
<ul id="lorem-ipsum-main">
...
...
...
</ul>
</div>
</div>
How can I achieve this feature using jquery? Your help and guidance will be very much appreciated. Thank you.
Use .html()
$("#selected-div").html('<div id="lorem-ipsum-wrapper">..');
or .load()
$("#selected-div").load("/path/to/html")
var data = '<div id="lorem-ipsum-wrapper">
<ul id="lorem-ipsum-main">
<li id="btn-header-wrapper" class="main-btn">
T
<ul>
<li>
T1
</li>
<li>
T2
</li>
<li>
T3
</li>
<li>
T4
</li>
</ul>
</li>
<li class="main-btn">
<b>E</b>
</li>
<li id="btn-justify-wrapper" class="main-btn">
Gender
<ul>
<li>
M
</li>
<li>
F
</li>
<li>
other
</li>
</ul>
</li>
<li class="main-btn" id="btn-list-wrapper">
List
<ul>
<li>
List 1
</li>
<li>
List 2
</li>
</ul>
</li>
<span class="clear_both"></span>
</ul>
</div>';
$("#selected-div").html(data);
You can use the JQuery text() method like this
$("#selected-div").text($('#lorem-ipsum-wrapper').text());
Here is the JS code :
$(document).ready(function(){
$("#selecteddiv").load('add.html');
});
and in add.html, you can have your html code which you want to append.
here is the working Plnkr link.
hope it helps you
append would also be an option
http://api.jquery.com/append/
$("#selected-div").append($("<h1>Some content</h1>"));

Categories