Render all months in sidebar
This commit is contained in:
@@ -1,29 +1,24 @@
|
|||||||
<div class="diary-cal panel panel-sidebar"
|
<div class="diary-cal panel panel-sidebar"
|
||||||
data-display-year="{{.DisplayYear}}"
|
data-display-year="{{.DisplayYear}}"
|
||||||
data-display-month="{{.DisplayMonth}}">
|
data-display-month="{{.DisplayMonth}}">
|
||||||
<div class="panel-header"><a href="{{.DiaryURL}}">Chronological</a></div>
|
<div class="panel-header row">
|
||||||
<div class="diary-cal-nav">
|
<a href="{{.DiaryURL}}">Chronological</a>
|
||||||
<div class="dropdown diary-cal-drop">
|
<div class="dropdown diary-cal-drop">
|
||||||
<button type="button" class="btn" data-cal-month-link data-action="cal-month-drop" aria-expanded="false" title="Monat wählen"> {{.DisplayMonthName}} </button>
|
<button type="button" class="btn" data-action="cal-year-drop" aria-expanded="false" title="Jahr wählen">{{.DisplayYear}} ▾</button>
|
||||||
<div class="dropdown-menu scrollable">
|
|
||||||
{{range .Months}}<a class="btn btn-block" data-cal-month-jump="{{.Num}}" href="{{.AnchorURL}}">{{.Name}}</a>{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a href="{{.YearURL}}" class="diary-cal-heading">{{.DisplayYear}}</a>
|
|
||||||
<div class="dropdown diary-cal-drop">
|
|
||||||
<button type="button" class="btn" data-action="cal-year-drop" aria-expanded="false" title="Jahr wählen">▾</button>
|
|
||||||
<div class="dropdown-menu align-right scrollable">
|
<div class="dropdown-menu align-right scrollable">
|
||||||
{{range .Years}}<a class="btn btn-block{{if .IsCurrent}} cal-current{{end}}" href="{{.URL}}">{{.Num}}</a>{{end}}
|
{{range .Years}}<a class="btn btn-block{{if .IsCurrent}} cal-current{{end}}" href="{{.URL}}">{{.Num}}</a>{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{range .Months}}
|
{{range $i, $m := .Months}}
|
||||||
<table class="diary-cal-grid" data-cal-month="{{.Num}}"{{if ne .Num $.DisplayMonth}} hidden{{end}}>
|
{{if $i}}<hr/>{{end}}
|
||||||
|
<div class="diary-cal-month"><a href="{{$m.AnchorURL}}">{{$m.Name}}</a></div>
|
||||||
|
<table class="diary-cal-grid" data-cal-month="{{$m.Num}}">
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>Mo</th><th>Di</th><th>Mi</th><th>Do</th><th>Fr</th><th>Sa</th><th>So</th></tr>
|
<tr><th>Mo</th><th>Di</th><th>Mi</th><th>Do</th><th>Fr</th><th>Sa</th><th>So</th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Weeks}}<tr>{{range .}}<td class="{{if .IsCurrent}}cal-current{{else if .IsToday}}cal-today{{end}}{{if and .Num (not .HasEntry)}} cal-empty{{end}}">{{if .Num}}<a href="{{.URL}}">{{.Num}}</a>{{end}}</td>{{end}}</tr>
|
{{range $m.Weeks}}<tr>{{range .}}<td class="{{if .IsCurrent}}cal-current{{else if .IsToday}}cal-today{{end}}{{if and .Num (not .HasEntry)}} cal-empty{{end}}">{{if .Num}}<a href="{{.URL}}">{{.Num}}</a>{{end}}</td>{{end}}</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
+30
-34
@@ -3,47 +3,43 @@
|
|||||||
if (!cal) return;
|
if (!cal) return;
|
||||||
cal.querySelectorAll(".dropdown > button").forEach(wireDropdown);
|
cal.querySelectorAll(".dropdown > button").forEach(wireDropdown);
|
||||||
|
|
||||||
var displayYear = parseInt(cal.dataset.displayYear, 10);
|
var displayMonth = parseInt(cal.dataset.displayMonth, 10);
|
||||||
var current = parseInt(cal.dataset.displayMonth, 10);
|
|
||||||
var monthLabel = cal.querySelector("[data-cal-month-link]");
|
|
||||||
var months = {};
|
var months = {};
|
||||||
cal.querySelectorAll("[data-cal-month]").forEach(function (t) {
|
cal.querySelectorAll("[data-cal-month]").forEach(function (t) {
|
||||||
months[parseInt(t.dataset.calMonth, 10)] = t;
|
months[parseInt(t.dataset.calMonth, 10)] = t;
|
||||||
});
|
});
|
||||||
var jumpLinks = {};
|
|
||||||
cal.querySelectorAll("[data-cal-month-jump]").forEach(function (a) {
|
|
||||||
jumpLinks[parseInt(a.dataset.calMonthJump, 10)] = a;
|
|
||||||
});
|
|
||||||
|
|
||||||
function show(m) {
|
// Centering only applies inside the persistent desktop rail (.sidebar). On
|
||||||
if (m === current) return;
|
// mobile the widget is re-parented into .overlay-body, where we leave the
|
||||||
if (!months[m]) return;
|
// grids stacked from January and do not scroll (design decision).
|
||||||
months[current].hidden = true;
|
function railContainer() {
|
||||||
months[m].hidden = false;
|
var el = cal.parentElement;
|
||||||
current = m;
|
while (el) {
|
||||||
if (monthLabel) {
|
if (el.classList) {
|
||||||
var label = jumpLinks[m];
|
if (el.classList.contains("overlay-body")) return null;
|
||||||
if (label) monthLabel.textContent = " " + label.textContent + " ";
|
if (el.classList.contains("sidebar")) return el;
|
||||||
}
|
}
|
||||||
|
el = el.parentElement;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dropdown month picks scroll via the href anchor; we also swap the grid
|
// Scroll only the rail so the given month grid sits in its vertical center;
|
||||||
// so the calendar reflects what the user just navigated to.
|
// the main document/window position is untouched (priority: don't disturb
|
||||||
Object.keys(jumpLinks).forEach(function (key) {
|
// the reading position).
|
||||||
var a = jumpLinks[key];
|
function centerMonth(m) {
|
||||||
a.addEventListener("click", function () { show(parseInt(key, 10)); });
|
var grid = months[m];
|
||||||
});
|
if (!grid) return;
|
||||||
|
var container = railContainer();
|
||||||
// Any in-page anchor click (#YYYY-MM or #YYYY-MM-DD) updates the calendar
|
if (!container) return;
|
||||||
// so it tracks the user's focus through the year page.
|
var offset = grid.getBoundingClientRect().top -
|
||||||
function syncFromHash() {
|
container.getBoundingClientRect().top + container.scrollTop;
|
||||||
var h = window.location.hash;
|
container.scrollTop = offset - (container.clientHeight - grid.clientHeight) / 2;
|
||||||
if (!h) return;
|
|
||||||
var m = h.match(/^#(\d{4})-(\d{2})(?:-\d{2})?$/);
|
|
||||||
if (!m) return;
|
|
||||||
if (parseInt(m[1], 10) !== displayYear) return;
|
|
||||||
show(parseInt(m[2], 10));
|
|
||||||
}
|
}
|
||||||
window.addEventListener("hashchange", syncFromHash);
|
|
||||||
syncFromHash();
|
// Center the current month once, on initial render. Anchor navigation
|
||||||
|
// (#YYYY-MM / #YYYY-MM-DD) deliberately does NOT re-center the rail —
|
||||||
|
// re-scrolling on every hop is disorienting; the today/current cell
|
||||||
|
// highlighting is enough to keep bearings.
|
||||||
|
centerMonth(displayMonth);
|
||||||
})();
|
})();
|
||||||
|
|||||||
+9
-15
@@ -757,23 +757,17 @@ aside.tree-sidebar:empty { display: none; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* === Diary calendar === */
|
/* === Diary calendar === */
|
||||||
.diary-cal-nav {
|
/* Header row: "Chronological" on the left, the [year ▾] dropdown pushed to the
|
||||||
display: flex;
|
right. Composes with .row (flex + centering); space-between splits the two. */
|
||||||
align-items: center;
|
.diary-cal .panel-header { justify-content: space-between; }
|
||||||
justify-content: center;
|
.diary-cal-drop .dropdown-menu { min-width: 0; }
|
||||||
gap: 0.2rem;
|
/* Per-month caption above each grid, linking to that month's anchor. */
|
||||||
margin-bottom: 0.4rem;
|
.diary-cal-month {
|
||||||
font-size: var(--font-sm);
|
font-size: var(--font-sm);
|
||||||
|
margin: var(--space-3) 0 0.2rem;
|
||||||
}
|
}
|
||||||
.diary-cal-nav .diary-cal-drop + .diary-cal-heading { margin-left: var(--space-3); }
|
.diary-cal-month a { color: var(--link); }
|
||||||
/* Anchor the month/year dropdowns to the nav row instead of the ▾ button so
|
.diary-cal-month a:hover { color: var(--link-hover); }
|
||||||
the menu spans the full panel width rather than overflowing the 14rem
|
|
||||||
sidebar with its default min-width: 9rem. */
|
|
||||||
.diary-cal-nav { position: relative; }
|
|
||||||
.diary-cal-nav .diary-cal-drop { position: static; }
|
|
||||||
.diary-cal-nav .dropdown-menu { left: 0; right: 0; min-width: 0; }
|
|
||||||
.diary-cal-heading { color: var(--link); }
|
|
||||||
.diary-cal-heading:hover { color: var(--link-hover); }
|
|
||||||
.diary-cal-grid {
|
.diary-cal-grid {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
|||||||
@@ -343,8 +343,8 @@ type calYear struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calMonthGrid carries everything the template needs to render one month's
|
// calMonthGrid carries everything the template needs to render one month's
|
||||||
// grid plus the dropdown / heading entry that targets it. The calendar
|
// grid plus the caption that links to it. The calendar widget renders all 12
|
||||||
// widget ships all 12 in the initial HTML; JS swaps which one is visible.
|
// stacked vertically; JS centers the current month in the rail on load.
|
||||||
type calMonthGrid struct {
|
type calMonthGrid struct {
|
||||||
Num int
|
Num int
|
||||||
Name string
|
Name string
|
||||||
@@ -355,9 +355,7 @@ type calMonthGrid struct {
|
|||||||
type calendarData struct {
|
type calendarData struct {
|
||||||
DisplayYear int
|
DisplayYear int
|
||||||
DisplayMonth int
|
DisplayMonth int
|
||||||
DisplayMonthName string // pre-resolved so the template doesn't need arithmetic
|
|
||||||
DiaryURL string
|
DiaryURL string
|
||||||
YearURL string
|
|
||||||
Months []calMonthGrid
|
Months []calMonthGrid
|
||||||
Years []calYear
|
Years []calYear
|
||||||
}
|
}
|
||||||
@@ -491,9 +489,7 @@ func computeCalendarWidget(diaryRootFS, diaryRootURL, fsPath string, depth int)
|
|||||||
data := calendarData{
|
data := calendarData{
|
||||||
DisplayYear: displayYear,
|
DisplayYear: displayYear,
|
||||||
DisplayMonth: displayMonth,
|
DisplayMonth: displayMonth,
|
||||||
DisplayMonthName: months[displayMonth-1].Name,
|
|
||||||
DiaryURL: diaryRootURL,
|
DiaryURL: diaryRootURL,
|
||||||
YearURL: yearURL,
|
|
||||||
Months: months,
|
Months: months,
|
||||||
Years: years,
|
Years: years,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user