<body class="remarkdown h1-underline h2-underline h3-underline hr-center ul-star pre-tick"> | <body class="remarkdown h1-underline h2-underline h3-underline hr-center ul-star pre-tick"> | ||||
<template id="theme-selector"> | |||||
<form> | |||||
<fieldset> | |||||
<legend>Thème</legend> | |||||
<label> | |||||
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="light" name="chosen-color-scheme"> Clair | |||||
</label> | |||||
</fieldset> | |||||
</form> | |||||
</template> | |||||
<article> | <article> | ||||
<h1>Bienvenue</h1> | <h1>Bienvenue</h1> | ||||
</footer> | </footer> | ||||
<script src="/static/david/js/instantpage-3.0.0.min.js" type="module" defer></script> | <script src="/static/david/js/instantpage-3.0.0.min.js" type="module" defer></script> | ||||
<template id="theme-selector"> | |||||
<form> | |||||
<fieldset> | |||||
<legend>Thème</legend> | |||||
<label> | |||||
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="light" name="chosen-color-scheme"> Clair | |||||
</label> | |||||
</fieldset> | |||||
</form> | |||||
</template> | |||||
<script type="text/javascript"> | <script type="text/javascript"> | ||||
/* This is a work in progress with Anthony https://ricaud.me */ | /* This is a work in progress with Anthony https://ricaud.me */ | ||||
function loadThemeForm(templateName) { | function loadThemeForm(templateName) { | ||||
const themeSelectorTemplate = document.querySelector(templateName) | const themeSelectorTemplate = document.querySelector(templateName) | ||||
const clone = themeSelectorTemplate.content.cloneNode(true) | |||||
const form = document.body.insertAdjacentElement( | |||||
'afterbegin', | |||||
clone.firstElementChild | |||||
) | |||||
const form = themeSelectorTemplate.content.firstElementChild | |||||
themeSelectorTemplate.replaceWith(form) | |||||
form.addEventListener('change', (e) => { | form.addEventListener('change', (e) => { | ||||
const chosenColorScheme = e.target.value | const chosenColorScheme = e.target.value | ||||
}) | }) | ||||
} | } | ||||
const mediaQueryTest = '(prefers-color-scheme: dark)' | |||||
const prefersColorSchemeDark = '(prefers-color-scheme: dark)' | |||||
window.addEventListener('load', () => { | window.addEventListener('load', () => { | ||||
let mediaRules = [] | |||||
let ruleFound = false | |||||
let hasDarkRules = false | |||||
for (const styleSheet of Array.from(document.styleSheets)) { | for (const styleSheet of Array.from(document.styleSheets)) { | ||||
let mediaRules = [] | |||||
for (const cssRule of styleSheet.cssRules) { | for (const cssRule of styleSheet.cssRules) { | ||||
if (cssRule.type !== CSSRule.MEDIA_RULE) continue | |||||
if (cssRule.type !== CSSRule.MEDIA_RULE) { | |||||
continue | |||||
} | |||||
// WARNING: Safari does not have/supports `conditionText`. | // WARNING: Safari does not have/supports `conditionText`. | ||||
if (cssRule.conditionText) { | if (cssRule.conditionText) { | ||||
if (cssRule.conditionText !== mediaQueryTest) continue | |||||
if (cssRule.conditionText !== prefersColorSchemeDark) { | |||||
continue | |||||
} | |||||
} else { | } else { | ||||
if (cssRule.cssText.startsWith(mediaQueryTest)) continue | |||||
} | |||||
// At that point, only a media cssRule matching our media query | |||||
// test should remain, hence the renaming. | |||||
const mediaRule = cssRule | |||||
for (const innerCssRule of mediaRule.cssRules) { | |||||
mediaRules.push(innerCssRule) | |||||
ruleFound = true | |||||
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) { | |||||
continue | |||||
} | |||||
} | } | ||||
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules)) | |||||
} | } | ||||
// WARNING: do not try to insert a Rule to a styleSheet you are | // WARNING: do not try to insert a Rule to a styleSheet you are | ||||
// currently iterating on, otherwise the browser will be stuck | // currently iterating on, otherwise the browser will be stuck | ||||
// in a infinite loop… | // in a infinite loop… | ||||
for (const mediaRule of mediaRules) { | for (const mediaRule of mediaRules) { | ||||
styleSheet.insertRule(mediaRule.cssText) | styleSheet.insertRule(mediaRule.cssText) | ||||
hasDarkRules = true | |||||
} | } | ||||
mediaRules = [] | |||||
} | } | ||||
if (ruleFound) loadThemeForm('#theme-selector') | |||||
if (hasDarkRules) { | |||||
loadThemeForm('#theme-selector') | |||||
} | |||||
}) | }) | ||||
</script> | </script> | ||||
</body> | </body> |
{% block lang %}fr{% endblock %} | {% block lang %}fr{% endblock %} | ||||
{% block title %}Accueil{% endblock %} | {% block title %}Accueil{% endblock %} | ||||
{% block content %} | {% block content %} | ||||
<template id="theme-selector"> | |||||
<form> | |||||
<fieldset> | |||||
<legend>Thème</legend> | |||||
<label> | |||||
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="light" name="chosen-color-scheme"> Clair | |||||
</label> | |||||
</fieldset> | |||||
</form> | |||||
</template> | |||||
<article> | <article> | ||||
<h1>Bienvenue</h1> | <h1>Bienvenue</h1> | ||||
{% endblock content %} | {% endblock content %} | ||||
{% block extra_bottom %} | {% block extra_bottom %} | ||||
<template id="theme-selector"> | |||||
<form> | |||||
<fieldset> | |||||
<legend>Thème</legend> | |||||
<label> | |||||
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé | |||||
</label> | |||||
<label> | |||||
<input type="radio" value="light" name="chosen-color-scheme"> Clair | |||||
</label> | |||||
</fieldset> | |||||
</form> | |||||
</template> | |||||
<script type="text/javascript"> | <script type="text/javascript"> | ||||
/* This is a work in progress with Anthony https://ricaud.me */ | /* This is a work in progress with Anthony https://ricaud.me */ | ||||
function loadThemeForm(templateName) { | function loadThemeForm(templateName) { | ||||
const themeSelectorTemplate = document.querySelector(templateName) | const themeSelectorTemplate = document.querySelector(templateName) | ||||
const clone = themeSelectorTemplate.content.cloneNode(true) | |||||
const form = document.body.insertAdjacentElement( | |||||
'afterbegin', | |||||
clone.firstElementChild | |||||
) | |||||
const form = themeSelectorTemplate.content.firstElementChild | |||||
themeSelectorTemplate.replaceWith(form) | |||||
form.addEventListener('change', (e) => { | form.addEventListener('change', (e) => { | ||||
const chosenColorScheme = e.target.value | const chosenColorScheme = e.target.value | ||||
}) | }) | ||||
} | } | ||||
const mediaQueryTest = '(prefers-color-scheme: dark)' | |||||
const prefersColorSchemeDark = '(prefers-color-scheme: dark)' | |||||
window.addEventListener('load', () => { | window.addEventListener('load', () => { | ||||
let mediaRules = [] | |||||
let ruleFound = false | |||||
let hasDarkRules = false | |||||
for (const styleSheet of Array.from(document.styleSheets)) { | for (const styleSheet of Array.from(document.styleSheets)) { | ||||
let mediaRules = [] | |||||
for (const cssRule of styleSheet.cssRules) { | for (const cssRule of styleSheet.cssRules) { | ||||
if (cssRule.type !== CSSRule.MEDIA_RULE) continue | |||||
if (cssRule.type !== CSSRule.MEDIA_RULE) { | |||||
continue | |||||
} | |||||
// WARNING: Safari does not have/supports `conditionText`. | // WARNING: Safari does not have/supports `conditionText`. | ||||
if (cssRule.conditionText) { | if (cssRule.conditionText) { | ||||
if (cssRule.conditionText !== mediaQueryTest) continue | |||||
if (cssRule.conditionText !== prefersColorSchemeDark) { | |||||
continue | |||||
} | |||||
} else { | } else { | ||||
if (cssRule.cssText.startsWith(mediaQueryTest)) continue | |||||
} | |||||
// At that point, only a media cssRule matching our media query | |||||
// test should remain, hence the renaming. | |||||
const mediaRule = cssRule | |||||
for (const innerCssRule of mediaRule.cssRules) { | |||||
mediaRules.push(innerCssRule) | |||||
ruleFound = true | |||||
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) { | |||||
continue | |||||
} | |||||
} | } | ||||
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules)) | |||||
} | } | ||||
// WARNING: do not try to insert a Rule to a styleSheet you are | // WARNING: do not try to insert a Rule to a styleSheet you are | ||||
// currently iterating on, otherwise the browser will be stuck | // currently iterating on, otherwise the browser will be stuck | ||||
// in a infinite loop… | // in a infinite loop… | ||||
for (const mediaRule of mediaRules) { | for (const mediaRule of mediaRules) { | ||||
styleSheet.insertRule(mediaRule.cssText) | styleSheet.insertRule(mediaRule.cssText) | ||||
hasDarkRules = true | |||||
} | } | ||||
mediaRules = [] | |||||
} | } | ||||
if (ruleFound) loadThemeForm('#theme-selector') | |||||
if (hasDarkRules) { | |||||
loadThemeForm('#theme-selector') | |||||
} | |||||
}) | }) | ||||
</script> | </script> | ||||
{% endblock extra_bottom %} | {% endblock extra_bottom %} |