<ul> <li> list items adding onclick - javascript

I'm trying to add onclick to my list items and get the href with pure JavaScript.
I had it working from just a div but as soon as I added list items I was unable to get it to work.
var navBarDiv = document.getElementById("navbar");
var contentDiv = document.getElementById("content");
var navBarList = navBarDiv.getElementsByTagName("ul");
// Attach click listeners for each of the nav links.
for (var i = 0; i < navBarList.length; i++) {
var navBarItems = navBarList[i].getElementsByTagName("li");
for (var j = 0; j < navBarItems.length; j++) {
navBarItems[j].addEventListener('click', function (e) {
e.preventDefault();
var pageURL = this.attributes['href'].value;
GetFileDoc(pageURL, function (doc) {
contentDiv.innerHTML = doc.getElementById("content").innerHTML;
});
});
}
}
<div id="navbar">
<ul>
<li>Homepage</li>
<li>About Us</li>
<li>Gallery</li>
<li>Contact Us</li>
</ul>
</div>

This appears to be the problem:
var pageURL = this.attributes['href'].value;
You're adding the click handler to the li element, not the a element. So there is no href attribute. I imagine there are two options:
Drill into the element further to get the href of the child a element, or
Add the click handler to the a element instead
For the first option, you might do something like this instead:
var pageURL = this.getElementsByTagName("a")[0].attributes['href'].value;
You'd want to put in some error checking of course, unless you're very confident that there will always be that first a element that you want.
For the second option, you might just modify what you're looping over. Perhaps something like this:
var navBarItems = navBarList[i].getElementsByTagName("a");
Assuming there are no other a elements in the hierarchy that you don't want to use for this.

Try with
a tag is the children of li so you need use querySelectorfor target the child element
And simply use with element.href for getting href value
var navBarDiv = document.getElementById("navbar");
var contentDiv = document.getElementById("content");
var navBarList = navBarDiv.getElementsByTagName("ul");
for (var i = 0; i < navBarList.length; i++) {
var navBarItems = navBarList[i].getElementsByTagName("li");
for (var j = 0; j < navBarItems.length; j++) {
navBarItems[j].addEventListener('click', function(e) {
e.preventDefault();
var pageURL = this.querySelector('a').href;
console.log(pageURL)
//GetFileDoc(pageURL, function(doc) {
//contentDiv.innerHTML = doc.getElementById("content").innerHTML;
// });
});
}
}
<div id="navbar">
<ul>
<li>Homepage</li>
<li>About Us</li>
<li>Gallery</li>
<li>Contact Us</li>
</ul>
</div>

You are adding event to each li in the list. According to the rest of the code, espscialy the line this.attributes['href'].value you expect to have link element loaded. You can load all the link elements instead right away by using
navBarList[i].querySelectorAll("a");
which gives you all the inner links.

Try this one:
var navBarDiv = document.getElementById("navbar");
var contentDiv = document.getElementById("content");
var navBarLinks = navBarDiv.getElementsByTagName("a");
// Attach click listeners for each of the nav links.
for (var i = 0; i < navBarLinks.length; i++) {
navBarLinks[i].addEventListener('click', function (e) {
e.preventDefault();
var pageURL = this.attributes['href'].value;
GetFileDoc(pageURL, function (doc) {
contentDiv.innerHTML = doc.getElementById("content").innerHTML;
});
});
}
}
It's nearly the same except I filter directly to the anchor-tags and then there is a href attribute.

Without using ES6
Array.prototype.slice.call(document.querySelectorAll('#navbar ul li a')).map(function(item) {
item.addEventListener('click', function(e) {
e.preventDefault();
console.log("href", e.target.href);
});
});
<div id="navbar">
<ul>
<li>Homepage</li>
<li>About Us</li>
<li>Gallery</li>
<li>Contact Us</li>
</ul>
</div>
Using ES6
[...document.querySelectorAll('#navbar ul li a')]
.map((item) => {
item.addEventListener('click', (e) => {
e.preventDefault();
console.log("href", e.target.href);
});
});
<div id="navbar">
<ul>
<li>Homepage</li>
<li>About Us</li>
<li>Gallery</li>
<li>Contact Us</li>
</ul>
</div>
jQuery
jQuery('#navbar ul li').click(function() {
console.log("href", $(this).attr('href'))
});

