I have a table using flexbox that’s populated with d3.js. The columns can be sorted by clicking on the header row.
I have a select in one of these rows. When I click on the dropdown, I don’t want the table to sort. But if I click that header row outside of the dropdown, I do want it to sort. Is this doable?
data = [
{
"name": "Dave",
"dept": "Marketing",
"region": "South",
"items": 28
},
{
"name": "Amy",
"dept": "IT",
"region": "West",
"items": 46
},
{
"name": "John",
"dept": "Sales",
"region": "North",
"items": 35
},
{
"name": "Sarah",
"dept": "Communications",
"region": "North",
"items": 13
}
]
drawTable(data)
sortTable(data)
function drawTable(data) {
// not working
// when redrawing table, trying to re-initialize sort function
sortTable(data)
d3.select('#data-table').remove()
let table = d3.select('#table').append('div').attr('id', 'data-table')
let row = table.selectAll('.row')
.data(data)
.enter()
.append('div')
.attr('class', 'row')
let grid = row
.append('div')
.attr('class', 'grid')
let name = grid.append('div')
.attr('class', 'box')
.html(d => d.name)
let dept = grid.append('div')
.attr('class', 'box')
.html(d => d.dept)
let state = grid.append('div')
.attr('class', 'box')
.html(d => d.region)
let initiative = grid.append('div')
.attr('class', 'box')
.html(d => d.items)
}
function sortTable(data) {
d3.selectAll(".name,.dept,.region,.items").on('click', function () {
d3.select(this).classed("sortAsc", d3.select(this).classed("sortAsc") ? false : true);
let sortClasses = d3.select(this).attr("class")
let splitSortClasses = sortClasses.split(' ')
let sortVar = splitSortClasses[2]
if (sortClasses.includes('sortAsc')) {
data.sort((a, b) => d3.ascending(a[sortVar], b[sortVar]))
} else {
data.sort((a, b) => d3.descending(a[sortVar], b[sortVar]))
}
drawTable(data)
})
}
.grid {
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.grid>div {
display: flex;
flex-basis: calc(100%/4 - 28px);
justify-content: center;
flex-direction: column;
padding: 10px;
}
.box {
margin: 0;
}
.box {
color: #000;
border: .5px solid #ccc;
}
.hrbox {
background-color: #ddd;
color: #111;
font-weight: bold;
background-size: 1.5rem;
background-repeat: no-repeat;
background-position: center right;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%234f4f4f' d='M16.29 14.29L12 18.59l-4.29-4.3a1 1 0 00-1.42 1.42l5 5a1 1 0 001.42 0l5-5a1 1 0 00-1.42-1.42zM7.71 9.71L12 5.41l4.29 4.3a1 1 0 001.42 0 1 1 0 000-1.42l-5-5a1 1 0 00-1.42 0l-5 5a1 1 0 001.42 1.42z'/%3E%3C/svg%3E");
text-align: left !important;
}
.hrbox.sortAsc {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%234f4f4f' d='M11.29 11.46a1 1 0 001.42 0l3-3A1 1 0 1014.29 7L12 9.34 9.71 7a1 1 0 10-1.42 1.46zm3 1.08L12 14.84l-2.29-2.3A1 1 0 008.29 14l3 3a1 1 0 001.42 0l3-3a1 1 0 00-1.42-1.42z'/%3E%3C/svg%3E");
}
.hrbox.sortDesc {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%234f4f4f' d='M12.71 12.54a1 1 0 00-1.42 0l-3 3A1 1 0 009.71 17L12 14.66 14.29 17a1 1 0 001.42 0 1 1 0 000-1.42zm-3-1.08L12 9.16l2.29 2.3a1 1 0 001.42 0 1 1 0 000-1.42l-3-3a1 1 0 00-1.42 0l-3 3a1 1 0 001.42 1.42z'/%3E%3C/svg%3E");
}
#attr {
width: 60px;
margin-left: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>
<div id="table">
<div class="grid">
<div class="box hrbox name">
<div style="display: flex;">
<div>name</div>
<select id="attr"></select>
</div>
</div>
<div class="box hrbox dept">
<div>dept</div>
</div>
<div class="box hrbox region">
<div>region</div>
</div>
<div class="box hrbox items">
<div>items</div>
</div>
</div>
<div id="data-table"></div>
</div>