0

Attempting to set up a simple dark mode function that persists. The dark mode itself works, but can't hide button display (they will only hide once clicked on and the function is triggered).

Edit: I should clarify - the issue I am having is getting the button to stay hidden on refresh/when I click to a different page. The dark mode remains (black background & white text) but the button reappears until I click it again.

In my console I am getting the following error - Uncaught TypeError: Cannot read properties of null (reading 'style') at js:27:36

Apologies I am new to JavaScript

var body = document.querySelector("body");

var theme = localStorage.getItem('darkmode');


function dark() {
  body.style.color = 'white';
  body.style.backgroundColor = 'black';
  document.getElementById('dark').style.display = 'none';
  document.getElementById('light').style.display = 'block';
  localStorage.setItem('darkmode', true);
}

function light() {
  body.style.color = 'black';
  body.style.backgroundColor = 'white'
  document.getElementById('light').style.display = 'none';
  document.getElementById('dark').style.display = 'block';
  localStorage.setItem('darkmode', false);
}

if (theme == "true") {
  body.style.color = 'white';
  body.style.backgroundColor = 'black';
  document.getElementById('dark').style.display = 'none';
  document.getElementById('light').style.display = 'block';
} else if (theme == "false") {
  body.style.color = 'black';
  body.style.backgroundColor = 'white'
  document.getElementById('light').style.display = 'none';
  document.getElementById('dark').style.display = 'block';
}
<a id='dark' class='navbar-link' href="#" onclick="dark()" role="button">Darkmode!</a>
<a id='light' class='navbar-link' href="#" onclick="light()" role="button">Lightmode!</a>

Seems to be a getElementByID issue as the rest of the if function works as expected, not sure if this has to be triggered by a function call or if there is an alternative.

Feff
  • 1
  • 1
  • *"Seems to be a getElementByID issue"* - What specific observation leads you to this conclusion? When you use your browser's script debugger to step through the code line by line as it executes, which operation first produces an unexpected result? What were the values used in that operation? What was the result? What result was expected? Why? (As an aside, the code [appears to work just fine](https://jsfiddle.net/03fjwkr8/)...) – David Jun 21 '23 at 17:45
  • Your code works perfectly fine. What is the error you are getting. Note that if you are running this inside any sandbox then the `localStorage` may not be accessible. – Aniket Pandey Jun 21 '23 at 17:59
  • I should clarify - the issue I am having is getting the button to stay hidden on refresh/when I click to a different page. The dark mode remains (black background & white text) but the button reappears until I click it again, which tells me the if logic for theme works, but its an issue involving the id – Feff Jun 21 '23 at 18:29

2 Answers2

1

The issue is that theme has no value until a button is clicked. When the code runs for the first time darkmode is not set in local storage and therefore it will be undefined, which is not equal to 'true' or 'false'.

The quick fix is to change whichever value you want to be the default's conditional

if (theme === 'true' || theme === undefined)` {
// show light mode
}

OR

if (theme === 'false' || theme === undefined') {
// show dark mode
}

My suggestion though is to instead set the value theme in local storage "dark mode" to delete it when in default

var theme = localStorage.getItem('theme');
function Dark() {
...
localStorage.setItem('theme','darkmode');
}
function Light() {
localStorage.removeItem('theme')
}

if (theme === 'darkmode') {
// show dark
} else {
 // show light
}
adam.k
  • 622
  • 3
  • 15
  • Instead of including the clause in the conditional, you could just use an `if/else` instead of an `if/else if`, and let the `else` handle it. – Darryl Noakes Jun 21 '23 at 18:49
0

The problem that you are experiencing is theme is empty on load if it wasn't set.

For my answer I simplified your code to toggle a dark class on body and use a single link that toggles the theme.

The body's default theme is set as the light theme. I check to see if darkMode exists and if not, set darkMode variable to false to indicate it's in light mode.

If it is darkMode add the dark class to body. If not dark mode, we don't need to do anything.

Then I attach a click handler to your link so we can tell it what to do on click. By toggling the dark class, it will either add it or remove it.

I also set the darkMode to if body contains the darkMode class or not (true/false).

<a class='navbar-link btn-ToggleTheme' href="#" role="button">Change Theme</a>

body{
  color:#000;
  background:#fff;
}

body.dark{
  color:#fff;
  background:#000;
}

const toggleBTN = document.querySelector(".btn-ToggleTheme")
const body = document.body;

const darkMode = localStorage.getItem("darkMode") || false;
if(darkMode)body.classList.add("dark")

toggleBTN.addEventListener("click",(e) => {
    body.classList.toggle("dark");
    localStorage.setItem('darkMode',(body.classList.contains("dark-mode")));
});
imvain2
  • 15,480
  • 1
  • 16
  • 21