1/** 2 3Doxygen Awesome 4https://github.com/jothepro/doxygen-awesome-css 5 6MIT License 7 8Copyright (c) 2021 - 2023 jothepro 9 10Permission is hereby granted, free of charge, to any person obtaining a copy 11of this software and associated documentation files (the "Software"), to deal 12in the Software without restriction, including without limitation the rights 13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14copies of the Software, and to permit persons to whom the Software is 15furnished to do so, subject to the following conditions: 16 17The above copyright notice and this permission notice shall be included in all 18copies or substantial portions of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26SOFTWARE. 27 28*/ 29 30class DoxygenAwesomeDarkModeToggle extends HTMLElement { 31 // SVG icons from https://fonts.google.com/icons 32 // Licensed under the Apache 2.0 license: 33 // https://www.apache.org/licenses/LICENSE-2.0.html 34 static lightModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FCBF00"><rect fill="none" height="24" width="24"/><circle cx="12" cy="12" opacity=".3" r="3"/><path d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"/></svg>` 35 static darkModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FE9700"><rect fill="none" height="24" width="24"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27 C17.45,17.19,14.93,19,12,19c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z" opacity=".3"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"/></svg>` 36 static title = "Toggle Light/Dark Mode" 37 38 static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" 39 static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" 40 41 static _staticConstructor = function() { 42 DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) 43 // Update the color scheme when the browsers preference changes 44 // without user interaction on the website. 45 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 46 DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() 47 }) 48 // Update the color scheme when the tab is made visible again. 49 // It is possible that the appearance was changed in another tab 50 // while this tab was in the background. 51 document.addEventListener("visibilitychange", visibilityState => { 52 if (document.visibilityState === 'visible') { 53 DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() 54 } 55 }); 56 }() 57 58 static init() { 59 $(function() { 60 $(document).ready(function() { 61 const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle') 62 toggleButton.title = DoxygenAwesomeDarkModeToggle.title 63 toggleButton.updateIcon() 64 65 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 66 toggleButton.updateIcon() 67 }) 68 document.addEventListener("visibilitychange", visibilityState => { 69 if (document.visibilityState === 'visible') { 70 toggleButton.updateIcon() 71 } 72 }); 73 74 $(document).ready(function(){ 75 document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) 76 }) 77 $(window).resize(function(){ 78 document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) 79 }) 80 }) 81 }) 82 } 83 84 constructor() { 85 super(); 86 this.onclick=this.toggleDarkMode 87 } 88 89 /** 90 * @returns `true` for dark-mode, `false` for light-mode system preference 91 */ 92 static get systemPreference() { 93 return window.matchMedia('(prefers-color-scheme: dark)').matches 94 } 95 96 /** 97 * @returns `true` for dark-mode, `false` for light-mode user preference 98 */ 99 static get userPreference() { 100 return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || 101 (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) 102 } 103 104 static set userPreference(userPreference) { 105 DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference 106 if(!userPreference) { 107 if(DoxygenAwesomeDarkModeToggle.systemPreference) { 108 localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) 109 } else { 110 localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) 111 } 112 } else { 113 if(!DoxygenAwesomeDarkModeToggle.systemPreference) { 114 localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) 115 } else { 116 localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) 117 } 118 } 119 DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() 120 } 121 122 static enableDarkMode(enable) { 123 if(enable) { 124 DoxygenAwesomeDarkModeToggle.darkModeEnabled = true 125 document.documentElement.classList.add("dark-mode") 126 document.documentElement.classList.remove("light-mode") 127 } else { 128 DoxygenAwesomeDarkModeToggle.darkModeEnabled = false 129 document.documentElement.classList.remove("dark-mode") 130 document.documentElement.classList.add("light-mode") 131 } 132 } 133 134 static onSystemPreferenceChanged() { 135 DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference 136 DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) 137 } 138 139 static onUserPreferenceChanged() { 140 DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) 141 } 142 143 toggleDarkMode() { 144 DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference 145 this.updateIcon() 146 } 147 148 updateIcon() { 149 if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) { 150 this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon 151 } else { 152 this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon 153 } 154 } 155} 156 157customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle); 158