使用JavaScript更改按钮文本,取决于body元素使用的class。

huangapple go评论69阅读模式
英文:

Change button text using javascript, depending on the class used by the body

问题

I have implemented a dark / light theme on my website using this guide. The two color schemes are specified as classes in CSS and applied/changed on the body using javascript). Js selects the theme automatically depending on the OS' preference, or through manual input triggered by a button (which then overrides the OS' settings). The preference is then saved to localStorage. Because I'm using a button to change between the themes manually, I'd like to change the text on it accordingly - "Dark Mode" when class="light-mode" is applied on the body in order to change to the dark theme, and "Light Mode" as the buttons' text when class="dark-mode" is applied.

I'm still learning javascript. Following is what I came up with:

if (document.body.classList.contains("dark-theme")) {
  document.getElementById("theme-btn").innerHTML="Light Mode";
} else if (document.body.classList.contains("light-theme")) {
  document.getElementById("theme-btn").innerHTML="Dark Mode";
}

I figured, this could do the trick (compare if class applied to the body is "dark-theme", if yes: change button text using the button's id to "Light Mode", doing the opposite if "light-theme" is applied).

Following is the html I have in use now (working as far as applying dark / light mode goes), including the script that applies the CSS classes to the body:

/* Color theme picker implementation javascript */
const btn = document.querySelector(".btn-toggle"); /* Select the button */
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)"); /* Check for dark mode preference at the OS level*/

const currentTheme = localStorage.getItem("theme"); /* Get the user's theme preference from local storage, if it's available */
if (currentTheme == "dark") { /* If the user's preference in localStorage is dark... */
  document.body.classList.toggle("dark-theme"); /* ...let's toggle the .dark-theme class on the body */
} else if (currentTheme == "light") { /* Otherwise, if the user's preference in localStorage is light... */
  document.body.classList.toggle("light-theme"); /* ...let's toggle the .light-theme class on the body */
}

btn.addEventListener("click", function () { /* Listen for a click on the button */
if (prefersDarkScheme.matches) { /* If the user's OS setting is dark and matches our .dark-mode class... */
  document.body.classList.toggle("light-theme"); /* ...then toggle the light mode class */
  var theme = document.body.classList.contains("light-theme") /* ...but use .dark-mode if the .light-mode class is already on the body, */
    ? "light"
    : "dark";
} else {
  document.body.classList.toggle("dark-theme"); /* Otherwise, let's do the same thing, but for .dark-mode */
  var theme = document.body.classList.contains("dark-theme")
    ? "dark"
    : "light";
}
localStorage.setItem("theme", theme); /* Finally, let's save the current preference to localStorage to keep using it */
/* Default colors */
body {
  --text-color: #000000;
  --bkg-color: #ffffff;
}

/* Dark theme colors */
body.dark-theme {
  --text-color: #ffffff;
  --bkg-color: #000000;
}

/* Styles for users who prefer dark mode at the OS level */
@media (prefers-color-scheme: dark) {
  /* defaults to dark theme */
  body {
    --text-color: #ffffff;
    --bkg-color: #000000;
  }
  /* Override dark mode with light mode styles if the user decides to swap */
  body.light-theme {
    --text-color: #000000;
    --bkg-color: #ffffff;
  }
}
<!DOCTYPE html>

<head>
  <meta charset="utf-8"/>
  <meta content="width=device-width, initial-scale=1" name="viewport"/>
</head>

<body class="body">
  
  <button class="btn-toggle">Dark Mode</button>

</body>

I'd really appreciate if someone had any inputs on what route to go or a better idea on how to achieve this. Thanks a lot for any help!

英文:

I have implemented a dark / light theme on my website using this guide. The two color schemes are specified as classes in CSS and applied/changed on the body using javascript). Js selects the theme automatically depending on the OS' preference, or through manual input triggered by a button (which then overrides the OS' settings). The preference is then saved to localStorage. Because I'm using a button to change between the themes manually, I'd like to change the text on it accordingly - "Dark Mode" when class="light-mode" is applied on the body in order to change to the dark theme, and "Light Mode" as the buttons' text when class="dark-mode" is applied.

