get ul li elements inside other ul li Javascript - javascript

I'm having trouble getting elements that are inside other elements. I want to overwrite a text that was already written in my HTML document.
My HTML code:
<div class="row">
<div class="col-12 col-md-6">
<h3 class="h3 generalfont">Industry Experience</h3>
<article>
<ul>
<li>
Project FIUBA, Algorithms and Programming I, Argentina, 2021
<ul>
<li>Project FIUBA, Algorithms and Programming I, Argentina, 2022</li>
</ul>
</li>
</ul>
</article>
<div>
<input id="edit-aboutme" type="text" oninput="asignar_palabras_2(this.value)" style="display: none;">
</div>
</div>
</div>
My Javascript code:
function cambiar_parrafo_2(){
document.querySelector("input").style.display = "inline";
let container = document.querySelector(".col-12");
let texto = container.querySelectorAll("article > ul > li");
for (let i = 0; i < texto.length; i++) {
texto[i].textContent = "";
}
}
The Javascript code before only delete text into li elements, the function is call when user click an image (I didn't add that piece of code to avoid making it extensive)...
So, after deleting the text, I want to write something new given by the user on input but it doesn't overwrite it.
This is the code that I thought:
function asignar_palabras_2(value) {
let container = document.querySelector(".col-12");
let texto = container.querySelectorAll("article > ul > li > ul > li");
for (let i = 0; i < texto.length; i++) {
texto[i].textContent = value;
}
}
Thanks in advance for your answers.

It would be much more helpful to give them useful classnames, so that you can select them directly.
eg: outer and inner.
function cambiar_parrafo_2(value) {
document.querySelector("input").style.display = "inline"
let container = document.querySelector(".col-12")
let texto = container.querySelectorAll("article ul.inner li")
for (let i = 0; i < texto.length; i++) {
texto[i].textContent = value
}
}
cambiar_parrafo_2('sdfsdfds')
<div class="row">
<div class="col-12 col-md-6">
<h3 class="h3 generalfont">Industry Experience</h3>
<article>
<ul class="outer">
<li>
Project FIUBA, Algorithms and Programming I, Argentina, 2021
<ul class="inner">
<li>Project FIUBA, Algorithms and Programming I, Argentina, 2022</li>
</ul>
</li>
</ul>
</article>
<div>
<input id="edit-aboutme" type="text" oninput="cambiar_parrafo_2(this.value)" style="display: none;">
</div>
</div>
</div>

Related

How come my 'click' eventListener works for the first 2 <li>'s and not the rest?

I am relatively new to programming. I got my 'click' eventListener to work, and when you click on the first two li's in the ul, the class of the div toggles on and off. However, when you click on any li after the second one, it toggles the class of every other div and not the one that is clicked on? If you need more clarification regarding the situation, feel free to let me know.
For example, if the for loop were to print:
Bench Press
Deadlift
Squat
Shoulder press
Curl
If i click on 'bench press' and 'deadlift' it will toggle .info and show the information for it; but if i were to click on 'squat' it will toggle .info for the 'curl' instead, so on and so forth...
Here is all the code,
<div>
{% for workout in workouts %}
<ul>
<li class="item">{{ workout.name }}</li>
{% autoescape false %}
<div class="info" id="info">
<p>{{ workout.description }}</p>
</div>
{% endautoescape %}
</ul>
{% endfor %}
</div>
let li = document.querySelectorAll("li");
let info = document.querySelectorAll(".info");
for (let i = 0; i < li.length; i++) {
li[i].addEventListener("click", function () {
info[i].classList.toggle("info");
});
}
.info {
display: none;
}
Your javascript code is fine.
Make sure your HTML is valid.
Each html tag has to be properly closed.
So ether <tag /> or <tag> </tag>, when the browser encounters what it deems incomplete, it will attempt to patch things up, that could cause your <li> and <div> pairs to misalign.
I saw you've edited your question, so it might not be relevant anymore.
note that you debug and inspect the actual html the browser has interpreted, rightclick-> inspect will open a view where you can see the state of the browser
let li = document.querySelectorAll("li");
let info = document.querySelectorAll(".info");
for (let i = 0; i < li.length; i++) {
li[i].addEventListener("click", function() {
info[i].classList.toggle("info");
});
}
.info {
display: none;
}
.info-colour {
background: chocolate;
}
.item {
margin-top: 1rem;
background: orange;
}
p {
margin: 0
}
<div>
<ul>
<li class="item"> workout.name 1</li>
<div class="info info-colour">
<p> workout.description 1 </p>
<div>
Necessary Workout Equpiment: [Specific Machinery]
</div>
</div>
<li class="item">workout.name 2</li>
<div class="info info-colour">
<p> workout.description 2 </p>
<div>
Necessary Workout Equpiment: [Specific Machinery]
</div>
</div>
<li class="item">workout.name 3</li>
<div class="info info-colour">
<p> workout.description 3 </p>
<div>
Necessary Workout Equpiment: [Specific Machinery]
</div>
</div>
</ul>
</div>
The i variable stores the last value after the loop, since it is in another callback function.
Try this fix:
let li = document.querySelectorAll("li");
for (let i = 0; i < li.length; i++) {
let liItem = li[i];
liItem.addEventListener("click", function () {
liItem.querySelector("div").classList.toggle("info");
});
}

How I can read styles in ul tag using loop

Is there any way to read background-color and color in styles and put it in list using javascript specifically loop ?
HTML
<ul id="list">
<li>
<div class="card">
<div class="test1" style="background-color: #fff333;"></div>
<p class="test2" style="color: #000;">#ef5777</p>
</div>
</li>
</ul>
JavaScript
<script>
var background = [];
var colors = [];
// is there any way to put background and color in one array without 2 array ?
// after that what should I do ?
</script>
If your just wanting to retrieve what's in the style attribute, then you can just use getAttribute("style") on the DOM node.
If your wanting the physical color, that also takes into account CSS, there is getComputedStyle too,.
Here is an example of the getAttribute way.
const items = document.querySelectorAll('#list *');
const styles = [];
for (const item of items) {
const st = item.getAttribute("style");
if (st) styles.push(st);
}
console.log(styles);
<ul id="list">
<li>
<div class="card">
<div class="test1" style="background-color: #fff333;">xx</div>
<p class="test2" style="color: #000;">#ef5777</p>
</div>
</li>
</ul>
And here is an example of using getComputedStyle
const items = document.querySelectorAll('#list *');
const colors = [];
const background = [];
for (const item of items) {
const c = window.getComputedStyle(item);
colors.push(c.getPropertyValue('color'));
background.push(c.getPropertyValue('background-color'));
}
console.log(colors);
console.log(background);
<ul id="list">
<li>
<div class="card">
<div class="test1" style="background-color: #fff333;">xx</div>
<p class="test2" style="color: #000;">#ef5777</p>
</div>
</li>
</ul>

How to search for value in all descendant textNodes(Javascript)?

So basically I am making a Chrome extension which sorts the search results on Ebay by their popularity(number of times sold). To do this I need to find all li elements which have a descendant text node containing the text ...+ Sold where ... is a number.
Basically, search results on Ebay look like this:
<li class="s-item">
<div class="s-item__wrapper clearfix">
<div class="s-item__image-section">
<!-- other stuff -->
</div>
<div class="s-item__info clearfix">
<!-- other stuff -->
<div class="s-item__details clearfix">
<!-- other stuff -->
<div><span><span>62+ Sold</span></span></div>
</div>
</div>
</div>
</li>
In every li element I have to search for the text Sold and extract the number out of that text node to process it further. How can I do that?
You cannot do that only by using childNodes or children properties because they return only the children and not all descendants of the current node. So you will have to write your own function for that, something like:
function getDescendants(node, arr) {
var i;
arr = arr || [];
for (i = 0; i < node.childNodes.length; i++) {
arr.push(node.childNodes[i])
getDescendants(node.childNodes[i], arr);
}
return arr;
}
Using this function, you just simply iterate over all descendants and check if they are text nodes ( nodeType == 3 ) and after that search for the word Sold in them. Extracting the number is pretty easy after that.
Something like:
var searchValue = "Sold";
var descendants = getDescendants(listItem);
for(var j = 0; j < descendants.length; j++) {
if(descendants[j].nodeType == 3){
if(descendants[j].nodeValue.indexOf(searchValue) > -1){
var text = descendants[j].nodeValue.trim();
//"37+ Sold" for example
var soldNr = text.substring(0, text.indexOf(searchValue)-2);
//you process your number(soldNr) further
}
}
}
Use a selector string: select li.s-item span to select all spans which descend from an li with a class of s-item, check to see if the span's only child is a text node with "Sold" in it, and if so, do whatever you need to do with it.
If you're sure that any <li> will do, and not just those with a class of s-item, then use 'li span' instead:
document.querySelectorAll('li span').forEach(({ childNodes, textContent }) => {
if (childNodes.length !== 1 || childNodes[0].nodeType !== 3 || !textContent.includes('Sold')) return;
const count = textContent.match(/\d+/);
console.log('Processing span with sold number ' + count);
});
<ul>
<li class="s-item">
<div class="s-item__wrapper clearfix">
<div class="s-item__image-section">
<!-- other stuff -->
</div>
<div class="s-item__info clearfix">
<!-- other stuff -->
<div class="s-item__details clearfix">
<!-- other stuff -->
<div><span><span>62+ Sold</span></span>
</div>
</div>
</div>
</div>
</li>
<li class="s-item">
<div class="s-item__wrapper clearfix">
<div class="s-item__image-section">
<!-- other stuff -->
</div>
<div class="s-item__info clearfix">
<!-- other stuff -->
<div class="s-item__details clearfix">
<!-- other stuff -->
<div><span><span>333+ Sold</span></span>
</div>
</div>
</div>
</div>
</li>
</ul>

Combine multiple for loops to remove classes on click

I'm looking for some advice regarding having 2-3 for loops in one javascript statement to find elements with a particular class then add and remove classes. I'm fairly new to javascript so bear with me.
What I have so far works but I just don't want to get into bad habits down the line. As an example I have a navigation link that has a class of to--kenya, there is also another element with the same class and when either of these 2 elements are clicked i want the same thing to happen which will be to add an active--section class to the associated section named kenya.
The first for loop will look for all the elements with the class name to--kenya and add a click listener to them. If neither of these 2 elements has the class active--section it then runs another for loop looking for all the sections that have a class called active--section and removes it if it has the class. Then a third for loop runs checking all the navigation links to find a link with the active--link class then removes it if it has it. Once this is complete i just add a class to my new active navigation link as well as add the active--section class to the now active section.
Hope this makes sense, I'm just looking for the cleanest way of doing this.
<main class="main__wrapper">
<nav class="navigation">
<div class="navigation__inner">
<div class="navigation__logo">
Safari
</div>
<ul class="navigation__destinations">
<li class="navigation__destinations--item">
Home
</li>
<li class="navigation__destinations--item">
Kenya
</li>
<li class="navigation__destinations--item">
Botswana
</li>
<li class="navigation__destinations--item">
South Africa
</li>
<li class="navigation__destinations--item">
</li>
</ul>
<ul class="navigation__list">
<li class="navigation__item">
Contact
</li>
</ul>
</div>
</nav>
<div class="up__next">
<div class="up__next__box up__next--kenya to--kenya up__next__box--active">
<div class="up__next__content">
<div class="up__next__info">
<h4 class="up__next__heading">Next</h4>
<span class="up__next__text">Kenya - Maasai Mara National Reserve</span>
</div>
</div>
<div class="up__next__img">
<div class="up__next__img--kenya"></div>
</div>
</div>
</div>
<section class="home sections active--section">
<div class="home__info__box">
<h2 class="heading__primary home__heading--primary">Heading</h2>
<span class="home__info__box--text">text</span>
</div>
</section>
<section class="kenya sections">
<div class="kenya__info__box">
<h2 class="heading__primary kenya__heading--primary">Masai Mara</h2>
<span class="kenya__info__box--text">text</span>
</div>
</section>
</main>
//Global variables
var sections = document.querySelectorAll('.sections');
var navLink = document.querySelectorAll('.navigation__link');
var navHome = document.querySelector('.navigation__link--home');
var navKenya = document.querySelector('.navigation__link--kenya');
var home = document.querySelector('.home');
var kenya = document.querySelector('.kenya');
var toKenya = document.querySelectorAll('.to--kenya');
var upNextKenya = document.querySelector('.up__next--kenya');
//Event listeners
for (var i = 0; i < toKenya.length; i++) {
toKenya[i].addEventListener('click', function () {
if (!kenya.classList.contains('active--section')) {
for (var s = 0; s < sections.length; s++) {
sections[s].classList.remove('active--section');
}
for (var l = 0; l < navLink.length; l++) {
navLink[l].classList.remove('active--link');
}
kenya.classList.add('active--section');
navKenya.classList.add('active--link');
upNextKenya.classList.remove('up__next__box--active');
}
});
}

trouble getting a filtering search bar to work

i'm trying to get a filtering search bar to work that filters results of a list as you type it in the bar, and its not working. i tried to add an event listener but that didn't seem to work well either. any ideas?
js
function myFunction() {
// search for robots
var input, filter, ul, li, a, i;
input = document.getElementById('searchbox1');
filter = input.value.toUpperCase();
ul = document.getElementById("robotlist");
li = ul.getElementsByClassName('robotlist1');
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByClassName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
html of list i'm trying to search through:
<fieldset>
<legend>Mr. Robot's Top Robot Models</legend>
<ul id="robotlist">
<li class="robotlist1">
<article id="robo1">
<h4>
<label for="imgrobo1"> Name:</label>
R.E.T.</h4>
<img id="imgrobo1" src="images/roboDog.png" width=200 height=200 alt="robo1">
<h5><strong>Description:</strong> <br>This was our first robot.
He was modeled after the famous movie character E.T.</h5>
</article>
</li>
<li class="robotlist1">
<article id="robo2">
<h4>
<label for="imgrobo2"> Name:</label>
Butler.Bot</h4>
<img id="imgrobo2" src="images/robot2.png" width=200 height=200 alt="robo1">
<h5><strong>Description:</strong> <br>This was our second robot.
He makes a mean martini!</h5>
</article>
</li>
<li class="robotlist1">
<article id="robo3">
<h4>
<label for="imgrobo3"> Name:</label>
Mega Man</h4>
<img id="imgrobo3" src="images/robot3.png" width=200 height=200 alt="robo1">
<h5><strong>Description:</strong> <br>This is our newest model.
This one will follow you around the house.</h5>
</article>
</li>
</ul>
</fieldset>

Categories

Resources