Compare commits

...

9 Commits

Author SHA1 Message Date
Oleksandr Kozachuk 93fe6bcdd2 Simplify events.js 2025-06-20 07:51:19 +02:00
Kiyomichi Kosaka 456f0744c4 Merge pull request #63 from ok2/codex/add-properties-to-control-event-visibility 2025-06-20 07:49:53 +02:00
Kiyomichi Kosaka 7bfee30e71 feat(events): configurable visibility 2025-06-20 07:49:34 +02:00
Kiyomichi Kosaka 2e6d870c0f Merge pull request #62 from ok2/codex/fix-visibility-of-event-labels-and-line-thickness 2025-06-20 07:47:54 +02:00
Kiyomichi Kosaka 88c37b566a Fix detail view labels for small events 2025-06-20 07:47:31 +02:00
Kiyomichi Kosaka 47d4a66b0f Merge pull request #61 from ok2/codex/fix-event-overflow-in-detail-view 2025-06-20 07:42:01 +02:00
Kiyomichi Kosaka 38a7de5ef8 fix(detail): clamp long events 2025-06-20 07:41:46 +02:00
Kiyomichi Kosaka 5e2ec31e4f Merge pull request #60 from ok2/codex/fix-bugs-in-analog-clock-and-megasequence 2025-06-20 07:35:29 +02:00
Kiyomichi Kosaka ec8f238a05 Fix detail view navigation and full screen 2025-06-20 07:35:04 +02:00
3 changed files with 103 additions and 44 deletions
+10 -8
View File
@@ -10,14 +10,16 @@
// 2 = every second unit, ...).
// label - short description displayed on the calendar.
// 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).
window.SPECIAL_EVENTS = [
{ start: '49f4.9332', label: 'Afina', unit: 'cosmocycle', interval: 1 },
{ start: '11e5.f552', label: 'Oleks', unit: 'cosmocycle', interval: 1 },
{ start: '4d07.a2b2', label: 'Vincent', unit: 'cosmocycle', interval: 1 },
{ start: '3edc.d430', label: 'Hochzeitstag', unit: 'cosmocycle', interval: 1 },
{ start: '330d.d4ae', label: 'Zusammentag', unit: 'cosmocycle', interval: 1 },
{ start: '11de.0c52', label: 'Anna', unit: 'cosmocycle', interval: 1 },
{ start: '467f.ae61', label: 'Iris', unit: 'cosmocycle', interval: 1 },
{ start: '6854.7a75', cobie: '6854.7a75', label: 'Sleep', unit: 'second', interval: 86400, duration: 28800 }
{ 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 }
];
+68 -35
View File
@@ -44,14 +44,6 @@ let updateInterval;
let lastRenderedEonstrip = null;
let currentDetailCob = null;
function fmt(d, o) {
// shift if TAI, then format
const shifted = currentTimezone==='TAI'
? new Date(d.getTime() + getTAIOffsetAt(d)*1000)
: d;
return shifted.toLocaleString('en-US', o);
}
function formatSafeDate(rawDate, cobSeconds, intlOptions) {
if (rawDate instanceof Date && !isNaN(rawDate.getTime())) {
// Date is valid: optionally shift for TAI vs UTC, then format:
@@ -71,10 +63,6 @@ function formatSafeDate(rawDate, cobSeconds, intlOptions) {
// parseCobiets, floorDiv and other CoBiE helpers are provided by cobie.js
function getCurrentTAIOffset() {
return getTAIOffsetAt(new Date());
}
function getHumanDiff(d1, d2) {
// make sure start ≤ end
let start = d1 < d2 ? d1 : d2;
@@ -617,6 +605,7 @@ function updateCalendar() {
const cellStart = cellCob;
const cellEnd = cellCob + COBIE_UNITS.eonstrip;
window.SPECIAL_EVENTS.forEach(ev => {
if (ev.showMega === false) return;
const startCob = parseCobiets(ev.start || ev.cobie);
if (startCob === null) return;
const endCob = ev.end ? parseCobiets(ev.end) : Number.POSITIVE_INFINITY;
@@ -713,17 +702,36 @@ function showEonstripDetail(index, startCob) {
}
if (Array.isArray(window.SPECIAL_EVENTS)) {
const offsetStart = ((startCob % COBIE_UNITS.cosmocycle) + COBIE_UNITS.cosmocycle) % COBIE_UNITS.cosmocycle;
const events = [];
const start = startCob;
const end = startCob + COBIE_UNITS.eonstrip;
window.SPECIAL_EVENTS.forEach(ev => {
const evCob = parseCobiets(ev.cobie || ev.start);
if (evCob === null) return;
const evOffset = ((evCob % COBIE_UNITS.cosmocycle) + COBIE_UNITS.cosmocycle) % COBIE_UNITS.cosmocycle;
if (evOffset >= offsetStart && evOffset < offsetStart + COBIE_UNITS.eonstrip) {
const rel = (evOffset - offsetStart) / COBIE_UNITS.eonstrip;
const durSec = ev.duration ? ev.duration : 0;
const dur = durSec / COBIE_UNITS.eonstrip;
events.push({ label: ev.label, start: rel, end: rel + dur });
if (ev.showDetail === false) return;
const startCobEv = parseCobiets(ev.start || ev.cobie);
if (startCobEv === null) return;
const endCobEv = ev.end ? parseCobiets(ev.end) : Number.POSITIVE_INFINITY;
const unitVal = COBIE_UNITS[ev.unit] || COBIE_UNITS.cosmocycle;
const interval = (ev.interval || 1) * unitVal;
let duration = 0;
if (typeof ev.duration === 'string') {
const d = parseCobiets(ev.duration);
if (d !== null) duration = d;
} else if (typeof ev.duration === 'number') {
duration = ev.duration;
}
if (start > endCobEv) return;
let n = Math.floor((start - startCobEv) / interval);
if (n < 0) n = 0;
let occ = startCobEv + n * interval;
if (occ + duration <= start) occ += interval;
while (occ < end && occ <= endCobEv) {
const relStart = (occ - start) / COBIE_UNITS.eonstrip;
const relEnd = (occ + duration - start) / COBIE_UNITS.eonstrip;
events.push({ label: ev.label, start: relStart, end: relEnd });
occ += interval;
}
});
events.sort((a,b)=>a.start-b.start);
@@ -737,17 +745,33 @@ function showEonstripDetail(index, startCob) {
const width = 100 / (columns.length || 1);
events.forEach(ev=>{
const left = ev.col * width;
const elem = document.createElement(ev.end>ev.start ? 'div':'div');
if (ev.end>ev.start) {
elem.className='event-box';
elem.style.height=((ev.end-ev.start)*100)+'%';
const displayStart = Math.max(0, ev.start);
const displayEnd = Math.min(1, ev.end);
const elem = document.createElement('div');
if (ev.end > ev.start) {
elem.className = 'event-box';
const h = (displayEnd - displayStart) * 100;
if (h < 2) {
elem.classList.add('small-event');
elem.style.height = '4px';
} else {
elem.className='event-line';
elem.style.height = (h > 0 ? h : 0) + '%';
}
} else {
elem.className = 'event-line';
}
elem.style.top = (displayStart * 100) + '%';
elem.style.left = left + '%';
elem.style.width = `calc(${width}% - 2px)`;
if (elem.classList.contains('small-event') || elem.className === 'event-line') {
const label = document.createElement('span');
label.className = 'event-label';
label.textContent = ev.label;
elem.appendChild(label);
} else {
elem.textContent = ev.label;
}
elem.style.top=(ev.start*100)+'%';
elem.style.left=left+'%';
elem.style.width=`calc(${width}% - 2px)`;
elem.textContent=ev.label;
timeline.appendChild(elem);
});
}
@@ -769,6 +793,12 @@ function detailNow() {
showEonstripDetail(start);
}
function exitDetailView() {
document.getElementById('eonstripDetailView').style.display = 'none';
document.getElementById('calendarView').style.display = 'block';
currentDetailCob = null;
}
function getStep(mods) {
// base step = 1 megasequence
let step = 1;
@@ -796,6 +826,10 @@ function getStep(mods) {
function navigatePeriod(evt, direction) {
const step = getStep(evt);
if (currentDetailCob !== null) {
exitDetailView();
}
animateSwipe(direction, () => {
currentOffset += direction * step;
updateCalendar();
@@ -831,6 +865,9 @@ function goToNow() {
manualCobiets = 0;
compareManualMode = false;
currentOffset = 0;
if (currentDetailCob !== null) {
exitDetailView();
}
updateCurrentTime();
updateCalendar();
clearInterval(updateInterval);
@@ -924,11 +961,7 @@ if (matchingOption) {
currentTimezone = userTimezone;
}
document.getElementById('backToCalendar').addEventListener('click', () => {
document.getElementById('eonstripDetailView').style.display = 'none';
document.getElementById('calendarView').style.display = 'block';
currentDetailCob = null;
});
document.getElementById('backToCalendar').addEventListener('click', exitDetailView);
document.getElementById('detailPrev').addEventListener('click', detailPrev);
document.getElementById('detailNext').addEventListener('click', detailNext);
document.getElementById('detailNow').addEventListener('click', detailNow);
+25 -1
View File
@@ -403,6 +403,7 @@
height: 400px;
border-left: 2px solid #00ffff;
margin-left: 40px;
overflow: hidden;
}
.timeline-block {
@@ -429,8 +430,30 @@
}
.event-line {
height: 2px;
height: 4px;
padding: 0;
overflow: visible;
}
.event-box.small-event {
overflow: visible;
padding: 0;
}
.event-line .event-label,
.event-box.small-event .event-label {
position: absolute;
left: 100%;
top: 50%;
transform: translateY(-50%);
margin-left: 4px;
background: rgba(255,0,255,0.3);
border: 1px solid rgba(0,255,255,0.5);
border-radius: 4px;
padding: 2px 4px;
white-space: nowrap;
color: #fff;
font-size: 0.7em;
}
/* Layout combining current time and analog clock */
@@ -602,6 +625,7 @@ body.fullscreen-clock .current-time,
body.fullscreen-clock .timezone-selector,
body.fullscreen-clock .calendar-controls,
body.fullscreen-clock .calendar-view,
body.fullscreen-clock .detail-view,
body.fullscreen-clock .time-details,
body.fullscreen-clock .explanations {
display: none;