crackhawk
crackhawk

Reputation: 15

Toggle one button - toggle the other one as well

you guys helped me with this before. Thanks to you both toggles are working now.

Now I have one more question:

Is it possible, when clicking on a toggle (no matter which one) to activate/deactivate the other one at the same time as well? so that the status is always the same?

Assuming that works: What would happen if i set "input type="checkbox" checked" for one toggle?

Example: https://jsfiddle.net/zndyf9e6/

const btns = document.querySelectorAll(".btn-toggle-darkmode");
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");

const currentTheme = localStorage.getItem("theme");
if (currentTheme == "dark") {
console.log(currentTheme)
  document.body.classList.toggle("dark-theme");
} else if (currentTheme == "light") {
  document.body.classList.toggle("light-theme");
}

btns.forEach(function(btn){
btn.addEventListener("click", function() {
  if (prefersDarkScheme.matches) {
    document.body.classList.toggle("light-theme");
    var theme = document.body.classList.contains("light-theme") ?
      "light" :
      "dark";
  } else {
    document.body.classList.toggle("dark-theme");
    var theme = document.body.classList.contains("dark-theme") ?
      "light" :
      "dark";
  }
  localStorage.setItem("theme", theme);
});
})

Thank you!

Upvotes: 0

Views: 327

Answers (1)

Mister Jojo
Mister Jojo

Reputation: 22320

you over-complicated the code unnecessarily. But in your defense, the management of dark mode is itself a bag of knots. I have done several tests and research on the issue and my current conclusion is that code window.matchMedia ('(prefers-color-scheme: dark)'). Matches is not really usable today.

I activated the dark mode on FireFox or Chrome, neither of the 2 browsers is detected, neither in css, nor in javascript. Except in debug mode, firefox allows you to change this flag, but this is only valid while you are using the page.

Discussions about Bugzilla are going round and round, there have been differents changed implementations over the versions of FireFox and also of Chrome, and I feel like there is some sort of confusion between using a theme (via extension) and the management of this simple flag as it is imagined in css - js.

I still left the JS code on this part, I deleted it in the CSS because it doesn't do anything. everything depends on the addition (or not) of the class on the <body> tag.

I also cleaned your CSS, and redone your checkbox buttons which were also uselessly complicated

base code (without window.matchMedia or localStorage ):

(function() // IIFE Closure
  {
  const
    darkClass    = 'dark-theme' 
  , darkModeBtns = document.querySelectorAll('label.btn-dark-mode > input[type="checkbox"]')
  , syncBnts     = flag => darkModeBtns.forEach(bt=>bt.checked = flag)
    ;
  let darkMode = false // default 
    ;
  document.body.classList.toggle(darkClass, darkMode ) // init page

  // toggle dark mode via checkboxes
  darkModeBtns.forEach( bt=>
    {
    bt.checked = darkMode // init page
    bt.oninput =_=>
      {
      document.body.classList.toggle(darkClass, bt.checked )
      syncBnts(bt.checked )
      }
    })
  })()
:root {
  --background   : #f7f7f8;
  --main         : #ffffff;
  --border       : #e0e4e7;
  --text         : #244357;
  --link         : #0f6c9e;
  --button-hover : #e8ebf0;
}
body {
  background-color : var(--background);
  padding-top      : 15px;
  padding-bottom   : 15px;
  color            : var(--text);
  font-family      : sans-serif;
  line-height      : 1.75;
  }
body.dark-theme {
  --background   : #18191a;
  --main         : #242526;
  --border       : #30343a;
  --text         : #909090;
  --link         : #ffffffd7;
  --button-hover : #26292e;
  }

label.btn-dark-mode > input { display: none; }
label.btn-dark-mode {
  display       : inline-block;
  position      : relative;
  width         : 40px;
  height        : 20px;
  margin        : 0 auto;
  border-radius : 40px;
  border        : 1px solid var(--border);
  overflow      : hiden;
  cursor        : pointer;
  }
label.btn-dark-mode::before, 
label.btn-dark-mode::after {
  position         : absolute;
  display          : block;
  border-radius    : 50%;
  content          : ' ';
  overflow         : hiden;
  }
label.btn-dark-mode::before {
  top              : 3px;
  left             : 2px;
  width            : 14px;
  height           : 14px;
  background-color : var(--link);
  transition       : 0.5s ease transform, 0.2s ease background-color;
  }
body.dark-theme label.btn-dark-mode::before {
  transform        : translateX(22px);
  }
label.btn-dark-mode::after {
  top              : -8px;
  left             : 0px;
  width            : 15px;
  height           : 15px;
  background-color : var(--background);
  transition       : transform ease 0.5s;
  transform        : scale(0);
  }
body.dark-theme label.btn-dark-mode::after {
  transform        : scale(1) translate(18px,8px);
  }
<label class="btn-dark-mode"><input type="checkbox"></label>
<label class="btn-dark-mode"><input type="checkbox"></label>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, 
  dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas 
  ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, 
  enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque 
  vitae, consequat in, pretium a, enim. Pellentesque congue.
</p>


<label class="btn-dark-mode"><input type="checkbox"></label>

full JS code (with window.matchMedia and localStorage ):

(function() // IIFE Closure
  {
  const
    darkClass    = 'dark-theme' 
  , darkModeBtns = document.querySelectorAll('label.btn-dark-mode > input[type="checkbox"]')
  , syncBnts     = flag => darkModeBtns.forEach(bt=>bt.checked = flag)
    ;
  let darkMode = !!window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
    ;
  darkMode = JSON.parse( localStorage.getItem(darkClass) || darkMode.toString() )

  document.body.classList.toggle(darkClass, darkMode ) // init page

  // toggle dark mode via checkboxes
  darkModeBtns.forEach(bt=>
    {
    bt.checked = darkMode // init page
    bt.oninput =_=>
      {
      document.body.classList.toggle(darkClass, bt.checked )
      syncBnts(bt.checked )
      localStorage.setItem(darkClass, bt.checked.toString() )
      }
    })

  // toggle dark mode via browser preference
  window
  .matchMedia('(prefers-color-scheme: dark)')
  .addListener(e =>
    {
    syncBnts( e.matches )
    document.body.classList.toggle(darkClass, e.matches )
    localStorage.setItem(darkClass, e.matches.toString() )
    });
  })()

Upvotes: 3

Related Questions