Please try this code
var navBarDiv = document.getElementById("navbar");
var contentDiv = document.getElementById("content");
var navBarList = navBarDiv.getElementsByTagName("ul");
// Attach click listeners for each of the nav links.
for (var i = 0; i < navBarList.length; i++) {
var navBarItems = navBarList[i].getElementsByTagName("li");
for (var j = 0; j < navBarItems.length; j++) {
navBarItems[j].addEventListener('click', function (e) {
e.preventDefault();
var pageURL = this.getElementsByTagName('a')[0].href;
alert(pageURL);
GetFileDoc(pageURL, function (doc) {
contentDiv.innerHTML = doc.getElementById("content").innerHTML;
});
});
}
}

Related

How can I move a list item to the top on click?

If I click on a specific list item then it will goes to up in the list.
For example if i click on Price list it show above of the color list.
function setOnTop() {
var listItems = document.querySelector("li");
for (var i = 0; i < listItems.length; i++) {
listItems[$i].addEventListener("click", function() {
//Move on top
});
}
}
<ul>
<li>Color</li>
<li>Size</li>
<li>Price</li>
</ul>
const ul = document.querySelector("ul");
const li = ul.querySelectorAll("li");
function setTop() {
ul.prepend(this);
}
li.forEach((el) => {
el.addEventListener("click", setTop);
});
<ul>
<li>Color</li>
<li>Size</li>
<li>Price</li>
</ul>

How to change add and remove active class in JavaScript

I have navigation Bar where I want to add active class and remove it from a previous clicked list I think it's a basic thing but I'm new in javascript so i couldn't figure out the solution. I have code that works but the last and first list does not remove.
HTML CODE
<div id="icon-layout">
<ul>
<li>CLOTHING</li>
<li>BAGS</li>
<li>SHOES</li>
<li>ACCESSORIES</li>
<li>BEAUTY</li>
<li>ABOUT US</li>
<li>SERVICE</li>
</ul>
</div>
CSS
#icon-layout .active{
background-color: #FF4136;
color: white;
}
JAVASCRIPT
var activeclass = document.querySelectorAll('#icon-layout li');
for (var i = 0; i < activeclass.length; i++) {
activeclass[i].addEventListener('click', activateClass);
}
function activateClass(e) {
var previous = e.target.previousElementSibling;
var next = e.target.nextElementSibling;
e.target.classList.add('active');
previous.classList.remove('active');
next.classList.remove('active');
}
var activeclass = document.querySelectorAll('#icon-layout li');
for (var i = 0; i < activeclass.length; i++) {
activeclass[i].addEventListener('click', activateClass);
}
function activateClass(e) {
for (var i = 0; i < activeclass.length; i++) {
activeclass[i].classList.remove('active');
}
e.target.classList.add('active');
}
You may loop through all elements and remove class before adding one
Try using JQuery as it would definitely make your task easier:
$('#icon-layout li').on('click', function() {
$('.icon-layout li.active').removeClass('active');
$(this).addClass('active');
});

Calling a function in mylibray onclick passing this

