How to highlight selected <li> item only? - javascript

I am trying to learn web designing and when trying to add class into it through java script ran into trouble.
html code:
<ul>
<li onclick="switchChannel(channel1)>
#Channel1
</li>
<li onclick="switchChannel(channel2) class="selected">
#Channel2
</li>
<li onclick="switchChannel(channel3)>
#Channel3
</li>
css code:
.selected{
color:blue;
border-left:4px solid blue;
}
javascript:script.js
function switchChannel(channelName) {
}
javascript:channel.js
var channel1={
name:"Channel1",
createdOn:new Date("April 1, 2016"),
starred:false
};
var channel2={
name:"Channel1",
createdOn:new Date("April 1, 2016"),
starred:false
};
I want to be able to click a channel1 from the list and apply .selected class to it but when channel2 is clicked remove .selected from channel1 and apply it to channel2 and so on...
If I have messed up anything else in the code please feel free to comment on it.

There are a lot of answers here but they don't seem to be addressing the actual issue. Here is a quick example using vanilla JavaScript to accomplish what you are asking for.
function switchChannel(el){
// find all the elements in your channel list and loop over them
Array.prototype.slice.call(document.querySelectorAll('ul[data-tag="channelList"] li')).forEach(function(element){
// remove the selected class
element.classList.remove('selected');
});
// add the selected class to the element that was clicked
el.classList.add('selected');
}
.selected{
color:blue;
border-left:4px solid blue;
}
<!-- Add the data-tag attribute to this list so you can find it easily -->
<ul data-tag="channelList">
<li onclick="switchChannel(this)">Channel 1</li>
<li onclick="switchChannel(this)" class="selected">Channel 2</li>
<li onclick="switchChannel(this)">Channel 3</li>
</ul>

You should use getElementsByIdand getElementsbyTagNameto manipulate the DOM:
function selectChannel(channelNumber) {
let listItems = document.getElementById("items").getElementsByTagName("li");
var length = listItems.length;
for (var i = 0; i < length; i++) {
listItems[i].className = i+1 == channelNumber ? "selected" : "";
}
}
.selected {
color: blue;
border-left: 4px solid blue;
}
<ul id="items">
<li onclick="selectChannel(1)">#channel1</li>
<li onclick="selectChannel(2)" class="selected">#channel2</li>
<li onclick="selectChannel(3)">#channel3</li>
</ul>

This solution uses jQuery but I thought this might help you out. A CodePen showing a version of this in action can be seen here.
jQuery(document).ready(function(){
jQuery('li').click(function(event){
//remove all pre-existing active classes
jQuery('.selected').removeClass('selected');
//add the active class to the link we clicked
jQuery(this).addClass('selected');
event.preventDefault();
});
});

I solved it. And I thank you every for your help.
$('li').removeClass('selected');
$('li:contains(' + channelName.name + ')').addClass('selected');

Related

JavaScript QuerySelector not returning last child

I'm trying to select the last child element of the class .nav-item and I've tried it several ways. It doesn't grab the item and just returns 'null' and applying styles will either grab the first item or return the following error:
main.js:25 Uncaught TypeError: Cannot read property 'style' of null
at main.js:25
My code :
The top part works fine and does apply the border, but I want to apply a border on the right of the last item and a border on the left of the first item. The last item is not working.
Can anyone point out my mistake?
The HTML if that helps:
let items = document.querySelectorAll('.nav-item');
for (let i = 0; i < items.length; i++) {
items[i].style.borderTop = '0.2em solid white';
items[i].style.borderBottom = '0.2em solid white';
}
// First and Last Item
// var secondItem = document.querySelector('.list-group-item:nth-child(2)');
// secondItem.style.color = 'coral';
let lastItem = document.querySelector('.nav-item:nth-child(4)');
console.log(lastItem);
lastItem.style.borderRight = '0.2em solid white';
<nav>
<h1>Item Lister</h1>
<ul class="nav" id="list">
<li class="nav-item">One</li>
<li class="nav-item">One</li>
<li class="nav-item">One</li>
<li class="nav-item">One</li>
</ul>
</nav>
So your <nav> element has one child: the <ul>. The <a> elements are children of the <ul>.
To fix this, you would need to querySelect .nav-item ul:nth-child(4).
Here's something to visualize it a little better. The <nav> is the parent to the <ul>, who is the parent to the <a>s. That makes <nav> the grandparent to the <a>s.
nav
ul
a
li
a
li
a
li
a
li
Also important like Karl-André Gagnon said to make sure the <li> is a child of the <ul>:
nav
ul
li
a
li
a
li
a
li
a
To achieve expected result, use below option of using document.querySelectorAll
Get all elements of class - nav-item irrespective parent and child relation
Convert HTML collection into Array using Array.from
Using pop() method get the last element to style
let lastItem = Array.from(document.querySelectorAll('.nav-item')).pop();
Sample working code for reference
let items = document.querySelectorAll('.nav-item');
for (let i = 0; i < items.length; i++) {
items[i].style.borderTop = '0.2em solid white';
items[i].style.borderBottom = '0.2em solid white';
}
// First and Last Item
// var secondItem = document.querySelector('.list-group-item:nth-child(2)');
// secondItem.style.color = 'coral';
let lastItem = Array.from(document.querySelectorAll('.nav-item')).pop();
console.log(lastItem);
lastItem.style.borderRight = '0.2em solid black';
<nav>
<h1>Item Lister</h1>
<ul class="nav" id="list">
<li class="nav-item">One</li>
<li class="nav-item">One</li>
<li class="nav-item">One</li>
<li class="nav-item">One</li>
</ul>
</nav>
Codepen - https://codepen.io/nagasai/pen/jOOvVjq
Issue::
:nth-child works with sibling elements, so :nth-child(4) is not available
As per MDN
The :nth-child() CSS pseudo-class matches elements based on their position in a group of siblings.
I used the options lastElementChild and firstElementChild. These worked.
Please change .nav-item to a. It serves your purpose as a is the child element of parent ul not the .nav-item.
let lastItem = document.querySelector('a:nth-child(4)');
It worked for me. Let me know if it is working for you.

