table = (data, options) => {
options = Object.assign({}, defaultOptions, options);
const { sortable, rank, paged } = options;
let sortKey = undefined;
let sortDirection = true;
let page = 0;
if (sortable && rank) {
throw new Error("A table can either be ranked or sortable, but not both");
}
let columns = Object.keys(data[0]).map(key => {
const opts = options.columns[key] || {};
return {
key: key,
type: opts.type || typeof data[0][key],
options: opts
};
});
function bake() {
if (sortKey) {
data = data.slice().sort((a, b) => {
let as = a[sortKey];
let bs = b[sortKey];
if (as == bs) return JSON.stringify(a).localeCompare(JSON.stringify(b));
let res = as > bs ? 1 : as < bs ? -1 : 0;
if (sortDirection) res = -res;
return res;
});
}
let rows = data.slice(page * paged, page * paged + paged);
let pages = Math.ceil(data.length / paged);
return html`<div><div>
<style>
.pretty-pager {
text-align: center;
}
.pretty-pager button {
padding-left: .5rem;
padding-right: .5rem;
cursor: pointer;
background: #efefef;
border: 2px solid #efefef;
font-family: Alegreya;
font-size: 12px;
font-weight: 400;
font-style: italic;
visibility:hidden;
}
.pretty-pager button:hover {
background: #ffffff;
border: 2px solid #efefef;
}
.pretty-table.normal {
font-family: Alegreya;
font-size: 13px;
text-align: center;
font-weight: 500;
font-style: italic;
}
.pretty-table.normal th,
.pretty-table.normal td {
padding: 2px 2px;
}
.pretty-table th,
.pretty-table td {
vertical-align: top;
font-family: Alegreya;
font-size: 13px;
text-align: center;
font-weight: 500;
font-style: italic;
}
.pretty-table thead th {
font-family: Alegreya;
font-size: 13px;
font-weight: 500;
font-style: normal;
visibility:hidden;
}
.pretty-table thead th.column-type-number string {
order: 1;
}
.pretty-table th.sortable {
cursor: pointer;
}
.pretty-table thead th.column-type-number,
.pretty-table tbody td.cell-type-number,
.pretty-table tbody td.cell-rank {
text-align:right;
}
.pretty-table tbody td.cell-type-number,
.pretty-table tbody td.cell-rank {
font-family: Alegreya;
font-size: 14px;
}
.pretty-table tbody td.cell-rank {
padding-right: 1em;
color: #666;
}
</style>
<table class='pretty-table ${options.style}'>
${
options.header === false
? ``
: html`<thead>
${rank ? html`<th></th>` : ""}
${columns.map(c => {
return th(c, sortKey, sortDirection, sortable);
})}
</thead>`
}
<tbody>
${rows.map(
(row, i) => html`<tr>
${rank ? html`<td class='cell-rank'>${i + 1}</td>` : ""}
${columns.map(c => {
let displayValue = (c.options.formatter || identity)(
row[c.key],
i,
row
);
if (
displayValue instanceof window.HTMLElement &&
displayValue.tagName == "TD"
) {
return displayValue;
}
return html`<td class='cell-type-${
c.type
}'>${displayValue}</td>`;
})}
</tr>`
)}
</tbody>
</table>
${
pages
? html`<div class='pretty-pager'>
${Array.from({ length: pages }).map(
(_, i) => html`<button data-page="${i}">${i+1}</button>`
)}
</div>`
: ""
}
</div></div>`;
}
let dom = bake();
function rerender() {
dom.firstChild.remove();
dom.appendChild(bake().firstChild);
}
// dom.addEventListener("click", e => {
// if (e.target.tagName === "TH" && sortable) {
// if (sortKey == e.target.dataset.key) {
// sortDirection = !sortDirection;
// }
// sortKey = e.target.dataset.key;
// rerender();
// }
// if (e.target.tagName === "BUTTON") {
// if (e.target.dataset.action) {
// switch (e.target.dataset.action) {
// case "next":
// page++, rerender();
// break;
// case "previous":
// page--, rerender();
// break;
// }
// } else if (e.target.dataset.page) {
// (page = parseInt(e.target.dataset.page)), rerender();
// }
// }
// });
return dom;
}