toggle class on click with javascript - javascript

I am trying to create a simple on click event using js (no jQuery)
If I run the below code it only works for the first item I click.
var listItem = document.querySelector('li');
listItem.addEventListener('click', function(event) {
this.classList.toggle('clicked');
});
.clicked {
color:red;
}
<ul id="mylist">
<li>item 1</li>
<li>item 2</li>
</ul>
I looked at an alternative using
var listItem = document.getElementById('mylist');
listItem.addEventListener('click', function(event) {
this.classList.toggle('clicked');
});
.clicked {
background-color:red;
}
<ul id="mylist">
<li>item 1</li>
<li>item 2</li>
</ul>
but this just toggles the ul rather than the li I clicked.
How can I target all li in my list so that each time they are clicked their class is toggeled

You should use querySelectorAll instead of querySelector, then loop over all list items:
var listItems = document.querySelectorAll('li');
for(var i = 0; i < listItems.length; i++){
listItems[i].addEventListener('click', function(event) {
this.classList.toggle('clicked');
});
}

Related

How do I get the call back function to log the value of the data attribute with mouseover?

So I have a 'li' list here that I have selected, and I'm using a for loop to add a mouseover event listener to each of those tags.
<ul>
<li data-animal="horse">Animal 1</li>
<li data-animal="dog">Animal 2</li>
<li data-animal="cat">Animal 3</li>
</ul>
And I've come to a halt, because the call back function should log the value of each data attribute when the mouse move over it. How can I achieve this?
const mouseOverLoop = document.querySelectorAll("li");
for (let i = 0; i < mouseOverLoop.lenght; i++) {
mouseOverLoop[i].addEventListener("mouseover", hoverOver);
}
function hoverOver() {
console.log();
}
There are 2 problems:
A typo, it should be mouseOverLoop.length (not lenght)
The console.log() doesn't have a string to log.
You can use the event's target property to identify the proper element, and the getAttribute method to get the attribute value.
function hoverOver(e) {
console.log(e.target.getAttribute('data-animal'));
}
const mouseOverLoop = document.querySelectorAll("li");
for (let i = 0; i < mouseOverLoop.length; i++) {
console.log(mouseOverLoop[i]);
mouseOverLoop[i].addEventListener("mouseover", hoverOver);
}
function hoverOver(e) {
console.log(e.target.getAttribute('data-animal'));
}
<ul>
<li data-animal="horse">Animal 1</li>
<li data-animal="dog">Animal 2</li>
<li data-animal="cat">Animal 3</li>
</ul>
<ul id="animals">
<li data-animal="horse">Animal 1</li>
<li data-animal="dog">Animal 2</li>
<li data-animal="cat">Animal 3</li>
</ul>
document.getElementById("animals").addEventListener("mouseover", function({ target: { dataset } }) {
if (dataset.animal) {
console.log(dataset.animal);
}
});

Javascript: Selecting List from UL

var ul = document.getElementById("parent-list");
document.querySelectorAll("#parent-list li").onclick = function() {
alert('click!');
}
<ul id="parent-list">
<li id="item-1">Item 1</li>
<li id="item-2">Item 2</li>
<li id="item-3">Item 3</li>
<li id="item-4">Item 4</li>
<li id="item-5">Item 5</li>
<li id="item-6">Item 6</li>
<li id="item-7">Item 7</li>
<li id="item-8">Item 8</li>
<li id="item-9">Item 9</li>
</ul>
I'm trying to have an alert popup of the item clicked when I click on a "li" element with javascript only. I know how to do in jquery but I can't figure out how to do it with javascript.
fiddle: https://jsfiddle.net/7jcksznz/1/
querySelectorAll returns an HTML collection. You would need to attach the event to each one. You would need to loop over the collection.
var lis = document.querySelectorAll("#test li");
for (var i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", function() {
console.log(this.innerHTML);
});
}
<ul id="test">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
A better option is to add one click on the UL and use the event to determine which li was clicked.
document.getElementById("test").addEventListener("click", function(event) {
var li = event.target;
console.log(li.innerHTML);
});
<ul id="test">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
document.querySelectorAll("#parent-list li") get a collection of HTMLElement,so,you can do like this:
window.onload = function()
{
var ul = document.getElementById("parent-list");
ul.onclick = function(e)
{
if(e.target.tagName = "LI")
{
alert(1);
}
}
}
querySelectAll returns array of nodes.
you have to iterate over the nodes to add the event listner.
var ul = document.getElementById("parent-list");
var li_items = document.querySelectorAll("#parent-list li");
for (var i = 0 ; i < li_items.length ; i++)
li_items[i].onclick = function (){alert(this.id);}
Use an event-listener targeted on each element rather than directly assigning an onclick function to a NamedNodeMap.
/* get an array of list items */
var items = Array.prototype.slice.call(
document.querySelectorAll('li[id|="item"]')
);
/* add event-listener to each item */
items.forEach(function(item) {
item.addEventListener('click', clickAlert, false);
});
/* click function */
function clickAlert(evt) {
alert(evt.target.id +' clicked!');
}
See:
Array.prototype.slice
Array.prototype.forEach
eventTarget.addEventListener
NamedNodeMap

