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
|
// data that only the cell metadata knows. The listener runs on every draw, so
|
||||||
// it survives scrolling and virtualisation -- a stylesheet cannot, since the
|
// it survives scrolling and virtualisation -- a stylesheet cannot, since the
|
||||||
// DOM cells are recycled across columns as you scroll.
|
// 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() {
|
function applyGroupRules() {
|
||||||
const grid = gridRef.current
|
const grid = gridRef.current
|
||||||
const table = grid?.regular_table
|
const table = grid?.regular_table
|
||||||
@ -967,6 +972,11 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
const body = table.querySelectorAll('tbody td')
|
const body = table.querySelectorAll('tbody td')
|
||||||
// The deepest column path is a leaf; anything shorter is an aggregate of
|
// 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 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
|
let depth = 0
|
||||||
const metas = []
|
const metas = []
|
||||||
for (const td of body) {
|
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 }
|
try { meta = table.getMeta(td) } catch { meta = null }
|
||||||
metas.push([td, meta])
|
metas.push([td, meta])
|
||||||
const path = meta?.column_header
|
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
|
let prevGroup = null
|
||||||
@ -982,7 +992,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
td.classList.remove('pf-group-start', 'pf-subtotal')
|
td.classList.remove('pf-group-start', 'pf-subtotal')
|
||||||
const path = meta?.column_header
|
const path = meta?.column_header
|
||||||
if (!Array.isArray(path) || !path.length) { prevGroup = null; continue }
|
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]
|
const group = named[0]
|
||||||
if (group !== prevGroup) { td.classList.add('pf-group-start'); prevGroup = group }
|
if (group !== prevGroup) { td.classList.add('pf-group-start'); prevGroup = group }
|
||||||
if (named.length < depth) td.classList.add('pf-subtotal')
|
if (named.length < depth) td.classList.add('pf-subtotal')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user