How to toggle a class in DOM, i want to make a dark mode toggle in class container-fluid
function DarkModeToggle() {
var element = document.getElementsByClassName("container-fluid");
element.classList.toggle("dark-mode");
}
and get this error
Uncaught TypeError: Cannot read properties of undefined (reading 'toggle')
at DarkModeToggle (main.js:4:21)
at HTMLButtonElement.onclick (index.html:26:46)
any solution to add a class and toggle it
As the name says getElementsByClassName() function is not returning one element instead returning an array of matching elements! Of course if the class name matches to only one element, there will be only one element in the array.
See also the docs: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName?retiredLocale=de
So you need to modify your access to the elements:
var elements = document.getElementsByClassName("container-fluid");
if(elements.length === 1) {
elements[0].classList.toggle("dark-mode");
}
The code above is expecting / checking if there is only one result. If you expect more results, you need to do a i.e. for loop to modify all.
Related
I need a help. I have a button in html with class "rekapitulace". And i want to do if a user click on that button, it will show a item in text input with class "jmeno". I wrote this but it isnt correct. Any solutions?
function rekapitulaceButton() {
var rekapitulaceButton = document.getElementsByClassName('rekapitulace')
rekapitulaceButton.addEventListener('click', precistUdaje)
}
function precistUdaje() {
var jmeno = document.getElementsByClassName('jmeno')
localStorage.setItem('local-jmeno', jmeno)
console.log(localStorage.getItem('local-jmeno'))
}
getElementsByClassName() returns all elements of provided class name, not just a single element. Notice how the name of that method contains plural elements word.
To get the first element, you can do:
const rekapitulaceButton = document.getElementsByClassName('rekapitulace')[0];
Another possibility is document.querySelector(), which always returns one element (first match) or null:
const rekapitulaceButton = document.querySelector('.rekapitulace');
document.getElementsByClassName('rekapitulace') return a nodelist array so if you need return an one node elment using id instead of class
document.getElementById('rekapitulace')
Note that you may be misusing localStorage for your debugging. The second argument of .set should be a string.
As mentioned already, you should really try to use IDs instead of classes for targeting the right input, and document.getElementsByClassName returns multiple elements and not just one element.
I am trying to use javaScript to determine if an element with a specific class name exists on an html page. The element in question is only sometimes loaded on the page.
When I use document.getElementsByClassName('element-in-question').innerHTML = "Hello"
It will work when the element exists, but when it doesn't exist, it will return as "cannot set property of innerHTML of undefined and the rest of the code will not run.
Is there a way to check if an element exists, and only modify it when it does without breaking the rest of the code?
Thanks for the help
You can also use document.querySelector which will return the first element within the document if it exists, if not, it returns null.
const targetElement = document.querySelector('.element-in-question');
if (targetElement) {
targetElement.innerText = 'Hi there!';
}
<div class="element-in-question"></div>
Tip: If you're just adding text consider using innerText instead of innerHTML.
Just wrap you code with if statement :
const elemts = document.getElementsByClassName('element-in-question');
if(elemts.length) {
// this actually need to be elemts[0].innerHTML
elemts.innerHTML = "Hello"
}
Note: document.getElementsByClassName will return array/collection of elements so if you really know that there is no other elements keep using it otherwise switch to getElementById.
as per documentation:
The getElementsByClassName() method returns a collection of all
elements in the document with the specified class name, as an
HTMLCollection object.
It's very simple with the condition IF
If you want to get elements by class, the function will return an array (a collection of all elements in the document with the specified class name), so you will check as following :
if (document.getElementsByClassName('class-in-question').length > 0) {
// Existed
}
If you want to get an element by specified id, the function will return an objet HTML with that id, so you will check as following :
if (document.getElementById('id-in-question')) {
// Existed
}
var menu = document.getElementsByClassName("menu");
var a = window.getComputedStyle(menu, null).fontSize();
var fontSize = parseFloat(a);
alert("HELLO");
That is the code. So I want to get the font-size of a class named menu. Then, I want to alert("HELLO"). But, the alert won't run and when I change the alert into alert(fontSize), it is not working either. Is anything wrong with my code?
You should pass an element to .getComputedStyle method. .getElementsByClassName returns a collection. You either need to select the first element from the set or use .querySelector for selecting the target element. Also note that returned object by .getComputedStyle doesn't have fontSize method, it's a property. You can also use the .getPropertyValue for getting a specific value:
// select the first .menu element
var menu = document.querySelector(".menu");
var a = window.getComputedStyle(menu, null).getPropertyValue('font-size');
var menu = document.querySelector(".menu");
var styles = menu.computedStyleMap();
styles will give the object which has all the styles available in it. Just print it and check if you got it.
There are a couple of things wrong with your code.
First, getComputedStyle
expects its first argument to be a single DOM element.
getElementsByClassName
returns a
HTMLCollection,
an array-like object containing a live
collection of DOM elements. That
is why, if you look in your error console, you should see an error message along
the lines of "TypeError: Argument 1 of Window.getComputedStyle does not
implement interface Element.".
Second, getComputedStyle returns a
CSSStyleDeclaration
object, which does not have a .fontSize method. It does however have a
getPropertyValue
method that you can use to get the font size.
// use querySelector, which returns a single DOM element that is the first in
// the DOM to match the provided query string
let menu = document.querySelector(".menu");
// You can just omit the second parameter if you are not targeting a pseudo
// element.
let styles = window.getComputedStyle(menu);
// get the font size in px
let fontSize = styles.getPropertyValue('font-size');
fontSize = parseFloat(fontSize);
alert('font-size =' + fontSize);
.menu {
font-size: 1.5em;
}
<div class="menu">Menu</div>
I'm learning not use jquery only pure javascript, just start and have trouble .....
how to select child dom
<div class="row-button">
<input type="submit" />
</div>
I'm trying below code but all shows error message.
var submit_button = document.getElementsByClassName("row-button");
console.log(submit_button.nodeType); //undefined
console.log(submit_button.firstChild); // undefined
console.log(submit_button.childNodes[0]); // TypeError: 'undefined' is not an object (evaluating 'submit_button.childNodes[0]')
or I thought maybe need to add window onload to sure dom ready so
window.onload = function () {
var submit_button = document.getElementsByClassName("row-button");
console.log(submit_button.nodeType); //undefined
console.log(submit_button.firstChild); // undefined
console.log(submit_button.childNodes[0]); // TypeError: 'undefined' is not an object (evaluating 'submit_button.childNodes[0]')
}
Pay attention: it's getElementsByClassName.
This means it returns a NodeList (an array-like object) of matching elements.
Try:
submit_button = document.querySelector(".row-button");
This will not only add support for IE8, but also return a single element, that being the first element with the desired class.
getElementsByClassName("row-button")
returns an array of elements of class "row-button". So to get its first (and only in your code) child, use
var submit_button = document.getElementsByClassName("row-button")[0];
I'm am battling with a javascript function I'm working on.
Inside a for loop I'm iterating all elements with class "visible", inside that loop
I'm preforming two actions.
elements[i].removeAttribute("class");
elements[i].setAttribute("class", "hidden");
For some reason only 1 is valid. 2 produces an error saying:
Uncaught TypeError: Cannot call method 'setAttribute' of undefined
Even when I log elements[i] using console.log; after the first console.log call
the element exists, but on the second console.log elements[i] is 'undefined'
What the hell am I missing here, this is driving me crazy, if my laptop wasn't so expensive
it would have been broken by now. Help :(
Here's the function:
function hide_visable_elements()
{
// remove body EventListener
var body = document.getElementsByTagName("body");
body[0].removeEventListener("click", hide_visable_elements, true);
var elements = document.getElementsByClassName("visible");
for (var i = 0; i < elements.length; i++)
{
console.log(elements[i]); // Works like a swiss clock
elements[i].removeAttribute("class");
console.log(elements[i]); // why elements[i] is 'undefined' now ???
elements[i].setAttribute("class", "hidden"); // << turns to useless code
}
}
This is because getElementsByClassName returns a NodeList, which is live. That is, it updates itself when the elements it refers to change.
When you remove the class attribute from an element in the NodeList, it gets removed from that list (since it no longer has the visible class name).
You don't actually need to remove the attribute. Just setting it will do the job just as well. But since the NodeList is changing as you manipulate the elements it contains, you need to count backwards through it (as each time you change one element of it, it is removed so the length decreases by one):
for (var i = elements.length - 1; i >= 0; i--) {
elements[i].setAttribute("class", "hidden");
}
getElementsByClassName is a live NodeList so changing className of the items immediately affects whole list. I would recommend use querySelectorAll insead.
Plus instead of var body = document.getElementsByTagName("body"); use document.body.
I think that the problem is elements[i].removeAttribute("class"); since you selected the element using a class getElementsByClassName("visible"); . I think so when you remove class attribute completely from the element things are going wrong.
Try some tweak with the code. You are not suppose to remove attribute class if you are planning to use the same element which is selected using class attribute.