Files
deskhub/wordpress-plugin/deskhub-tickets/assets/theme.js
T
2026-11-01 11:17:41 +00:00

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);
})();