-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsql-query-demo.html
More file actions
138 lines (128 loc) · 7.51 KB
/
Copy pathsql-query-demo.html
File metadata and controls
138 lines (128 loc) · 7.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SQL Results · Cerious-Scroll</title>
<link rel="stylesheet" href="shared-styles.css?v=20260922">
</head>
<body>
<header class="topbar" data-auto-topbar></header>
<main class="content">
<div class="demo-page sql-page">
<div class="demo-page__header">
<h1><span data-demo-icon="sql"></span>SQL Results</h1>
<p>200,000 rows returned: click a row to select it.</p>
</div>
<pre class="sql-editor"><span class="kw">SELECT</span> id, customer, product, amount, status, created_at
<span class="kw">FROM</span> orders
<span class="kw">WHERE</span> amount > 0
<span class="kw">ORDER BY</span> created_at <span class="kw">DESC</span>;</pre>
<div class="demo-toolbar">
<span class="stat">✓ <strong>200,000</strong> rows · 0.024s</span>
<span class="spacer"></span>
<span class="stat">Selected row: <strong id="selectedLabel">none</strong></span>
</div>
<div class="demo-scroll sql-scroll" id="scroll">
<div class="sql-h-scroll" id="hscroll">
<div class="sql-head">
<div class="sql-head__cell">id</div>
<div class="sql-head__cell">customer</div>
<div class="sql-head__cell">product</div>
<div class="sql-head__cell">amount</div>
<div class="sql-head__cell">status</div>
<div class="sql-head__cell">date</div>
</div>
<div data-cerious-scroll-content class="sql-scroll-content"></div>
</div>
</div>
</div>
</main>
<script src="dist/cerious-scroll.bundle.js?v=20260922"></script>
<script src="demo-icons.js?v=20260922"></script>
<script src="demo-docs.js?v=20260922"></script>
<script src="demo-bootstrap.js?v=20260922"></script>
<script>
(function () {
const SQL_TOTAL = 200000;
const CUSTOMERS = ['Acme Co', 'Globex', 'Initech', 'Umbrella', 'Stark Ind', 'Wayne Ent', 'Soylent', 'Hooli', 'Pied Piper', 'Wonka'];
const PRODUCTS = ['Enterprise Plan', 'Pro Seat', 'API Credits', 'Storage 1TB', 'Support Pack', 'Add-on: SSO', 'Training', 'Migration'];
const STATUSES = ['paid', 'pending', 'refunded', 'failed'];
const { hash, randInt, pick } = window.demoUtils;
function makeResult(index) {
const id = 100000 + index;
const amount = Math.round((hash(index, 1) * 4800 + 19) * 100) / 100;
const daysAgo = randInt(index, 0, 720, 2);
const date = new Date(Date.UTC(2026, 0, 1) - daysAgo * 86400000).toISOString().slice(0, 10);
return {
id,
customer: pick(CUSTOMERS, index, 3),
product: pick(PRODUCTS, index, 4),
amount,
status: STATUSES[index % STATUSES.length],
date,
};
}
function escapeHtml(s) {
return s.replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
}
let selected = null;
const host = document.getElementById('scroll');
const hScroll = document.getElementById('hscroll');
function render(i, container) {
const r = makeResult(i);
const row = document.createElement('div');
row.className = 'sql-row' + (selected === i ? ' selected' : '');
row.dataset.index = i;
row.innerHTML =
'<div class="sql-cell id">' + r.id + '</div>' +
'<div class="sql-cell">' + escapeHtml(r.customer) + '</div>' +
'<div class="sql-cell">' + escapeHtml(r.product) + '</div>' +
'<div class="sql-cell num">$' + r.amount.toLocaleString() + '</div>' +
'<div class="sql-cell"><span class="sql-badge sql-' + r.status + '">' + r.status + '</span></div>' +
'<div class="sql-cell">' + r.date + '</div>';
container.appendChild(row);
}
const demo = window.mountDemo({
host: host,
total: SQL_TOTAL,
render: render,
options: {
touch: { enabled: true, getHorizontalScrollTarget: () => hScroll },
wheel: { enabled: true, getHorizontalScrollTarget: () => hScroll },
},
});
host.addEventListener('click', (e) => {
const row = e.target.closest('.sql-row');
if (!row) return;
const i = parseInt(row.dataset.index, 10);
selected = i;
document.getElementById('selectedLabel').textContent = makeResult(i).id;
demo.refresh();
});
})();
</script>
<!-- "How to build this": the options this demo exists to show,
pulled out of the page source and put next to the demo. -->
<script>
// Deferred on some pages, inline on others: either way this runs
// before demo-docs.js has executed unless we wait for it.
(function (config) {
function mount() { window.demoDocs(config); }
if (window.demoDocs) mount();
else document.addEventListener('DOMContentLoaded', mount);
}({
"feature": "Result sets with selection and stable identity",
"intro": "A result grid is a plain vertical scroller over an array of rows, with one subtlety worth stating: selection must be keyed on something stable. Re-run the query, sort a column, or filter, and index 40 is a different row than it was, so a selection stored as a set of indices silently selects the wrong things. Store row identity instead and the selection survives anything you do to the view.",
"code": "\n const selected = new Set(); // row IDS, never row indices\n\n const scroller = new CeriousScroll(host, result.rows.length, {\n render: function (index, container) {\n const row = result.rows[index];\n container.textContent = '';\n const el = buildResultRow(row, result.columns);\n el.dataset.rowId = row.id;\n el.classList.toggle('is-selected', selected.has(row.id));\n container.appendChild(el);\n }\n });\n\n host.addEventListener('click', function (e) {\n const el = e.target.closest('[data-row-id]');\n if (!el) return;\n const id = el.dataset.rowId;\n selected.has(id) ? selected.delete(id) : selected.add(id);\n scroller.refresh();\n });\n ",
"notes": [
"Key selection on row identity. Indices are a property of the current view, not of the data.",
"A new result set means a new length and a full repaint: <code>updateTotalElements()</code> then <code>refresh()</code>.",
"Column widths should be fixed once per result set, not measured from the mounted rows.",
"For very wide result sets, render only the columns you want visible and let the user choose the rest; the engine virtualizes rows, not columns."
],
"docs": "https://github.com/ceriousdevtech/cerious-scroll/blob/main/docs/IMPLEMENTATION_GUIDE.md"
}));
</script>
</body>
</html>