I have this DOM and I want to make like a filter removing li according text included in h5 tag.
<div class="total">
<ul>
<li>
<h5>this super heroe is super cool: Clark Kent</h5>
</li>
</ul>
<ul>
<li>
<h5>I always wanted to be Batman</h5>
</li>
</ul>
<ul>
<li>
<h5>Somedays I will be transform as Spiderman </h5>
</li>
</ul>
<ul>
<li>
<h5>This women is incredible Catwoman</h5>
</li>
</ul>
<li>
<ul>
<h5>The worst character is Joker</h5>
</ul>
</li>
<ul>
<li>
<h5>Someone knows about Green Lantern </h5>
</li>
</ul>
</div>
I need to make a filter according string into this array which has not coma
let appDataTab = ["Clark Kent Catwoman Joker"]
My goal is to remove all li that its h5 doesn't content "Clark Kent" "Catwoman" and "Joker"
As you can see the appDataTab content these string with no separation.
Here is the updated code after adding additional code after validating from my end.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="total">
<ul>
<li>
<h5>this super heroe is super cool: Clark Kent</h5>
</li>
</ul>
<ul>
<li>
<h5>I always wanted to be Batman</h5>
</li>
</ul>
<ul>
<li>
<h5>Somedays I will be transform as Spiderman </h5>
</li>
</ul>
<ul>
<li>
<h5>This women is incredible Catwoman</h5>
</li>
</ul>
<ul>
<li>
<h5>The worst character is Joker</h5>
</li>
</ul>
<ul>
<li>
<h5>Someone knows about Green Lantern </h5>
</li>
</ul>
</div>
<script>
$(function () {
var prohibited = ['Clark Kent', 'Catwoman', 'Joker'];
$("li").each(function (index) {
var wordFound = false;
for (var i = 0; i < prohibited.length; i++) {
if ($(this).text().indexOf(prohibited[i]) > -1) {
wordFound = true;
break;
}
}
if (wordFound == false) {
$(this).parent().remove();
}
});
})
</script>
</body>
</html>
Your should first make it a regular comma seperated array, then look for the element and remove the li containing the element.
Steps are commented one by one:
$(document).ready(function () {
//Your array
var appDataTab = ["Clark Kent Catwoman Joker"];
//Split with more than 1 space (2 space)
var appDataSplit = appDataTab[0].split(" ");
//Remove empty elements
var filtered = appDataSplit.filter(function (el) {
return el != "";
});
//Trim elements from extra spaces
var cleanFiltered = [];
for (i=0; i < filtered.length; i++){
cleanFiltered.push(filtered[i].trim());
}
console.log(cleanFiltered);
//look for any li containing the words in cleanFilter array
$("li").each(function(){
for (i=0; i < cleanFiltered.length;i++){
if ($(this).text().indexOf(cleanFiltered[i]) > -1) {
$(this).remove();
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="total">
<ul>
<li>
<h5>this super heroe is super cool: Clark Kent</h5>
</li>
</ul>
<ul>
<li>
<h5>I always wanted to be Batman</h5>
</li>
</ul>
<ul>
<li>
<h5>Somedays I will be transform as Spiderman </h5>
</li>
</ul>
<ul>
<li>
<h5>This women is incredible Catwoman</h5>
</li>
</ul>
<ul>
<li>
<h5>The worst character is Joker</h5>
</li>
</ul>
<ul>
<li>
<h5>Someone knows about Green Lantern </h5>
</li>
</ul>
</div>
Related
I have many list-items(li's) and every single one has its own ID. Is there a way to change the color of a specific Li by its ID for example by a button or something(pls in Javascript). Thanks for any help!
const li = `
<li id= "${doc_id}">
<div class="collapsible-header grey lighten-4 right-align"> ${name} ${distance}km von dir entfernt (${Ort},${PLZ}) </div>
<div class="collapsible-body white"><span>lol${name} lat</span>
</li>
`;
You could do something like this where you loop over and use setAttribute to apply a class.
const ul = document.getElementById("list");
const items = ul.getElementsByTagName("li");
console.log("+++", items);
for(let i=0; i<items.length; i++) {
items[i].setAttribute("class", "test");
}
.test {
color: #f00;
}
<ul id="list">
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
</ul>
I have an unordered nested list
I want to count these nested lists in such a way that inside <li>Animals</li> there are 19 animals inside this li. I wanted to count all li having the name of animals using Javascript. How should I proceed?
<ul>
<li>
Animals
<ul>
<li>
Mammals
<ul>
<li>Apes
<ul>
<li>Chimpanzee</li>
<li>Gorilla</li>
<li>Orangutan</li>
</ul>
</li>
<li>Coyotes</li>
<li>Dogs</li>
<li>Elephants</li>
<li>Horses</li>
<li>Whales</li>
</ul>
</li>
<li>
Other
<ul>
<li>
Birds
<ul>
<li>Albatross</li>
<li>Emu</li>
<li>Ostrich</li>
</ul>
</li>
<li>Lizards</li>
<li>Snakes</li>
</ul>
</li>
</ul>
</li>
<li>Fish
<ul>
<li>Goldfish</li>
<li>Salmon</li>
<li>Trout</li>
</ul>
</li>
</ul>
#mplungjan put forward this solution in the comments and it works. document.querySelectorAll("ul")[1].querySelectorAll("li").length
this gives 17 which is the correct count (after clarification in comments which overrode the first count given which was 19).
The question asks about traversing and we show that step by step here so as to help with more general solutions.
We first have to find the element which is holding all the other lists. I have assumed that that ul element is the first in the document. In the general case we'd probably find such an element by knowing it's id or its class.
We then find the li element which is associated with Animals and again we assume it's the first one, as it is in the HTML given. However, if it was to be more sophisticated you'd want to look for the li element that has Animals as its innerHTML.
We then find the associated lis and count them.
Here is the code and you can run the snippet to see it gets to 17 (which was clarified in comments, the original count in the question was given as 19, also clarified was that this has nothing to do with counting actual animal names, only to do with counting li elements).
<!DOCTYPE html>
<html>
<body>
<ul>
<li>
Animals
<ul>
<li>
Mammals
<ul>
<li>Apes
<ul>
<li>Chimpanzee</li>
<li>Gorilla</li>
<li>Orangutan</li>
</ul>
</li>
<li>Coyotes</li>
<li>Dogs</li>
<li>Elephants</li>
<li>Horses</li>
<li>Whales</li>
</ul>
</li>
<li>
Other
<ul>
<li>
Birds
<ul>
<li>Albatross</li>
<li>Emu</li>
<li>Ostrich</li>
</ul>
</li>
<li>Lizards</li>
<li>Snakes</li>
</ul>
</li>
</ul>
</li>
<li>Fish
<ul>
<li>Goldfish</li>
<li>Salmon</li>
<li>Trout</li>
</ul>
</li>
</ul>
<script>
var firstUL = document.getElementsByTagName('UL')[0]; //assuming the whole list is the first UL in the document
var animalsLI = firstUL.getElementsByTagName('LI')[0];
var animalsLIUL = animalsLI.getElementsByTagName('UL')[0];
var animalsLIs = animalsLI.getElementsByTagName('LI');
alert('The count of LIs is ' + animalsLIs.length);
</script>
</body>
</html>
I'm struggling to understand how to get the last item in an each() loop. I asked a question last week on this topic, which can be seen here: .find() relationship with loops, each() and this keyword - .find() returning 4 when it should only be 2
The original requirement was to check a series of uls inside uls, and if there were more than 1 lists I need to add a class. Now - I need to build upon this code where if there are more than three lists inside a div, or it is the last ul in a series, I need to add a class to the last ul as well.
I did research on the topic and will be referencing this answer: Last element in .each() set
For reference, the first sample case is below:
$(function(e) {
var getMenuItems = $(".item");
getMenuItems.each(function( index ) {
if ($(this).find("ul.sub-menu").length > 0) {
$(this).addClass("red");
}
});
});
.red {background-color: red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="item">
<ul class="sub-menu">
<li></li>
</ul>
</li>
<li class="item">
</li>
<li class="item">
<ul class="sub-menu">
<li></li>
</ul>
</li>
<li class="item">
</li>
</ul>
This code just checks if there are more than 1 lists inside a div and if there are add a class.
Now the next step is to not only add a class to the divs with more than 1 list but the last ul in the series irregardless of amount of lists. The answer Last element in .each() set suggests to simply cross reference index and see if you are at the last item.
The highest upvoted answer says to:
Check index against the length of the set and you're good to go:
That concept integrated into my sample looks like this:
$(function(e) {
var getMenuItems = $(".item");
var howManyListItems = getMenuItems.length;
getMenuItems.each(function( index ) {
if ($(this).find("ul.sub-menu").length > 0) {
$(this).addClass("red");
} else if (index == (howManyListItems.length - 1)) {
console.log($(this));
$(this).addClass("red");
}
});
});
.red {background-color: red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="item">
<ul class="sub-menu">
<li></li>
</ul>
</li>
<li class="item">
</li>
<li class="item">
<ul class="sub-menu">
<li></li>
</ul>
</li>
<li class="item">
</li>
<li class="item">
</li>
<li class="item">
</li>
<li class="item">
</li>
</ul>
The expected/desired behavior is to add the red to the last item but sadly that does not happen.
As can be seen as a troubleshooting measure, console logging this into that conditional returns nothing. So is that not the last item of the array? How would you modify it/target it? What does that conditional represent? Since console logging does nothing, how does one go about troubleshooting this code?
How do you hit the last element in an each loop and modify it's DOM properties?
This is as easy as:
$(function(e) {
$(".sub-menu:last-of-type").last().addClass("red");
});
.red {background-color: red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="item">
<ul class="sub-menu">
<li></li>
</ul>
</li>
<li class="item">
</li>
<li class="item">
<ul class="sub-menu">
<li></li>
</ul>
</li>
<li class="item">
</li>
<li class="item">
</li>
<li class="item">
</li>
<li class="item">
</li>
</ul>
I wish to find an easy jQuery solution to iterate through a list's child selectors, in this instance, the ul > li span span child selectors, find the text, copy the text as the list item ID, all while removing the whitespace and replacing with underscore if there are any (for instance, in the example below, HR Area would become HR_Area then get added as the list item ID as li id="HR_Area").
<ul id="menu">
<li><span class="additional-background"><span class="menu-item">Staff</span></span>
<ul>
<li>Directory</li>
</ul>
</li>
<li><span class="additional-background"><span class="menu-item">HR Area</span></span>
<ul>
<li>Manage Vacation Time</li>
</ul>
</li>
</ul>
Thx in advance.
This will select only the immediate li inside #menu.
I hope this is what you expected.
$(document).ready(function() {
$("#menu>li .menu-item").each(function() {
$(this).closest("li").attr("id", $(this).text().split(' ').join('_'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="menu">
<li>
<a href="/">
<span class="additional-background">
<span class="menu-item">Staff</span>
</span>
</a>
<ul>
<li>Directory
</li>
</ul>
</li>
<li>
<a href="/">
<span class="additional-background">
<span class="menu-item">HR Area</span>
</span>
</a>
<ul>
<li>Manage Vacation Time
</li>
</ul>
</li>
</ul>
Just iterate over the immediate child which is an li.
Then access the span and replace the spaces with underscore and set the id accordingly.
// Iterate over the immediate li elements for the ul
$('#menu > li').each(function(elem) {
var $this = $(this);
// Access the span element
var $span = $('.menu-item', $this),
spanText = $span.text(),
// Replace space with underscore
replacedText = spanText.split(' ').join('_');
// Set the id of for the li element
$this.attr('id', replacedText);
});
$('#menu > li').each(function(elem) {
console.log($(this).attr('id'));
});
Check Fiddle
Try This:-
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(document).ready(function(){
$("#menu").find("li").each(function(){
$(this).find("span").each(function(){
var txt = $(this).html();
txt = txt.replace(" ","_");
$(this).closest("li").attr("ID",txt);
});
});
});
</script>
</head>
<body>
<ul id="menu">
<li><span class="additional-background"><span class="menu-item">Staff</span></span>
<ul>
<li>Directory</li>
</ul>
</li>
<li><span class="additional-background"><span class="menu-item">HR Area</span></span>
<ul>
<li>Manage Vacation Time</li>
</ul>
</li>
</ul>
</body>
</html>
I'm manually scraping data from some websites just using "Javascript:;" in a browser's
address bar. It's easier than copy/pasting.
I've come across a few instances where I have to do: object.parentNode.parentNode....
to get some information and as it varies from site to site it could be at any level.
Obviously I don't want a loop and traverse it as that would make a simple task a bit more
extensive.
Is there a way to do say: object.parentNode[4] or something such as without jQuery?
I don't think you'll manage to avoid a good ol' loop:
for(var i=0; i<4 && node.parentNode; node=node.parentNode, i++); alert(node);
I wrote a function to do exactly this in Vanilla JavaScript:
https://github.com/ryanpcmcquen/queryparent
Here's the es5 version:
https://github.com/ryanpcmcquen/queryparent/blob/master/index-es5.js
Or if you only need to support modern browsers, you can use the es6 version:
https://github.com/ryanpcmcquen/queryparent/blob/master/index.js
You call it like so:
queryParent(SELECTOR, PARENT);
It will return the raw JavaScript node.
Here's a demo of it getting the exact class selector you would want, even though there is another element with the same selector (that you would not want):
https://jsfiddle.net/ryanpcmcquen/zkw0gdj7/
/*! queryParent.js v1.2.1 by ryanpcmcquen */
/*global module*/
/*jshint esversion:6*/
const d = document;
const qu = 'querySelector';
const queryParent = (s, p) => {
const q = (x) => d[qu](x);
const qa = (y) => d[`${qu}All`](y);
const pa = qa(p);
(typeof s === 'string') && (s = q(s));
return [...pa].filter((n) => {
return (n.contains(s)) ? n : false;
}).pop();
};
//module.exports = queryParent;
console.log(
queryParent('.bar', '.foo')
);
// PSST! Check the console!
<div>
<ul class="foo">
But there is also a <code>foo</code> we don't want here.
</ul>
<ul class="foo">
The <code>foo</code> we want is here.
<li>
<ul>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<ul></ul>
</li>
<li>
<ul></ul>
</li>
<li>
<ul class="bar"><code>bar</code> is here.</ul>
</li>
</ul>
</li>
</ul>
</div>
The reason I find this more useful, is that it does not rely on a certain number of .parent() calls (or conversely .parentNode in pure JS). For that reason it makes your code more future proof and less likely to stop working should the markup structure change.