Diff -- /var/www/vhosts/3dshawn.com/site1/assets/js/ds_charts.js
Diff
/var/www/vhosts/3dshawn.com/site1/assets/js/ds_charts.js
added on local at 2026-07-10 23:21:49
Added
+64
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to e38dd7f34efa
to e38dd7f34efa
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.| 1 | /* | |
| 2 | * DriftSense -- chart interactivity. | |
| 3 | * | |
| 4 | * Attaches a floating tooltip to every .ds-timeline SVG on the page. | |
| 5 | * The chart itself emits per-day <g class="ds-day"> with: | |
| 6 | * data-key = ISO date (drilldown link basis) | |
| 7 | * data-label = display label ("Jul 10") | |
| 8 | * data-file, data-schema = counts | |
| 9 | * data-link-file, data-link-schema = drilldown URLs | |
| 10 | * | |
| 11 | * Click on a bar segment is handled by the SVG <a> wrappers -- no JS | |
| 12 | * needed for navigation. This script only handles the hover tooltip. | |
| 13 | */ | |
| 14 | (function () { | |
| 15 | 'use strict'; | |
| 16 | ||
| 17 | var tooltip; | |
| 18 | function tip() { | |
| 19 | if (tooltip) return tooltip; | |
| 20 | tooltip = document.createElement('div'); | |
| 21 | tooltip.className = 'chart-tooltip'; | |
| 22 | tooltip.innerHTML = '' | |
| 23 | + '<div class="ct-date"></div>' | |
| 24 | + '<div class="ct-row"><span class="ct-swatch" style="background:#14b8a6"></span>' | |
| 25 | + '<span class="ct-file">0</span> file changes</div>' | |
| 26 | + '<div class="ct-row"><span class="ct-swatch" style="background:#f59e0b"></span>' | |
| 27 | + '<span class="ct-schema">0</span> schema changes</div>' | |
| 28 | + '<div class="ct-hint">Click to drill in</div>'; | |
| 29 | document.body.appendChild(tooltip); | |
| 30 | return tooltip; | |
| 31 | } | |
| 32 | ||
| 33 | function attach(svg) { | |
| 34 | if (svg.__dsAttached) return; svg.__dsAttached = true; | |
| 35 | svg.querySelectorAll('g.ds-day').forEach(function (g) { | |
| 36 | g.addEventListener('mouseenter', function (e) { | |
| 37 | var t = tip(); | |
| 38 | t.querySelector('.ct-date').textContent = g.getAttribute('data-label') || ''; | |
| 39 | t.querySelector('.ct-file').textContent = g.getAttribute('data-file') || '0'; | |
| 40 | t.querySelector('.ct-schema').textContent = g.getAttribute('data-schema') || '0'; | |
| 41 | var hint = t.querySelector('.ct-hint'); | |
| 42 | var fv = parseInt(g.getAttribute('data-file') || '0', 10); | |
| 43 | var sv = parseInt(g.getAttribute('data-schema') || '0', 10); | |
| 44 | hint.style.display = (fv + sv) > 0 ? '' : 'none'; | |
| 45 | t.classList.add('on'); | |
| 46 | }); | |
| 47 | g.addEventListener('mousemove', function (e) { | |
| 48 | var t = tip(); | |
| 49 | t.style.left = e.clientX + 'px'; | |
| 50 | t.style.top = e.clientY + 'px'; | |
| 51 | }); | |
| 52 | g.addEventListener('mouseleave', function () { | |
| 53 | if (tooltip) tooltip.classList.remove('on'); | |
| 54 | }); | |
| 55 | }); | |
| 56 | } | |
| 57 | ||
| 58 | function init() { | |
| 59 | document.querySelectorAll('svg.ds-timeline').forEach(attach); | |
| 60 | } | |
| 61 | if (document.readyState === 'loading') { | |
| 62 | document.addEventListener('DOMContentLoaded', init); | |
| 63 | } else { init(); } | |
| 64 | })(); |