diff --git a/events.js b/events.js index 9ae1f8b..bacb49b 100644 --- a/events.js +++ b/events.js @@ -12,15 +12,16 @@ // duration - optional length of the event in seconds. // showMega - optional boolean, show label on the megasequence view (default true). // showDetail - optional boolean, show event in the detail view (default true). +// color - optional hex color for the event (used in detail view) window.SPECIAL_EVENTS = [ - { cobie: '49f4.9332', label: 'Afina', unit: 'cosmocycle', interval: 1 }, - { cobie: '11e5.f552', label: 'Oleks', unit: 'cosmocycle', interval: 1 }, - { cobie: '4d07.a2b2', label: 'Vincent', unit: 'cosmocycle', interval: 1 }, - { cobie: '3edc.d430', label: 'Hochzeitstag', unit: 'cosmocycle', interval: 1 }, - { cobie: '330d.d4ae', label: 'Zusammentag', unit: 'cosmocycle', interval: 1 }, - { cobie: '11de.0c52', label: 'Anna', unit: 'cosmocycle', interval: 1 }, - { cobie: '467f.ae61', label: 'Iris', unit: 'cosmocycle', interval: 1 }, - { cobie: '6854.7a75', label: 'Sleep', unit: 'second', interval: 86400, duration: 28800, showMega: false }, - { cobie: '6854.9695', label: 'Night', unit: 'second', interval: 86400, duration: 28800, showMega: false, shiftWithTimezone: true } + { cobie: '49f4.9332', label: 'Afina', color: '#e57373', unit: 'cosmocycle', interval: 1 }, + { cobie: '11e5.f552', label: 'Oleks', color: '#64b5f6', unit: 'cosmocycle', interval: 1 }, + { cobie: '4d07.a2b2', label: 'Vincent', color: '#81c784', unit: 'cosmocycle', interval: 1 }, + { cobie: '3edc.d430', label: 'Hochzeitstag', color: '#ffb74d', unit: 'cosmocycle', interval: 1 }, + { cobie: '330d.d4ae', label: 'Zusammentag', color: '#ba68c8', unit: 'cosmocycle', interval: 1 }, + { cobie: '11de.0c52', label: 'Anna', color: '#4db6ac', unit: 'cosmocycle', interval: 1 }, + { cobie: '467f.ae61', label: 'Iris', color: '#7986cb', unit: 'cosmocycle', interval: 1 }, + { cobie: '6854.7a75', label: 'Sleep', color: '#546e7a', unit: 'second', interval: 86400, duration: 28800, showMega: false }, + { cobie: '6854.9695', label: 'Night', color: '#212121', unit: 'second', interval: 86400, duration: 28800, showMega: false, shiftWithTimezone: true } ]; diff --git a/script.js b/script.js index 5b73cf3..291fc87 100644 --- a/script.js +++ b/script.js @@ -44,6 +44,36 @@ let updateInterval; let lastRenderedEonstrip = null; let currentDetailCob = null; +function hexToRgba(hex, alpha) { + if (!hex) return ''; + let c = hex.replace('#', ''); + if (c.length === 3) { + c = c.split('').map(x => x + x).join(''); + } + const r = parseInt(c.substring(0,2),16); + const g = parseInt(c.substring(2,4),16); + const b = parseInt(c.substring(4,6),16); + return `rgba(${r},${g},${b},${alpha})`; +} + +function getContrastColor(hex) { + if (!hex) return '#fff'; + let c = hex.replace('#',''); + if (c.length === 3) c = c.split('').map(x=>x+x).join(''); + const r = parseInt(c.substr(0,2),16); + const g = parseInt(c.substr(2,2),16); + const b = parseInt(c.substr(4,2),16); + const yiq = (r*299 + g*587 + b*114) / 1000; + return yiq >= 128 ? '#000' : '#fff'; +} + +function applyEventColors(elem, color, alpha) { + if (!color || !elem) return; + elem.style.setProperty('--bg-color', hexToRgba(color, alpha)); + elem.style.setProperty('--border-color', color); + elem.style.setProperty('--text-color', getContrastColor(color)); +} + function getTimezoneOffsetSeconds(date) { if (currentTimezone === 'UTC') return 0; if (currentTimezone === 'TAI') return getTAIOffsetAt(date); @@ -761,6 +791,7 @@ function showEonstripDetail(index, startCob) { const relEnd = (occ + duration - start) / COBIE_UNITS.eonstrip; events.push({ label: ev.label, + color: ev.color, start: relStart, end: relEnd, cobStart: occ, @@ -772,16 +803,30 @@ function showEonstripDetail(index, startCob) { } }); events.sort((a,b)=>a.start-b.start); - const columns = []; + + const groups = []; + let active = []; events.forEach(ev=>{ + active = active.filter(a=>a.end>ev.start); + if (active.length===0) { + groups.push({events:[],columns:[],maxCols:0}); + } + const g = groups[groups.length-1]; let col=0; - while(columns[col] && columns[col] > ev.start) col++; - columns[col] = ev.end; + while(g.columns[col] && g.columns[col] > ev.start) col++; + g.columns[col] = ev.end; ev.col = col; + g.maxCols = Math.max(g.maxCols, col+1); + g.events.push(ev); + active.push(ev); }); - const width = 100 / (columns.length || 1); + groups.forEach(g=>{ + const width = 100/(g.maxCols||1); + g.events.forEach(ev=>ev.width=width); + }); + events.forEach(ev=>{ - const left = ev.col * width; + const left = ev.col * ev.width; const displayStart = Math.max(0, ev.start); const displayEnd = Math.min(1, ev.end); const elem = document.createElement('div'); @@ -799,7 +844,9 @@ function showEonstripDetail(index, startCob) { } elem.style.top = (displayStart * 100) + '%'; elem.style.left = `calc(var(--scale-width) + ${left}%)`; - elem.style.width = `calc(${width}% - 2px)`; + elem.style.width = `calc(${ev.width}% - 2px)`; + + if (ev.color) applyEventColors(elem, ev.color, 0.4); if (elem.classList.contains('small-event') || elem.className === 'event-line') { const label = document.createElement('span'); @@ -809,6 +856,7 @@ function showEonstripDetail(index, startCob) { } label.textContent = ev.label; elem.appendChild(label); + if (ev.color) applyEventColors(label, ev.color, 0.5); } else { elem.textContent = ev.label; } diff --git a/style.css b/style.css index 362d053..2dec2b7 100644 --- a/style.css +++ b/style.css @@ -441,11 +441,11 @@ .event-box, .event-line { position: absolute; left: var(--scale-width); - background: rgba(255,0,255,0.4); - border: 1px solid rgba(0,255,255,0.7); + background: var(--bg-color, rgba(255,0,255,0.4)); + border: 1px solid var(--border-color, rgba(0,255,255,0.7)); border-radius: 4px; padding: 2px 4px; - color: #fff; + color: var(--text-color, #fff); font-size: 0.75em; overflow: visible; white-space: nowrap; @@ -476,15 +476,15 @@ left: 50%; transform: translate(-50%, -2px); margin-bottom: 2px; - background: rgba(255,0,255,0.5); - border: 1px solid rgba(0,255,255,0.8); + background: var(--bg-color, rgba(255,0,255,0.5)); + border: 1px solid var(--border-color, rgba(0,255,255,0.8)); border-radius: 4px; padding: 2px 6px; white-space: nowrap; - color: #fff; + color: var(--text-color, #fff); font-size: 0.75em; font-weight: 600; - text-shadow: 0 0 4px #ff00ff; + text-shadow: 0 0 4px var(--border-color, #ff00ff); z-index: 4; }