How to get immediate child of <ul> using cheerio - javascript

I have html file html content like this :
<ul>
<li class="class_1">111</li>
<li class="class_2">
<ul>
<li class="class_3">222</li>
<li class="class_4">333</li>
</ul>
</li>
<li class="class_5">444</li>
</ul>
After Loading html content in cheerio module and while searching for immediate li childs it's getting all items from child ul as well like this :
this._$$=cheerio.load(<htmlContent>, {xmlMode : true});
const liElements = this._$$(`ul > *`);
When i print liElements in after converting to html content i am getting output like this :
<li class="class_1">111</li>
<li class="class_2">
<ol>
<li class="class_3">222</li>
<li class="class_4">333</li>
</ol>
</li>
<li class="class_5">444</li>
<li class="class_3">222</li>
<li class="class_4">333</li>
You can see content from child ul is repeating here. I tried a lots of options from cheerio documentation but no luck. Can any help me to get immediate li child of ul.
Many Thanks in Advance.

the issue is that ul > *is too generic and it will return all the ul child even ones inside ul under li tag
maybe you have two solutions to fix this situation
1) put a class name on top ul
<ul class="main-ul">
<li class="class_1">111</li>
<li class="class_2">
<ul>
<li class="class_3">222</li>
<li class="class_4">333</li>
</ul>
</li>
<li class="class_5">444</li>
</ul>
selector became const liElements = this._$$(.main-ul > li);
2) get child of ul inside li tag and remove them from list of all child
const liWithLiParent= this._$$(`li > ul > *`);
const liElements = this._$$(`ul > *`).filter(li => !liWithLiParent.some(liWithParent => liWithParent === li));

Simplest is just to remove the child ul's
$('ul ul').remove()

Related

Trying to get the value of very next element of the current selected element using jQuery

