From 2d836356433b2cd8f8d5816e42d0e22bdf025e8a Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 8 Aug 2022 03:57:02 +0200 Subject: [PATCH] Play UI: row numbers; cell selection; hysteresis --- programs/server/play.html | 59 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/programs/server/play.html b/programs/server/play.html index 1801d243749..a941dd62c68 100644 --- a/programs/server/play.html +++ b/programs/server/play.html @@ -278,13 +278,24 @@ display: none; } - /* When mouse pointer is over table cell, will display full text (with wrap) instead of cut. */ - td.left:hover + /* When mouse pointer is over table cell, will display full text (with wrap) instead of cut. + * We also keep it for some time on mouseout for "hysteresis" effect. + */ + td.left:hover, .td-hover-hysteresis { white-space: pre-wrap; max-width: none; } + .td-selected + { + white-space: pre-wrap; + max-width: none; + background-color: var(--table-hover-color); + border: 2px solid var(--border-color); + display: block; + } + td.transposed { max-width: none; @@ -298,6 +309,13 @@ vertical-align: middle; } + .row-number + { + text-align: right; + background-color: var(--table-header-color); + color: var(--misc-text-color); + } + div.empty-result { opacity: 10%; @@ -793,7 +811,17 @@ return; } + const should_display_row_numbers = response.data.length > 3; + let thead = document.createElement('thead'); + + if (should_display_row_numbers) { + let th = document.createElement('th'); + th.className = 'row-number'; + th.appendChild(document.createTextNode('№')); + thead.appendChild(th); + } + for (let idx in response.meta) { let th = document.createElement('th'); const name = document.createTextNode(response.meta[idx].name); @@ -803,7 +831,9 @@ /// To prevent hanging the browser, limit the number of cells in a table. /// It's important to have the limit on number of cells, not just rows, because tables may be wide or narrow. + /// Also we permit rendering of more records but only if elapsed time is not large. const max_rows = 10000 / response.meta.length; + const max_render_ms = 200; let row_num = 0; const column_is_number = response.meta.map(elem => !!elem.type.match(/^(Nullable\()?(U?Int|Decimal|Float)/)); @@ -819,18 +849,41 @@ column_need_render_bars: column_need_render_bars, }; + const start_time = performance.now(); + + function tdMouseEnter(e) { + let elem = e.target; + elem.classList.add('td-hover-hysteresis'); + elem.onmouseleave = _ => { + setTimeout(() => { elem && elem.classList.remove('td-hover-hysteresis') }, 1000); + } + } + + function tdClick(e) { + let elem = e.target; + elem.classList.add('td-selected'); + } + let tbody = document.createElement('tbody'); for (let row_idx in response.data) { let tr = document.createElement('tr'); + if (should_display_row_numbers) { + let td = document.createElement('td'); + td.className = 'row-number'; + td.appendChild(document.createTextNode(1 + +row_idx)); + tr.appendChild(td); + } for (let col_idx in response.data[row_idx]) { let cell = response.data[row_idx][col_idx]; const td = renderCell(cell, col_idx, settings); + td.onmouseenter = tdMouseEnter; + td.onclick = tdClick; tr.appendChild(td); } tbody.appendChild(tr); ++row_num; - if (row_num >= max_rows) { + if (row_num >= max_rows && performance.now() - start_time >= max_render_ms) { break; } }