Code only works in dev tools debugger

Hi, I am building a dark mode switcher. Therefore I implemented the dark-mode class in CSS. I toggle this via JS:

const button = document.getElementById("button");

button.addEventListener("click", toggler);

function toggler() {
  var element = document.body;
  document.body.classList.toggle("dark-mode");
}

Strange thing: It only works when running the chrome / firefox debugger in devtool (Clicken the source, setting a mouse click event and going step by step though the code. It does not work without devtools.) What am I missing?
Thank you very much

Here is a link to codepen.

Hi @sh11, surely you wanted to post a link to a pen including your code? ;-) Anyway, the JS as is works for me…

1 Like

Hi @m3g4p0p thank you for your reply. But I don’t understand, why my code works while running debugging mode in devtools – but not without. Do you have an idea? Have a nice day

Where have you placed the JS in relation to the html?

1 Like

Hi @PaulOB in a separate file on the same level. alerting “hi” when running the toggler function works.

</body>

<script src="./app.js"></script>

</html>

Best, Sven
Bildschirmfoto 2021-03-18 um 09.44.54

  var element = document.body; // <--- redundant
  document.body.classList.toggle("dark-mode");

Just to point out, you assign document.body to ‘element’ then never use it.

Given document.body is only used once in that function, you could probably do without it.

1 Like

Should be

<script src="./app.js"></script>
</body>
</html>

Just before the closing body tag :slight_smile:

2 Likes

Hi @rpg_digital, thank you very much. :slight_smile:
But placing the script tag above the closing body-tag does not help either. It’s like before: Opening debugger tool in devtools: Page switche to dark mode. without dev tool, no dark side of my page. Pls. see attached screenshot.

Is there a working example where we can debug this more easily?

You put up a codepen but it was empty. Can you replicate the problem in a codepen?

Hi @PaulOB of course. Here is the CodePen Thank you very much for your help!

I think its because the span is over the button and thus the button never gets clicked.

Try this instead.

const button = document.querySelector("#button span");

button.addEventListener("click", toggler);

function toggler() { 
document.querySelector('body').classList.toggle("dark-mode");
}
2 Likes

Came up with a similar fix, just adding the eventListener to the input switch instead

const button = document.getElementById("switch");

button.addEventListener("click", toggler);

function toggler() {
  document.body.classList.toggle("dark-mode");
}
2 Likes

Thank you so much. This is the HTML related to the button

 <div>
      <p>Dark Mode</p>
        <div id="button">
          <label>
            <input id="switch" type="checkbox">
              <span></span>
          </label>
        </div>
</div>

I would never get it, that this span nested inside the button would cause this trouble. I just watched it in the inspector and based on this the span only covers a tiny piece of the button.

(Attached a screenshot)

I just wonder, why dev Tools registered a click event. And also logging messages were possible – but not switching color. This is sth. I don’t get.

Thank you very much for your time and help

Actually I think the issue is that the click event is firing twice and so the toggle class goes on and off quickly.

I added a console.log statement here and on one click it shows it twice.

It seems to be the label element that causes this because if you remove it then your code works OK. I’m guessing the label element simulates a click on the input resulting in effectively two clicks each time but I’ll leave that to the JS gurus to confirm :slight_smile:

2 Likes

@PaulOB is correct.

If you tweak the code to log the event target ((e) =>{ console.log(e.target), you might get a better understanding of what’s happening.

The attachment to the #button element is tagging all of the sub-elements of #button with the trigger. When you click on the label, it’s clicking both the input and the span, so they both fire the event.

If you retarget your javascript to bind the click event to the element with id switch (for those that don’t want to dig: bind it to just the input element), you’ll find it works correctly.

2 Likes

It might be somewhat confusing to call a checkbox wrapper “button” anyway… why not just use the actual checked state instead?

document
  .getElementById('switch')
  .addEventListener('change', event => {
    document.body.classList.toggle(
      'dark-mode',
      event.target.checked
    )
  })

codepen

4 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.