I am trying to get the value of very next element of the current/selected element for example here is the list
<ul>
<li class="abc selected">test </li>
<li class="abc">test1 </li>
<li class="abc">test2 </li>
</ul>
From the above code I am trying to get the value of "a" tag which is very next to the selected li, in above case I am try to get the value of a tag which is test1 and this "a" tag is within the very next li after the selected one.
I tried to use the jQuery below but its fetching the empty result. Any help
var linktext1= jQuery(".selected").next("li a").text();
alert (linktext1);
The selector string passed to .next will filter out the next element if it doesn't match the selector string. But the next element is a li, not an a, so .next('li a') won't work.
Use .next("li").find('a') instead:
var linktext1 = jQuery(".selected").next("li").find('a').text();
console.log(linktext1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="abc selected">test </li>
<li class="abc">test1 </li>
<li class="abc">test2 </li>
</ul>
In this particular situation, though, there's no need for a li selector to pass to .next, because what is .selected will be a li, so any of its siblings will also be lis:
var linktext1 = jQuery(".selected").next().find('a').text();
console.log(linktext1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="abc selected">test </li>
<li class="abc">test1 </li>
<li class="abc">test2 </li>
</ul>
I think you should remove "li a" and it works. Below is the code
var linktext1= jQuery(".selected").next().text();
alert (linktext1);
Here is the example jsfiddle

How to target all nested list items beyond a specific level using jquery?

I have a list
<ul>
<li>
<ul>
<li>
<ul>
<li> <-- start targeting list items here including children -->
<ul>
<li> <-- included -->
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
I want to target all list items starting with the second or third nested list including all children thereafter using jquery
var selector = $('ul > li > ul > li > ul li');
The third li has three ul parents. You need to filter li's using .filter() and in it function check length of ul's parent of every li to filtering nested li's.
$("ul:first li").filter(function(){
return $(this).parents("ul").length > 2 ? true : false;
}).css("color", "red");
$("ul:first li").filter(function(){
return $(this).parents("ul").length > 2 ? true : false;
}).css("color", "red");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>First
<ul>
<li>Second
<ul>
<li>Third
<ul>
<li>Fourth</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

How to get specific element javascript based on style

I need to acces an element that has a certain style.
This is my structure
<ul>
<li> Hi </li>
<li> bye </li>
<li> third one </li>
</ul>
The list items are placed on top of each other (last one first) and I can dislike something or like something. Once I do that, it gets a style display:none like following:
<ul>
<li> Hi </li>
<li> bye </li>
<li style:"display:none;"> third one </li>
</ul>
Now after I did that I want to be able to acces the last element that does not have display:none, (the bye) how can I do this?
I was thinking of something in the form of:
var myId = $("#slider > ul li").last().attr("id");
But obviously I always get the ID of the item that is hidden since its still there.
Can I do something like select last where !display:hidden ?
Can I do something like select last where !display:hidden ?
Yes, with jQuery's :visible pseudo-class:
var myId = $("#slider > ul li:visible").last().attr("id");
(Note: Your li elements don't actually have id values, but that's a tweak.)
Live Example:
var listItem = $("#slider > ul li:visible").last();
$("<p>")
.text("Text of last visible item: " + listItem.text())
.appendTo(document.body);
<div id="slider">
<ul>
<li>Hi</li>
<li>bye</li>
<li style="display:none;">third one</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Can use ':visible' selector
var myId = $("#slider > ul li:visible").last().attr("id");
It should work using:
$("#slider > ul li:visible").last().attr("id");
https://api.jquery.com/visible-selector/
so your inline styling is a bit off it should be
<ul>
<li> Hi </li>
<li> bye </li>
<li style="display:none;"> third one </li>
</ul>
You could do a few different things, best is probably just iterate through and check for where display = none, then go to the previous element:
$('ul').children().each(function(e) {
if($(this)[0].style.display == 'none') {
console.log($(this).prev());
}
})

get list equal height inside div element

Please take a look at this FIDDLE. I have two pairs of unordered lists, each of which is inside a div element.pricing-table. The following code can find the li with the same classes, get the max height and set the height of all of them to the same. But I want to limit it to getting the max-height of each pair of lists inside each div element.
I think this line is giving me problem because it is getting all the lists with the same classes in the document:
var elems = $('.pricing-table ul li.' + elem.className),
I don't think I can use $(this) and update it like $(this +elem.className). Any suggestions?
Jquery script:
$(document).ready( function(){
$('.pricing-table ul li').each(function(i, elem) {
var elems = $('.pricing-table ul li.' + elem.className),
heights = $.map(elems, function(li) {
return $(li).height();
}),
max = Math.max.apply(null, heights);
elems.height(max);
});
});
HTML
<div class="pricing-table">
<ul>
<li class="heading">Bronze</li>
<li class="year">2003<p>(Text)..........</li>
<li class="package">Starter package</li>
<li class="location">Africa (Text).......)</li>
<li class="description">Text............ </li>
</ul>
<ul class="feature">
<li class="heading">Silver</li>
<li class="year">2004</li>
<li class="package">Intermediate package</li>
<li class="location">Asia</li>
<li class="description">Text............ </li>
</ul>
</div>
<div class="pricing-table">
<ul>
<li class="heading">Bronze</li>
<li class="year">2003<p>(Text)..........</li>
<li class="package">Starter package</li>
<li class="location">Africa (Text).......)</li>
<li class="description">Text............ </li>
</ul>
<ul class="feature">
<li class="heading">Silver</li>
<li class="year">2004</li>
<li class="package">Intermediate package</li>
<li class="location">Asia</li>
<li class="description">Text............ </li>
</ul>
</div>
You’d need to get only the li that are descendants of your current .pricing-table element, so you’ll have to iterate over the latter first:
$(document).ready(function () {
$('.pricing-table').each(function (i, e) {
$(e).find('ul li').each(function (i, elem) {
var elems = $(e).find('ul li.' + elem.className),
heights = $.map(elems, function (li) {
return $(li).height();
}),
max = Math.max.apply(null, heights);
elems.height(max);
});
});
});
… or something like that. http://jsfiddle.net/p3sfy/3867/
(Still kinda ugly, since it will iterate over the li multiple times, so that’s rather just a “quick fix” – but I don’t wanna think about anything more sophisticated here before I have not first heard a convincing argument why this data is not marked up using tables in the first place …?)

Display nested list over hovering at parent list

I have a menu structure in which sub menus are present as nested lists like this
<nav>
<ul>
<li class="itm">A
<ul>
<li>One</li>
<li>Two
<ul>
<li>Menu Item</li>
<li> Menu Item </li>
<li> Menu Item </li>
</ul>
</li>
<li> Three </li>
<li> Four </li>
</ul>
</li>
<li class="icon"><span class="img"></span></li>
<li class="itm">B</li>
<li class="itm">C</li>
</ul>
</nav>
Nowi want to show the sub menu (sub list) when the cursor hovers over the parent li and for that I am doing this:
$('nav ul li').hover(function () {
console.log(this);
$(this > ul).fadeIn();
}, function () {
$(this > ul).fadeOut();
});
But on hover it showing this error in JS Console: Uncaught ReferenceError: ul is not defined
Your selector is combining this, which is a literal, and what should be a string in a selector (> ul). ul is being treated as a variable, and the ul variable doesn't exist.
Try this:
http://jsfiddle.net/cyzsw/
$(this).children('ul').fadeIn();

Categories