How to change classes with using JavaScript which has no ID? - javascript

I am in trouble with changing the value of this code. In this code, I wanna change the class "selected" with a number set by JavaScript code.
Briefly speaking, I wanna reach the "li" items and give let say: 4 as a value, and it will add "selected" to the related class and will delete the previous one.
Edit: Additionally, it should also change the < div class="select-box">1< /div> value accordingly.
Here is the code:
<div class="select-container xl" id="_channel">
<label class="select-title T_channel xl">Channel:</label>
<div class="tp-select">
<div class="select-box">1</div>
<div class="select-icon-container"><span class="select-icon"></span></div>
<ul class="drop-down" style="max-height: 204.55px; display: none;">
<li style="cursor: default; border-bottom: 1px solid rgb(204, 204, 204);"></li>
<li data-val="0" class="option-item">Auto</li>
<li data-val="1" class="option-item selected">1</li>
<li data-val="2" class="option-item">2</li>
<li data-val="3" class="option-item">3</li>
<li data-val="4" class="option-item">4</li>
<li data-val="5" class="option-item">5</li>
<li data-val="6" class="option-item">6</li>
<li data-val="7" class="option-item">7</li>
<li data-val="8" class="option-item">8</li>
<li data-val="9" class="option-item">9</li>
<li data-val="10" class="option-item">10</li>
<li data-val="11" class="option-item">11</li>
<li data-val="12" class="option-item">12</li>
<li data-val="13" class="option-item">13</li>
</ul>
</div>
</div>
Thanks;

let x = document.querySelector(".select-box").innerText;
let options = document.querySelectorAll("li.option-item");
options.forEach(item => {
if (item.getAttribute("data-val") == x){
item.classList.add("selected");
}
else{
item.classList.remove("selected");
}
});
console.log(options);
<div class="select-container xl" id="_channel">
<label class="select-title T_channel xl">Channel:</label>
<div class="tp-select">
<div class="select-box">4</div>
<div class="select-icon-container"><span class="select-icon"></span></div>
<ul class="drop-down" style="max-height: 204.55px; display: none;">
<li style="cursor: default; border-bottom: 1px solid rgb(204, 204, 204);"></li>
<li data-val="0" class="option-item">Auto</li>
<li data-val="1" class="option-item selected">1</li>
<li data-val="2" class="option-item">2</li>
<li data-val="3" class="option-item">3</li>
<li data-val="4" class="option-item">4</li>
<li data-val="5" class="option-item">5</li>
<li data-val="6" class="option-item">6</li>
<li data-val="7" class="option-item">7</li>
<li data-val="8" class="option-item">8</li>
<li data-val="9" class="option-item">9</li>
<li data-val="10" class="option-item">10</li>
<li data-val="11" class="option-item">11</li>
<li data-val="12" class="option-item">12</li>
<li data-val="13" class="option-item">13</li>
</ul>
</div>
</div>

Use a query selector that matches the class and data-val value.
// Remove the old selected item
document.querySelectorAll(".option-item.selected").forEach(item => item.classList.remove("selected"));
// Select the desired item
document.querySelector(".option-item[data-val='4']").classList.add("selected");
.option-item.selected {
color: red;
}
<div class="select-container xl" id="_channel">
<label class="select-title T_channel xl">Channel:</label>
<div class="tp-select"><div class="select-box">1</div>
<div class="select-icon-container"><span class="select-icon"></span></div>
<ul class="drop-down" style="max-height: 204.55px;">
<li style="cursor: default; border-bottom: 1px solid rgb(204, 204, 204);"></li>
<li data-val="0" class="option-item">Auto</li>
<li data-val="1" class="option-item selected">1</li>
<li data-val="2" class="option-item">2</li>
<li data-val="3" class="option-item">3</li>
<li data-val="4" class="option-item">4</li>
<li data-val="5" class="option-item">5</li>
<li data-val="6" class="option-item">6</li>
<li data-val="7" class="option-item">7</li>
<li data-val="8" class="option-item">8</li>
<li data-val="9" class="option-item">9</li>
<li data-val="10" class="option-item">10</li>
<li data-val="11" class="option-item">11</li>
<li data-val="12" class="option-item">12</li>
<li data-val="13" class="option-item">13</li>
</ul>
</div>
</div>

