Skip to content

Commit 2cf61cb

Browse files
committed
filters (just one for now: search)
1 parent 68ae61c commit 2cf61cb

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

docs/summary-table.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const Inputs = ({..._Inputs, table})
4848

4949
function table(data, options = {}) {
5050
if (!data) return data;
51-
const table = _Inputs.table(data, options);
51+
let table = _Inputs.table(data, options);
5252

5353
// Duck typing Arrow table
5454
if (!Array.isArray(data?.schema?.fields)) return container;
@@ -66,16 +66,44 @@ function table(data, options = {}) {
6666
const th = d3.select(container).select("thead").selectAll("th").data([{}, ...fields]);
6767
th.append("div").classed("type", true).html(({type}) => type);
6868
const summaries = th.append("div").classed("summary", true);
69+
70+
const textFields = fields.filter(({type}) => type === "Utf8");
6971
const footer = html`<footer style="width: 100%; height: 1em;">
70-
<div style="position: absolute; left: 0;"><!-- <input type="search" placeholder="Search text fields"> --></div>
72+
${textFields.length ? html`<div style="position: absolute; left: 0;"><input type="search" placeholder="Search text fields" onkeyup=${search} onchange=${search}></div>` : ""}
7173
<div style="position: absolute; right: 0;">${data.numRows.toLocaleString("en-US")} rows</div>
7274
</footer>`;
7375
container.appendChild(footer);
7476

77+
const filters = new Map();
78+
7579
requestAnimationFrame(() => {
7680
for (const s of summaries.filter(({type}) => type)) summary(s);
7781
});
7882
return container;
83+
84+
function refresh() {
85+
const index0 = d3.range(data.length ?? data.numRows);
86+
let index = index0;
87+
for (const [, f] of filters) index = index.filter(f);
88+
table.replaceWith(table = _Inputs.table(index === index0 ? data : take(data, index), options))
89+
}
90+
function take(data, index) {
91+
return Array.from(index, (i) => data.get(i));
92+
}
93+
94+
function search() {
95+
const value = this.value;
96+
filters.delete("search");
97+
if (value) {
98+
try {
99+
const re = new RegExp(`(^|\b)${value}`, "ui");
100+
filters.set("search", (i) => textFields.some(({values}) => re.test(values.get(i))));
101+
} catch(error) {
102+
console.warn(error);
103+
}
104+
}
105+
refresh();
106+
}
79107
}
80108

81109
async function summary(div) {

0 commit comments

Comments
 (0)