I'm making an inventory page for a website. I want to be able to sort the items with check boxes. What i think i need is to apply a div class to each of them and use document.getElementsByClassName to change the display to none for the ones i want hidden.
Anyway i tried with document.getElementsById, but i could only change the first one with the corresponding Id. Apperarently i need to change the class. This is where im at now.
P.S The [sc:1 ] is shortcoder for wordpress. It seemed to work when i used Id.
<script>
function toggle() {
var e = document.getElementsByClassName('truck');
if(e.style.display == "block")
e.style.display = "none";
else
e.style.display = 'block';
}
</script>
<input type="checkbox" id="checkme" onclick="toggle()">Dump Truck
<div class="truck">This is text that should hide</div>
<div class="truck">[sc:1 ]</div>
<div class="sweeper">[sc:2 ]</div>
<div class="sweeper">[sc:3 ]</div>
You have to iterate over the set that document.getElementsByClassName('truck'); returns:
for (var i = 0; i < e.length; i++) {
if(e[i].style.display == "block")
e[i].style.display = "none";
else
e[i].style.display = 'block';
}
document.getElementsByClassName returns a set of elements that match that class name, so you have an array of DOM elements: [elem1, elem2, elem3, ..]. You can't just simply set [].display == prop - you have to iterate over the set and set the display for each element.
document.getElementsByClassName('truck'); always returns the array list of all the elements that has the class "track", so even if you have a single element that has the class "truck" the getElementsByClassName('truck') would return the single element in an array.
Please note, get**Elements**ByClassName has the plural form of element which refers to a set of element items to be fetched.
For your case, you have to iterate the array items to get each element and perform operations.
Try the following code block instead
<script>
function toggle() {
var e = document.getElementsByClassName('truck');
// Get all the elements that has the class name 'truck', so for your example,
// there are 2 items and the array e would have 2 items (i.e. e[0] will have the
// div element that has 'This is text that should hide' as the inner HTML and e[1]
// will have the div element that has [sc:1 ] as the inner HTML
for (var x=0; x < e.length; x++) {
if(e[x].style.display == "block") // Get the xth element's style
e[x].style.display = "none";
else
e[x].style.display = 'block';
}
}
</script>
Please note, even if you have a single item with the class name "truck" you would find it on the 0th location of the returned array (i.e. e[0]).
Related
HTML
<div id="divID">
<label></label>
<textarea></textarea>
</div>
JavaScript
function invisible(){
let div = document.getElementById("divID");
let children = div.childNodes;
for (let i = 0; i < children.length; i++) {
children[i].style.display = "none";
}
}
After calling the function nothing happens. What I'm doing wrong?
You have to set divID to your div tag.
<div id="divID">
<label></label>
<textarea></textarea>
</div>
And then you have to use div.children in invisible function.
function invisible(){
let div = document.getElementById("divID");
let children = div.children;
for (let i = 0; i < children.length; i++) {
children[i].style.display = "none";
}
}
<input type="button" onClick=" invisible()" value="Remove" />
<div id="divID">
<label></label>
<textarea></textarea>
</div>
You can make the function more reusable by accepting the element whose children are to be hidden as the first argument. It currently only works for the element with id of "divID".
function invisible(parent){
for(const child of parent.children) child.style.display = 'none';
}
invisible(document.querySelector('div'))
<div>
<label>Label</label>
<textarea>Textarea</textarea>
</div>
The problem seems to be your use of childNodes instead of children as other answers have pointed out.
This answer attempts to give some more context on what is happening in addition to the other answers.
let div = document.getElementById("divID");
console.log(div.childNodes)
// Returns something like
NodeList(5) [text, label, text, textarea, text]
console.log(div.children)
// Returns something like
HTMLCollection(2) [label, textarea]
So childNodes returns a NodeList and children returns an HTMLCollection.
The definition children on mdn explains the difference between children and childNodes:
Element.children includes only element nodes. To get all child nodes, including non-element nodes like text and comment nodes, use Node.childNodes.
The problem is that these text nodes don't have a style property. So it returns undefined. Trying to access the display property on style then causes a TypeError. Since the first element is a text element the loop fails immediately and the label and textarea are never hidden.
use children instead of childNodes:
function invisible(){
let div = document.getElementById("divID");
let children = div.children; //<== children instead of childNodes
for (let i = 0; i < children.length; i++) {
children[i].style.display = "none";
}
}
//just to test after 1.5 sec all children of divID will be removed(display=none)
setTimeout(invisible, 1500)
<div id='divID'>
<label>test1</label>
<textarea>test2</textarea>
</div>
I have two buttons defined with their IDs : but-toggle, but-close for show hide a panel :
<button id="but-toggle">Panel</button>
<div id="main-panel" style="display:none">
<button id="but-close">X</button>
<!-- some panel data -->
</div>
Now i have a JS function which toggle the panel (show/hide) assigned to but-toggle as following :
(function(){document.getElementById("but-toggle").addEventListener("click",function(){
var pan = document.getElementById("main-panel");
if(pan.style.display==="inline-block")
{pan.style.display="none"}
else
{pan.style.display="inline-block"}
});})();
My question is how to use the same function for both buttons without writing two func, one for each.
I want a solution for elements based on their ids, since the classes are differents and can't use getElementByClass for this
Thanks
You can use document.querySelector to get a list of elements from a list of IDs:
function toggleFn() {
const pan = document.getElementById("main-panel");
if(pan.style.display === "inline-block") {
pan.style.display = "none";
} else {
pan.style.display = "inline-block";
}
}
document.querySelector("#Id1, #Id2")
.forEach(elem => elem.addEventListener(toggleFn);
You can use the below to get all buttons
var btns=document.getElementsByTagName('button');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
//code
});
}
(OR)
if you use input tag with type button
document.querySelectorAll("input[type=button]");
(OR)
Based on multiple IDs
document.querySelectorAll('#id1, #id2, #id3');
then you can add eventListener
My Assignment: Hi! I am doing an assignment in school where I am supposed write code in Javascript in order to toggle visibility for the submenus each belonging to their own topmenu in a navigation bar for a webpage. The visibility should be set to hidden by default and should be shown when a topmenu is clicked on.
I know how to toggle visibility for ONE submenu belonging to a topmenu, but fail to make my code work for multiple elements. My HTML-code:
<a class="left_top1" onclick = "toggle()">Opinion</a><br>
<div class="left_submenu_1" style="display: none;">
<a class="left_sub1">Leaders</a><br>
<a class="left_sub1">Debates</a><br>
</div>
<br>
<a class="left_top2" onclick = "toggle()">Economy</a><br>
<div class="left_submenu_2" style="display: none;">
<a class="left_sub2">News</a><br>
<a class="left_sub2">Your Economy</a><br>
</div>
My Problem: The topmenus I speak of are "Opinion" and "Economy". The visibility of the div with the class "left_submenu_1" should be toggled when you click the topmenu "left_top1". Thus should the visibilily of the div with the class "left_submenu_2" be toggled when you click the topmenu "left_top2". This is what I fail to do. My Javascript code is so far:
function toggle() {
var e = document.querySelectorAll("div.left_submenu_1, div.left_submenu_2");
for (var i=0; i < e.length; i++) { // I know this will enable/disable the visibility for ALL elements selected from the querySelectorAll, which should NOT happen
if(e[i].style.display == "none") {
e[i].style.display = "block";
} else if(e[i].style.display == "block") {
e[i].style.display = "none";
}
}
}
Anyone who knows how to solve this issue of mine? I know there are errors in the for-loop (as I wrote next to it), but this is the best I can manage for now.
Please note: We are NOT allowed to use jQuery or to give the topmenus id:s, as the idea is to use one general function to toggle the visibility. Furthermore, the code which enables the toggle-function should be done in Javascript.
I would approach it by passing the class name of the div to be shown (or hidden) into the function to begin with.
HTML
<a class="left_top1" onclick = "toggle('.left_submenu_1')">Opinion</a>
Then in the function you can grab the element and toggle it's display state.
JavaScript
function toggle(qs) {
var e = document.querySelector(qs);
e.style.display = e.style.display === 'block' ? 'none' : 'block';
}
The e.style.display === 'block' ? 'none' : 'block' part is saying if the elements display state is equal to block, return none, otherwise return block.
The return value is set as the new element display state due to the e.style.display = beforehand.
Tring to make it work modifying it as less as possible :
- use onClick="toggle(this)" in the anchors tags
- use a bit different toggle function like:
function toggle (el) {
var e = document.querySelectorAll('.' + el.className.replace('top', 'submenu_'))[0];
e.style.display = e.style.display.match(/none/) ? '' : 'none';
}
hope it helps, but I have to suggest You to make a small step forward and search for event delegation. Bye
I'm trying to add a second class to a group of buttons using a for loop in jQuery, with the second class set to the number of the current iterator(i). The first class for each button is assigned to "users". I want each button to have a dynamic second class so that when clicked, I can use its second class as an index to access a particular key in an object.
The problem I'm having is that each button has its second class set to 0. "users" is an array with length 4, so the buttons should have as their second class 0,1,2,3 in order.
$(document).ready(function(){
for(var i = 0; i < users.length; i++) {
var $currentUser = $('<button class="users '+ i +'"></button>');
$currentUser.text(users[i]);
$currentUser.appendTo('.userList');
}
$(".users").click(function() {
alert($(".users").attr('class').split());
// Alert returns "users 0" for each button.
});
});
The alert at the bottom is just a placeholder for now to check that the classes are set correctly. Thanks!
change code to below . change $(".users") to $(this) when you click on element.
$(".users").attr('class') always return all button element.
$(".users").click(function() {
alert($(this).attr('class').split());
});
When you use a getter method like .attr('class') on a set of elements, it will return the value of the first element in the set. when you say $('.users') it will return all elements with the class users.
In your case you want to have reference to the clicked button, which is available in the click handler as this so you can
$(document).ready(function() {
var users = ['u1', 'u2', 'u3']
for (var i = 0; i < users.length; i++) {
var $currentUser = $('<button class="users ' + i + '"></button>');
$currentUser.text(users[i]);
$currentUser.appendTo('.userList');
}
$(".users").click(function() {
alert(this.className.split(/\s+/));
alert(this.classList); //for ie 10+
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="userList"></div>
I have multiple div elements with same id='mydiv'.I want to calculate these divs and Iam using the code
document.getElementById('mydiv').length
But it is not working
What you should do is use class instead of ID's. ID is for one element only, class is for multiple.
http://jsfiddle.net/d7AHV/
It won't work as getElementById will always return an element with the specified ID and null if the specified ID doesn't exist
From ECMA
getElementById(elementId) This method returns a Element. The elementId
parameter is of type DOMString.
What you can do is to assign each div with class
<div class="mydiv"></div>
<div class="mydiv"></div>
<div class="mydiv"></div>
<div class="mydiv"></div>
<div class="mydiv"></div>
And iterate over:
var divs = document.getElementsByTagName('div');
var count = 0;
for(var i = 0; i < divs.length; i++) {
if(divs[i].className == 'mydiv') count++;
}
alert(count);
If your clients support document.getElementsByClassName(), it's even more concise:
alert(document.getElementsByClassName('mydiv').length)
You've been told about multiple elements with the same ID, but in rare cases it might be unavoidable (e.g. an XML document over which you have no control). The only adverse behaviour is that selecting by ID will usually only return the first one (but that's not guaranteed).
You can count elements with the same id by looping over all the elements in the document and counting the ones with a matching id, e.g.
function countSameIds(id) {
var allNodes = document.getElementsByTagName('*');
for (var i=allNodes.length, count=0; i; ) {
if (allNodes[--i].id == id) {
++count;
}
}
return count;
}