I'm still learning javascript. Following is what I came up with:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    if (document.body.classList.contains(&quot;dark-theme&quot;)) {
      document.getElementById(&quot;theme-btn&quot;).innerHTML=&quot;Light Mode&quot;;
    } else if (document.body.classList.contains(&quot;light-theme&quot;) {
      document.getElementById(&quot;theme-btn&quot;).innerHTML=&quot;Dark Mode&quot;;
    }

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width&quot;&gt;
&lt;/head&gt;
&lt;body class=&quot;dark-theme&quot;&gt;
  
  &lt;button class=&quot;btn-toggle&quot; id=&quot;theme-btn&quot;&gt;Dark Mode&lt;/button&gt;

&lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

I figured, this could do the trick (compare if class applied to the body is "dark-theme", if yes: change button text using the button's id to "Light Mode", doing the opposite if "light-theme" is applied).

Following is the html I have in use now (working as far as applying dark / light mode goes), including the script that applies the CSS classes to the body:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

/* Color theme picker implementation javascript */

    const btn = document.querySelector(&quot;.btn-toggle&quot;); /* Select the button */
    const prefersDarkScheme = window.matchMedia(&quot;(prefers-color-scheme: dark)&quot;); /* Check for dark mode preference at the OS level*/

    const currentTheme = localStorage.getItem(&quot;theme&quot;); /* Get the user&#39;s theme preference from local storage, if it&#39;s available */
    if (currentTheme == &quot;dark&quot;) { /* If the user&#39;s preference in localStorage is dark... */
      document.body.classList.toggle(&quot;dark-theme&quot;); /* ...let&#39;s toggle the .dark-theme class on the body */
    } else if (currentTheme == &quot;light&quot;) { /* Otherwise, if the user&#39;s preference in localStorage is light... */
      document.body.classList.toggle(&quot;light-theme&quot;); /* ...let&#39;s toggle the .light-theme class on the body */
    }

    btn.addEventListener(&quot;click&quot;, function () { /* Listen for a click on the button */
    if (prefersDarkScheme.matches) { /* If the user&#39;s OS setting is dark and matches our .dark-mode class... */
      document.body.classList.toggle(&quot;light-theme&quot;); /* ...then toggle the light mode class */
      var theme = document.body.classList.contains(&quot;light-theme&quot;) /* ...but use .dark-mode if the .light-mode class is already on the body, */
        ? &quot;light&quot;
        : &quot;dark&quot;;
    } else {
      document.body.classList.toggle(&quot;dark-theme&quot;); /* Otherwise, let&#39;s do the same thing, but for .dark-mode */
      var theme = document.body.classList.contains(&quot;dark-theme&quot;)
        ? &quot;dark&quot;
        : &quot;light&quot;;
    }
    localStorage.setItem(&quot;theme&quot;, theme); /* Finally, let&#39;s save the current preference to localStorage to keep using it */
    });

<!-- language: lang-css -->

/* Default colors */
body {
  --text-color: #000000;
  --bkg-color: #ffffff;
}

/* Dark theme colors */
body.dark-theme {
  --text-color: #ffffff;
  --bkg-color: #000000;
}

/* Styles for users who prefer dark mode at the OS level */
@media (prefers-color-scheme: dark) {
  /* defaults to dark theme */
  body {
    --text-color: #ffffff;
    --bkg-color: #000000;
  }
  /* Override dark mode with light mode styles if the user decides to swap */
  body.light-theme {
    --text-color: #000000;
    --bkg-color: #ffffff;
  }
}

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;

&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;/&gt;
  &lt;meta content=&quot;width=device-width, initial-scale=1&quot; name=&quot;viewport&quot;/&gt;
&lt;/head&gt;

&lt;body class=&quot;body&quot;&gt;
  
  &lt;button class=&quot;btn-toggle&quot;&gt;Dark Mode&lt;/button&gt;

&lt;/body&gt;

<!-- end snippet -->

I'd really appreciate if someone had any inputs on what route to go or a better idea on how to achieve this. Thanks a lot for any help!

答案1

得分: 1

我让整个事情运行起来了... 在某种程度上。我的解决方案相当巧妙,但并不完全有效。以下是我得到的结果。
在我的第一次尝试中,问题在于在body的classList中都找到了"class="light-mode"和"class="dark-mode"",只是它们没有..."应用"吗?只要我找不到一个js方法来检查哪个类是"活动的",这种方法就不起作用 - 因为if/else条件总是为真,所以if子句总是被执行。

所以... 我得到了最简单(也最复杂)的一组函数来实现我想要的功能。基本上,脚本会检查localStorage,看是否已经保存了一个主题,如果是的话,就应用正确的按钮文本。然后,每次单击按钮时再次执行if-else语句(相同的if/else子句在代码中出现了两次,是否有更好的方法来处理这个?)

<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
</head>

<body>
  <button class="btn-toggle" id="theme-btn">Change Theme</button>
  <script>
    /* 根据localStorage中的颜色主题更改"theme-btn".innerHTML */
    if (localStorage.getItem("theme") == "dark") {
      document.getElementById("theme-btn").innerHTML = "Light Mode";
    } else if (localStorage.getItem("theme") == "light") {
      document.getElementById("theme-btn").innerHTML = "Dark Mode";
    }
    btn.addEventListener("click", function() { /* 监听按钮上的事件更改并检查localStorage中的主题更改 */
      if (localStorage.getItem("theme") == "dark") {
        document.getElementById("theme-btn").innerHTML = "Light Mode";
      } else if (localStorage.getItem("theme") == "light") {
        document.getElementById("theme-btn").innerHTML = "Dark Mode";
      }
    });
  </script>
</body>

与我的网站的其余部分一起,这个工作得很好。唯一的问题是,当localStorage中还没有存储键时,不能应用正确的文本。因此,这个解决方案只在手动单击按钮后才起作用... 对于新访问者则不起作用。

在寻找不同的解决方案时,我认为还可以有另一种方法 - 首先检查操作系统的首选项,然后监听按钮点击。不幸的是,我失败了 - 我会明天记录我尝试了什么。

英文:

I got the whole thing to work... somewhat. My solution is pretty hacky, and doesn't work completely. Below is what I got.
The issue with my first try in the answer, is that both classes, "light-mode" and "dark-mode" are found in the body's classList, just not... "applied"? As long as I don't find a js-method to check which class is "active", this approach won't work - because both conditions if/else are always true, so the if-clause gets always executed.

So... I got the easiest (and most convoluted) set of functions to do what I wanted to achieve. Basically, the script checks localStorage to see if a theme has already been saved, and if so, applies the correct button-text. Then, the if-else-statement is executed again on every time the button is clicked (the same if/else-clause is in the code twice, is there any better way to go about this?)

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;button class=&quot;btn-toggle&quot; id=&quot;theme-btn&quot;&gt;Change Theme&lt;/button&gt;
  &lt;script&gt;
    /* Change &quot;theme-btn&quot;.innerHTML depending on color theme in localStorage */
    if (localStorage.getItem(&quot;theme&quot;) == &quot;dark&quot;) {
      document.getElementById(&quot;theme-btn&quot;).innerHTML = &quot;Light Mode&quot;;
    } else if (localStorage.getItem(&quot;theme&quot;) == &quot;light&quot;) {
      document.getElementById(&quot;theme-btn&quot;).innerHTML = &quot;Dark Mode&quot;;
    }
    btn.addEventListener(&quot;click&quot;, function() { /* Listen to Event-change in button and check localStorage for change in theme */
      if (localStorage.getItem(&quot;theme&quot;) == &quot;dark&quot;) {
        document.getElementById(&quot;theme-btn&quot;).innerHTML = &quot;Light Mode&quot;;
      } else if (localStorage.getItem(&quot;theme&quot;) == &quot;light&quot;) {
        document.getElementById(&quot;theme-btn&quot;).innerHTML = &quot;Dark Mode&quot;;
      }
    });
  &lt;/script&gt;
&lt;/body&gt;

<!-- end snippet -->

Together with the rest of my site, this works fine. Only problem is, when there's no key yet stored in localStorage, the correct text is not applied. Thus, this solution only works until after the button is clicked manually... and doesn't work for new visitors.

Looking for a different solution, I figured there could be another approach - check the OS' preference first, and then listen to the button-click. Sadly, I failed miserably - I'll document what I tried tomorrow.

huangapple
  • 本文由 发表于 2023年2月18日 23:51:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75494506.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定