you should use getElementsByClassName
So your code will look something like
document.getElementsByClassName("selected")

It sounds like you are looking for nth-child
For example
var selectedElement = document.querySelector(".drop-down:nth-child(4)");
selectedElement.classList.add('selected');

Add an ID to the ul and then select the nth child element.
const selected = 4
documentGetElementById(‘myUl’)
.childNodes[selected-1]
.classList
.add(‘selected’)

Since you want all the li elements with "selected" and then modify the class of a specific element. A js code like this should work.
//remove the selected class first
document.querySelector("selected").className = "option-item"
//get all li items with class option-item
listOfLi = document.querySelectorAll("li.option-item")
selectedElement = listOfLi.filter(e=>e.data-val==4)//whatever value you want to match it with
selectedElement.className = whatever classes you want to assign.(eg."selected")

Related

Closest in if statement and parse data in function loop

HTML code from menu:
<ul id="sidebarMenu" class="nav nav-sidebar" data-nav-type="accordion">
<li class="nav-item nav-item-submenu nav-item-expanded nav-item-open">
<i class="fad fa-user-tie fa-fw mr-2"></i>Webadmin
<ul class="nav nav-group-sub">
<li class="nav-item nav-item-submenu nav-item-expanded nav-item-open"><i class="fas fa-abacus mr-2"></i>tester
<ul class="nav nav-group-sub">
<li class="nav-item nav-item-submenu nav-item-expanded nav-item-open">
<i class="fas fa-abacus mr-2"></i>tester 2
<ul class="nav nav-group-sub">
<li class="nav-item">
<i class="fad fa-cogs fa-fw mr-2"></i>Site instellingen
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item"><i class="fad fa-list fa-fw mr-2"></i>Menu aanpassen</li>
</ul>
</li>
</ul>
What I want is add a class 'nav-item-expanded nav-item-open' on al related li with class nav-item-submenu.
So if the user is an a page that the menu collapse automatically the sub menus until the link
I have the next code:
This works. But its limited on my script this wil go back for 5 subs. But if the user want to use by example 6 menus the script fails. Sorry for my bad writing: D
$('.nav-item > a.active')
.closest('.nav-item-submenu')
.addClass('nav-item-expanded nav-item-open')
.parent()
.closest('.nav-item-submenu')
.addClass('nav-item-expanded nav-item-open')
.parent()
.closest('.nav-item-submenu')
.addClass('nav-item-expanded nav-item-open')
.parent()
.closest('.nav-item-submenu')
.addClass('nav-item-expanded nav-item-open')
.parent()
.closest('.nav-item-submenu')
.addClass('nav-item-expanded nav-item-open')
how can I simplify this code?
Example that I have tried:
var test = function(data = '') {
if (data === '') {
data = $('.nav-item > a.active').closest('.nav-item-submenu');
} else {
data = data.parent().closest('nav-item-submenu');
}
if (data.length > 0) {
data.addClass('nav-item-expanded nav-item-open');
test(data);
}
};
but that's not working.
You can use .parentsUntil() to simplify this. It returns all ancestors up to a point and can filter them. It takes two parameters:
Selector for the final ancestor to stop at.
Selector to filter the ancestors by.
This is almost the opposite of .find() which will traverse descendants instead. However, .find() will always work at any depth, it does not have a stop conditions like .parentsUntil().
A single call to .parentsUntil('#sidebarMenu', '.nav-item-submenu') will return all ancestor elements that you want - the .nav-item-submenu ones. At that point, you can add the classes you want or manipulate them further, if needed.
$('button').on('click', function() {
$('.nav-item > a.active')
.parentsUntil('#sidebarMenu', '.nav-item-submenu')
.addClass('nav-item-expanded nav-item-open');
})
.nav-item-submenu {
min-height: 50px;
padding: 5px;
border: 1px dashed black;
}
.nav-item-expanded {
border: 2px solid black;
}
.nav-item-open {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="sidebarMenu" class="nav nav-sidebar" data-nav-type="accordion">
<li class="nav-item nav-item-submenu">
A
<ul class="nav nav-group-sub">
<li class="nav-item nav-item-submenu">B1
<ul class="nav nav-group-sub">
<li class="nav-item nav-item-submenu">
C
<ul class="nav nav-group-sub">
<li class="nav-item">
D
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item">B2</li>
</ul>
</li>
</ul>
<button>Click me</button>

How to add styles to only one element of a ul list

I need to add additional styles to only one element of a list depending if the string matches with the url.
In this moment is identifying a unique string form a list and one element in the url, then it compare these two and add the styles depending if the strings are equal, but when doing this is applaying the style to all the elements in the list.
The result should add the styles only to the elements that match the string in the url.
<ul class="__filter--list--categoria" style="display: block;">
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas">Cervezas</a>
<ul>
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas/nacionales" style="background: red;">Nacionales</a>
</li>
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas/internacionales" style="background: red;">Internacionales</a>
</li>
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas/artesanales" style="background: red;">Artesanales</a>
</li>
</ul>
</li>
</ul>
var currentUrl = window.location.href.split('/')[5];
var categoryName = $('.__filter--list--categoria .__filter--list--item li .__anchor');
var categoryArray = [];
$(categoryName).each(function() {
categoryArray.push($(this).text())
});
for (x = 0; x < categoryArray.length; x++) {
var categoryString = categoryArray[x].toLowerCase();
if (categoryString === currentUrl) {
console.log('EQUAL...')
$(categoryName).css('background', 'red')
} else {
console.log('NOT EQUAL...')
}
}
You can loop li item by each method, and check href with testurl
let testurl = '/t/cervezas/nacionales';
$('li').each(function(index,item){
let href = $(item).find('a').attr('href');
if(href == testurl){
$(item).css('border', '1px solid green');
}
})
let testurl = '/t/cervezas/nacionales';
$('li').each(function(index,item){
let href = $(item).find('a').attr('href');
if(href == testurl){
$(item).css('border', '1px solid green');
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="__filter--list--categoria" style="display: block;">
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas">Cervezas</a>
<ul>
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas/nacionales" style="background: red;">Nacionales</a>
</li>
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas/internacionales" style="background: red;">Internacionales</a>
</li>
<li class="__filter--list--item">
<a class="__anchor" href="/t/cervezas/artesanales" style="background: red;">Artesanales</a>
</li>
</ul>
</li>
</ul>
Just to explain what is causing the issue, your problem is with this line:
$(categoryName).css('background', 'red')
This is applying the background red to every element that matches the categoryName selector, which is all your anchor tags. You don't currently have a class that uniquely identifies the different url's, see https://stackoverflow.com/a/56634800/264607 for a way to loop through your li elements and apply the style to the correct one

How to sort list items based on id attribute using jquery?

Hello so I have this problem, I use magento and my I can't find a place how to switch my tabs in position so I thought JQuery could come in hand. So this is what i have as an example
<li id="tab-4">
<li id="tab-3">
<li id="tab-2">
<li id="tab-1">
And i need to make it
<li id="tab-1">
<li id="tab-2">
<li id="tab-3">
<li id="tab-4">
Is there a fast way to do it? Or I have to do it one by one?
I guess you have an <ul> around you <li>
ul = $('ul'); // your parent ul element
ul.children().each(function(_,li){ul.prepend(li)})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="tab-4">4</li>
<li id="tab-3">3</li>
<li id="tab-2">2</li>
<li id="tab-1">1</li>
</ul>
Pure JS solution.
var a = document.getElementsByTagName('li');
var b = document.getElementById('list');
var arr = [];
Array.from(a).forEach(v => arr.push(v));
arr.reverse().forEach(v => b.append(v));
<ul id='list'>
<li id="tab-4">4</li>
<li id="tab-3">3</li>
<li id="tab-2">2</li>
<li id="tab-1">1</li>
</ul>
Also, for a sollution working (actually sorting) regardless of the initial order you can use sort() and append like this:
$("ul li").sort(function(a,b){
if(a.id.substring(4, 5) < b.id.substring(4, 5)) {
return -1;
} else {
return 1;
}
}).each(function() { $('ul').append(this);});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="tab-4">4</li>
<li id="tab-1">1</li>
<li id="tab-3">3</li>
<li id="tab-2">2</li>
</ul>
$(".list > li").detach().sort(function(a, b) {
return +a.id.replace("tab-","") - b.id.replace("tab-","") ;
}).appendTo("ul.list");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li id="tab-3">3
<li id="tab-4">4
<li id="tab-2">2
<li id="tab-1">1
</ul>
If your HTML code like this you can write your code using detach and a single appendTo like this.
More about detach(): https://www.w3schools.com/jquery/html_detach.asp

Show first level children of a nested ul li using jquery

I have an HTML file like this:
JS:
function functionName(event) {
event.stopPropagation();
var item = event.data.param;
document.getElementById("list").innerHTML = item;
}
$(document).ready(function() {
$("li").each(function() {
$(this).on('click', {param: this.id}, functionName);
});
});
HTML:
<div id="main">
<div id="tree">
<ul class="xyz">
<li class="hide">AVC</li>
<li class="hide">Anna</li>
<li class="hide">Peter</li>
<li id="foo1">Gary
<ul class="xyz">
<li class="hide">John</li>
<li class="hide">Anna</li>
<li id="foo2">Briton
<ul class="xyz">
<li class="hide">gg</li>
<li class="hide">hh</li>
<li id="foo3">Layla
<ul class="xyz">
<li class="hide">gg</li>
<li class="hide">hh</li>
<li id="foo4">Undertaker
<ul class="xyz">
<li class="hide">gg</li>
<li class="hide">hh</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div id="list"></div>
</div>
I have two div tags whose id is receptively tree and list. Tree div contains the nested ul li tags and each li have unique id.
I want to show the first level children of a ul li tag. For example, when I am clicking on Gary, it should show the first level children ( John, Anna, Britton) in right div i.e. list.
Right now I am able to get the id of ul li element in list div when clicking any item.
How can I traverse the first level children of clicking element using jquery/javascript and display them in list div?
Thanks
Try using find() ,> ul selects the direct descendant
$('li[id^="foo"]').click(function(e){
e.stopPropagation();
var x = $(this).last().find(' > ul').clone().find('ul').remove().end();
console.log(x[0])
$('#list').html(x);
$('#list .hide').show();
});
simple demo : https://jsfiddle.net/sk30mwud/4/
'$('#tree').on('click', 'li', function(){
$(this).find('> ul > li').toggleClass('hide');
return false;
})'
Can you please take a look at this approach:
It uses .contents().get(0).nodeValue to fetch the text present in child li nodes and not from its childerns if any.
function functionName(event) {
event.stopPropagation();
var item = event.data.param;
var names = [];
$("#" + item).children("ul").children("li").each(function() {
names.push($(this).contents().get(0).nodeValue);
});
$("#list").text(names.join(","));;
}
$(document).ready(function() {
$("li").each(function() {
$(this).on('click', {
param: this.id
}, functionName);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="main">
<div id="tree">
<ul class="xyz">
<li class="hide">AVC</li>
<li class="hide">Anna</li>
<li class="hide">Peter</li>
<li id="foo1">Gary
<ul class="xyz">
<li class="hide">John</li>
<li class="hide">Anna</li>
<li id="foo2">Briton
<ul class="xyz">
<li class="hide">gg</li>
<li class="hide">hh</li>
<li id="foo3">Layla
<ul class="xyz">
<li class="hide">gg</li>
<li class="hide">hh</li>
<li id="foo4">Undertaker
<ul class="xyz">
<li class="hide">gg</li>
<li class="hide">hh</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div id="list"></div>
</div>

Javascript/JQuery- Highlighting one link at a time on click

I have some links I'd like to be highlighted when you select them, but only one at a time. I found this JQuery code, however, I can't get it to work. The links won't highlight even when I click it. I had a really straight forward Javascript function that changed the color of the link with the onlick. But I would like for it to only highlight the most recently clicked link.
The new JQuery is presented in the code, it appears like it should work I just don't know why it's not. The Javascript function, selectedLink(), I used to call on the onlick method. I'm willing to use either or, I just want the functionality.
.highlight {
color: #3385D6;
border: 1px solid;
border-color: #BBBBBB;
background:#70AAE2;
font-weight: bold;
}
function selectedLink(id){
var sublink = document.getElementById(id);
sublink.style.background = "#CCCCCC";
sublink.style.color = "#3385D6";
sublink.style.fontWeight = "bold";
sublink.style.border = "1px solid";
sublink.style.borderColor = "#BBBBBB";
}
<input type="radio" name="UItab" id="tabf" >
<label for="tabf"><span>Menu Item</span></label>
<div>
<div>
<ul class="sub-menu">
<li id="">SecondLevel A</li></td>
<li id="">SecondLevel B</li>
<li id="">SecondLevel C</li>
</ul>
</div>
<div id="togglebox">
<li id="">ThirdLevel A</li>
<li id="">ThirdLevel B</li>
<li id="">ThirdLevel C</li>
</div>
<div id="barbox">
<li id="">Fourth Level A</li>
<li id="">Fourth Level B</li>
<li id="">Fourth Level C</li>
</div>
<div id="piebox">
<li id="">Fourth Level A</li>
<li id="">Fourth Level B</li>
<li id="">Fourth Level C</li>
</div>
<script>
$('a').click(
function(e){
e.preventDefault;
$('.highlight').removeClass('highlight');
$(this).addClass('highlight')
});
</script>
Code is fine just wrap around a $(function(){/*here*/});
$(function () {
$('a').click(function (e) {
e.preventDefault();
$('.highlight').removeClass('highlight');
$(e.target).addClass('highlight');
});
});
function selectedLink(id) {
var sublink = document.getElementById(id);
sublink.style.background = "#CCCCCC";
sublink.style.color = "#3385D6";
sublink.style.fontWeight = "bold";
sublink.style.border = "1px solid";
sublink.style.borderColor = "#BBBBBB";
}
function toggle_visibility(s) {}
.highlight {
color: #3385D6;
border: 1px solid;
border-color: #BBBBBB;
background:#70AAE2;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="radio" name="UItab" id="tabf" >
<label for="tabf"><span>Menu Item</span></label>
<div>
<div>
<ul class="sub-menu">
<li id="">SecondLevel A</li>
<li id="">SecondLevel B</li>
<li id="">SecondLevel C</li>
</ul>
</div>
<div id="togglebox">
<li id="">ThirdLevel A</li>
<li id="">ThirdLevel B</li>
<li id="">ThirdLevel C</li>
<li id="">ThirdLevel D</li>
<li id="">ThirdLevel E</li>
<li id="">ThirdLevel F</li>
</div>
<div id="barbox">
<li id="">Fourth Level A</li>
<li id="">Fourth Level B</li>
<li id="">Fourth Level C</li>
</div>
instead of removing class to .highlight, remove class for all a elements
$(a).removeClass('highlight');
It may not be the solution but it looks like you should use e.preventDefault() instead of e.preventDefault
may be this will work:
$(document).ready(function(){
$('a').click(function(e){
e.preventDefault();
//All a tag having class highlight
$('a.highlight').removeClass('highlight');
$(this).addClass('highlight');
});
});
Try this:
$('a').click(
function(e){
e.preventDefault();
$(this).addClass('highlight').siblings().removeClass('highlight');
});

Categories