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>
Related
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;
});
});
}
}
For some reason I need to loop through various elements and change their style when they are clicked. This is the code(https://jsfiddle.net/wd4z1kvs/1/) I am trying:
var myscroll = {};
myscroll.list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");
for( var j=0; j < 5; j++) {
myscroll.list[j].anchor = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li")[j].getElementsByTagName("a")[0];
myscroll.list[j].anchor.addEventListener("click", function() {
alert(j);
myscroll.list[1].anchor.innerHTML = "hello" + j;
myscroll.list[j].anchor.innerHTML = "yellow" + j;
});
}
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active">Home</li>
<li>Artists</li>
<li>Songs</li>
<li>Beats</li>
<li>Contact</li>
</ul>
</div>
The problem seems to be that the event works with j's present value. It doesn't take the value of the parameter when the code was actually run.
The simplest solution is to use a forEach, or some other looping callback function:
myscroll.list.forEach(function(item, j) {
item.anchor = document.getElementsByClassName("navbar-right")[0]
.getElementsByTagName("li")[j]
.getElementsByTagName("a")[0];
item.anchor.addEventListener("click", function() {
alert(j);
myscroll.list[1].anchor.innerHTML = "hello" + j;
item.anchor.innerHTML = "yellow" + j;
});
});
Try this:
var myscroll = {};
myscroll.list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");
for( var j=0; j < 5; j++) {
(function(j) {
/* j variable is just a local copy of the j variable from your loop */
myscroll.list[j].anchor = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li")[j].getElementsByTagName("a")[0];
myscroll.list[j].anchor.addEventListener("click", function() {
alert(j);
myscroll.list[1].anchor.innerHTML = "hello" + j;
myscroll.list[j].anchor.innerHTML = "yellow" + j;
});
}(j));
}
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active">Home</li>
<li>Artists</li>
<li>Songs</li>
<li>Beats</li>
<li>Contact</li>
</ul>
</div>
As noticed #Andreas there is a closure in a loop.
The events don't remember values, they only keep a link (reference) to
the environment where they were created. In this case, the variable j
happens to live in the environment where the three events were
defined. So, all events, when they need to access the value, reach
back to the environment and find the most current value of j. After
the loop, the j variable's value is 5. So, all five events point to
the same value.
use this:
var myscroll = {};
var list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");
myscroll.list = list;
for (var j = 0; j < 5; j++) {
var anchor = list[j].getElementsByTagName("a")[0];
anchor.setAttribute("index",j);
myscroll.list[j].anchor = anchor;
anchor.addEventListener("click", function () {
alert(this.getAttribute("index"));
this.innerHTML = "hello" + this.getAttribute("index");
//this.innerHTML = "yellow" + this.getAttribute("index");
this.style.backgroundColor = "yellow";
});
}
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
I'm trying to check which li have been clicked in the unordered list. only the first li seems to work becouse it will alert 0 but rest of the li wont respond with an alert. Nodelist should contain element 0,1,2. Raw javascript only.
HTML
<ul class="slideshow-buttons">
<li></li>
<li></li>
<li></li>
</ul>
Javasript
var $ = function (selector) {
return document.querySelector(selector);
};
var knappar = $('.slideshow-buttons').getElementsByTagName('li');
for (var i = 0; i < knappar.length; i++) {
var knapp = knappar[i];
knapp.onclick = knappTryck;
}
Problem seems to be inside knappTryck
function knappTryck(){
var childs = $('.slideshow-buttons').getElementsByTagName("li");
for (var c = 0; c < childs.length; i++) {
if (this == childs[c])
alert (c);
break;
}
}
the problem is here:
for (var c = 0; c < childs.length; i++) {
you use element c to parse the vector but you increment i. Replace c with i or the other way around
Also add braces to the if statement
Since you are using jQuery, make it 100% with jQuery :)
This will work :)
jQuery Code:
$(document).ready(function() {
$(".slideshow-buttons li").live("click", function() {
alert($(this).index());
});
});
You can use a closure.
for (var i = 0; i < knappar.length; i++) {
var knapp = knappar[i];
knapp.onclick = (function(i){
return function(){
console.log(i, this); // this is the li you clicked, and i is the index
}
})(i);
}
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.