Skip to content

Commit

Permalink
Merge pull request #128 from Anjalbaral/fixed-table-header
Browse files Browse the repository at this point in the history
Fixed table header
  • Loading branch information
melalj authored May 17, 2024
2 parents 0af8ce3 + a7a2144 commit c463807
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 60 deletions.
2 changes: 1 addition & 1 deletion dist/maptable.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 19 additions & 6 deletions dist/maptable.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/maptable.js.map

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions dist/maptable.min.js

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions docs/examples/table-with-fixed-header.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en">

<head>
<link rel="stylesheet" href="../vendor/bootstrap.min.css">
<link rel="stylesheet" href="../maptable.css">
<title>MapTable example</title>
<style>
.table thead {
background-color:#fff;
}
</style>
</head>

<body>

<script src="../vendor/d3.min.js" charset="utf-8"></script>
<script src="../vendor/topojson.min.js"></script>
<script src="../maptable.js"></script>

<div class="container">
<div class="panel panel-default">
<div class="panel-heading">[Example] Table with fixed header</div>
<div class="panel-body">
Demonstating: rendering a table and filters with fixed table header<br />
<br>
<div class="btn-group">
<a href="./table-with-fixed-header.html" target="_blank" class="btn btn-default">Open in a new window</a>
<a href="https://github.com/Packet-Clearing-House/maptable/tree/master/docs/examples/table-with-fixed-header.html" target="_blank"
class="btn btn-default">View source code</a>
</div>
</div>
</div>

<div id="vizContainer"></div>
</div>
<script>
var viz = d3.maptable('#vizContainer')
.json('table.json')
.columns({
position: {
filterMethod: 'dropdown',
},
office: {
filterMethod: 'dropdown',
},
start_date: {
filterMethod: 'compare',
filterInputType: 'date',
dataParse: function (val) {
return new Date(val).getTime();
}
},
salary: {
filterMethod: 'compare',
filterInputType: 'number',
cellContent: function (d) {
const v = parseInt(d.salary.replace(/[^0-9]+/g, ''), 10);
return '$' + v.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
},
dataParse: function (val) {
return parseInt(val.replace(/[^0-9]+/g, ''), 10);
}
},
links: {
virtual: function (d) {
return '<a href="#' + d.extn + '">Link</a>';
}
}
})
.filters({
show: ['name', 'position', 'office', 'salary', 'start_date']
})
.table({
show: ['name', 'position', 'office', 'salary', 'start_date', 'links'],
header: {className: "mt-header-fixed", top: 0}
})
.render();
</script>


</body>

</html>
1 change: 1 addition & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ <h1>MapTable <a href="https://github.com/Packet-Clearing-House/maptable" target=
<a href="examples/multiple-maptable.html" data-value="multiple-maptable" target="viewer">multiple maptables</a>
<a href="examples/negative-values.html" data-value="negative-values" target="viewer">negative values</a>
<a href="examples/table-only.html" data-value="table-only" target="viewer">table only</a>
<a href="examples/table-with-fixed-header.html" data-value="table-with-fixed-header" target="viewer">fixed table header</a>
<a href="examples/tooltip-country.html" data-value="tooltip-country" target="viewer">tooltip country w/ legend</a>
<a href="examples/heatmap.html" data-value="heatmap" target="viewer">heatmap</a>
<a href="examples/aggregate.html" data-value="aggregate" target="viewer">aggregate</a>
Expand Down
2 changes: 1 addition & 1 deletion docs/maptable.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 19 additions & 6 deletions docs/maptable.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions docs/maptable.min.js

Large diffs are not rendered by default.

