Check which list element have been clicked - javascript

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

Related

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>

how to apply a java script array with an already orded list in html

Hi I was wondering if anyone could help me out. I need to apply an array I created in Java Script on the HTML page that already has the order list created.I keep on getting error messages that say "Cannot read property of 'inner.HTML' undefined.
Any help would be greatly appreciated:)
thanks!
Here is my code:
< div id = "results" >
< ul >
< li id = "1-1" > < /li>
<li id="1-2"></li >
< li id = "1-3" > < /li>
<li id="1-4"></li >
< li id = "1-5" > < /li>
</ul >
< /div>
</article >
< script >
//declared global variable with an array of variables.
var places = ["Switzerland", "Canada", "Australia", "Norway", "New Zealand"]
// function to place the country's name in the
// li id.
function processPlaces() {
var locations = "";
for (var i = 0; i < places.length; i++) {
var listItem = i + 1;
var list = document.getElementById("1-" + listItem);
locations = list.getElementsByTagName("li");
locations[1].innerHTML += places[i];
}
}
//runs setUpPage () function when page loads.
if (window.addEventListener) {
window.addEventListener("load", processPlaces, false);
} else if (window.attachEvent) {
window.attachEvent("onload", processPlaces, false);
} < /script>
ids cannot start with a number, so preface them with l or some letter (you can see the change in the snippet).
HTML elements cannot have spaces immediately following <, so < div> will render as text, and < /div> will also render as text. Make sure to remove all the excessive spacing.
Further, when you access the element with getElementById that is the actual <li> element, and using getElementsByTagName inside of that element will find nothing because there are no children to the <li> elements. Instead of taking that approach, remove it and simply use the <li> element you already have from using getElementById. Once you make these changes, your code should run as intended.
//declared global variable with an array of variables.
var places = ["Switzerland", "Canada", "Australia", "Norway", "New Zealand"]
// function to place the country's name in the
// li id.
function processPlaces() {
var locations = "";
for (var i = 0; i < places.length; i++) {
var listItem = i + 1;
var list = document.getElementById("l1-" + listItem);
list.innerHTML = places[i];//directly access <li> element
//locations = list.getElementsByTagName("li");
//locations[1].innerHTML += places[i];
}
}
//runs setUpPage () function when page loads.
if (window.addEventListener) {
window.addEventListener("load", processPlaces, false);
} else if (window.attachEvent) {
window.attachEvent("onload", processPlaces, false);
}
<div id = "results">
<ul>
<li id = "l1-1"></li>
<li id = "l1-2"></li >
<li id = "l1-3"></li>
<li id = "l1-4"></li >
<li id = "l1-5"></li>
</ul >
</div>
If the array is ordered already, why not just append to the <ul>? First set and id on your unordered list <ul id="myList">
for (var i = places.length - 1; i >= 0; i--) {
$('#myList').after($('<li />', { 'text': places[i] }));
};
JSFiddle
Cleaned it up a bit.
You can't have spaces right after < in your html tags.
Also, you cant start IDs with numbers.
Edit: Too slow, Travis answer explains this much better :)
var places = ["Switzerland", "Canada", "Australia", "Norway", "New Zealand"];
function processPlaces() {
for (var i = 0; i < places.length; i++) {
document.getElementById('a-' + (i+1)).innerHTML = places[i];
}
}
if (window.addEventListener) {
window.addEventListener("load", processPlaces, false);
} else if (window.attachEvent) {
window.attachEvent("onload", processPlaces, false);
}
<div id="results">
<ul>
<li id="a-1"></li>
<li id="a-2"></li>
<li id="a-3"></li>
<li id="a-4"></li>
<li id="a-5"></li>
</ul>
</div>

Javascript - How to get all elements and do same thing on each of them

