Skip to content

Commit ad00d26

Browse files
updating the table
1 parent 2102e2c commit ad00d26

File tree

2 files changed

+160
-150
lines changed

2 files changed

+160
-150
lines changed

docs/prepare_summary_tables.py

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import glob
2+
import textwrap
23
from argparse import ArgumentParser
34
from datetime import datetime
45
from pathlib import Path
@@ -53,6 +54,163 @@ def wrap_dataset_name(name: str):
5354
},
5455
}
5556

57+
DATA_TABLE_TEMPLATE = textwrap.dedent(
58+
r"""
59+
<!-- jQuery + DataTables core -->
60+
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
61+
<link rel="stylesheet" href="https://cdn.datatables.net/v/bm/dt-1.13.4/datatables.min.css"/>
62+
<script src="https://cdn.datatables.net/v/bm/dt-1.13.4/datatables.min.js"></script>
63+
64+
<!-- Buttons + SearchPanes (+ Select required by SearchPanes) -->
65+
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.dataTables.min.css">
66+
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
67+
<link rel="stylesheet" href="https://cdn.datatables.net/select/1.7.0/css/select.dataTables.min.css">
68+
<link rel="stylesheet" href="https://cdn.datatables.net/searchpanes/2.3.1/css/searchPanes.dataTables.min.css">
69+
<script src="https://cdn.datatables.net/select/1.7.0/js/dataTables.select.min.js"></script>
70+
<script src="https://cdn.datatables.net/searchpanes/2.3.1/js/dataTables.searchPanes.min.js"></script>
71+
72+
<style>
73+
/* Styling for the Total row (placed in tfoot) */
74+
table.sd-table tfoot td {
75+
font-weight: 600;
76+
border-top: 2px solid rgba(0,0,0,0.2);
77+
background: #f9fafb;
78+
/* Match body cell padding to keep perfect alignment */
79+
padding: 8px 10px !important;
80+
vertical-align: middle;
81+
}
82+
83+
/* Right-align numeric-like columns (2..8) consistently for body & footer */
84+
table.sd-table tbody td:nth-child(n+2),
85+
table.sd-table tfoot td:nth-child(n+2) {
86+
text-align: right;
87+
}
88+
/* Keep first column (Dataset/Total) left-aligned */
89+
table.sd-table tbody td:first-child,
90+
table.sd-table tfoot td:first-child {
91+
text-align: left;
92+
}
93+
</style>
94+
95+
<TABLE_HTML>
96+
97+
<script>
98+
// Helper: robustly extract values for SearchPanes when needed
99+
function tagsArrayFromHtml(html) {
100+
if (html == null) return [];
101+
// If it's numeric or plain text, just return as a single value
102+
if (typeof html === 'number') return [String(html)];
103+
if (typeof html === 'string' && html.indexOf('<') === -1) return [html.trim()];
104+
// Else parse any .tag elements inside HTML
105+
const tmp = document.createElement('div');
106+
tmp.innerHTML = html;
107+
const tags = Array.from(tmp.querySelectorAll('.tag')).map(function(el){
108+
return (el.textContent || '').trim();
109+
});
110+
return tags.length ? tags : [tmp.textContent.trim()];
111+
}
112+
113+
// Helper: parse human-readable sizes like "4.31 GB" into bytes (number)
114+
function parseSizeToBytes(text) {
115+
if (!text) return 0;
116+
const s = String(text).trim();
117+
const m = s.match(/([\d,.]+)\s*(TB|GB|MB|KB|B)/i);
118+
if (!m) return 0;
119+
const value = parseFloat(m[1].replace(/,/g, ''));
120+
const unit = m[2].toUpperCase();
121+
const factor = { B:1, KB:1024, MB:1024**2, GB:1024**3, TB:1024**4 }[unit] || 1;
122+
return value * factor;
123+
}
124+
125+
document.addEventListener('DOMContentLoaded', function () {
126+
const table = document.getElementById('datasets-table');
127+
if (!table || !window.jQuery || !window.jQuery.fn || !window.jQuery.fn.DataTable) {
128+
return;
129+
}
130+
131+
const $table = window.jQuery(table);
132+
if (window.jQuery.fn.DataTable.isDataTable(table)) {
133+
return;
134+
}
135+
136+
// 1) Move the "Total" row into <tfoot> so sorting/filtering never moves it
137+
const $tbody = $table.find('tbody');
138+
const $total = $tbody.find('tr').filter(function(){
139+
return window.jQuery(this).find('td').eq(0).text().trim() === 'Total';
140+
});
141+
if ($total.length) {
142+
let $tfoot = $table.find('tfoot');
143+
if (!$tfoot.length) $tfoot = window.jQuery('<tfoot/>').appendTo($table);
144+
$total.appendTo($tfoot);
145+
}
146+
147+
// 2) Initialize DataTable with SearchPanes button
148+
const FILTER_COLS = [1,2,3,4,5,6];
149+
// Detect the index of the size column by header text
150+
const sizeIdx = (function(){
151+
let idx = -1;
152+
$table.find('thead th').each(function(i){
153+
const t = window.jQuery(this).text().trim().toLowerCase();
154+
if (t === 'size on disk' || t === 'size') idx = i;
155+
});
156+
return idx;
157+
})();
158+
159+
const dataTable = $table.DataTable({
160+
dom: 'Blfrtip',
161+
paging: false,
162+
searching: true,
163+
info: false,
164+
language: {
165+
search: 'Filter dataset:',
166+
searchPanes: { collapse: { 0: 'Filters', _: 'Filters (%d)' } }
167+
},
168+
buttons: [{
169+
extend: 'searchPanes',
170+
text: 'Filters',
171+
config: { cascadePanes: true, viewTotal: true, layout: 'columns-4', initCollapsed: false }
172+
}],
173+
columnDefs: (function(){
174+
const defs = [
175+
{ searchPanes: { show: true }, targets: FILTER_COLS }
176+
];
177+
if (sizeIdx !== -1) {
178+
defs.push({
179+
targets: sizeIdx,
180+
render: function(data, type) {
181+
if (type === 'sort' || type === 'type') {
182+
return parseSizeToBytes(data);
183+
}
184+
return data;
185+
}
186+
});
187+
}
188+
return defs;
189+
})()
190+
});
191+
192+
// 3) UX: click a header to open the relevant filter pane
193+
$table.find('thead th').each(function (i) {
194+
if ([1,2,3,4].indexOf(i) === -1) return;
195+
window.jQuery(this)
196+
.css('cursor','pointer')
197+
.attr('title','Click to filter this column')
198+
.on('click', function () {
199+
dataTable.button('.buttons-searchPanes').trigger();
200+
window.setTimeout(function () {
201+
const idx = [1,2,3,4].indexOf(i);
202+
const $container = window.jQuery(dataTable.searchPanes.container());
203+
const $pane = $container.find('.dtsp-pane').eq(idx);
204+
const $title = $pane.find('.dtsp-title');
205+
if ($title.length) $title.trigger('click');
206+
}, 0);
207+
});
208+
});
209+
});
210+
</script>
211+
"""
212+
)
213+
56214

