How to iterate through ul list using Javascript? - javascript

I have the following HTML page (page is simplified here as it is a sample of the real one):
<html>
<head>
<script type="text/javascript" src="JavaScript/Painting.js"></script>
</head>
<body>
<div id="center-wrapper">
<div id="side-menu">
<ul>
<li><a onclick="Paint()">About</a></li>
<li><a onclick="Paint()">Contents</a></li>
<li><a onclick="Paint()">Visual</a></li>
<li><a onclick="Paint()">CSS</a></li>
<li><a onclick="Paint()">Javascript</a></li>
</ul>
</div>
</div>
</body>
</html>
And I have the Painting.js file (again, a bit simplified):
function Paint()
{
var e = window.event;
var sender;
if (e.target)
{
sender = e.target;
}
else
{
if (e.srcElement)
{
sender = e.srcElement;
}
}
for (element in sender.parentNode.parentNode.getElementsByTagName("a"))
{
element.style.color = 'blue';
element.style.backgroundColor = '#FFFFFF';
}
sender.style.color = '#FFFFFF';
sender.style.backgroundColor = '#000000';
}
The basic idea is:
Find a HTML element that caused the event.
Go up until you reach the <ul> element.
Loop through the list items; find the <a> tags and change their color and background
Upon exiting the loop, change the color and the background of the HTML element that caused the event.
Now, I can't seem to get to the part located in the for loop. I think I am making a mistake by calling GetElementsByTagName() method. Could you help me out? Thanks.

You should call getElementsByTagName() only once, caching the result.
Then iterate over the collection like this (instead of using for/in).
var a_elements = sender.parentNode.parentNode.getElementsByTagName("a");
for (var i = 0, len = a_elements.length; i < len; i++ ) {
a_elements[ i ].style.color = 'blue';
a_elements[ i ].style.backgroundColor = '#FFFFFF';
}
sender.style.color = '#FFFFFF';
sender.style.backgroundColor = '#000000';
To get the target, you can pass it as the parameter in the inline onclick:
<ul>
<li><a onclick="Paint(this)">About</a></li>
<li><a onclick="Paint(this)">Contents</a></li>
<li><a onclick="Paint(this)">Visual</a></li>
<li><a onclick="Paint(this)">CSS</a></li>
<li><a onclick="Paint(this)">Javascript</a></li>
</ul>
Then your javascript can look like this:
function Paint( sender ) {
var a_elements = sender.parentNode.parentNode.getElementsByTagName("a");
for (var i = 0, len = a_elements.length; i < len; i++ ) {
a_elements[ i ].style.color = 'blue';
a_elements[ i ].style.backgroundColor = '#FFFFFF';
}
sender.style.color = '#FFFFFF';
sender.style.backgroundColor = '#000000';
}
Example: http://jsbin.com/aroda3/

Basically:
In order to find the element which caused the event you have to add an identifier to the a or li element and then use it as a parameter to your function. For example:
<li id='id_li1'><a onclick="Paint(id_li1)">About</a></li>
You can also use the ul id as parameter for your function, so you can know which is the ul that you need. I supposed that you generate your ul dinamically:
<a onclick="Paint(id_li1, id_ul)">About</a>
Then you have the reference for the ul and you can implement a function to iterate on the list items and give to the function the ul node using the id_ul. For example:
function processUL(ul) {
if (!ul.childNodes || ul.childNodes.length == 0) return;
// Iterate LIs
for (var itemi=0;itemi<ul.childNodes.length;itemi++) {
var item = ul.childNodes[itemi];
if (item.nodeName == "LI") {
// Iterate things in this LI in the case that you need it put your code here to get the a element and change the color and background
.....
}
}
}

I know you can't use jQuery for this, but I thought I'd supply a solution for others that may be able to:
$(function(){
$("li a").click(function(){
$(this).parent().siblings().each(function(){
$(this).find("a").css({'color':'blue','background-color':'white'});
});
$(this).css({'color':'white','background-color':'black'});
return false;
});
});

You can get the ul element with document.getelementbyid and then use the "children" property of the element which is a list of the list elements inside it.

No. Getting links by getElementsByTagName("a") is your one-off web-developer solution.
You can also traverse the DOM properly by childNodes, and this solution generalizes to all UL lists you may have:
_($("#my-list")[0].childNodes).filter(function(node) { return node.nodeName == "LI"; })
It uses underscore and jQuery.

Related

Is there any way to select elements in loop