61 changes: 31 additions & 30 deletions src/components/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default class Table {
constructor(maptable, options) {
this.maptable = maptable;
this.options = options;

if (this.options.defaultSorting) {
if (Array.isArray(this.options.defaultSorting) && this.options.defaultSorting.length === 2) {
this.sorting = this.options.defaultSorting;
Expand Down Expand Up @@ -43,17 +42,14 @@ export default class Table {
this.maptable.node.appendChild(this.node);
}

this.node = d3.select(this.node)
.append('table')
.attr('class', this.options.className);
this.node = d3.select(this.node).append('table').attr('class', this.options.className);

this.header = this.node.append('thead');

this.body = this.node.append('tbody');

if (this.options.show) {
const arrayDiff = this.options.show
.filter((i) => Object.keys(this.maptable.columnDetails).indexOf(i) < 0);
const arrayDiff = this.options.show.filter((i) => Object.keys(this.maptable.columnDetails).indexOf(i) < 0);
if (arrayDiff.length > 0) {
throw new Error(`MapTable: invalid columns "${arrayDiff.join(', ')}"`);
}
Expand All @@ -62,24 +58,38 @@ export default class Table {
this.activeColumns = Object.keys(this.maptable.columnDetails);
}

this.header.selectAll('tr')
// make table header fixed
if (this.options.header) {
if (this.options.header.className) {
this.header.attr('class', `${this.options.header.className}`);
}

// set custom top header space
if (this.options.header.top) {
this.header.attr('style', `top:${this.options.header.top || '0'}px;`);
} else {
this.header.attr('style', 'top:0px;');
}
}

this.header
.selectAll('tr')
.data([1])
.enter()
.append('tr')
.selectAll('th')
.data(this.activeColumns
.map((k) => utils.extendRecursive({ key: k }, this.maptable.columnDetails[k])))
.data(this.activeColumns.map((k) => utils.extendRecursive({ key: k }, this.maptable.columnDetails[k])))
.enter()
.append('th')
.attr('class', (d) => {
let output = (d.sorting) ? 'mt-table-sortable' : '';
output += (d.nowrap) ? ' nowrap' : '';
let output = d.sorting ? 'mt-table-sortable' : '';
output += d.nowrap ? ' nowrap' : '';
return output;
})
.attr('data-key', (d) => utils.sanitizeKey(d.key))
.attr('onselectstart', 'return false;')
.attr('unselectable', 'on')
.attr('style', (d) => ((d.nowrap) ? 'white-space:nowrap;' : ''))
.attr('style', (d) => (d.nowrap ? 'white-space:nowrap;' : ''))
.on('click', (d) => {
if (this.isSorting) return;
this.isSorting = true;
Expand Down Expand Up @@ -128,27 +138,23 @@ export default class Table {

let tableData = this.maptable.data;
if (this.options.distinctBy) {
tableData = d3.nest()
tableData = d3
.nest()
.key((d) => d[this.options.distinctBy])
.entries(this.maptable.data)
.map((g) => g.values[0]);
}

// Enter
this.body.selectAll('tr')
.data(tableData)
.enter()
.append('tr');
this.body.selectAll('tr').data(tableData).enter().append('tr');

// Exit
this.body.selectAll('tr')
.data(tableData)
.exit()
.remove();
this.body.selectAll('tr').data(tableData).exit().remove();

// Update
const uniqueCollapsedRows = [];
this.body.selectAll('tr')
this.body
.selectAll('tr')
.data(tableData)
.attr('class', (row) => {
if (this.options.rowClassName) {
Expand All @@ -166,11 +172,7 @@ export default class Table {
}
tds += '>';

if (!(
this.options.collapseRowsBy.indexOf(columnKey) !== -1
&& uniqueCollapsedRows[columnKey]
&& uniqueCollapsedRows[columnKey] === row[columnKey]
)) {
if (!(this.options.collapseRowsBy.indexOf(columnKey) !== -1 && uniqueCollapsedRows[columnKey] && uniqueCollapsedRows[columnKey] === row[columnKey])) {
if (column.cellContent) {
tds += column.cellContent(row);
} else if (column.virtual) {
Expand All @@ -197,13 +199,12 @@ export default class Table {
sortableColums[i].setAttribute('class', 'mt-table-sortable');
}
this.sorting.forEach((column) => {
this.container.querySelector(`#column_header_${utils.sanitizeKey(column.key)}`)
.setAttribute('class', `mt-table-sortable sort_${column.mode}`);
this.container.querySelector(`#column_header_${utils.sanitizeKey(column.key)}`).setAttribute('class', `mt-table-sortable sort_${column.mode}`);
});
this.maptable.data = this.maptable.data.sort((a, b) => {
let compareBool = false;
this.sorting.forEach((column) => {
const d3SortMode = (column.mode === 'asc') ? d3.ascending : d3.descending;
const d3SortMode = column.mode === 'asc' ? d3.ascending : d3.descending;
const columnDetails = this.maptable.columnDetails[column.key];
let el1 = a[column.key];
let el2 = b[column.key];
Expand Down
Loading

0 comments on commit c463807

Please sign in to comment.