57215
def _tag_normalizer(kind: str):
58216
canonical = {k.lower(): v for k, v in DATASET_CANONICAL_MAP.get(kind, {}).items()}
@@ -226,8 +384,9 @@ def main(source_dir: str, target_dir: str):
226384
escape=False,
227385
table_id="datasets-table",
228386
)
387+
html_table = DATA_TABLE_TEMPLATE.replace("<TABLE_HTML>", html_table)
229388
table_path = target_dir / "dataset_summary_table.html"
230-
with open(table_path, "+w", encoding="utf-8") as f:
389+
with open(table_path, "w", encoding="utf-8") as f:
231390
f.write(html_table)
232391
copyfile(table_path, STATIC_DATASET_DIR / table_path.name)
233392

docs/source/dataset_summary/table.rst

Lines changed: 0 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -25,152 +25,3 @@ In addition, EEG-DaSh will incorporate a subset of the data converted from `NEMA
2525
</figure>
2626

2727
Pathology, modality, and dataset type now surface as consistent color-coded tags so you can scan the table at a glance.
28-
29-
.. raw:: html
30-
31-
<!-- jQuery + DataTables core -->
32-
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
33-
<link rel="stylesheet" href="https://cdn.datatables.net/v/bm/dt-1.13.4/datatables.min.css"/>
34-
<script src="https://cdn.datatables.net/v/bm/dt-1.13.4/datatables.min.js"></script>
35-
36-
<!-- Buttons + SearchPanes (+ Select required by SearchPanes) -->
37-
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.dataTables.min.css">
38-
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
39-
<link rel="stylesheet" href="https://cdn.datatables.net/select/1.7.0/css/select.dataTables.min.css">
40-
<link rel="stylesheet" href="https://cdn.datatables.net/searchpanes/2.3.1/css/searchPanes.dataTables.min.css">
41-
<script src="https://cdn.datatables.net/select/1.7.0/js/dataTables.select.min.js"></script>
42-
<script src="https://cdn.datatables.net/searchpanes/2.3.1/js/dataTables.searchPanes.min.js"></script>
43-
44-
<style>
45-
/* Styling for the Total row (placed in tfoot) */
46-
table.sd-table tfoot td {
47-
font-weight: 600;
48-
border-top: 2px solid rgba(0,0,0,0.2);
49-
background: #f9fafb;
50-
/* Match body cell padding to keep perfect alignment */
51-
padding: 8px 10px !important;
52-
vertical-align: middle;
53-
}
54-
55-
/* Right-align numeric-like columns (2..8) consistently for body & footer */
56-
table.sd-table tbody td:nth-child(n+2),
57-
table.sd-table tfoot td:nth-child(n+2) {
58-
text-align: right;
59-
}
60-
/* Keep first column (Dataset/Total) left-aligned */
61-
table.sd-table tbody td:first-child,
62-
table.sd-table tfoot td:first-child {
63-
text-align: left;
64-
}
65-
</style>
66-
67-
<script>
68-
// Helper: robustly extract values for SearchPanes when needed
69-
function tagsArrayFromHtml(html) {
70-
if (html == null) return [];
71-
// If it's numeric or plain text, just return as a single value
72-
if (typeof html === 'number') return [String(html)];
73-
if (typeof html === 'string' && html.indexOf('<') === -1) return [html.trim()];
74-
// Else parse any .tag elements inside HTML
75-
var tmp = document.createElement('div');
76-
tmp.innerHTML = html;
77-
var tags = Array.from(tmp.querySelectorAll('.tag')).map(function(el){
78-
return (el.textContent || '').trim();
79-
});
80-
return tags.length ? tags : [tmp.textContent.trim()];
81-
}
82-
83-
// Helper: parse human-readable sizes like "4.31 GB" into bytes (number)
84-
function parseSizeToBytes(text) {
85-
if (!text) return 0;
86-
var s = String(text).trim();
87-
var m = s.match(/([\d,.]+)\s*(TB|GB|MB|KB|B)/i);
88-
if (!m) return 0;
89-
var value = parseFloat(m[1].replace(/,/g, ''));
90-
var unit = m[2].toUpperCase();
91-
var factor = { B:1, KB:1024, MB:1024**2, GB:1024**3, TB:1024**4 }[unit] || 1;
92-
return value * factor;
93-
}
94-
95-
$(function () {
96-
var $table = $('#datasets-table');
97-
if (!$table.length) {
98-
return;
99-
}
100-
if ($.fn.DataTable && $.fn.DataTable.isDataTable($table[0])) {
101-
return;
102-
}
103-
104-
// 1) Move the "Total" row into <tfoot> so sorting/filtering never moves it
105-
var $tbody = $table.find('tbody');
106-
var $total = $tbody.find('tr').filter(function(){
107-
return $(this).find('td').eq(0).text().trim() === 'Total';
108-
});
109-
if ($total.length) {
110-
var $tfoot = $table.find('tfoot');
111-
if (!$tfoot.length) $tfoot = $('<tfoot/>').appendTo($table);
112-
$total.appendTo($tfoot);
113-
}
114-
115-
// 2) Initialize DataTable with SearchPanes button
116-
var FILTER_COLS = [1,2,3,4,5,6];
117-
// Detect the index of the size column by header text
118-
var sizeIdx = (function(){
119-
var idx = -1;
120-
$table.find('thead th').each(function(i){
121-
var t = $(this).text().trim().toLowerCase();
122-
if (t === 'size on disk' || t === 'size') idx = i;
123-
});
124-
return idx;
125-
})();
126-
127-
var table = $table.DataTable({
128-
dom: 'Blfrtip',
129-
paging: false,
130-
searching: true,
131-
info: false,
132-
language: {
133-
search: 'Filter dataset:',
134-
searchPanes: { collapse: { 0: 'Filters', _: 'Filters (%d)' } }
135-
},
136-
buttons: [{
137-
extend: 'searchPanes',
138-
text: 'Filters',
139-
config: { cascadePanes: true, viewTotal: true, layout: 'columns-4', initCollapsed: false }
140-
}],
141-
columnDefs: (function(){
142-
var defs = [
143-
{ searchPanes: { show: true }, targets: FILTER_COLS }
144-
];
145-
if (sizeIdx !== -1) {
146-
defs.push({
147-
targets: sizeIdx,
148-
render: function(data, type) {
149-
if (type === 'sort' || type === 'type') {
150-
return parseSizeToBytes(data);
151-
}
152-
return data;
153-
}
154-
});
155-
}
156-
return defs;
157-
})()
158-
});
159-
160-
// 3) UX: click a header to open the relevant filter pane
161-
$table.find('thead th').each(function (i) {
162-
if ([1,2,3,4].indexOf(i) === -1) return;
163-
$(this).css('cursor','pointer').attr('title','Click to filter this column');
164-
$(this).on('click', function () {
165-
table.button('.buttons-searchPanes').trigger();
166-
setTimeout(function () {
167-
var idx = [1,2,3,4].indexOf(i);
168-
var $container = $(table.searchPanes.container());
169-
var $pane = $container.find('.dtsp-pane').eq(idx);
170-
var $title = $pane.find('.dtsp-title');
171-
if ($title.length) $title.trigger('click');
172-
}, 0);
173-
});
174-
});
175-
});
176-
</script>

0 commit comments

Comments
 (0)