Refactoring the data table into a single container (#2719)

* feat: Bounding the table to a single container

* Making the table more responsive

* fixing design

* remove references to adjustDataTables

* remove useless table-scroll function

* Fix naming and restore old styling

* fix border top & font size

* fix firefox css bug

* fix for XML/JSON Importers

* Fixed styling

* fixed typos

* fixed column rendering and added a sticky header

* fixed firefox borders

* fixed border and table background

* fix importer stylings (td)

Co-authored-by: kushthedude <kushthedude@gmail.com>
This commit is contained in:
Lisa Chandra 2020-06-16 15:10:13 +05:30 committed by GitHub
parent 749704518c
commit 95e5e19eb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 113 deletions

View File

@ -619,7 +619,6 @@ DataTableCellUI.prototype._startEdit = function(elmt) {
self._cell = o.cell; self._cell = o.cell;
self._dataTableView._updateCell(self._rowIndex, self._cellIndex, self._cell); self._dataTableView._updateCell(self._rowIndex, self._cellIndex, self._cell);
self._render(); self._render();
self._dataTableView._adjustDataTables();
} }
} }
); );

View File

@ -68,11 +68,9 @@ DataTableView.prototype.getSorting = function() {
}; };
DataTableView.prototype.resize = function() { DataTableView.prototype.resize = function() {
this._adjustDataTables();
var topHeight = var topHeight =
this._div.find(".viewpanel-header").outerHeight(true) + this._div.find(".viewpanel-header").outerHeight(true);
this._div.find(".data-header-table-container").outerHeight(true);
var tableContainerIntendedHeight = this._div.innerHeight() - topHeight; var tableContainerIntendedHeight = this._div.innerHeight() - topHeight;
var tableContainer = this._div.find(".data-table-container").css("display", "block"); var tableContainer = this._div.find(".data-table-container").css("display", "block");
@ -99,11 +97,13 @@ DataTableView.prototype.render = function() {
'<div class="viewpanel-sorting" bind="sortingControls"></div>' + '<div class="viewpanel-sorting" bind="sortingControls"></div>' +
'<div class="viewpanel-paging" bind="pagingControls"></div>' + '<div class="viewpanel-paging" bind="pagingControls"></div>' +
'</div>' + '</div>' +
'<div bind="dataHeaderTableContainer" class="data-header-table-container">' +
'<table bind="headerTable" class="data-header-table"></table>' +
'</div>' +
'<div bind="dataTableContainer" class="data-table-container">' + '<div bind="dataTableContainer" class="data-table-container">' +
'<table bind="table" class="data-table"></table>' + '<table class="data-table">'+
'<thead bind="tableHeader" class="data-table-header">'+
'</thead>'+
'<tbody bind="table" class="data-table">'+
'</tbody>'+
'</table>' +
'</div>' '</div>'
); );
var elmts = DOM.bind(html); var elmts = DOM.bind(html);
@ -133,7 +133,7 @@ DataTableView.prototype.render = function() {
this._renderSortingControls(elmts.sortingControls); this._renderSortingControls(elmts.sortingControls);
} }
this._renderDataTables(elmts.table[0], elmts.headerTable[0]); this._renderDataTables(elmts.table[0], elmts.tableHeader[0]);
this._div.empty().append(html); this._div.empty().append(html);
// show/hide null values in cells // show/hide null values in cells
@ -210,7 +210,7 @@ DataTableView.prototype._renderPagingControls = function(pageSizeControls, pagin
.appendTo(pageSizeControls); .appendTo(pageSizeControls);
}; };
DataTableView.prototype._renderDataTables = function(table, headerTable) { DataTableView.prototype._renderDataTables = function(table, tableHeader) {
var self = this; var self = this;
var columns = theProject.columnModel.columns; var columns = theProject.columnModel.columns;
@ -223,21 +223,21 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
var renderColumnKeys = function(keys) { var renderColumnKeys = function(keys) {
if (keys.length > 0) { if (keys.length > 0) {
var tr = headerTable.insertRow(headerTable.rows.length); var tr = tableHeader.insertRow(tableHeader.rows.length);
$(tr.insertCell(0)).attr('colspan', '3'); // star, flag, row index $(tr.appendChild(document.createElement("th"))).attr('colspan', '3'); // star, flag, row index
for (var c = 0; c < columns.length; c++) { for (var c = 0; c < columns.length; c++) {
var column = columns[c]; var column = columns[c];
var td = tr.insertCell(tr.cells.length); var th = tr.appendChild(document.createElement("th"));
if (self._collapsedColumnNames.hasOwnProperty(column.name)) { if (self._collapsedColumnNames.hasOwnProperty(column.name)) {
$(td).html('&nbsp;'); $(th).html('&nbsp;');
} else { } else {
for (var k = 0; k < keys.length; k++) { for (var k = 0; k < keys.length; k++) {
// if a node is a key in the tree-based data (JSON/XML/etc), then also display a dropdown arrow (non-functional currently) // if a node is a key in the tree-based data (JSON/XML/etc), then also display a dropdown arrow (non-functional currently)
// See https://github.com/OpenRefine/OpenRefine/blob/master/main/src/com/google/refine/model/ColumnGroup.java // See https://github.com/OpenRefine/OpenRefine/blob/master/main/src/com/google/refine/model/ColumnGroup.java
// and https://github.com/OpenRefine/OpenRefine/tree/master/main/src/com/google/refine/importers/tree // and https://github.com/OpenRefine/OpenRefine/tree/master/main/src/com/google/refine/importers/tree
if (c == keys[k]) { if (c == keys[k]) {
$('<img />').attr("src", "../images/down-arrow.png").appendTo(td); $('<img />').attr("src", "../images/down-arrow.png").appendTo(th);
break; break;
} }
} }
@ -250,8 +250,8 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
var nextLayer = []; var nextLayer = [];
if (groups.length > 0) { if (groups.length > 0) {
var tr = headerTable.insertRow(headerTable.rows.length); var tr = tableHeader.insertRow(tableHeader.rows.length);
$(tr.insertCell(0)).attr('colspan', '3'); // star, flag, row index $(tr.appendChild(document.createElement("th"))).attr('colspan', '3'); // star, flag, row index
for (var c = 0; c < columns.length; c++) { for (var c = 0; c < columns.length; c++) {
var foundGroup = false; var foundGroup = false;
@ -265,10 +265,10 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
} }
} }
var td = tr.insertCell(tr.cells.length); var th = tr.appendChild(document.createElement("th"));
if (foundGroup) { if (foundGroup) {
td.setAttribute("colspan", columnGroup.columnSpan); th.setAttribute("colspan", columnGroup.columnSpan);
td.style.background = "#FF6A00"; th.style.background = "#FF6A00";
if (columnGroup.keyColumnIndex >= 0) { if (columnGroup.keyColumnIndex >= 0) {
keys.push(columnGroup.keyColumnIndex); keys.push(columnGroup.keyColumnIndex);
@ -302,9 +302,9 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
*------------------------------------------------------------ *------------------------------------------------------------
*/ */
var trHead = headerTable.insertRow(headerTable.rows.length); var trHead = tableHeader.insertRow(tableHeader.rows.length);
DOM.bind( DOM.bind(
$(trHead.insertCell(trHead.cells.length)) $(trHead.appendChild(document.createElement("th")))
.attr("colspan", "3") .attr("colspan", "3")
.addClass("column-header") .addClass("column-header")
.html( .html(
@ -317,15 +317,15 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
}); });
this._columnHeaderUIs = []; this._columnHeaderUIs = [];
var createColumnHeader = function(column, index) { var createColumnHeader = function(column, index) {
var td = trHead.insertCell(trHead.cells.length); var th = trHead.appendChild(document.createElement("th"));
$(td).addClass("column-header").attr('title', column.name); $(th).addClass("column-header").attr('title', column.name);
if (self._collapsedColumnNames.hasOwnProperty(column.name)) { if (self._collapsedColumnNames.hasOwnProperty(column.name)) {
$(td).html("&nbsp;").click(function(evt) { $(th).html("&nbsp;").click(function(evt) {
delete self._collapsedColumnNames[column.name]; delete self._collapsedColumnNames[column.name];
self.render(); self.render();
}); });
} else { } else {
var columnHeaderUI = new DataTableColumnHeaderUI(self, column, index, td); var columnHeaderUI = new DataTableColumnHeaderUI(self, column, index, th);
self._columnHeaderUIs.push(columnHeaderUI); self._columnHeaderUIs.push(columnHeaderUI);
} }
}; };
@ -342,16 +342,13 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
var rows = theProject.rowModel.rows; var rows = theProject.rowModel.rows;
var renderRow = function(tr, r, row, even) { var renderRow = function(tr, r, row, even) {
$(tr).empty(); $(tr).empty();
var cells = row.cells; var cells = row.cells;
var tdStar = tr.insertCell(tr.cells.length); var tdStar = tr.insertCell(tr.cells.length);
var star = $('<a href="javascript:{}">&nbsp;</a>') var star = $('<a href="javascript:{}">&nbsp;</a>')
.addClass(row.starred ? "data-table-star-on" : "data-table-star-off") .addClass(row.starred ? "data-table-star-on" : "data-table-star-off")
.appendTo(tdStar) .appendTo(tdStar)
.click(function() { .click(function() {
var newStarred = !row.starred; var newStarred = !row.starred;
Refine.postCoreProcess( Refine.postCoreProcess(
"annotate-one-row", "annotate-one-row",
{ row: row.i, starred: newStarred }, { row: row.i, starred: newStarred },
@ -361,7 +358,6 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
onDone: function(o) { onDone: function(o) {
row.starred = newStarred; row.starred = newStarred;
renderRow(tr, r, row, even); renderRow(tr, r, row, even);
self._adjustDataTables();
} }
}, },
"json" "json"
@ -374,7 +370,6 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
.appendTo(tdFlag) .appendTo(tdFlag)
.click(function() { .click(function() {
var newFlagged = !row.flagged; var newFlagged = !row.flagged;
Refine.postCoreProcess( Refine.postCoreProcess(
"annotate-one-row", "annotate-one-row",
{ row: row.i, flagged: newFlagged }, { row: row.i, flagged: newFlagged },
@ -384,7 +379,6 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
onDone: function(o) { onDone: function(o) {
row.flagged = newFlagged; row.flagged = newFlagged;
renderRow(tr, r, row, even); renderRow(tr, r, row, even);
self._adjustDataTables();
} }
}, },
"json" "json"
@ -426,63 +420,6 @@ DataTableView.prototype._renderDataTables = function(table, headerTable) {
} }
renderRow(tr, r, row, even); renderRow(tr, r, row, even);
} }
$(table.parentNode).bind('scroll', function(evt) {
self._adjustDataTableScroll();
});
};
DataTableView.prototype._adjustDataTables = function() {
var dataTable = this._div.find('.data-table');
var headerTable = this._div.find('.data-header-table');
if (dataTable.length === 0 || headerTable.length === 0) {
return;
}
dataTable = dataTable[0];
headerTable = headerTable[0];
if (dataTable.rows.length === 0) {
return;
}
var dataTr = dataTable.rows[0];
var headerTr = headerTable.rows[headerTable.rows.length - 1];
var marginColumnWidths =
$(dataTr.cells[0]).outerWidth(true) +
$(dataTr.cells[1]).outerWidth(true) +
$(dataTr.cells[2]).outerWidth(true) -
DOM.getHPaddings($(headerTr.cells[0])) + 1;
$(headerTable)
.find('> tbody > tr > td:first-child')
.width('1%')
.children()
.first()
.width(marginColumnWidths);
for (var i = 1; i < headerTr.cells.length; i++) {
var headerTd = $(headerTr.cells[i]);
var dataTd = $(dataTr.cells[i + 2]);
var commonWidth = Math.max(
Math.min(headerTd.width(), 100),
dataTd.width()
);
headerTd.width('1%').find('> div').width(commonWidth);
dataTd.children().first().width(commonWidth);
}
this._adjustDataTableScroll();
};
DataTableView.prototype._adjustDataTableScroll = function() {
var dataTableContainer = this._div.find('.data-table-container');
var headerTableContainer = this._div.find('.data-header-table-container');
if (dataTableContainer.length > 0 && headerTableContainer.length > 0) {
headerTableContainer
.find('> .data-header-table')
.css('left', '-' + dataTableContainer[0].scrollLeft + 'px');
}
}; };
DataTableView.prototype._showRows = function(start, onDone) { DataTableView.prototype._showRows = function(start, onDone) {

View File

@ -34,7 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@import-less url("../theme.less"); @import-less url("../theme.less");
.default-importing-parsing-data-panel { .default-importing-parsing-data-panel {
font-size: 1.1em; font-size: 1.12em;
position: absolute; position: absolute;
overflow: auto; overflow: auto;
} }

View File

@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.viewpanel-rowrecord, .viewpanel-pagesize, .viewpanel-sorting { .viewpanel-rowrecord, .viewpanel-pagesize, .viewpanel-sorting {
top: @padding_normal; top: @padding_normal;
padding: 0 10px 0 0; padding: 0 10px 0 0;
float: left; float: left;
} }
.viewpanel-paging { .viewpanel-paging {
@ -55,45 +55,62 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
font-weight: bold; font-weight: bold;
} }
.data-header-table-container { .data-table-header {
border-top: 1px solid @chrome_primary;
border-bottom: 2px solid @chrome_primary;
background: @fill_primary;
overflow: visible;
}
.data-header-table {
width: 1px; width: 1px;
position: relative; position: relative;
background: @fill_primary;
} }
.data-table-container { .data-table-container {
overflow: auto; overflow: auto;
border-top: 1px solid @chrome_primary;
} }
.data-header-table, .data-table { .data-table-header, .data-table {
margin: 0; margin: 0;
padding: 0; padding: 0;
font-size: 1.1em; font-size: 1.05em;
border-collapse: collapse; border-collapse: separate;
} }
.data-table td, .data-header-table td { .data-table td, .data-table-header td, .data-table-header th {
padding: 2px 5px; padding: 2px 5px;
} }
.data-table td { .data-table td {
border-bottom: 1px dotted #ddd; border-bottom: 0.02rem dotted #ddd;
border-right: 1px solid #ddd; border-right: 0.02rem solid #ddd;
} }
.data-header-table td {
border-bottom: 1px dotted @chrome_primary; .data-table-header td, .data-table-header th {
border-right: 1px solid @chrome_primary; border-bottom: 0.02rem dotted @chrome_primary;
border-right: 0.02rem solid @chrome_primary;
}
table {
position: relative;
}
th.column-header {
position: -webkit-sticky; /* Safari */
position: sticky;
top: 0;
z-index: 1;
will-change: transform;
}
th {
text-align: left;
} }
table.data-header-table > tbody > tr > td { table.data-header-table > tbody > tr > td {
overflow: hidden !important; overflow: hidden !important;
} }
table > thead > tr > th {
overflow: hidden !important;
}
table.data-table > tbody > tr.odd > td { table.data-table > tbody > tr.odd > td {
background: @fill_secondary; background: @fill_secondary;
} }
@ -102,7 +119,8 @@ table.data-table > tbody > tr.contextual > td > div {
opacity: 0.3; opacity: 0.3;
} }
table.data-header-table td.column-header, table.data-table td.column-header { table.data-table-header td.column-header, table.data-table-header th.column-header,
table.data-table td.column-header, table.data-table th.column-header {
vertical-align: top; vertical-align: top;
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
@ -112,9 +130,9 @@ table.data-header-table td.column-header, table.data-table td.column-header {
} }
/* For the preview in the importing stage */ /* For the preview in the importing stage */
table.data-table td.column-header { table.data-table td.column-header, table.data-table th.column-header {
background: @fill_primary; background: @fill_primary;
border-bottom: 2px solid @chrome_primary; border-bottom: 0.12rem solid @chrome_primary;
} }
.column-header-name { .column-header-name {