I've got this onclick call that works.
<ul id="ul_name" onclick="javascript:mylibrary.ul_action(this);">
I don't want to manually add the call on every ul so i tried this one:
window.onload = function() {
var u = document.querySelectorAll(".myclass ul");
var i;
for (i = 0; i < u.length; i++) {
u[i].onclick = mylibrary.ul_action(this);
};
};
But it doesn't work. It's this's scope wrong? Or what? Thank you.
You are calling the function immediately and assigning the return value as your click event handler.
You need to create a new function that calls your existing function with the argument you want (which isn't this because you want it to be the element):
window.onload = function() {
var mylibrary = {
ul_action: function(ul) {
console.log(ul.innerText);
}
};
var u = document.querySelectorAll(".myclass ul");
var i;
for (i = 0; i < u.length; i++) {
u[i].onclick = mylibrary.ul_action.bind(window, u[i]);
};
};
<main class="myclass">
<ul>
<li>One</li>
</ul>
<ul>
<li>Two</li>
</ul>
</main>

addEventListener click for Unordered List

Attempting to convert a for loop that steps through an unordered list of hyperlinks adding an 'onclick' function to each into one using an eventlistener for an assignment. I have been unable to get a working model.
Here is the navlist and links I am working with, note that these I cannot edit or change in any way.
<body>
<ul id="navlist">
<li id="l0"> Sniffer </li>
<li id="l1"> is </li>
<li id="l2"> good </li>
<li id="l3"> programmer </li>
</ul>
<script>
var myLinks = [
'http://bing.com/search?q=Sniffer',
'http://bing.com/search?q=is',
'http://bing.com/search?q=good',
'http://bing.com/search?q=programmer'
];
And here is the code sample that I am converting:
window.onload=function() {
for (var i=0; i< myLinks.length; i++) {
// document.getElementById("l"+i).getElementsByTagName("a")[0]).href=myLinks[i];
document.getElementById("l"+i).getElementsByTagName("a")[0].onclick=(function(idx) {
var idx = i;
return function() {
window.location.href = myLinks[idx];
return false; // cancel href
};
})(i);
}
}
</script>
</body>
I have attempted a few different ways of formatting the specific document elements in the concatenation. but none of them work. Here is my most recent and simplest attempt:
window.onload=function() {
for (var i=0; i< myLinks.length; i++) {
document.getElementById("l"+i).addEventListener("click", function() {
var idx = i;
return function() {
window.location.href = myLinks[idx];
return false; // cancel href
};
})(i);
}
}
I very much need help with this as I have tried to work with this code for a decent number of hours. I don't really even understand what the code is doing to be able to convert to a click event.
Thanks in advance.
You can do it this way:
var myLinks = [
'http://bing.com/search?q=Sniffer',
'http://bing.com/search?q=is',
'http://bing.com/search?q=good',
'http://bing.com/search?q=programmer'];
window.onload = function() {
for (var i = 0, len = myLinks.length; i < len; i++) {
document.getElementById("l" + i).addEventListener("click", (function (idx) {
return function () {
window.location.href = myLinks[idx];
return false; // cancel href
};
})(i));
}
};
Event delegation is a nice solution to this problem:
var myLinks = [
'http://bing.com/search?q=Sniffer',
'http://bing.com/search?q=is',
'http://bing.com/search?q=good',
'http://bing.com/search?q=programmer'
];
var list = document.getElementById('list');
list.addEventListener('click', function (event) {
if (event.target && event.target.nodeName === "A") {
event.preventDefault();
var index = Array.prototype.indexOf.call(list.children, event.target.parentNode);
var href = myLinks[index];
console.log('link to ' + href + ' was clicked.');
// window.location = href;
}
});
Fiddle

Delete <li>'s that have the same value in another <li>

If there were two <ul>'s, one called list_a and the other called list_b, using javascript and not using any libraries like jQuery, how would you delete the <li>'s in list_a that have the same value as those in list_b?
Heres the example HTML:
<ul id="list_a">
<li value="1">list_a_0</li>
<li value="8">list_a_8</li>
<li value="9">list_a_9</li>
</ul>
<ul id="list_b">
<li value="8">list_b_8</li>
<li value="9">list_b_9</li>
<li value="2">list_b_2</li>
</ul>
The end result should be:
<ul id="list_a">
<li value="1">list_a_0</li>
<!-- DELETED TWO <li>'s -->
</ul>
<ul id="list_b">
<li value="8">list_b_8</li>
<li value="9">list_b_9</li>
<li value="2">list_b_2</li>
</ul>
The javascript so far that I can build (that doesn't work) is:
window.onload=function()
{
init();
function init()
{
var listA = document.getElementById("list_a");
for(var i in listA.childNodes)
{
var x = listA.childNodes[i];
var listB = document.getElementById("list_b");
for(var j in listB.childNodes)
{
var y = listB.childNodes[j];
if(x.innerHTML == y.innerHTML)
listA.removeChild(listA);
}
}
}
}
Thanks!
DEMO: http://jsfiddle.net/rmXrZ/
window.onload = function() {
var listA = document.getElementById("list_a");
var listB = document.getElementById("list_b");
for (var i = 0; i < listA.children.length; i++) {
var x = listA.children[i];
for (var j = 0; j < listB.children.length; j++) {
var y = listB.children[j];
if (x.value == y.value) {
listA.removeChild(x);
i--;
}
}
}
}
Don't use for-in for iteration of numeric indices
Cache the DOM selection instead of re-selecting in the loop
Use .children instead of .childNodes to avoid text nodes between elements
Compare .value instead of .innerHTML
Remove x instead of listA
When an element is removed from listA, decrement i, because removal from the DOM means removal from the .children collection.
function init() {
var listA = document.getElementById("list_a");
var listB = document.getElementById("list_b");
for(var i =0; i<listA.children.length;i++) {
var x = listA.children[i];
for(var j in listB.children) {
var y = listB.children[j];
if(x.value == y.value)
x.parentNode.removeChild(x);
}
}
}
Avoid hitting the DOM on multiple occasions, also in this case children is a better choice of data.

Categories