grayscale/example/js/theme-builder.js

149 lines
3.8 KiB
JavaScript
Raw Normal View History

2021-10-13 22:29:04 +00:00
///////////////////////////////////////////////
2021-10-16 06:04:57 +00:00
// Grayscale Theme Builder
2021-10-13 22:29:04 +00:00
///////////////////////////////////////////////
2021-10-16 06:04:57 +00:00
// query helper
2021-10-13 22:29:04 +00:00
const $ = document.querySelector.bind(document);
function HEXToRGB(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
function RGBToHSL(r,g,b) {
// Make r, g, and b fractions of 1
r /= 255;
g /= 255;
b /= 255;
// Find greatest and smallest channel values
let cmin = Math.min(r,g,b),
cmax = Math.max(r,g,b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
// Calculate hue
// No difference
if (delta == 0)
h = 0;
// Red is max
else if (cmax == r)
h = ((g - b) / delta) % 6;
// Green is max
else if (cmax == g)
h = (b - r) / delta + 2;
// Blue is max
else
h = (r - g) / delta + 4;
h = Math.round(h * 60);
// Make negative hues positive behind 360°
if (h < 0)
h += 360;
// Calculate lightness
l = (cmax + cmin) / 2;
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
// Multiply l and s by 100
s = +(s * 100).toFixed(0);
l = +(l * 100).toFixed(0);
return {
h,s,l
};
}
2021-10-16 06:04:57 +00:00
// refresh current page theme
function refresh() {
2021-10-13 22:29:04 +00:00
const form = $('#settings');
2021-10-16 06:04:57 +00:00
// convert hex-to-rbg-to-hsl
2021-10-13 22:29:04 +00:00
const rgb = HEXToRGB(form.elements['theme'].value);
const hsl = RGBToHSL(rgb.r, rgb.g, rgb.b);
2021-10-16 06:04:57 +00:00
// build theme string
const theme = String(`
2021-10-13 22:29:04 +00:00
:root {
2021-10-14 22:23:32 +00:00
--Hsl: ${hsl.h};
--hSl: ${hsl.s}%;
--hsL: ${hsl.l}%;
--font: ${form.elements['font'].value};
--size: ${form.elements['size'].value}px;
--space: ${form.elements['spacing'].value}rem;
--line: ${form.elements['line'].value};
--radius: ${form.elements['radius'].value}rem;
}`).replace(/\s/g, '');
2021-10-16 06:04:57 +00:00
// override :root to update page theme
$('#dynamic').innerHTML = theme;
return theme;
}
2021-10-13 22:29:04 +00:00
2021-10-16 06:04:57 +00:00
// download custom grayscaled theme
function download(css) {
const filename = `grayscaled.css`;
let el = document.createElement('a');
el.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(css));
el.setAttribute('download', filename);
el.style.display = 'none';
el.click();
2021-10-13 22:29:04 +00:00
}
2021-10-16 06:04:57 +00:00
// page download button
2021-10-13 22:29:04 +00:00
$('input[type="submit"]').addEventListener('click', (e) => {
e.preventDefault();
2021-10-16 06:04:57 +00:00
// get current theme
const theme = refresh();
2021-10-16 06:04:57 +00:00
// get style rules as text
function getText(x) {
// exclude :root theme vars
if(x.selectorText !== ':root') {
return x.cssText;
}
}
2021-10-16 06:04:57 +00:00
// get grayscale stylesheet as dom object
var css = $('#grayscale');
2021-10-16 06:04:57 +00:00
// convert stylesheet dom object to string
var style = Array.prototype.map.call(css.sheet.cssRules, getText).join('\n');
// build custom grayscaled theme & minify
const grayscaled = `${theme}${style}`.replace(/\s/g, '');
download(grayscaled);
2021-10-13 22:29:04 +00:00
});
2021-10-16 06:04:57 +00:00
// toggle light / dark mode
2021-10-13 22:29:04 +00:00
$('#mode').addEventListener('click', () => {
const attr = $('html').getAttribute('data-theme');
if(attr && attr === 'dark') {
$('html').setAttribute('data-theme', 'light');
} else {
$('html').setAttribute('data-theme', 'dark');
}
});
2021-10-16 06:04:57 +00:00
// refresh page theme on changes
$('#radius').addEventListener('click', refresh);
$('#font').addEventListener('click', refresh);
$('#size').addEventListener('click', refresh);
$('#spacing').addEventListener('click', refresh);
$('#line').addEventListener('click', refresh);
$('#theme').addEventListener('change', refresh);