124 lines
6.1 KiB
JavaScript
124 lines
6.1 KiB
JavaScript
/* DeskHub Tickets: übernimmt Farben vom Theme.
|
|
* Schrift, Hintergrund und Rahmen kommen schon per CSS (currentColor). Hier wird nur die Akzentfarbe gelesen,
|
|
* und zwar aus Knöpfen oder Links der Seite. Eine feste Farbe aus den Einstellungen (data-dht-accent) hat Vorrang. */
|
|
(function () {
|
|
'use strict';
|
|
|
|
function parse(c) {
|
|
var m = /rgba?\(\s*([\d.]+)[ ,]+([\d.]+)[ ,]+([\d.]+)(?:[ ,/]+([\d.%]+))?\s*\)/.exec(c || '');
|
|
if (!m) { return null; }
|
|
var a = m[4] === undefined ? 1 : (m[4].indexOf('%') > -1 ? parseFloat(m[4]) / 100 : parseFloat(m[4]));
|
|
return { r: +m[1], g: +m[2], b: +m[3], a: a };
|
|
}
|
|
|
|
function lum(c) {
|
|
var f = function (v) { v /= 255; return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4); };
|
|
return 0.2126 * f(c.r) + 0.7152 * f(c.g) + 0.0722 * f(c.b);
|
|
}
|
|
|
|
function contrast(a, b) {
|
|
var l1 = lum(a), l2 = lum(b);
|
|
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
|
|
}
|
|
|
|
function css(c) { return 'rgb(' + Math.round(c.r) + ',' + Math.round(c.g) + ',' + Math.round(c.b) + ')'; }
|
|
|
|
// Hintergrund, der hinter dem Formular wirklich zu sehen ist
|
|
function pageBackground(el) {
|
|
for (var n = el; n && n.nodeType === 1; n = n.parentNode) {
|
|
var c = parse(getComputedStyle(n).backgroundColor);
|
|
if (c && c.a > 0.5) { return c; }
|
|
}
|
|
return { r: 255, g: 255, b: 255, a: 1 };
|
|
}
|
|
|
|
function saturation(c) {
|
|
var mx = Math.max(c.r, c.g, c.b), mn = Math.min(c.r, c.g, c.b);
|
|
return mx === 0 ? 0 : (mx - mn) / mx;
|
|
}
|
|
|
|
// Farbwert (auch #hex oder Name) in rgb umrechnen
|
|
function resolve(wrap, value) {
|
|
if (!value) { return null; }
|
|
var span = document.createElement('span');
|
|
span.style.color = value;
|
|
if (!span.style.color) { return null; }
|
|
wrap.appendChild(span);
|
|
var c = parse(getComputedStyle(span).color);
|
|
wrap.removeChild(span);
|
|
return c;
|
|
}
|
|
|
|
// Akzent der Seite: häufigste kräftige Farbe von Knöpfen (Füllung oder Rand), sonst Linkfarbe.
|
|
// Die Farbe dient als Füllung, die Schrift darauf wird extra gewählt: ein geringer Kontrast zum Hintergrund (z. B. Orange auf Weiß) ist also in Ordnung.
|
|
function themeAccent(wrap, bg) {
|
|
var counts = {}, best = null, bestN = 0;
|
|
function add(c, weight) {
|
|
if (!c || c.a < 0.9 || saturation(c) < 0.25 || contrast(c, bg) < 1.3) { return; }
|
|
var k = css(c);
|
|
counts[k] = (counts[k] || 0) + weight;
|
|
if (counts[k] > bestN) { bestN = counts[k]; best = c; }
|
|
}
|
|
var sel = '.wp-element-button, .wp-block-button__link, .button, .btn, [class*="btn"], [class*="button"], [role="button"], button, input[type="submit"], a';
|
|
var nodes = document.querySelectorAll(sel);
|
|
for (var i = 0; i < nodes.length && i < 400; i++) {
|
|
if (wrap.contains(nodes[i])) { continue; }
|
|
var st = getComputedStyle(nodes[i]);
|
|
add(parse(st.backgroundColor), /wp-element-button|wp-block-button__link|(^|\s)(button|btn)(\s|$)/.test(nodes[i].className || '') ? 4 : 2);
|
|
if (parseFloat(st.borderTopWidth) > 0) { add(parse(st.borderTopColor), 1); }
|
|
}
|
|
if (best) { return best; }
|
|
// Farbvariablen bekannter Themes und Seitenbauer (Block-Themes, Elementor, Astra, Kadence …)
|
|
var names = ['--wp--preset--color--primary', '--wp--preset--color--accent', '--e-global-color-accent', '--e-global-color-primary',
|
|
'--ast-global-color-0', '--global-palette1', '--global-palette-btn-bg', '--primary-color', '--accent-color', '--theme-color-primary',
|
|
'--color-primary', '--color-accent', '--primary', '--accent', '--brand-color'];
|
|
var rootStyle = getComputedStyle(document.documentElement);
|
|
for (var k = 0; k < names.length; k++) {
|
|
var v = rootStyle.getPropertyValue(names[k]).trim();
|
|
if (!v) { continue; }
|
|
var vc = resolve(wrap, v);
|
|
if (vc && vc.a > 0.9 && saturation(vc) >= 0.25 && contrast(vc, bg) >= 1.3) { return vc; }
|
|
}
|
|
var server = resolve(wrap, getComputedStyle(wrap).getPropertyValue('--dht-server-accent').trim());
|
|
if (server) { return server; }
|
|
var probe = document.createElement('a');
|
|
probe.href = '#';
|
|
probe.style.cssText = 'position:absolute;visibility:hidden';
|
|
(wrap.parentNode || document.body).appendChild(probe);
|
|
var lc = parse(getComputedStyle(probe).color);
|
|
probe.parentNode.removeChild(probe);
|
|
return lc && saturation(lc) >= 0.25 ? lc : null;
|
|
}
|
|
|
|
function apply(wrap) {
|
|
var bg = pageBackground(wrap);
|
|
var fg = parse(getComputedStyle(wrap).color) || { r: 0, g: 0, b: 0, a: 1 };
|
|
var dark = lum(bg) < 0.4;
|
|
// Felder und Rahmen: feste Mischfarben aus Seitenhintergrund und Schriftfarbe (unabhängig von der Akzentfarbe)
|
|
var mix = function (t) { return css({ r: bg.r + (fg.r - bg.r) * t, g: bg.g + (fg.g - bg.g) * t, b: bg.b + (fg.b - bg.b) * t }); };
|
|
wrap.style.setProperty('--dht-field-bg', mix(0.07));
|
|
wrap.style.setProperty('--dht-border', mix(0.3));
|
|
wrap.style.setProperty('--dht-muted', mix(0.7));
|
|
wrap.style.setProperty('--dht-bg', css(bg));
|
|
wrap.style.setProperty('--dht-fg', css(fg));
|
|
wrap.style.setProperty('color-scheme', dark ? 'dark' : 'light');
|
|
|
|
var accent;
|
|
if (wrap.getAttribute('data-dht-accent') === 'fixed') {
|
|
accent = resolve(wrap, getComputedStyle(wrap).getPropertyValue('--dht-theme-accent').trim());
|
|
} else {
|
|
accent = themeAccent(wrap, bg);
|
|
if (accent) { wrap.style.setProperty('--dht-theme-accent', css(accent)); }
|
|
}
|
|
if (!accent) { return; }
|
|
// Schrift auf dem Knopf: schwarz oder weiß, je nachdem, was besser lesbar ist
|
|
var white = { r: 255, g: 255, b: 255 }, black = { r: 17, g: 17, b: 17 };
|
|
wrap.style.setProperty('--dht-theme-on-accent', contrast(accent, white) >= contrast(accent, black) ? '#fff' : '#111');
|
|
}
|
|
|
|
function ready() { document.querySelectorAll('.dht-wrap').forEach(apply); }
|
|
if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', ready); } else { ready(); }
|
|
// Nochmal nach dem Laden: Theme-Stile und Schriften können später kommen
|
|
window.addEventListener('load', ready);
|
|
})();
|