drop down menu will not work - javascript

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.

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

addEventListener is just running the function, not saving the function

So I am trying to set up a function that will hide and show certain parts of the page, without the use of any outside libraries with Javascript. My problem seems to be that addEventListener is not attaching the event listener to the DOM=object but just running it.
The parts on the site I am using are:
<a class="tab" href="#index" id="index">Weapons</a>
<a class="tab" href="#armor" id="armor">Armor</a>
<a class="tab" href="#items" id="items">Items</a>
<div id="index_content" class="tab_content">
This is the content to display in weapons
</div>
<div id="armor_content" class="tab_content">
Welcome to armor!
</div>
<div id="items_content" class="tab_content">
Items are probably the best of the tabs.
</div>
My Javascript is:
function clear(key){
"use strict";
key = String(key);
//hides all content in items
for (var i = 0; i < itemArray.length; i++) {
document.getElementById(itemArray[i]+"_content").style.display = "none";
}
//shows current item
document.getElementById(key).style.display = "block";
return;
}
function tabsInit(){
"use strict";
for(var i = 0; i < itemArray.length; i++){
document.getElementById(itemArray[i]).addEventListener("click",clear(itemArray[i]));
}
}
window.onload = function(){
"use strict";
tabArray = document.getElementsByClassName("tab");
//add Items into item array
for(var i = 0; i < tabArray.length; i++){
itemArray[i] = tabArray[i].id;
}
tabsInit();
}
You're assuming you need the ID to get to the bound element. You don't. Assign clear as the event handler, and use this inside the function, though I think you were setting the wrong item to "block".
Also, I'm not sure why you're creating an array of IDs. You can just use the list of elements directly, and create a similar list of the _content elements if needed.
Here's a rewrite of your code.
document.addEventListener("DOMContentLoaded", function() {
"use strict";
const tabArray = document.querySelectorAll(".tab");
const contentArray = document.querySelectorAll(".tab_content");
tabsInit();
function tabsInit() {
for (var i = 0; i < tabArray.length; i++) {
tabArray[i].addEventListener("click", clear);
}
}
function clear() {
//hides all content in items
for (var i = 0; i < contentArray.length; i++) {
contentArray[i].style.display = "none";
}
//shows current item
document.querySelector("#" + this.id + "_content").style.display = "block";
}
});
div[id$=_content]:not(:first-of-type) {
display: none;
}
<a class="tab" href="#index" id="index">Weapons</a>
<a class="tab" href="#armor" id="armor">Armor</a>
<a class="tab" href="#items" id="items">Items</a>
<div id="index_content" class="tab_content">
This is the content to display in weapons
</div>
<div id="armor_content" class="tab_content">
Welcome to armor!
</div>
<div id="items_content" class="tab_content">
Items are probably the best of the tabs.
</div>
use let to keep the variable i in the correct scope and use an anonymous function to call clear on it..
function tabsInit(){
"use strict";
for(let i = 0; i < itemArray.length; i++){
document.getElementById(itemArray[i])
.addEventListener("click",()=>clear(itemArray[i]));
}
}
You're assigning the function result as a event listener.
You should use a function instead:
.addEventListener("click", function() { clear(itemArray[i]); })
Now that will be called every time the event fires.
var demo = document.getElementById("demo")
demo.addEventListener("click",function(){
//code here
}
)
<button id="demo"></button>

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/

Attach event to child elements

<div class="tabContainer">
<ul class="Tabs" id="tabset">
<li id="tab1" class="selected" onclick="tabs(this)">Home</li>
<li id="tab2" onclick="tabs(this)">Tab 2</li>
<li id="tab3" onclick="tabs(this)">Tab 3</li>
</ul>
</div>
I want to remove onclick="tabs(this)" and turn it into an event. How can I do this?
Currently the below code is my solution which isn't working.
var h=$("tabset").children;
for (i=0;i<h.length;i++) h[i].onclick=tabs(this);
Oh and no jquery please, but var $ = function(x){return document.getElementById(x)};
NOTE: I need the (this) part.
You seem to be using some $ function in your code which is not standard. For example if you are using jQuery your code could look like this:
$('#tabset li').on('click', tabs);
If you don't want to use jQuery then you will have to adapt your selector:
var h = document.getElementById('tabset').getElementsByTagName('li');
for (var i = 0; i < h.length; i++) {
h[i].onclick = tabs;
}
or since you declared:
var $ = function(x){
return document.getElementById(x)
};
you could also use:
var h = $('tabset').getElementsByTagName('li');
for (var i = 0; i < h.length; i++) {
h[i].onclick = tabs;
}
I'd suggest:
var lis = document.getElementById('tabset').getElementsByTagName('li');
for (var i = 0, len = lis.length; i < len; i++){
lis[i].onclick = tabs; // inside the function 'this' will refer to the node.
}
JS Fiddle demo.
Though you could assign the click-handler to the containing ul element:
var list = document.getElementById('tabset');
tabset.onclick = list.addEventListener('click', function(e){
tabs(e.target);
}, false);
JS Fiddle demo.
You could, now I see what you're doing with your function, avoid using getElementById() and simply chain:
$('tabset').addEventListener('click', function(e){
tabs(e.target);
}, false);
JS Fiddle demo.
With jQuery, as you appeared (prior to an edit) to be trying to use:
$('#tabset li').click(function(){
tabs(this);
});

How to iterate through ul list using 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.

Categories