Change color of child elements with the onclick event of parent element

I have a 3 <a> tags with each having class categoryItem wrapped inside of their respective parents with each having class categoryLists.
What I want is to have a tag of color red when li is clicked. For eg: If first li is clicked then it should only color the first a tag instead of coloring all of the a tags.
I tried using for loop but it doesn't seem to work as it colors the whole elements having a tags.
function changeColor() {
let catItem = document.getElementsByClassName('categoryItem');
for(let i = 0; i < catItem.length; i++) {
catItem[i].style.setProperty('color', 'red', 'important');
}
}
.categoryItem {
text-decoration: none;
color: green;
}
<li class="categoryList" onclick="changeColor()">First
First Link
</li>
<li class="categoryList" onclick="changeColor()">Second
Second Link
</li>
<li class="categoryList" onclick="changeColor()">Third
Third Link
</li>
Try this. No need for ids:
function changeColor(el) {
el.querySelector('a.categoryItem').style.setProperty('color', 'red', 'important');
}
.categoryItem {
text-decoration: none;
color: green;
}
<ul>
<li class="categoryList" onclick="changeColor(this)">First
First Link
</li>
<li class="categoryList" onclick="changeColor(this)">Second
Second Link
</li>
<li class="categoryList" onclick="changeColor(this)">Third
Third Link
</li>
</ul>
Pass this to your inline js function call that way your function will have a reference to the element that was clicked.
onclick="changeColor(this)"
Then use querySelector() or similar DOM method to get the child anchor tag of that element.
var item = listElement.querySelector('a.categoryItem');
And from there do the necessary manipulation, note using css classes instead of direct style manipulation.
item.classList.remove('active')
Demo
function changeColor(listElement) {
//clear the active class from current active
var active = listElement.parentElement.querySelector('a.categoryItem.active');
if(active){
active.classList.remove('active');
}
//set the class of the newly clicked element.
var item = listElement.querySelector('a.categoryItem');
if (item) {
item.classList.add('active');
}
}
.categoryItem {
text-decoration: none;
color: green;
}
.categoryItem.active {
color: red;
}
<ul>
<li class="categoryList" onclick="changeColor(this)">First
First Link
</li>
<li class="categoryList" onclick="changeColor(this)">Second
Second Link
</li>
<li class="categoryList" onclick="changeColor(this)">Third
Third Link
</li>
</ul>

How to apply a class to a list item using JS or jQuery without grabbing by id and keeping active?

