I've made a dark mode toggle button for my demo website that adds a class to change the background color. The button works, but I want to swap out the image the button is using depending on if the class is present. It's not working. I think I've messed up MutationObserver somehow, can anyone help?
Javascript
let buttonIMG = document.getElementById("darkButtonIMG");
const observer = new MutationObserver(darkImage);
observer.observe(buttonIMG, {
attributes: true
});
function darkImage() {
let buttonIMG = document.getElementById("darkButtonIMG");
let buttonSRC = buttonIMG.hasAttribute("dark");
if (buttonSRC === true) {
buttonIMG.setAttribute("src", "images/Sun_Icon.png");
} else {
buttonIMG.setAttribute("src", "images/Moon_Icon.png");
}
}
HTML
<nav>
<div class="row">
<button class="buttonHide" id="hamburgerBtn">☰</button>
<ul id="navOpen">
...
<li><button id="darkButton" type="button" class=""><img id="darkButtonIMG"src="images\Moon_Icon.png" alt="Dark mode icon"></button></li>
</ul>
</div> <!-- End of Navbar Row -->
</nav>
I want to swap out the image the button is using depending on if the
class is present.
I'm assuming that when you click the button you're adding class dark to it.
In your callback method you're checking for the presence of dark attribute, but you should check for the presence of a class instead.
let buttonSRC = buttonIMG.classList.contains("dark");
You need to setAttribute for check hasAttribute
let buttonIMG = document.getElementById("darkButtonIMG");
const observer = new MutationObserver(darkImage);
observer.observe(buttonIMG, {
attributes: true
});
function darkImage() {
let buttonIMG = document.getElementById("darkButtonIMG");
let buttonSRC = buttonIMG.hasAttribute("dark");
if (buttonSRC === true) {
buttonIMG.setAttribute("src", "images/Sun_Icon.png");
buttonIMG.removeAttribute("dark");
} else {
buttonIMG.setAttribute("src", "images/Moon_Icon.png");
buttonIMG.setAttribute("dark", "dark");
}
}
Related
Having issues with disabled={true} HTML button. App is in JavaScript + React. I set button initial value disabled={true} .For example purposes I will call it id="button1". Once I click another button let's say id=button2, I re-enable my button1 with code document.getElementById('button1').disabled=false;. Button re-enables but once clicked it has no functionality, it looks like it is still disabled. What am I doing wrong ?
OK here is my simplified code:
function App() {
const approve = () => {
console.log('test');
};
const filterWeek2 = () => {
document.getElementById('approve').removeAttribute("disabled");
};
return (
<div className="App">
<nav>
<ul className="nav-area">
<li><button id="Week2" onClick={filterWeek2}>WEEK 2</button></li>
<li><button id="approve" onClick={approve} disabled="disabled">APPROVE</button></li>
</ul>
</nav>
</div>
);
}
export default withAuthenticator(App);
The disabled is a boolean attribute, Its presence on an HTML elements disables the element. If it is present on the element, it will disable the HTML element, doesn't matter what value it has.
You have to remove the attribute using removeAttribute to make it editable
const disabled = document.querySelector(".disabled");
const normal = document.querySelector(".normal");
normal.addEventListener("click", () => {
if (disabled.hasAttribute("disabled")) disabled.removeAttribute("disabled");
else disabled.setAttribute("disabled", true);
})
<button disabled class="disabled">button</button>
<button class="normal">toggle</button>
Since you are using React, then you can toggle disabled using state. DEMO
disabled={active}
If active is true then the HTML element is disable else enabled.
I want to change to make it function into my Angular project
the script code
<script>
let btn = document.querySelector("#btn");
let sidebar = document.querySelector(".sidebar");
let searchBtn = document.querySelector(".bx-search");
btn.onclick = function() {
sidebar.classList.toggle("active");
if(btn.classList.contains("bx-menu")) {
btn.classList.replace("bx-menu", "bx-menu-alt-right");
} else {
btn.classList.replace("bx-menu-alt-right", "bx-menu");
}
}
</script>
Angular does all of these actions differently. Instead of querying DOM elements and affecting them from a script, you bind those elements to the scope this.
Much of what you need to accomplish actually happens in the HTML, and there is no need for ID tags on your elements
In your app.component.ts
export class AppComponent {
isBXMenu = false; // this isn't required because its just a boolean used in the HTML but it's good form to have it here
bxMenuAlt = false; // this is now how you switch the class name. When you need it to be bx-menu-alt-right, set this.bxMenuAlt = true
toggleBXMenu():void() {
this.bxMenuAlt = !this.bxMenuAlt
}
}
In your HTML
<!-- here is your button -->
<i class='bx bx-menu' id="btn" (click)="isBXMenu=!isBXMenu"
*ngClass="{'bx-menu-alt-right': bxMenuAlt, 'bx-menu': !bxMenuAlt}" ></i>
Toggle sidebar BX Menu</button>
<!-- this is the new sidebar container -->
<div *ngClass="{'bx-menu':isBXMenu}" class='sidebar'>
<!-- ... -->
</div>
Let assume that I have a lot of html elements need to use MDCMenu. I don't want to init them one by one, so I init all of them with the code below:
html:
<button class="my-menu-toggle" data-toggle="mdc-menu" data-target="#my-menu">Menu Toggle</button>
<div class="mdc-menu" id="my-menu">
</div>
js:
document.querySelectorAll('[data-toggle="mdc-menu"]').forEach(toggleEl => {
let menuEl = document.querySelector(toggleEl.dataset.target);
let menu = new MDCMenu(menuEl);
toggleEl.addEventListener('click', (e) => {
menu.open = !menu.open;
});
// maybe I should do this, just wondering that if MDC already do same thing that I haven't figure out.
menuEl.MDCMenu = menu;
});
then I want to do somethings with one of menu, how can I get the MDCMenu instance of the element?
I'm trying to make active tabs that show content depending on which tab you click.
I absolutely need the first tab to be active by default so i put the "active" class manually in the HTML so the base content is shown.
The issue is, i do that through an empty variable to hold the state but after you've already clicked once. Here is the code :
function homeLoaded() {
menuLoaded();
function menuLoaded() {
const sideMenuChildren = document.getElementById("sidemenu").childNodes;
let currentTab;
for(let i = 0; i < sideMenuChildren.length; i++) {
const tab = sideMenuChildren[i];
tab.addEventListener(
"click",
function() {
if(currentTab) {
sideMenuChildren[currentTab].classList.remove("liactive");
}
currentTab = i;
sideMenuChildren[currentTab].classList.add("liactive");
showContent(tab.id);
console.log("I clicked " + i);
}
);
}
}
let currentPage;
function showContent(menuName) {
const pageContainer = document.getElementById("content");
const element = pageContainer.querySelector("." + menuName);
if(currentPage) {
currentPage.classList.remove("selected");
}
currentPage = element;
element.classList.add("selected");
}
}
Here is the HTML :
<div id="main" style="background-image: url(./images/bg2.png);">
<div id="box">
<ul id="sidemenu">
<li id="profil" class="liactive">Profil</li>
<li id="parcours">Parcours</li>
<li id="contact">Contact</li>
</ul>
<div id="content">
<div class="profil selected"><p>Blabla</p></div>
<div class="parcours"><p>Blablabla</p></div>
<div class="contact"><p>Blablablabla</p></div>
</div>
<div id="bottomnav">
<div id="bottomnavcontent">
</div>
</div>
</div>
</div>
What this does sadly is that when i click another tab...it does not remove the first active tab, so i have 2 active tabs until i re-click the first tab to store it in the variable. I don't know how to fix this.
demo of working codeYou can get event inside the event listener function. There you can get the target.
So,first Remove active class of current tab. Then, set active class for target element.
i.e
tab.addEventListener(
"click",
function (ev) {
const currentab = document.querySelector(".liactive");
currentab.classList.remove("liactive")
ev.target.classList.add("liactive")
}
)
My function is:
function onClickChange() {
let MyDiv = document.getElementById('myDIV')
if (MyDiv.style.display === 'none') {
MyDiv.style.display = ''
} else {
MyDiv.style.display = 'none'
}
}
And my div is:
<div id="myDIV"> Hello world</div>
<div id="backgroundColor" onClick={onClickChange}>I am div with image and I need a background color change toggle functionality based on "myDIV" toggle functionality</div>
Just as an information, I am using css "styled-components".Can anyone please help? Thanks in advance!
Happy coding :D
For this situation, you can use easily react state.
Example:
render method:
<div className={this.state.myClass} onClick={onClickChange}>I am div..</div>
onClickChange:
onClickChange() {
const {myClass} = this.state // read state first
if (myClass === 'red') {
this.setState({myClass: 'black'}) // set some black class name
} else {
this.setState({myClass: 'red'}) // set some red class name
}
}
When the state is changed, your render method is automatically called.
Dont use document.getElementById('myDIV') in REACT its antipattern.
Check below code, to change background color you can use style.backgroundColor for clicked div
function onClickChange(obj) {
let MyDiv = document.getElementById('myDIV');
//element.classList.toggle('mystyle');
if (MyDiv.style.display === 'none') {
MyDiv.style.display = ''
obj.style.backgroundColor="red";
} else {
MyDiv.style.display = 'none'
obj.style.backgroundColor="blue";
}
}
<div id="myDIV"> Hello world</div>
<div id="backgroundColor" onClick="onClickChange(this)">I am div with image and I need a background color change toggle functionality based on "myDIV" toggle functionality</div>