jQuery: Scroll down and scroll up with slide effect

The code below slides down and up four elements of the list. These elements, of course has its height. So the question is: how to slide down or up elements and at the same time slide page scroll?
Thank You.
$(document).ready(function() {
var list = $(".partners__ul li");
var numToShow = 4;
var button = $(".partners__button__a");
var numInList = list.length;
var isShowing = true;
list.hide();
if (numInList > numToShow) {
button.show();
}
list.slice(0, numToShow).show();
button.click(function() {
var showing = list.filter(':visible').length;
if (isShowing) {
list.slice(showing - 1, showing + numToShow).fadeIn(100, onFadeComplete);
} else {
list.slice(showing - numToShow, numInList).fadeOut(100, onFadeComplete);
}
});
function onFadeComplete() {
var nowShowing = list.filter(':visible').length;
if (nowShowing == numInList && isShowing) {
isShowing = false;
button.text("Show less");
} else if (isShowing) {
button.text("Show even more");
}
if (nowShowing == numToShow) {
button.text("Show more");
isShowing = true;
}
}
});
.partners__ul {
list-style: none;
padding: 0;
margin: 0;
}
.partners__ul li {
position: relative;
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<ul class="partners__ul">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
</ul>
<button class="partners__button__a">Show More</button>
<button class="partners__button__a_less" style="display:none">Show Less</button>
</div>
I often do something like the code below to get the slide animation:
$(".scrollto").click(function(e) {
var btn = $(e.currentTarget);
$('html, body').animate({
scrollTop: $(btn.attr("href")).offset().top
}, 1000);
});
I use the code above to implement animations(slide effect) to my header website. You can use it for your own. Also if you want you can add your html code and I can update the answer.
I hope it's helps.
EDITED:
Basically I have added a piece of code in your function onFadeComplete() as you can see below: DEMO
$("html, body").animate({ scrollTop: $('.partners__ul li').last().offset().top }, 1000);
I have set the scroll to the body so in the example is not working but in your website should work fine.

See more and see less button

Here's a script that shows 4 items each time a button is clicked. What i need is to change the text of the button after a click to "show even more" and then change to "show less" at the end when all items shown. I tried to add this:
if (nowShowing >= numInList) {
$('.partners__button__a').toggle(function() {
$(this).text('Show More');
}, function() {
$(this).text('Show Less');
button.show();
});
}
but it's not working the way I need.
And also how to add a reverse function to hide items?
Thank you.
$(document).ready(function() {
var list = $(".partners__ul li");
var numToShow = 4;
var button = $(".partners__button__a");
var numInList = list.length;
list.hide();
if (numInList > numToShow) {
button.show();
}
list.slice(0, numToShow).show();
button.click(function() {
var showing = list.filter(':visible').length;
list.slice(showing - 1, showing + numToShow).fadeIn();
var nowShowing = list.filter(':visible').length;
});
});
.partners__ul {
list-style: none;
padding: 0;
margin: 0;
}
.partners__ul li {
position: relative;
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<ul class="partners__ul">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
</ul>
<button class="partners__button__a">Show More</button>
</div>
I did something different. Used two buttons but instead of one just to hide and show at the same time when half content is visible. Not sure whether you need it this way, just thought about making it more functional.
$(document).ready(function() {
var list = $(".partners__ul li");
var numToShow = 4;
var button = $(".partners__button__a");
var buttonLess = $(".partners__button__a_less");
var numInList = list.length;
var nowShowing = 4;
list.hide();
if (numInList > numToShow) {
button.show();
}
list.slice(0, numToShow).show();
button.click(function() {
var showing = list.filter(':visible').length;
list.slice(showing - 1, showing + numToShow).fadeIn();
nowShowing = list.filter(':visible').length;
if(numInList === nowShowing) {
$(this).hide();
buttonLess.text('Show Less')
} else if(nowShowing > numToShow) {
$(this).text('Show Even More');
buttonLess.show();
}
});
buttonLess.click(function() {
var showing = list.filter(':visible').length;
list.slice(showing - numToShow, showing).fadeOut();
nowShowing = nowShowing - numToShow;
if(numToShow === nowShowing) {
$(this).hide();
button.text('Show More');
} else if(nowShowing < numInList) {
$(this).text('Show Less');
button.show();
}
});
});
.partners__ul {
list-style: none;
padding: 0;
margin: 0;
}
.partners__ul li {
position: relative;
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<ul class="partners__ul">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
</ul>
<button class="partners__button__a">Show More</button>
<button class="partners__button__a_less" style="display:none">Show Less</button>
</div>
Getting the text to change is easy enough, the simplest way would be to add this to the bottom of your button's click handler:
if(nowShowing == numInList){
$(this).text("Show less");
}
else{
$(this).text("Show even more");
}
As for the second item of showing less, you could add this (agin in the click handler)
if(showing < numInList){
list.slice(showing - 1, showing + numToShow).fadeIn();
}
else{
list.slice(showing - numToShow, numInList).fadeOut();
}
From here, you need to handle the fact that once you've shown everything and you start being able to show less, you need some form of boolean to indicate if we're currently in the state of "showing" or "hiding".
This then presents another problem! As you're fading in and out the :visible state will not be correct until after the fade has completed. Therefore you should defer the functionality using an overload of fadeIn / fadeOut which takes a callback.
The finished code can be seen below.
$(document).ready(function() {
var list = $(".partners__ul li");
var numToShow = 4;
var button = $(".partners__button__a");
var numInList = list.length;
var isShowing = true;
list.hide();
if (numInList > numToShow) {
button.show();
}
list.slice(0, numToShow).show();
button.click(function() {
var showing = list.filter(':visible').length;
if(isShowing){
list.slice(showing - 1, showing + numToShow).fadeIn(100,onFadeComplete);
}
else{
list.slice(showing - numToShow, numInList).fadeOut(100,onFadeComplete);
}
});
function onFadeComplete(){
var nowShowing = list.filter(':visible').length;
if(nowShowing == numInList && isShowing){
isShowing = false;
button.text("Show less");
}
else if(isShowing){
button.text("Show even more");
}
if(nowShowing == numToShow){
button.text("Show more");
isShowing = true;
}
}
});
.partners__ul {
list-style: none;
padding: 0;
margin: 0;
}
.partners__ul li {
position: relative;
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<ul class="partners__ul">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
</ul>
<button class="partners__button__a">Show More</button>
</div>

Javascript/jQuery - On hover over a li element, change class of another li element

i am having some trouble with the menu bar on this website: http://www.re-generation.ro/ro/campanii/minerit-aurifer .
Now, the second li element is active. What i want to do, is that on hover over any other li element in the menu, the class of the current active li element becomes blank and on on hover out, it becomes active again. If you visit the link you can easily understand what i what.
If you need any information pls ask.
thank you in advance!
My code:
var lis = document.getElementsByTagName('ul');
for (var i=0, len=lis.length; i<len; i++){
lis[i].onmouseover = function(){
var firstDiv = this.getElementsByTagName('li')[1];
firstDiv.className = '';
var ul = $(this).parent(document.this.getElementsByTagName('ul')[1]);
ul.className = '';
};
lis[i].onmouseout = function(){
var firstDiv = this.getElementsByTagName('li')[1];
firstDiv.className = 'active';
};
};
EDIT: Thank you all for your answers! That really helped!
The first thing you probably want to do is assign two different states/classes: active and current. One tells you which one should be shown, and the other actually toggles the visibility.
$('#menu').on('mouseover', '> li', function(e) {
# attach hover event to the menu, and check which LI you are hovering
if (!$(this).hasClass('.current)')) {
$('.current', '#menu').removeClass('active');
}
}).on('mouseout', '> li', function (e) {
if (!$(this).hasClass('.current)')) {
$('.current', '#menu').addClass('active');
}
});
Here you are selecting just the direct descendants and updating the class, provided it's not the currently active list item.
HTML:
<ul id="menu">
<li>Item 1</li>
<li class="current active">Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>​
JavaScript:
$('#menu li').on('mouseover', function() {
var li$ = $(this);
li$.parent('ul').find('li').removeClass('active');
li$.addClass('active');
})
.on('mouseout', function() {
var li$ = $(this);
li$.removeClass('active');
li$.parent('ul').find('li.current').addClass('active');
});​
DEMO
I would use JQuery for this. Something like this:
$('li').hover(function(){
$('li.active').removeClass('active').addClass('normal');
});
$('li').mouseleave(function(){
$('li.normal').removeClass('normal').addClass('active');
});
What you're missing is a way to remember what the default state is. Here is my answer, and a Fiddle
HTML:
<ul class="menuWithDefault">
<li>Link One</li>
<li class="active">Link One</li>
<li>Link One</li>
<li>Link One</li>
</ul>
Javascript:
$(".menuWithDefault").each(function() {
var defaultItem = $(this).find(".active").first();
$(this).find("li").hover(function() {
defaultItem.toggleClass('active', false);
$(this).toggleClass('active', true);
}, function() {
$(this).toggleClass('active', false);
defaultItem.toggleClass('active', true);
});
});​
​
$(document).ready(function(){
$('li').hover(function(){
$(this).addClass('active').siblings().removeClass('active')
});
});
li.active{
color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="active">List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
<li>List Item 4</li>
</ul>

Categories