Reputation: 23
I have been trying to hard to add 2 Toggle Buttons having different styles (css) on Menu Bar and footer page. They are to be used for night and dark mode.
However when I use
onclick="themeToggle()" id="theme-switcher"
for both of the buttons, only one of them works.
This is my Toggle Buttons Test Page.
This is the js which is being used :
var tSwitcher = document.getElementById('theme-switcher');
let element = document.body;
let onpageLoad = localStorage.getItem("theme") || "";
if(onpageLoad != null && onpageLoad == 'dark-mode'){
tSwitcher.checked = true;
}
element.classList.add(onpageLoad);
function themeToggle(){
if(tSwitcher.checked){
localStorage.setItem('theme', 'dark-mode');
element.classList.add('dark-mode');
} else {
localStorage.setItem('theme', '');
element.classList.remove('dark-mode');
}
}
This is the code for Two Toggle buttons
<label class="switcher">
<input type="checkbox" onclick="themeToggle()" id="theme-switcher">
<div>
<i class="fas fa-sun"></i>
<i class="fas fa-arrow-left arrow"></i>
<i class="fas fa-moon"></i>
</div>
</label>
<label class="switch" style="padding: 23px 0;">
<input type="checkbox" onclick="themeToggle()" id="theme-switcher">
<div>
<span></span>
</div>
Kindly help me in solving the issue with the code as well.
Thanks for the help.
Upvotes: 1
Views: 1704
Reputation: 2604
First of all, you cannot have two or more elements with the same id.
To detect what button is being clicked you can pass the event to the function as argument like this.
onclick="themeToggle(event)" class="switcher" id="theme-switcher-2"
Once you have the event you can get the object that has fired it (In your case the button) like this.
function themeToggle(event){
var tSwitcher = event.target;
if(tSwitcher.checked){
localStorage.setItem('theme', 'dark-mode');
element.classList.add('dark-mode');
} else {
localStorage.setItem('theme', '');
element.classList.remove('dark-mode');
}
}
EDIT
To set the default behaviour properly you have to add class="switcher"
to each button and do this.
var tSwitchers = document.querySelectorAll('.switcher'));
let onpageLoad = localStorage.getItem("theme") || "";
tSwitchers.forEach((element) => {
if(onpageLoad != null && onpageLoad == 'dark-mode'){
element.checked = true;
}
});
Upvotes: 0
Reputation: 6130
Because you are using ID in <input type="checkbox" onclick="themeToggle()" id="theme-switcher">
, which you repeat in other checkbox
. so only first ID in the DOM will be taken.
Change your <input type="checkbox" onclick="themeToggle()" id="theme-switcher">
To
<input type="checkbox" onclick="themeToggle()" class="theme-switcher">
And update the below code
Note: dont repeat ID
var tSwitcher = document.getElementsByClassName('theme-switcher');
let element = document.body;
let onpageLoad = localStorage.getItem("theme") || "";
if (onpageLoad != null && onpageLoad == 'dark-mode') {
for(let i = 0; i<tSwitcher.length; i++){
tSwitcher[i].checked = true;
}
}
if(onpageLoad) element.classList.add(onpageLoad);
So update your themeToggle()
to
function themeToggle() {
if (event.target.checked) {
localStorage.setItem('theme', 'dark-mode');
element.classList.add('dark-mode');
} else {
localStorage.setItem('theme', '');
element.classList.remove('dark-mode');
}
}
Upvotes: 2
Reputation: 647
You can't use the same ID for two or more HTML elements. Also, once you want to use this functionality in multiple elements, I strongly recommend you to not use onclick
inline. Instead, you can get all switchers from your page and add a listener to them:
const switchers = document.querySelectorAll('.switcher');
switchers.forEach((element) => {
element.addEventListener('click', (event) => {
themeToggle(event);
});
});
switcher
class to all elements<input type="checkbox" id="theme-switcher-1" class="switcher">
<input type="checkbox" id="theme-switcher-2" class="switcher">
<input type="checkbox" id="theme-switcher-3" class="switcher">
Using this approach, you can use this method all over your website or application and it's also easier to maintain.
Update: you should adjust the themeToggle() method like so:
function themeToggle(event){
var tSwitcher = event.target;
if(tSwitcher.checked){
localStorage.setItem('theme', 'dark-mode');
tSwitcher.classList.add('dark-mode'); // changed element to tSwitcher
console.log('Dark mode is on');
} else {
localStorage.setItem('theme', '');
tSwitcher.classList.remove('dark-mode'); // changed element to tSwitcher
console.log('Dark mode is off');
}
}
Obs.: You should adjust it into your code. I had to comment localStorage because it didn't work here.
const switchers = document.querySelectorAll('.switcher');
console.log(switchers);
switchers.forEach((element) => {
element.addEventListener('click', (event) => {
themeToggle(event);
});
});
function themeToggle(event){
var tSwitcher = event.target;
if(tSwitcher.checked){
//localStorage.setItem('theme', 'dark-mode');
tSwitcher.classList.add('dark-mode');
console.log('Dark mode is ON on ' + tSwitcher.id);
} else {
//localStorage.setItem('theme', '');
tSwitcher.classList.remove('dark-mode');
console.log('Dark mode is OFF on ' + tSwitcher.id);
}
}
<input type="checkbox" id="theme-switcher-1" class="switcher"><br />
<input type="checkbox" id="theme-switcher-2" class="switcher"><br />
<input type="checkbox" id="theme-switcher-3" class="switcher">
Upvotes: 0
Reputation: 115
If you are using getElementById it will return the first occurrence of that id from dom, and as you are having same id on both button it is updating the first button every time. Instead, you can except event object, in click function, and assign event.target to get the button element.
Upvotes: 0