So I'm using a CMS that doesn't allow me to apply an onclick on the a tag or use an onclick. So it basically outputs in code like the following:
<ul class="ul-class" id="ul-id">
<li class="nav-items">Something1</li>
<li class="nav-items">Something2</li>
<li class="nav-items">Something3</li>
<li class="nav-items">Something4</li>
<li class="nav-items">Something5</li>
</ul>
What I need to be able to do is apply a class showing an underline on the link that's been clicked that then leaves if another link has been clicked. Unfortunately I cannot get the class to stay present with the click.
I've tried this: JS Onclick Add Class
But the OP was using an onclick to latch onto.
What I've ended up with is this:
$(".nav-items").click(function (e) {
$(this).addClass("nav-active").siblings().removeClass("nav-active");
});
Then for the CSS I have:
a.nav-active{
border-bottom: 5px solid green;
padding-bottom: 10px;
}
The border pops up but leaves immediately. Is there something wrong with the code or do I need to put something else in to make the border permanent unless clicked elsewhere?
You can do something like:
Note: You have to use .nav-active instead of a.nav-active because your .nav-active is <li> and an <a>
$(function() {
$(".nav-items").click(function(e) {
e.preventDefault(); /* To prevent redirect of <a> */
$(".nav-items").removeClass("nav-active"); /* Remove the class to all nav-items */
$(this).addClass("nav-active"); /* Add the class to clicked nav-items*/
});
});
.nav-active {
border-bottom: 5px solid green;
padding-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="ul-class" id="ul-id">
<li class="nav-items">Something1</li>
<li class="nav-items">Something2</li>
<li class="nav-items">Something3</li>
<li class="nav-items">Something4</li>
<li class="nav-items">Something5</li>
</ul>
A possible approach with plain JavaScript
var myItems = Array.from(document.querySelectorAll(".nav-items")); // make array from NodeList
myItems.forEach(navItem => navItem.addEventListener("click", event => {
myItems.forEach(maybeSelectedBefore => maybeSelectedBefore.classList.remove("nav-active"));
event.target.classList.toggle("nav-active", true);
});
I had to reverse your CSS (to .nav-active a instead of a.nav-active) and add e.preventDefault(); to the jQuery, but otherwise it seems to be working. It wouldn't hurt to remove the class first before adding it, so change
$(this).addClass("nav-active").siblings().removeClass("nav-active");
to
$(this).siblings().removeClass("nav-active");
$(this).addClass("nav-active");

Dinamically lighten the background on each list item child

I have a stacked menu dropdown and I want each menu item to increasingly lighten gradually. I have done it manually using the sass lighten() rule, but I would like to know if there's a way to lighten it 5% dinamically for each new list-item increment. I guess some jquery should be combine to achieve this.
fiddle: http://jsfiddle.net/k2fjzro4/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="list-item-1">1</li>
<li class="list-item-2">2</li>
<li class="list-item-3">3</li>
<li class="list-item-4">4</li>
<li class="list-item-5">5</li>
</ul>
You could use the SASS's #for.
ul li {
padding: 10px;
background-color: #333;
}
#for $i from 1 through 10 {
li.list-item-#{$i} {
background-color: lighten(#333, $i*5%);
}
}
If you want it though to happen dynamically for the larger amount of items then JS is probably inevitable.
Edit : #Michał Kostrzyński posted the same answer. Leaving this here for the CodePen.
You can achieve this with a simple sass for expression.
Don't use javascript if you have SCSS enabled.
#for $i from 1 through 5 {
.list-item-#{$i} {
background-color:lighten(#333, 5%*$i)
}
}
See here :
https://codepen.io/Pauloscorps/pen/aVdrpY
for(var i = 1; i < 6;i++)
{
var opacity = 1/6*i ;
$('ul').append('<li class="list-item-'+i+'" style="background-color:rgba(0,0,0,'+opacity+')">'+i+'--'+opacity+'</li>');
}
ul li {
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
</ul>
Something like this maybe
Use each and rgba
var opacity = 1;
$("ul > li").each(function(index, element){
$(element).css("background-color", "rgba(51, 51, 51, "+opacity+")");
opacity -= 0.05;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="list-item-1">1</li>
<li class="list-item-2">2</li>
<li class="list-item-3">3</li>
<li class="list-item-4">4</li>
<li class="list-item-5">5</li>
</ul>

Javascript colour changer only changing colour on second click?

So i have a navbar and i am trying to make it so it highlights the current tab, however my javascript isnt working, it only works on the second click, and only if you double click.
function navColourChange(id){
var navBarLinks=document.getElementsByClassName("navLinks");
for(i=0;i<navBarLinks.length;i++){
navBarLinks[i].style.borderTop = "thick solid #ffffFF";
navBarLinks[i].style.color="#2F2933"
console.log(i)
}
var link = navBarLinks[id]
link.style.borderTop = "4px solid #01A2A6";
link.style.color="#01A2A6"
}
<div class="NavBar">
<ul>
<li>
HOME
</li>
<li>
ABOUT
</li>
<li>
PORTFOLIO
</li>
<li>
CONTACT
</li>
</ul>
</div>
Heres what it looks like
If what you really are looking for is a way to highligt the current page in your navbar, with JavaScript/jQuery, you can do something like this:
$(function() {
var currentPage = window.location.pathname.split('/').pop();
$('.NavBar ul li a[href*="'+currentPage+'"]').css({
borderTop: "4px solid #01A2A6",
color: "#01A2A6"
});
});
Here we find the filename from the url and then style that a-element in the navbar which has that filename as href.

Categories