I have a drop down menu created from li elements and each of them has a unique id. Instead of writing 4 different variables I want to create one loop (if possible and has sense) but I'm encountering a problem. After clicking on the particular li, the program should change the innerhtml with this li value.
function calories_calculator() {
const list = new Array(3);
list[0] = "1";
list[1] = "2"; /////// those numbers are id of li elements
list[2] = "3";
list[3] = "4";
const array = [];
for (var i = 0; i < list.length; i++) {
const f = document.getElementById(list[i]).onclick;
if (true) {
document.getElementById("display").innerHTML = list[i];
}
}
}
Is this what you want?
<ul>
<li id="id1"><button>aaaaa</button></li>
<li id="id2"><button>bbbbb</button></li>
<li id="id3"><button>ccccc</button></li>
<li id="id4"><button>ddddd</button></li>
</ul>
<div></div>
</body>
<script>
const elements = document.querySelectorAll('li')
elements.forEach(element => {
element.addEventListener('click' , () => {
document.querySelector('div').innerHTML = element.textContent;
})
})
</script>
</html>
It looks like there is a syntax issue with your "onclick" event handler. The onclick should be followed by an equal sign and then the function. I found this answer which might be useful:
Handling "onclick" event with pure JavaScript

Having issue in changing style through JavaScript

Hi i am trying to change Display property of any HTML Tag with certain attribute..
But after many tries i am unable to change the tag properties.. My code is as below
function getAllElementsWithAttribute(attribute)
{
var matchingElements = [];
var allElements = document.getElementsByTagName('*');
for (var i = 0; i < allElements.length; i++)
{
if (allElements[i].getAttribute(attribute))
{
// Element exists with attribute. Add to array.
matchingElements.push(allElements[i]);
}
}
return matchingElements;
}
tags = getAllElementsWithAttribute('data-shares');
for(i=0;i<tags.length;i++)
{
tags[i].style.display = "none";
}
And the HTML has below Tag
<div class="shareTools" data-shares="facebook" data-url="#" data-title="Facebook" data-description="Facebook">
<div class="shareToolsBox">
<ul class="shareToolsList">
<li data-share="facebook">
<span>Facebook</span>
</li>
</ul>
</div>
</div>
Does anyone has any idea how to change Tag Style of any tag which has attribut i-e data-shares...
Change the function call to:
tags = getAllElementsWithAttribute('data-shares');
Here's it working on a JS Bin demo: http://jsbin.com/ufogExo/1/ The <div>s with the data-shares attribute are all hidden.
The problem was indeed the extra commas you had on your function call arguments.
I believe this does what you want:
function getAllElementsWithAttribute(attribute)
{
var items = document.querySelectorAll('['+attribute+']'),
i = items.length;
while ( i-- > 0 && (items[i].style.display = 'none') );
}
getAllElementsWithAttribute('data-shares');
see
http://jsfiddle.net/754zR/

Getting the value of the clicked li element

First of all I'm adding an EventListener to the ul, as follows:
action_list_ul.addEventListener("click", set_ua_value, false);
The set_ua_value job is to:
• Listen to every click made on the ul childs (li elements)
• get the value (innerHTML?) of the a tag inside the clicked li
<ul id="action-list">
<li>foo</li>
<li>bar</li>
</ul>
In case foo was clicked on, I need to retrieve the "foo" string.
Since I'm fairly new to javascript, I'm not sure how to get the actual "this"
of the clicked li.
I do not want to use jQuery. Thanks :)
A quick and dirty way is to bind the event to the list, and filter by anchor tags:
JS
var action_list_ul = document.getElementById('action-list');
action_list_ul.addEventListener("click", set_ua_value, false);
function set_ua_value (e) {
if(e.target.nodeName == "A") {
console.log(e.target.innerHTML);
}
}
JS Bin
Alternately, you can filter by LI, and access the anchor through firstChild or childNodes[0].
Use something like:
var win = window, doc = document, bod = doc.getElementsByTagName('body')[0];
function E(e){
return doc.getElementById(e);
}
function actionListValue(element, func){
var cn = element.childNodes;
for(var i=0,l=cn.length; i<l; i++){
if(cn[i].nodeType === 1){
var nc = cn[i].childNodes;
for(var n=0,c=nc.length; n<c; n++){
if(nc[n].nodeType === 1){
nc[n].onclick = function(){
func(this.innerHTML);
}
}
}
}
}
}
actionListValue(E('action-list'), set_ua_value);
Here is an alternative:
var foo = document.getElementById("foo");
foo.addEventListener("click", modifyText);
function modifyText(e) {
console.log(e.target.innerHTML);
}
In this case the binding would have to be with the a elements.
<ul id="action-list">
<li>foo</li>
<li>bar</li>
</ul>
JS BIN

drop down menu will not work

