pandorga 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/_includes/page/timeline-section.html +228 -29
- data/_layouts/shell.html +1 -1
- data/assets/css/base.css +174 -116
- data/assets/css/ledger/bibliography.css +15 -10
- data/assets/css/ledger/chrome.css +3 -12
- data/assets/css/ledger/cv.css +21 -0
- data/assets/css/ledger/detail.css +29 -15
- data/assets/css/ledger/home.css +6 -2
- data/assets/css/ledger/sources.css +27 -12
- data/assets/css/ledger/writing.css +10 -15
- data/lib/pandorga/commands/new.rb +1 -1
- data/lib/pandorga/version.rb +1 -1
- data/scripts/test/test-highlighter-pills.rb +306 -0
- data/scripts/test/test-shell-a11y.rb +38 -0
- data/scripts/test/test-theme-contrast.rb +91 -0
- data/scripts/test/test-timeline-pan.mjs +147 -0
- data/scripts/test/test-timeline-pan.rb +116 -0
- data/scripts/validate.sh +7 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9f6585d9644f2c5715b1c18088443f0a17d57f65783b0805899ad2882cc57643
|
|
4
|
+
data.tar.gz: f749368069fe9166d3f483292abed8f8da5b32b0c5f7c1da0b2e798241f859ed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 81fff53869d080e555aa8cb77e19c8d8882da7855d23786ec01d255ae0e0d47c9b357f26fba11d8ca663dd697778fe7d8f3315bbff59ecdbd64820e90b4cc385
|
|
7
|
+
data.tar.gz: dba781ffd7ee1879bdd6676d45117a72b3dbdc8582b9c76cf45e04b9757889d36a0345282226602a7d2350398e7eb2b4089b0d7468d0c81185e92d3983cfec3c
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.14.0] — 2026-10-20
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Pills, tags, facets, filters, and buttons use a borderless felt-pen highlighter wash with deterministic nth-child geometry variants, quiet and strong mark strengths, solid fill on hover, and section-accented active rail links (PLT-AC-46).
|
|
10
|
+
- The CV timeline pans in time: drag the chart, use the ‹ Today › controls, or focus it and use the arrow keys, Page Up/Down, Home and End. Zoom, resize and lane toggles keep the date at the center in view. Selecting a period now takes Shift+drag (a plain drag pans) (PLT-AC-47).
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- The CV timeline no longer handles an input twice when the inline placeholder boots before the timeline data loads; zoom buttons and resize were affected before this change (PLT-AC-47).
|
|
15
|
+
|
|
5
16
|
## [1.13.0] — 2026-10-19
|
|
6
17
|
|
|
7
18
|
### Added
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
</ul>
|
|
22
22
|
</div>
|
|
23
23
|
|
|
24
|
+
<div class="cv-timeline-control-group">
|
|
25
|
+
<p class="cv-timeline-hint font-body text-xs text-on-surface-variant">Shift+drag to select a period</p>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
24
28
|
<div class="cv-timeline-control-group" id="timeline-selection-panel" hidden>
|
|
25
29
|
<h3 class="cv-timeline-control-title card-meta">Selected period</h3>
|
|
26
30
|
<p id="timeline-selection-range" class="cv-timeline-range code-technical"></p>
|
|
@@ -58,9 +62,12 @@
|
|
|
58
62
|
</div>
|
|
59
63
|
|
|
60
64
|
<div class="cv-timeline-canvas">
|
|
61
|
-
<div id="timeline-chart-wrapper" class="applet-canvas relative w-full overflow-x-auto">
|
|
65
|
+
<div id="timeline-chart-wrapper" class="applet-canvas relative w-full overflow-x-auto" tabindex="0" role="region" aria-label="Career timeline, use arrow keys to move in time">
|
|
62
66
|
<div id="timeline-chart" class="relative"></div>
|
|
63
67
|
<div id="timeline-zoom-controls" class="timeline-applet-control cv-timeline-zoom sticky left-0 z-10 flex items-center gap-2 border px-2 py-1.5 w-fit ml-2 mt-4 mb-4 pointer-events-auto">
|
|
68
|
+
<button type="button" id="timeline-pan-prev" class="timeline-zoom-btn timeline-applet-control font-label text-sm leading-none w-8 h-8 border text-on-surface-variant hover:border-primary hover:text-primary transition-colors" aria-label="Pan left">‹</button>
|
|
69
|
+
<button type="button" id="timeline-pan-today" class="timeline-zoom-btn timeline-applet-control font-label text-sm leading-none h-8 px-2 border text-on-surface-variant hover:border-primary hover:text-primary transition-colors" aria-label="Scroll to today">Today</button>
|
|
70
|
+
<button type="button" id="timeline-pan-next" class="timeline-zoom-btn timeline-applet-control font-label text-sm leading-none w-8 h-8 border text-on-surface-variant hover:border-primary hover:text-primary transition-colors" aria-label="Pan right">›</button>
|
|
64
71
|
<button type="button" id="timeline-zoom-out" class="timeline-zoom-btn timeline-applet-control font-label text-sm leading-none w-8 h-8 border text-on-surface-variant hover:border-primary hover:text-primary transition-colors" aria-label="Zoom out">−</button>
|
|
65
72
|
<span id="timeline-zoom-label" class="cv-timeline-zoom-label code-technical min-w-[3.5rem] text-center">2 yr</span>
|
|
66
73
|
<button type="button" id="timeline-zoom-in" class="timeline-zoom-btn timeline-applet-control font-label text-sm leading-none w-8 h-8 border text-on-surface-variant hover:border-primary hover:text-primary transition-colors" aria-label="Zoom in">+</button>
|
|
@@ -182,6 +189,13 @@
|
|
|
182
189
|
var el = document.getElementById('timeline-data');
|
|
183
190
|
|
|
184
191
|
function bootTimeline(payload) {
|
|
192
|
+
/* The inline stub can boot before the runtime JSON arrives, and the JSON
|
|
193
|
+
then boots again. Abort the earlier boot's listeners on persistent
|
|
194
|
+
elements so each input is handled once, by the current data. */
|
|
195
|
+
if (bootTimeline.listeners) bootTimeline.listeners.abort();
|
|
196
|
+
var listeners = new AbortController();
|
|
197
|
+
bootTimeline.listeners = listeners;
|
|
198
|
+
var bootScope = { signal: listeners.signal };
|
|
185
199
|
var meta = payload.meta || {};
|
|
186
200
|
var events = payload.events || [];
|
|
187
201
|
var buckets = Array.isArray(payload.writing_buckets) ? payload.writing_buckets : [];
|
|
@@ -255,7 +269,25 @@
|
|
|
255
269
|
var zoomLabel = document.getElementById('timeline-zoom-label');
|
|
256
270
|
var selectionLayer = null;
|
|
257
271
|
var selectionBand = null;
|
|
258
|
-
var
|
|
272
|
+
var registeredTracks = new Set();
|
|
273
|
+
var isSelecting = false;
|
|
274
|
+
var isPanCandidate = false;
|
|
275
|
+
var isPanning = false;
|
|
276
|
+
var pointerId = null;
|
|
277
|
+
var anchorMs = 0;
|
|
278
|
+
var startX = 0;
|
|
279
|
+
var startScroll = 0;
|
|
280
|
+
|
|
281
|
+
function panTarget(scrollLeft, visibleW, maxScroll, step) {
|
|
282
|
+
// step is a signed fraction of the visible width (e.g. 0.1, -0.9)
|
|
283
|
+
return Math.round(Math.min(maxScroll, Math.max(0, scrollLeft + step * visibleW)));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function centerPreservingScroll(centerMs, xPosMs, visibleW, maxScroll) {
|
|
287
|
+
// xPosMs maps a timestamp to an x pixel within the scroll content
|
|
288
|
+
var target = xPosMs(centerMs) - visibleW / 2;
|
|
289
|
+
return Math.round(Math.min(maxScroll, Math.max(0, target)));
|
|
290
|
+
}
|
|
259
291
|
|
|
260
292
|
function parseDate(s) {
|
|
261
293
|
var p = s.split('-');
|
|
@@ -287,12 +319,14 @@
|
|
|
287
319
|
var maxYear = new Date(maxT).getFullYear();
|
|
288
320
|
var rangeMs = maxT - minT || MS_DAY;
|
|
289
321
|
var chartW = 720;
|
|
322
|
+
var renderedClientW = 0;
|
|
290
323
|
|
|
291
324
|
function visibleChartWidth() {
|
|
292
325
|
return Math.max(480, (wrapper.clientWidth || 720) - LABEL_W);
|
|
293
326
|
}
|
|
294
327
|
|
|
295
328
|
function updateChartWidth() {
|
|
329
|
+
renderedClientW = wrapper.clientWidth;
|
|
296
330
|
var visibleW = visibleChartWidth();
|
|
297
331
|
var maxZoomYears = Math.max(MIN_ZOOM_YEARS, rangeMs / MS_YEAR);
|
|
298
332
|
if (zoomYears > maxZoomYears) zoomYears = maxZoomYears;
|
|
@@ -311,13 +345,26 @@
|
|
|
311
345
|
if (zoomLabel) zoomLabel.textContent = formatZoomLabel();
|
|
312
346
|
}
|
|
313
347
|
|
|
348
|
+
function centerTimeMs() {
|
|
349
|
+
/* Use the width the chart was last rendered at: on resize the wrapper
|
|
350
|
+
is already at its new width while chartW still maps the old one. */
|
|
351
|
+
var x = wrapper.scrollLeft + (renderedClientW || wrapper.clientWidth) / 2;
|
|
352
|
+
return minT + ((x - LABEL_W) / chartW) * rangeMs;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function renderKeepingCenter() {
|
|
356
|
+
var c = centerTimeMs();
|
|
357
|
+
render();
|
|
358
|
+
wrapper.scrollLeft = centerPreservingScroll(c, xPosMs, wrapper.clientWidth, Math.max(0, container.offsetWidth - wrapper.clientWidth));
|
|
359
|
+
if (typeof updatePanButtons === 'function') updatePanButtons();
|
|
360
|
+
}
|
|
361
|
+
|
|
314
362
|
function changeZoom(direction) {
|
|
315
363
|
var maxZoomYears = Math.max(MIN_ZOOM_YEARS, rangeMs / MS_YEAR);
|
|
316
364
|
var factor = direction > 0 ? 0.75 : 1.33;
|
|
317
365
|
zoomYears = Math.max(MIN_ZOOM_YEARS, Math.min(maxZoomYears, zoomYears * factor));
|
|
318
366
|
updateZoomLabel();
|
|
319
|
-
|
|
320
|
-
scrollToToday();
|
|
367
|
+
renderKeepingCenter();
|
|
321
368
|
}
|
|
322
369
|
|
|
323
370
|
function scrollToToday() {
|
|
@@ -606,23 +653,82 @@
|
|
|
606
653
|
}
|
|
607
654
|
|
|
608
655
|
function setupSelectionDrag(track) {
|
|
609
|
-
|
|
610
|
-
if (e.button !== 0 || e.target !== track) return;
|
|
611
|
-
dragState.active = true;
|
|
612
|
-
dragState.anchorMs = timeFromClientX(e.clientX);
|
|
613
|
-
setSelection(dragState.anchorMs, dragState.anchorMs);
|
|
614
|
-
e.preventDefault();
|
|
615
|
-
});
|
|
656
|
+
registeredTracks.add(track);
|
|
616
657
|
}
|
|
617
658
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
659
|
+
if (wrapper) {
|
|
660
|
+
wrapper.addEventListener('pointerdown', function (e) {
|
|
661
|
+
if (e.button !== 0) return;
|
|
662
|
+
if (e.pointerType === 'touch') return;
|
|
663
|
+
|
|
664
|
+
if (e.shiftKey && registeredTracks.has(e.target)) {
|
|
665
|
+
isSelecting = true;
|
|
666
|
+
pointerId = e.pointerId;
|
|
667
|
+
anchorMs = timeFromClientX(e.clientX);
|
|
668
|
+
setSelection(anchorMs, anchorMs);
|
|
669
|
+
if (wrapper.setPointerCapture) {
|
|
670
|
+
try { wrapper.setPointerCapture(e.pointerId); } catch (err) {}
|
|
671
|
+
}
|
|
672
|
+
e.preventDefault();
|
|
673
|
+
} else {
|
|
674
|
+
isPanCandidate = true;
|
|
675
|
+
isPanning = false;
|
|
676
|
+
pointerId = e.pointerId;
|
|
677
|
+
startX = e.clientX;
|
|
678
|
+
startScroll = wrapper.scrollLeft;
|
|
679
|
+
}
|
|
680
|
+
}, bootScope);
|
|
681
|
+
|
|
682
|
+
wrapper.addEventListener('pointermove', function (e) {
|
|
683
|
+
if (isSelecting) {
|
|
684
|
+
setSelection(anchorMs, timeFromClientX(e.clientX));
|
|
685
|
+
} else if (isPanCandidate) {
|
|
686
|
+
var dx = e.clientX - startX;
|
|
687
|
+
if (!isPanning && Math.abs(dx) >= 4) {
|
|
688
|
+
isPanning = true;
|
|
689
|
+
if (wrapper.setPointerCapture) {
|
|
690
|
+
try { wrapper.setPointerCapture(e.pointerId); } catch (err) {}
|
|
691
|
+
}
|
|
692
|
+
wrapper.classList.add('is-dragging');
|
|
693
|
+
hideTip();
|
|
694
|
+
}
|
|
695
|
+
if (isPanning) {
|
|
696
|
+
wrapper.scrollLeft = startScroll - dx;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}, bootScope);
|
|
622
700
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
701
|
+
var endPointerDrag = function () {
|
|
702
|
+
if (!isSelecting && !isPanCandidate) return;
|
|
703
|
+
|
|
704
|
+
if (pointerId !== null && wrapper.hasPointerCapture && wrapper.hasPointerCapture(pointerId)) {
|
|
705
|
+
try { wrapper.releasePointerCapture(pointerId); } catch (err) {}
|
|
706
|
+
}
|
|
707
|
+
wrapper.classList.remove('is-dragging');
|
|
708
|
+
|
|
709
|
+
var panned = isPanning;
|
|
710
|
+
|
|
711
|
+
isSelecting = false;
|
|
712
|
+
isPanCandidate = false;
|
|
713
|
+
isPanning = false;
|
|
714
|
+
pointerId = null;
|
|
715
|
+
|
|
716
|
+
if (panned) {
|
|
717
|
+
var suppressClick = function (clickEvent) {
|
|
718
|
+
clickEvent.stopPropagation();
|
|
719
|
+
clickEvent.preventDefault();
|
|
720
|
+
window.removeEventListener('click', suppressClick, true);
|
|
721
|
+
};
|
|
722
|
+
window.addEventListener('click', suppressClick, true);
|
|
723
|
+
setTimeout(function () {
|
|
724
|
+
window.removeEventListener('click', suppressClick, true);
|
|
725
|
+
}, 100);
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
wrapper.addEventListener('pointerup', endPointerDrag, bootScope);
|
|
730
|
+
wrapper.addEventListener('pointercancel', endPointerDrag, bootScope);
|
|
731
|
+
}
|
|
626
732
|
|
|
627
733
|
function renderBars(track, items, color, barHeight, ongoingAllowed, laneH, gap) {
|
|
628
734
|
items.forEach(function (ev) {
|
|
@@ -639,6 +745,7 @@
|
|
|
639
745
|
}
|
|
640
746
|
|
|
641
747
|
function render() {
|
|
748
|
+
registeredTracks.clear();
|
|
642
749
|
updateChartWidth();
|
|
643
750
|
container.innerHTML = '';
|
|
644
751
|
barRegistry = [];
|
|
@@ -798,16 +905,16 @@
|
|
|
798
905
|
container.style.height = y + 'px';
|
|
799
906
|
container.style.minHeight = '';
|
|
800
907
|
applySelectionHighlight();
|
|
908
|
+
updatePanButtons();
|
|
801
909
|
}
|
|
802
910
|
|
|
803
911
|
var resizeTimer;
|
|
804
912
|
window.addEventListener('resize', function () {
|
|
805
913
|
clearTimeout(resizeTimer);
|
|
806
914
|
resizeTimer = setTimeout(function () {
|
|
807
|
-
|
|
808
|
-
scrollToToday();
|
|
915
|
+
renderKeepingCenter();
|
|
809
916
|
}, 150);
|
|
810
|
-
});
|
|
917
|
+
}, bootScope);
|
|
811
918
|
|
|
812
919
|
/* The bars carry their colour as an inline style, so a palette swap has to
|
|
813
920
|
redraw them — the CSS variables alone cannot reach an already-painted
|
|
@@ -815,37 +922,129 @@
|
|
|
815
922
|
document.addEventListener('shell-theme-change', function () {
|
|
816
923
|
refreshColors();
|
|
817
924
|
render();
|
|
818
|
-
});
|
|
925
|
+
}, bootScope);
|
|
819
926
|
|
|
820
927
|
document.querySelectorAll('.timeline-lane-toggle').forEach(function (cb) {
|
|
821
928
|
cb.addEventListener('change', function () {
|
|
822
929
|
laneVisible[cb.dataset.lane] = cb.checked;
|
|
823
|
-
|
|
824
|
-
});
|
|
930
|
+
renderKeepingCenter();
|
|
931
|
+
}, bootScope);
|
|
825
932
|
});
|
|
826
933
|
|
|
827
934
|
var expandCb = document.getElementById('timeline-writing-expanded');
|
|
828
935
|
if (expandCb) {
|
|
829
936
|
expandCb.addEventListener('change', function () {
|
|
830
937
|
writingExpanded = expandCb.checked;
|
|
831
|
-
|
|
832
|
-
});
|
|
938
|
+
renderKeepingCenter();
|
|
939
|
+
}, bootScope);
|
|
833
940
|
}
|
|
834
941
|
|
|
835
942
|
if (selectionClear) {
|
|
836
|
-
selectionClear.addEventListener('click', clearSelection);
|
|
943
|
+
selectionClear.addEventListener('click', clearSelection, bootScope);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
function maxScrollLeft() {
|
|
947
|
+
return Math.max(0, container.offsetWidth - wrapper.clientWidth);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
951
|
+
|
|
952
|
+
function scrollBehavior() {
|
|
953
|
+
return reduceMotion && reduceMotion.matches ? 'auto' : 'smooth';
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function panBy(step) {
|
|
957
|
+
wrapper.scrollTo({
|
|
958
|
+
left: panTarget(wrapper.scrollLeft, wrapper.clientWidth, maxScrollLeft(), step),
|
|
959
|
+
behavior: scrollBehavior()
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
var panPrevBtn = document.getElementById('timeline-pan-prev');
|
|
964
|
+
if (panPrevBtn) {
|
|
965
|
+
panPrevBtn.addEventListener('click', function () { panBy(-0.9); }, bootScope);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
var panNextBtn = document.getElementById('timeline-pan-next');
|
|
969
|
+
if (panNextBtn) {
|
|
970
|
+
panNextBtn.addEventListener('click', function () { panBy(0.9); }, bootScope);
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
var panTodayBtn = document.getElementById('timeline-pan-today');
|
|
974
|
+
if (panTodayBtn) {
|
|
975
|
+
panTodayBtn.addEventListener('click', function () {
|
|
976
|
+
var todayX = xPosMs(todayT);
|
|
977
|
+
var target = Math.max(0, Math.min(maxScrollLeft(), todayX - wrapper.clientWidth + 24));
|
|
978
|
+
wrapper.scrollTo({ left: target, behavior: scrollBehavior() });
|
|
979
|
+
}, bootScope);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
function setPanButtonDisabled(btn, disabled) {
|
|
983
|
+
if (!btn) return;
|
|
984
|
+
btn.disabled = disabled;
|
|
985
|
+
btn.setAttribute('aria-disabled', disabled ? 'true' : 'false');
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function updatePanButtons() {
|
|
989
|
+
setPanButtonDisabled(panPrevBtn, wrapper.scrollLeft <= 0);
|
|
990
|
+
setPanButtonDisabled(panNextBtn, wrapper.scrollLeft >= maxScrollLeft() - 1);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
if (wrapper) {
|
|
994
|
+
wrapper.addEventListener('scroll', updatePanButtons, { passive: true, signal: listeners.signal });
|
|
995
|
+
wrapper.addEventListener('keydown', function (e) {
|
|
996
|
+
if (e.target !== wrapper || e.ctrlKey || e.metaKey || e.altKey) return;
|
|
997
|
+
var handled = true;
|
|
998
|
+
switch (e.key) {
|
|
999
|
+
case 'ArrowLeft':
|
|
1000
|
+
panBy(e.shiftKey ? -0.9 : -0.1);
|
|
1001
|
+
break;
|
|
1002
|
+
case 'ArrowRight':
|
|
1003
|
+
panBy(e.shiftKey ? 0.9 : 0.1);
|
|
1004
|
+
break;
|
|
1005
|
+
case 'PageUp':
|
|
1006
|
+
panBy(-0.9);
|
|
1007
|
+
break;
|
|
1008
|
+
case 'PageDown':
|
|
1009
|
+
panBy(0.9);
|
|
1010
|
+
break;
|
|
1011
|
+
case 'Home':
|
|
1012
|
+
wrapper.scrollTo({ left: 0, behavior: scrollBehavior() });
|
|
1013
|
+
break;
|
|
1014
|
+
case 'End':
|
|
1015
|
+
var todayX = xPosMs(todayT);
|
|
1016
|
+
var target = Math.max(0, Math.min(maxScrollLeft(), todayX - wrapper.clientWidth + 24));
|
|
1017
|
+
wrapper.scrollTo({ left: target, behavior: scrollBehavior() });
|
|
1018
|
+
break;
|
|
1019
|
+
case '+':
|
|
1020
|
+
case '=':
|
|
1021
|
+
changeZoom(1);
|
|
1022
|
+
break;
|
|
1023
|
+
case '-':
|
|
1024
|
+
case '−':
|
|
1025
|
+
changeZoom(-1);
|
|
1026
|
+
break;
|
|
1027
|
+
default:
|
|
1028
|
+
handled = false;
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
if (handled) {
|
|
1032
|
+
e.preventDefault();
|
|
1033
|
+
}
|
|
1034
|
+
}, bootScope);
|
|
837
1035
|
}
|
|
838
1036
|
|
|
839
1037
|
if (zoomInBtn) {
|
|
840
|
-
zoomInBtn.addEventListener('click', function () { changeZoom(1); });
|
|
1038
|
+
zoomInBtn.addEventListener('click', function () { changeZoom(1); }, bootScope);
|
|
841
1039
|
}
|
|
842
1040
|
if (zoomOutBtn) {
|
|
843
|
-
zoomOutBtn.addEventListener('click', function () { changeZoom(-1); });
|
|
1041
|
+
zoomOutBtn.addEventListener('click', function () { changeZoom(-1); }, bootScope);
|
|
844
1042
|
}
|
|
845
1043
|
|
|
846
1044
|
updateZoomLabel();
|
|
847
1045
|
render();
|
|
848
1046
|
scrollToToday();
|
|
1047
|
+
updatePanButtons();
|
|
849
1048
|
}
|
|
850
1049
|
|
|
851
1050
|
function loadTimeline() {
|
data/_layouts/shell.html
CHANGED
|
@@ -240,7 +240,7 @@
|
|
|
240
240
|
{%- for _item in _group.pages -%}
|
|
241
241
|
{%- assign _key = _item.key -%}
|
|
242
242
|
{%- assign _p = _all_pages | where: "key", _key | first -%}
|
|
243
|
-
<a href="{{ _p.url }}" class="site-rail-link{% if nav_active == _key %} is-active{% endif %}"
|
|
243
|
+
<a href="{{ _p.url }}" class="site-rail-link{% if nav_active == _key %} is-active{% if _p.accent and _p.accent != 'blue' %} page-accent--{{ _p.accent }}{% endif %}{% endif %}"
|
|
244
244
|
{% if nav_active == _key %}aria-current="page"{% endif %}>{{ _p.title }}</a>
|
|
245
245
|
{%- endfor -%}
|
|
246
246
|
{%- endfor -%}
|