I want to get all DIVs in DIV(id = room) and do the same javascript code on each one.
I think it should look like this
Get element by id room -> Get all divs inside -> do something on them(change each class to "grass")
or by using a loop.
How to do that?
Please don't use jQuery.
Modern browsers (IE9+):
var divs = document.querySelectorAll('#room div');
[].forEach.call(divs, function(div){
div.className = 'green';
});
var a = document.getElementById("room").getElementsByTagName("div");
for(i = 0; i < a.length; i++)
{
a[i].className = "grass";
}
Do you want to get all divs inside, or just direct children?
This one traverses direct children. If you want to go through all internal nodes, you need to recurse it.
function grassify(nodeId) {
var node = document.getElementById(nodeId);
for(var i in node.childNodes) {
// Do things with node.childNodes[i], for example:
node.childNodes[i].className = 'grass';
}
}
Then just:
grassify('room');
var room=document.getElementByID("#room");
var divs=room.getElementsByTagName("div");
for(var i=0;i<divs.length;i++){
doSomething(divs[i]);
}
Use getElementByID and getElementsByTagName
Use getElementsByTagName
First get a reference to the container element, then use getElementsByTagName for the type of element you want.
See http://jsfiddle.net/aQtTx/
JS:
var targetDiv = document.getElementById("div1");
var nestedDivs = document.getElementsByTagName("div");
for(var divIndex = 0; divIndex < nestedDivs.length; divIndex++)
{
nestedDivs[divIndex].style.backgroundColor = 'red';
}
function myFunction()
{
var a=document.getElementById('room').childNodes;
for (i=0; i<a.length; i++)
{
a[i].className="grass";
};
}
JsFiddle
var parent = document.getElementById("room");
var divs = parent.getElementsByTagName('div');
for (i=0; i<divs.length; i++)
{
divs[i].className="grass";
};

Toggling a class on and off for list elements - CSS and ONLY Javascript

