all repos — themeswitcher @ f5818864c52b9b5f3fc387ea2a8e6202b725e1b9


        
Peter Molnar github@petermolnar.net
Thu, 10 Jan 2019 08:20:47 +0000
commit

f5818864c52b9b5f3fc387ea2a8e6202b725e1b9

3 files changed, 114 insertions(+), 0 deletions(-)

jump to
A themeswitcher.css

@@ -0,0 +1,12 @@

+.theme input + label { + border-bottom: 3px solid transparent; +} + +.theme input:checked + label { + border-bottom: 3px solid #ccc; +} + +.theme, +.theme input { + display: none; +}
A themeswitcher.html

@@ -0,0 +1,23 @@

+<!-- <head> needs to contain the alternative style sheet --> +<style media="all"> + # normal CSS +</style> +<style id="css_alt" media="speech"> + # alt CSS +</style> + + +<!-- include this into the <body> to have controls --> +<form class="theme" aria-hidden="true"> + <span> + 🔆 + </span> + <span> + <input name="colorscheme" value="dark" id="darkscheme" type="radio"> + <label for="darkscheme">dark</label> + </span> + <span> + <input name="colorscheme" value="light" id="lightscheme" type="radio"> + <label for="lightscheme">light</label> + </span> +</form>
A themeswitcher.js

@@ -0,0 +1,79 @@

+var DEFAULT_THEME = 'dark'; +var ALT_THEME = 'light'; +var STORAGE_KEY = 'theme'; +var colorscheme = document.getElementsByName('colorscheme'); + +function indicateTheme(mode) { + for(var i = colorscheme.length; i--; ) { + if(colorscheme[i].value == mode) { + colorscheme[i].checked = true; + } + } +} + +function applyTheme(mode) { + var st = document.getElementById('css_alt'); + if (mode == ALT_THEME) { + st.setAttribute('media', 'all'); + } + else { + st.setAttribute('media', 'speech'); + } +} + +function setTheme(e) { + var mode = e.target.value; + var mql = window.matchMedia('(prefers-color-scheme: ' + ALT_THEME + ')'); + /* user wants == mql match => remove storage */ + if ((mode == DEFAULT_THEME && !mql.matches) || (mode == ALT_THEME && mql.matches)) { + localStorage.removeItem(STORAGE_KEY); + } + /* avoid needing cookie banners; besides, messages like this would make people understand that clicking on a thing + might do something to their computer */ + else { + if(confirm("I\'ll need to store your theme of choice in your browser, in a place called localStorage.\n\nAre you OK with this?")) { + localStorage.setItem(STORAGE_KEY, mode); + } + } + autoTheme(mql); +} + +function autoTheme(e) { + var mode = DEFAULT_THEME; + try { + var current = localStorage.getItem(STORAGE_KEY); + } catch(e) { + var current = DEFAULT_THEME; + } + if ( current != null) { + mode = current; + } + else if (e.matches) { + mode = ALT_THEME; + } + applyTheme(mode); + indicateTheme(mode); +} + +/* at 2019-01 this only works in Dev Safari on Mojave */ +var mql = window.matchMedia('(prefers-color-scheme: ' + ALT_THEME + ')'); +autoTheme(mql); +mql.addListener(autoTheme); + +/* only show controls if localstorage is available */ +var test = 'ping'; +try { + localStorage.setItem(test, test); + localStorage.removeItem(test); + /* add a listener for the controle */ + for(var i = colorscheme.length; i--; ) { + colorscheme[i].onclick = setTheme; + } + /* show the control */ + var themeforms = document.getElementsByClassName(STORAGE_KEY); + for(var i = themeforms.length; i--; ) { + themeforms[i].style.display = 'inline-block'; + } +} catch(e) { + console.log('localStorage is not available, manual theme switching is disabled'); +}