fix(positioning): prevent canvas collapse on type/range toggle
- Lock #positioning-canvas min-height to current offsetHeight before each HTMX swap, release it in htmx:afterSwap — prevents flash-to-zero during Chart.js initialization in the new content - Add CSS min-height:200px fallback on all canvas containers so they never fully collapse even before JS runs - Extract _swapCanvas() helper to deduplicate setRange/setType logic Root cause of visual collapse: cot_positioning_combined table missing (needs sqlmesh plan prod + export_serving to materialize). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -72,24 +72,29 @@ function _positioningUrl() {
|
||||
return POSITIONING_URL + '?range=' + currentRange + '&type=' + currentType;
|
||||
}
|
||||
|
||||
function _swapCanvas(url) {
|
||||
var el = document.getElementById('positioning-canvas');
|
||||
el.style.minHeight = el.offsetHeight + 'px';
|
||||
el.classList.add('canvas-loading');
|
||||
htmx.ajax('GET', url, { target: '#positioning-canvas', swap: 'innerHTML' });
|
||||
}
|
||||
|
||||
function setRange(val) {
|
||||
currentRange = val;
|
||||
var url = _positioningUrl();
|
||||
window.history.pushState({}, '', url);
|
||||
document.getElementById('positioning-canvas').classList.add('canvas-loading');
|
||||
htmx.ajax('GET', url, { target: '#positioning-canvas', swap: 'innerHTML' });
|
||||
_swapCanvas(url);
|
||||
}
|
||||
|
||||
function setType(val) {
|
||||
currentType = val;
|
||||
var url = _positioningUrl();
|
||||
window.history.pushState({}, '', url);
|
||||
document.getElementById('positioning-canvas').classList.add('canvas-loading');
|
||||
htmx.ajax('GET', url, { target: '#positioning-canvas', swap: 'innerHTML' });
|
||||
// Sync type pill active state immediately (canvas swap will also re-sync)
|
||||
document.querySelectorAll('#type-pills .filter-pill').forEach(function (btn) {
|
||||
btn.classList.toggle('active', btn.textContent.trim() === (val === 'combined' ? 'F+O Combined' : 'Futures'));
|
||||
});
|
||||
_swapCanvas(url);
|
||||
}
|
||||
|
||||
// MA toggles: client-side only — update Chart.js dataset visibility
|
||||
@@ -103,7 +108,9 @@ function toggleMA(key) {
|
||||
|
||||
document.addEventListener('htmx:afterSwap', function (e) {
|
||||
if (e.detail.target.id === 'positioning-canvas') {
|
||||
document.getElementById('positioning-canvas').classList.remove('canvas-loading');
|
||||
var el = document.getElementById('positioning-canvas');
|
||||
el.classList.remove('canvas-loading');
|
||||
el.style.minHeight = ''; // release height lock
|
||||
requestAnimationFrame(function() {
|
||||
['priceChart', 'cotChart'].forEach(function(id) {
|
||||
var c = Chart.getChart(id);
|
||||
|
||||
@@ -736,6 +736,13 @@
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
|
||||
/* Prevent canvas from collapsing to 0 height during HTMX swaps.
|
||||
Chart.js needs the container to have non-zero height before it can
|
||||
measure the aspect ratio. min-height is locked in JS before each swap. */
|
||||
#positioning-canvas, #supply-canvas, #warehouse-canvas, #weather-canvas {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
/* Freshness badges */
|
||||
.freshness-bar {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user