I have a drop down menu that is supposed to work with four different menu choices, each given the same class. But my code is not working. I want it to work with both chrome and IE. The situation where it crashes is in my init method. The console complains as following: Object # has no method 'getElementsByTagName'. Any solution ?
function hideorShowField(list) {
var nodes = list.getElementsByTagName("li");
for (i = 1; i < nodes.length; i++) {
if (nodes[i].style.display == 'none') {
nodes[i].style.display = 'block';
}
else {
nodes[i].style.display = 'none';
}
}
}
function init() {
var list = document.getElementsByClassName("undermeny");
list1.getElementsByTagName("li")[0].onclick = function () {
hideorShowField(list);
};
}
window.onload = init;
My html code:
<ul class="undermeny" >
<li>Opinion</li>
<li>Ledare</li>
<li>Aktuella frågor</li>
<li>Per T Ohlsson</li>
<li>Magda Forsberg</li>
</ul>
<ul class="undermeny" >
<li>Lokalt/Globalt</li>
<li>Malmö</li>
<li>Lund</li>
<li>Limhamn</li>
<li>Burlöv</li>
<li>Eslöv</li>
<li>Höör</li>
<li>Kävlinge</li>
<li>Lomma</li>
<li>Svedala</li>
<li>Staffanstorp</li>
<li>Trelleborg</li>
<li>Vellinge</li>
<li>Sverige</li>
<li>Öresund</li>
<li>Världen</li>
<li>Väder</li>
</ul>
<ul class="undermeny" >
<li>Ekonomi</li>
<li>Nyheter</li>
<li>Privata pengar</li>
<li>Börs</li>
<li>Fonder</li>
</ul>
<ul class="undermeny">
<li>Sport</li>
<li>Fotboll</li>
<li>Ishockey</li>
<li>Handboll</li>
<li>Fridrott</li>
</ul>
getElementsByClassName() returns a nodeList as well as getElementsByTagName(). So you probably need this:
list[0].getElementsByTagName("li")[0].onclick = function () {...};
Or you've to iterate over the listto attach eventhandlers to all 1st lielements within uls with class undermeny. That'll be something like this:
for (var n = 0; n < list.length; n++) {
list[n].getElementsByTagName("li")[0].onclick = function () {...};
}
list1 has not been initialized (although list has). Fix the typo, and then you can iterate over the items in list, calling getElementsByTagName() on each.

Selections and radioing - JavaScript

I have a list like this:
<ul>
<li id="adm-thumb" onclick="javascript:addBanner('bowling.jpg');">
<div class="adm-tick"></div>
<img src="img/banners/bowling.jpg" /></li>
<li id="adm-thumb" onclick="javascript:addBanner('kcc.jpg');">
<div class="adm-tick"></div>
<img src="img/banners/kcc.jpg" /></li>
<li id="adm-thumb" onclick="javascript:addBanner('paintballing.png');">
<div class="adm-tick"></div>
<img src="img/banners/paintballing.png" /></li>
</ul>
<input id="bannername" type="text" />
When one item is clicked, the value inside the addBanner() will be added to the input field, however, I want one list to be selected (which is done by css to make it look like it has) when it is equal to the value of the input value. If the value is equals to the value in the addBanner value then the clicked item should have a red background.
e.g.
function addBanner(label)
{
var Field = document.getElementById('bannername');
Field.value = label;
if(Field.value != label)
{
// I have no idea what to put here
// assign a class to it? prevent others having the same when ONLY one must have the selected state
}
}
Something like a div button that acts like a radio button.
You can modify the addBanner function to include the list item that was clicked. Then inside the function remove the class or style from all list elements first. Then apply the required class to the clicked element.
The list items would become:
<li onclick="javascript:addBanner('bowling.jpg', this);"> .. </li>
The addBanner function now has two parameters, the second one being the list element that was clicked:
/* CSS */
.highlighted {
background-color: red;
}
/* Javascript */
function addBanner(label, clickedItem) {
var listItems = document.getElementsByTagName("li");
// clear all existing classes
for(var i = 0; i < listItems.length; i++) {
listItems[i].className = '';
}
document.getElementById('bannername').value = label;
clickedItem.className = 'highlighted';
}
There are already 2 flaws in your code:
1)
Field.value = label;
if(Field.value != label)
{
// this will never run, because you set the Field.value to the
// label one line above
}
2) when you use an id you can only use it once, else you should use a class in your 'li' elements.
Your question is very vague. You want the clicked 'li' element to have a red background and the rest not red?
You can do this by plain JS:
var lis= document.getElementsByTagName("li");
for (i = 0; i < lis.length; i++) {
var li = lis[i]; if(li.className == "adm-thumb") {
li.backgroundColor = "transparent";
}
}
this.backgroundColor = "red";
or jQuery:
$('adm-thumb').css("backgroundColor", "transparent");
$(this).css("backgroundColor", "red");
The way the question is worded, it's a bit hard to understand exactly what you mean, but the code below should hopefully give you the results you are after:
var liList = document.getElementById('list').childNodes;
for (var i = 0; i < liList.length; i++){
liList[i].addEventListener('click',changeColor,false);
}
function changeColor(e) {
var el = e.target;
var liList = document.getElementById('list').childNodes;
for (var i = 0; i < liList.length; i++){
liList[i].backgroundColor = "black";
}
el.style.backgroundColor = "red";
}
You will need to assign an id to the ul element, and you can remove the onClick calls from the li elements:
<ul id="list">
<li><div class="adm-tick"></div><img src="img/banners/bowling.jpg" /></li>
<li><div class="adm-tick"></div><img src="img/banners/kcc.jpg" /></li>
<li><div class="adm-tick"></div><img src="img/banners/paintballing.png" /></li>
</ul>
You may want to read up on Javascript event handling as well

Categories