Recognise a subtotal by its zero-width padding
Perspective pads a subtotal's column path to full length rather than shortening it -- ['04 - Forecast', '', 'sales_usd'] -- so testing for an empty string found no subtotals and nothing was tinted. The blank test now strips zero-width spaces and the other invisibles alongside whitespace. The grand total falls out of the same rule, its path being blank at every level above the measure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
54d49ebc75
commit
f9424d9c42
@ -942,6 +942,11 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
// data that only the cell metadata knows. The listener runs on every draw, so
|
||||
// it survives scrolling and virtualisation -- a stylesheet cannot, since the
|
||||
// DOM cells are recycled across columns as you scroll.
|
||||
// Blank for this purpose means "no value at this level", which Perspective
|
||||
// writes as a zero-width space rather than an empty string.
|
||||
const notBlank = (v) =>
|
||||
v != null && String(v).replace(/[\s\u200b-\u200d\ufeff]/g, '') !== ''
|
||||
|
||||
function applyGroupRules() {
|
||||
const grid = gridRef.current
|
||||
const table = grid?.regular_table
|
||||
@ -967,6 +972,11 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
const body = table.querySelectorAll('tbody td')
|
||||
// The deepest column path is a leaf; anything shorter is an aggregate of
|
||||
// the levels below it, which is what makes a subtotal a subtotal.
|
||||
//
|
||||
// The empty levels are not empty strings. Perspective pads a subtotal's
|
||||
// path with zero-width spaces -- ['04 - Forecast', '\u200b', 'sales_usd']
|
||||
// -- so every path is the same length and a naive `!== ''` test finds no
|
||||
// subtotals at all.
|
||||
let depth = 0
|
||||
const metas = []
|
||||
for (const td of body) {
|
||||
@ -974,7 +984,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
try { meta = table.getMeta(td) } catch { meta = null }
|
||||
metas.push([td, meta])
|
||||
const path = meta?.column_header
|
||||
if (Array.isArray(path)) depth = Math.max(depth, path.filter(v => v != null && v !== '').length)
|
||||
if (Array.isArray(path)) depth = Math.max(depth, path.filter(notBlank).length)
|
||||
}
|
||||
|
||||
let prevGroup = null
|
||||
@ -982,7 +992,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
td.classList.remove('pf-group-start', 'pf-subtotal')
|
||||
const path = meta?.column_header
|
||||
if (!Array.isArray(path) || !path.length) { prevGroup = null; continue }
|
||||
const named = path.filter(v => v != null && v !== '')
|
||||
const named = path.filter(notBlank)
|
||||
const group = named[0]
|
||||
if (group !== prevGroup) { td.classList.add('pf-group-start'); prevGroup = group }
|
||||
if (named.length < depth) td.classList.add('pf-subtotal')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user