I’m trying to switch the theme based on OS level light/dark mode. Users may change the system settings while using the website. So, I need to update in real-time instead of page refresh. So, I’m using addEventListener
to get system current changes. addEventListener
works fine. But, It should work if the System Settings option is set to true.
I have stored System Settings as a boolean option in localStorage. If it is true then the only addEventListener should work. If it is false it should not work. But, my problem is addEventListener work in both cases. I mean it works if System Settings is neither true nor false. How do I handle addEventListener should work based on localStorage value (if System Settings sets true)?
JS
function defaultFunction() { localStorage.setItem('option', 'default'); localStorage.setItem('systemOption', false); } defaultFunction(); function myFunction() { let getOption = localStorage.getItem('option'); let themeDiv = document.getElementById('theme'); if(localStorage.getItem('systemOption') == 'true') { let osTheme = window.matchMedia('(prefers-color-scheme: dark)'); osTheme.addEventListener('change', event => { if(event.matches) { themeDiv.classList.add("dark"); themeDiv.classList.remove("default"); } else { themeDiv.classList.add("default"); themeDiv.classList.remove("dark"); } }) } else { if(getOption == 'dark') { themeDiv.classList.add("dark"); themeDiv.classList.remove("default"); } else if(getOption == 'default') { themeDiv.classList.add("default"); themeDiv.classList.remove("dark"); } } } myFunction(); function setDark() { localStorage.setItem('option', 'dark'); myFunction(); } function setLight() { localStorage.setItem('option', 'default'); myFunction(); } function checkBox() { let cBox = document.getElementById('system'); let sun = document.getElementById('sun'); let moon = document.getElementById('moon'); if(cBox.checked) { localStorage.setItem('systemOption', true); sun.classList.add('addOpacity'); moon.classList.add('addOpacity'); } else { localStorage.setItem('systemOption', false); sun.classList.remove('addOpacity'); moon.classList.remove('addOpacity'); } myFunction(); }
Advertisement
Answer
I think the problem is you are adding an event listener but you never removed it thus it’s always listening for that event.
Try adding/removing event listener conditionally like below
function changeListener(event) { if(event.matches) { themeDiv.classList.add("dark"); themeDiv.classList.remove("default"); } else { themeDiv.classList.add("default"); themeDiv.classList.remove("dark"); } } let osTheme = window.matchMedia('(prefers-color-scheme: dark)'); if(localStorage.getItem('systemOption') === 'true') { osTheme.addEventListener('change', changeListener); } else { osTheme.removeEventListener('change', changeListener); }
OR
Listen for event always and apply theme conditionally by checking localStorage
const osTheme = window.matchMedia('(prefers-color-scheme: dark)'); osTheme.addEventListener('change', event => { if(localStorage.getItem('systemOption') === 'true') { if(event.matches) { themeDiv.classList.add("dark"); themeDiv.classList.remove("default"); } else { themeDiv.classList.add("default"); themeDiv.classList.remove("dark"); } } });