For this particular challenge I am required to toggle membership of an already created class for all <li> elements in two given lists (at the same time). If a <li> element in either list is not currently assigned the class, it is assigned the class; if a <li> element in either list is currently assigned the class, the class is removed. Everytime a button is clicked, the class is added and removed (e.g on first click, the class could be added - then on second click, the class could be removed, etc).
I have been asked to do this particular task specifically in normal JavaScript. While I know that jQuery would be the easier option, I have been asked to undertake this task with just normal JavaScript.
When I press the button, the css class is being applied as expected (here, the font-family, font-size, and the font-stretch properties are being altered); however, when I click on the button the second time, nothing changes (e.g the class being removed), and everything going back to normal.
If anyone can point me towards a non-jQuery way of adjusting my current code, let me know.
Thanks for your help :).
Here is the relevant HTML, CSS, and JavaScript for this task:
HTML:
<ul id="newZealandList">
<li>Auckland</li>
<li>Wellington</li>
<li>Christchurch</li>
<li>Tauranga</li>
<li>Dunedin</li>
</ul>
<ul id="usaList">
<li>Los Angeles</li>
<li>San Francisco</li>
<li>San Diego</li>
<li>Denver</li>
<li>Boulder</li>
</ul>
<button id="modifyListsToggle">Change Lists - Toggle</button>
CSS:
.modifyListElements{
font-family:"Comic Sans MS", cursive;
font-size:24px;
font-stretch:extra-expanded;
}
JavaScript
var newZealandListItems = document.getElementById("newZealandList").getElementsByTagName("li");
var usaListItems = document.getElementById("usaList").getElementsByTagName("li");
function addClass(obj)
{
obj.className="modifyListElements";
}
function removeClass(obj)
{
obj.className = "";
}
function toggleClass()
{
for (var i = 0; i < newZealandListItems.length; i++) {
if(i.className != "modifyListElements") {
//newZealandListItems[i].className = "modifyListElements";
addClass(newZealandListItems[i]);
}
else
{
//newZealandListItems[i].className = "";
removeClass(newZealandListItems[i]);
}
}
for (var i = 0; i < usaListItems.length; i++) {
if(i.className != "modifyListElements") {
//usaListItems[i].className = "modifyListElements";
addClass(usaListItems[i]);
}
else
{
//usaListItems[i].className = "";
removeClass(usaListItems[i]);
}
}
}
var modifyListsToggle = document.getElementById("modifyListsToggle");
modifyListsToggle.onclick = toggleClass;
Issue is here
for (var i = 0; i < newZealandListItems.length; i++) {
if(i.className != "modifyListElements") {
//con....
and here
for (var i = 0; i < usaListItems.length; i++) {
if(i.className != "modifyListElements") {
//con....
i is just the loop counter variable, you need to use it access the item at that index so should be
for (var i = 0; i < newZealandListItems.length; i++) {
if (newZealandListItems[i].className != "modifyListElements") {
//con..
and
for (var i = 0; i < usaListItems.length; i++) {
if (usaListItems[i].className != "modifyListElements") {
//con..
On another note, this code will potentially have an issue if multiple classes are used, as the .className property will return all the classes on an element. If that may be an issue in the future, I would pursue using a className.replace('modifyListElements','') for remove (that way it will only remove that class and not other ones if there). And the tests for one class on className will also not work if multiple classes are there. In this case pursuing a test and then a .replace would probably be the solution.
A small bug in your code checking classname . I modified your code it working fine . Please check it
http://jsfiddle.net/kRva7/ .
var newZealandListItems = document.getElementById("newZealandList").getElementsByTagName("li");
var usaListItems = document.getElementById("usaList").getElementsByTagName("li");
function addClass(obj)
{
obj.className="modifyListElements";
}
function removeClass(obj)
{
obj.className = "";
console.log(obj.className);
}
function toggleClass()
{
for (var i = 0; i < newZealandListItems.length; i++) {
var item = newZealandListItems[i];
if(item.className != "modifyListElements") {
//newZealandListItems[i].className = "modifyListElements";
addClass(item);
}
else
{
//newZealandListItems[i].className = "";
removeClass(item);
}
}
for (var i = 0; i < usaListItems.length; i++) {
var item = usaListItems[i];
if(item.className != "modifyListElements") {
//usaListItems[i].className = "modifyListElements";
addClass(item);
}
else
{
//usaListItems[i].className = "";
removeClass(item);
}
}
}
var modifyListsToggle = document.getElementById("modifyListsToggle");
modifyListsToggle.onclick = toggleClass;
​
The easiest way you could do this (although IE support is problematic) is like this:
var btn = document.getElementById('modifyListsToggle'),
lists = document.querySelectorAll('ul');
btn.addEventListener('click', function(e) {
for(var i = 0; i < lists.length; i++) {
var items = lists[i].querySelectorAll('li');
for(var j = 0; j < items.length; j++) {
items[j].classList.toggle('modifyListElements');
}
}
}, false);
demo
querySelectorAll() is only supported by IE8+
addEventListener() is only supported by IE9+
classList is only supported by IE10

jQuery ":contains()" analog for pure JS

I'm writing a script for CasperJS. I need to click on the link that contains a span with "1". In jQuery can be used :contains('1'), but what the solution is for selectors in pure Javascript?
HTML: <a class="swchItem"><span>1</span></a><a class="swchItem"><span>2</span></a>
jQuery variant: $('a .swchItem span:contains("1")')
UPD CasperJS code:
casper.then(function () {
this.click('a .swchItem *select span with 1*')
})
Since 0.6.8, CasperJS offers XPath support, so you can write something like this:
var x = require('casper').selectXPath;
casper.then(function() {
this.click(x('//span[text()="1"]'))
})
Hope this helps.
Try the following. The difference between mine and gillesc's answer is I'm only getting a tags with the classname you specified, so if you have more a tags on the page without that class, you could have unexpected results with his answer. Here's mine:
var aTags = document.getElementsByTagName("a");
var matchingTag;
for (var i = 0; i < aTags.length; i++) {
if (aTags[i].className == "swchItem") {
for (var j = 0; j < aTags[i].childNodes.length; j++) {
if (aTags[i].childNodes[j].innerHTML == "1") {
matchingTag = aTags[i].childNodes[j];
}
}
}
}
var spans = document.getElementsByTagName('span'),
len = spans.length,
i = 0,
res = [];
for (; i < len; i++) {
if (spans.innerHTML == 1) res.push(spans[i]);
}
Is what you have to do unless the browser support native css queries.
jQuery is javascript. There are also a number of selector engines available as alternatives.
If you want to do it from scratch, you can use querySelectorAll and then look for appropriate content (assuming the content selector isn't implemented) and if that's not available, implement your own.
That would mean getting elements by tag name, filtering on the class, then looking for internal spans with matching content, so:
// Some helper functions
function hasClass(el, className) {
var re = new RegExp('(^|\\s)' + className + '(\\s|$)');
return re.test(el.className);
}
function toArray(o) {
var a = [];
for (var i=0, iLen=o.length; i<iLen; i++) {
a[i] = o[i];
}
return a;
}
// Main function
function getEls() {
var result = [], node, nodes;
// Collect spans inside A elements with class swchItem
// Test for qsA support
if (document.querySelectorAll) {
nodes = document.querySelectorAll('a.swchItem span');
// Otherwise...
} else {
var as = document.getElementsByTagName('a');
nodes = [];
for (var i=0, iLen=as.length; i<iLen; i++) {
a = as[i];
if (hasClass(a, 'swchItem')) {
nodes = nodes.concat(toArray(a.getElementsByTagName('span')));
}
}
}
// Filter spans on content
for (var j=0, jLen=nodes.length; j<jLen; j++) {
node = nodes[j];
if ((node.textContent || node.innerHTML).match('1')) {
result.push(node);
}
}
return result;
}

Categories