Last active
October 24, 2022 14:35
-
-
Save davebarnwell/cb786db3593f49a443df42ecef51759c to your computer and use it in GitHub Desktop.
add bar graph as background to html table column
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>HTML table with bar graph background in one or more columns</title> | |
<link rel="stylesheet" href="main.css"> | |
</head> | |
<body> | |
<div class="grid"> | |
<!-- ROW --> | |
<div> | |
<h1>Default style &<br>value in td is float or int</h1> | |
<!-- data-barcol attribute specifies column with numbers in TBODY --> | |
<table data-barcol="2"> | |
<thead> | |
<tr> | |
<th class="text-start">Fruit</th> | |
<th class="text-end">Qty</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr> | |
<td>Apple</td> | |
<td class="text-end">83</td> | |
</tr> | |
<tr> | |
<td>Pear</td> | |
<td class="text-end">151</td> | |
</tr> | |
<tr> | |
<td>Strawberry</td> | |
<td class="text-end">15</td> | |
</tr> | |
<tr> | |
<td>Melon</td> | |
<td class="text-end">17</td> | |
</tr> | |
<tr> | |
<td>Grape</td> | |
<td class="text-end">30</td> | |
</tr> | |
<tr> | |
<td>Orange</td> | |
<td class="text-end">90</td> | |
</tr> | |
<tr> | |
<td>Bannana</td> | |
<td class="text-end">115</td> | |
</tr> | |
<tr> | |
<td>Kiwi</td> | |
<td class="text-end">135</td> | |
</tr> | |
<tr> | |
<td>Star</td> | |
<td class="text-end">2</td> | |
</tr> | |
<tr> | |
<td>Mango</td> | |
<td class="text-end">50</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
<!-- ROW --> | |
<div> | |
<h1>Override color &<br>value in td data attribute</h1> | |
<table data-barcol="2"> | |
<thead> | |
<tr> | |
<th class="text-start">Fruit</th> | |
<th class="text-end">Price</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr> | |
<td>Apple</td> | |
<td class="text-end" data-value="83">$83.00</td> | |
</tr> | |
<tr> | |
<td>Pear</td> | |
<!-- value in data-value="" --> | |
<td class="text-end" data-value="151.8">$151.80</td> | |
</tr> | |
<tr> | |
<td>Strawberry</td> | |
<td class="text-end" data-value="15.2">$15.20</td> | |
</tr> | |
<tr> | |
<td>Melon</td> | |
<td class="text-end" data-value="17.2">$17.20</td> | |
</tr> | |
<tr> | |
<td>Grape</td> | |
<td class="text-end" data-value="30">$30.00</td> | |
</tr> | |
<tr> | |
<td>Orange</td> | |
<td class="text-end" data-value="90">$90.00</td> | |
</tr> | |
<tr> | |
<td>Bannana</td> | |
<td class="text-end" data-value="115">$115.00</td> | |
</tr> | |
<tr> | |
<td>Kiwi</td> | |
<td class="text-end" data-value="135">$135.00</td> | |
</tr> | |
<tr> | |
<td>Star</td> | |
<td class="text-end" data-value="2">$2.00</td> | |
</tr> | |
<tr> | |
<td>Mango</td> | |
<td class="text-end" data-value="50">$50.00</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
<!-- ROW --> | |
<div> | |
<h1>Color via heatmap function &<br> specify multiple columns</h1> | |
<!-- data-barcol attribute is CSV for cols to add bar background to --> | |
<table data-barcol="2,3"> | |
<thead> | |
<tr> | |
<th class="text-start">Fruit</th> | |
<th class="text-end">Qty</th> | |
<th class="text-end">% Extinction</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr> | |
<td>Apple</td> | |
<td class="text-end">83</td> | |
<td class="text-end">20</td> | |
</tr> | |
<tr> | |
<td>Pear</td> | |
<td class="text-end">151.8</td> | |
<td class="text-end">10</td> | |
</tr> | |
<tr> | |
<td>Strawberry</td> | |
<td class="text-end">15.2</td> | |
<td class="text-end">10</td> | |
</tr> | |
<tr> | |
<td>Melon</td> | |
<td class="text-end">17.2</td> | |
<td class="text-end">20</td> | |
</tr> | |
<tr> | |
<td>Grape</td> | |
<td class="text-end">30</td> | |
<td class="text-end">10</td> | |
</tr> | |
<tr> | |
<td>Orange</td> | |
<td class="text-end">90</td> | |
<td class="text-end">10</td> | |
</tr> | |
<tr> | |
<td>Bannana</td> | |
<td class="text-end">115</td> | |
<td class="text-end">80</td> | |
</tr> | |
<tr> | |
<td>Kiwi</td> | |
<td class="text-end">135</td> | |
<td class="text-end">20</td> | |
</tr> | |
<tr> | |
<td>Star</td> | |
<td class="text-end">2</td> | |
<td class="text-end">0</td> | |
</tr> | |
<tr> | |
<td>Mango</td> | |
<td class="text-end">50</td> | |
<td class="text-end">0</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
<p class="text-center">bar length is percentage the current value is of max value in the column</p> | |
<script defer src="main.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* NO CSS required to use this, purely for styling of this example */ | |
:root { | |
--bg-row-color: #dedede; | |
} | |
body { | |
font-family: sans-serif; | |
background-color: #f0f0f0; | |
} | |
.text-center { | |
text-align: center; | |
} | |
.grid { | |
display: grid; | |
column-gap: 1rem; | |
grid-template-columns: 1fr 1fr 1fr; | |
justify-items: center; | |
} | |
h1 { | |
font-size: 1.5rem; | |
} | |
table { | |
border-spacing: 0.25rem; | |
border: solid 1px var(--bg-row-color); | |
} | |
thead th { | |
min-width: 100px; | |
} | |
th, | |
td { | |
padding: 0.25rem; | |
} | |
tr:nth-child(even) { | |
/* Works with striped tables */ | |
background-color: var(--bg-row-color); | |
} | |
.text-start { | |
text-align: start; | |
} | |
.text-end { | |
text-align: end; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
The function to call that adds the bars | |
*/ | |
// TODO option for bars to grow from right, currently always the left of td | |
// TODO handle nagtive numbers e.g. min -10 to max 10, bar is percent of 20 | |
// TODO postive and negative numbers create bars in opposite directions from a common offset origin | |
function addTableDataBar(tableElm, opts = {}) { | |
const options = { | |
color: "rgba(179, 255, 201,1)" /* CSS color */, | |
dataAttr: null /* look for data-{attribute} for value on table cell */, | |
...opts | |
}; | |
let cols = tableElm.dataset.barcol.split(","); | |
cols = cols.map((v) => parseInt(v, 10)); | |
cols.forEach((col) => { | |
// get elms | |
const dataElms = tableElm.querySelectorAll(`tbody tr td:nth-child(${col})`); | |
// get values | |
const values = []; | |
let max = 0; | |
dataElms.forEach(function (elm, i) { | |
const row = { | |
elm: elm, | |
value: parseFloat( | |
options.dataAttr != null | |
? elm.dataset[options.dataAttr] | |
: elm.innerHTML | |
), | |
percent: null | |
}; | |
max = Math.max(max, row.value); | |
values.push(row); | |
}); | |
// Calc percent | |
values.forEach(function (row) { | |
row.percent = (row.value / max) * 100; | |
}); | |
// add background bar | |
values.forEach(function (row) { | |
// set background bar | |
const color = | |
typeof options.color === "function" | |
? options.color(row.percent / 100) | |
: options.color; | |
if (row.percent !== 0) { | |
row.elm.style.background = `linear-gradient(90deg, ${color} 0%, ${color} ${row.percent}%, rgba(0,0,0,0) ${row.percent}%)`; | |
} | |
}); | |
}); | |
} | |
/** | |
* Call function on table | |
*/ | |
// Get the tables value of data-graphcol attribute specifies column to style | |
const tables = document.querySelectorAll("[data-barcol]"); | |
// 1st table use default options | |
addTableDataBar(tables[0]); | |
// 2nd table use custom color and use value from data-value="" attribute on td rather than td content | |
addTableDataBar(tables[1], { | |
color: "rgba(237,151,187,1)", | |
dataAttr: "value" | |
}); | |
// 3rd table use heatmap colors by passing a function, and specify more than one column via data-graphcol="" on table | |
const heatMapColorforValue = (value) => { | |
/** 0=blue, 0.25=cyan, 0.5=green, 0.75=yellow, 1=red */ | |
const h = (1.0 - (value < 1 ? value : 1)) * 240; | |
return `hsl(${h}, 100%, 75%)`; | |
}; | |
addTableDataBar(tables[2], { | |
color: heatMapColorforValue | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment