Javascript: Selecting List from UL - javascript

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

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);
}
});

Next child LI that is wrapped in a different UL

I have the following list:
<ul>
<li class="item">One</li>
<li class="item">Two</li>
<li class="item">Three
<ul>
<li class="item">Something Original</li>
<li class="item selected">Something</li>
</ul>
</li>
<li>Four
<ul>
<li class="item">I want this selected next</li>
<li class="item">Good</li>
</ul>
</li>
</ul>
Using jQuery, how do I find the next li with the class="item" since it is wrapped in a different container. Obviously I cannot do $(".selected").next(".item") so how else can I do it?
JSFiddle: http://jsfiddle.net/q3f6v7zz/
Since the li elements are nested and you know that you want the next appearing li with a particular class, you can use .index() and do something like this
var $li = $('.item'); // <--- get the list of all lis with class .item
var index = $li.index($('.selected')); // <--- find the index of the one with .selected amongst all the lis
console.log($li.eq(index+1).html()); // <--- index+1 because you need the next appearing li after selected
If you want to move the selected class on keydown something like this should do
var $li = $('.item');
$(document).on('keydown', function(e) {
if (e.keyCode == 40) {
var index = $li.index($('.selected'));
$li.eq(index).removeClass('selected');
index = (index+1) % $li.length; // <--- to rotate the values from 0 to count of li.item elements
$li.eq(index).addClass('selected');
}
});
var $li = $('.item');
$(document).on('keydown', function(e) {
if (e.keyCode == 40) {
var index = $li.index($('.selected'));
$li.eq(index).removeClass('selected');
index = (index+1) % $li.length;
$li.eq(index).addClass('selected');
}
});
.selected {
background: green;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul>
<li class="item">One</li>
<li class="item">Two</li>
<li>Three
<ul>
<li class="item">Something</li>
<li class="item selected">Something Else</li>
</ul>
</li>
<li>Four
<ul>
<li class="item">I want this selected next</li>
<li class="item">Good</li>
</ul>
</li>
</ul>
You can get the index of the selected element within all lis, and then increment that index to get the next one.
$("ul").on("click", "li.item.selected", function() {
var all_li = $("li.item");
var selected_index = all_li.index(this);
var next_li = all_li.eq((selected_index + 1) % all_li.length);
$(this).removeClass("selected");
next_li.addClass("selected");
});
.item.selected {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="item">One</li>
<li class="item">Two</li>
<li class="item">Three
<ul>
<li class="item selected">Something</li>
</ul>
</li>
<li>Four
<ul>
<li class="item">I want this selected next</li>
<li class="item">Good</li>
</ul>
</li>
</ul>
I used the modulus so it will wrap around at the end.
Not sure what you are exactly looking for but you can use $(Element").parent().parent().find("li");
So in other words .parent() may be what you are looking for there is also .sibling() to find or you may want $('li').closest('ul').find('li')
which will go up the tree to find the nearest ul to the one you are looking for
https://api.jquery.com/closest/
You may also use:
Vanilla JS to do something similar to what was discussed by others with $index if it makes more sense to you:
Again this isn't as efficient but that is basically what JQuery is doing:
var myLis = document.getElementsByTagName('li');
var wantedIndex;
for(var i = 0;i<myLis.length; i++){
if(myLis[i].className === "active"){
wantedIndex = i+1; //gets the li which is next when selecting all lis
}
}

jquery .each (2nd line) add background color

I have a list showing in html like this:
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>...</li>
</ul>
Now, I added for each 2nd line a background color using this jquery:
$("ul li").each(function(index) {
if (index % 2 == 0) {
$(this).addClass("second-line");
}
});
BUT, each list item can be filtered to just view for the user currently logged in. So some lines will be hidden if I would filter the list. But after filtering the list, the jQuery to make each 2nd line is messed up.
How can I make that work?
I tried this:
$(".button").click(function() {
$("ul li").each(function(index) {
var uid = $(this).attr("data-uid");
var tuid = $(this).attr("data-tuid");
if (uid != tuid) {
$(this).hide(500);
}
});
$("ul li").each(function(index) {
if (index % 2 != 0) {
$(this).removeClass("second-line");
}
});
});
But no success.
you can use $( "ul li:nth-child(2)" ).addClass("second-line"); for the second elemnt.
You should try the :odd selector. With this one, you can select all the odd items (= 2nd, 4th,...). More info here: https://api.jquery.com/odd-selector/
you can make it with css.
like:
ul:nth-child(even){
background-color: #00ffff;
}
Hope it will helps you
ul li:nth-child(even) {
color: red;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
may this will work for you
$("ul li:even").each(function(index) {
$(this).removeClass("second-line");
});
jquery even

toggle class on click with 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');
});
}

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