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;
|
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) {
|
function setRange(val) {
|
||||||
currentRange = val;
|
currentRange = val;
|
||||||
var url = _positioningUrl();
|
var url = _positioningUrl();
|
||||||
window.history.pushState({}, '', url);
|
window.history.pushState({}, '', url);
|
||||||
document.getElementById('positioning-canvas').classList.add('canvas-loading');
|
_swapCanvas(url);
|
||||||
htmx.ajax('GET', url, { target: '#positioning-canvas', swap: 'innerHTML' });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setType(val) {
|
function setType(val) {
|
||||||
currentType = val;
|
currentType = val;
|
||||||
var url = _positioningUrl();
|
var url = _positioningUrl();
|
||||||
window.history.pushState({}, '', url);
|
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)
|
// Sync type pill active state immediately (canvas swap will also re-sync)
|
||||||
document.querySelectorAll('#type-pills .filter-pill').forEach(function (btn) {
|
document.querySelectorAll('#type-pills .filter-pill').forEach(function (btn) {
|
||||||
btn.classList.toggle('active', btn.textContent.trim() === (val === 'combined' ? 'F+O Combined' : 'Futures'));
|
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
|
// MA toggles: client-side only — update Chart.js dataset visibility
|
||||||
@@ -103,7 +108,9 @@ function toggleMA(key) {
|
|||||||
|
|
||||||
document.addEventListener('htmx:afterSwap', function (e) {
|
document.addEventListener('htmx:afterSwap', function (e) {
|
||||||
if (e.detail.target.id === 'positioning-canvas') {
|
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() {
|
requestAnimationFrame(function() {
|
||||||
['priceChart', 'cotChart'].forEach(function(id) {
|
['priceChart', 'cotChart'].forEach(function(id) {
|
||||||
var c = Chart.getChart(id);
|
var c = Chart.getChart(id);
|
||||||
|
|||||||
@@ -736,6 +736,13 @@
|
|||||||
transition: opacity 0.15s;
|
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 badges */
|
||||||
.freshness-bar {
|
.freshness-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user