var sortState = { sortBy: "sortArtist", sortOrder: "asc", }; function init() { fetch("/api/records") .then((response) => response.json()) .then((records) => { // prepare response records.forEach(apiResponseParsing); document.getElementById("search").addEventListener("input", (e) => { renderTable(search(records, e.target.value)); }); renderTable(records); }); } function renderTable(records, sortField) { if (sortField) { if (sortState.sortBy === sortField && sortState.sortOrder === "asc") { sortState.sortOrder = "desc"; } else { sortState.sortOrder = "asc"; } sortState.sortBy = sortField; } records.sort((one, two) => (one[sortState.sortBy] + one["sortName"]).localeCompare( two[sortState.sortBy] + two["sortName"] ) ); if (sortState.sortOrder === "desc") { records.reverse(); } records.forEach((e, i) => (e.rowNumber = i)); // re-key // rendering var recordElement = document.getElementById("records"); recordElement.innerHTML = TableTemplate(records); var recordCount = document.getElementById("recordCount"); recordCount.innerHTML = `${records.length} records`; // add listeners for selecting record to view Array.from(recordElement.querySelectorAll("tbody tr")) .slice(1) // remove header from Array .forEach((row) => { row.addEventListener("click", (e) => { // add listener to swap current record document.getElementById("current").innerHTML = RecordTemplate( records[e.currentTarget.id] ); }); }); // add sorting callbacks Array.from( recordElement.querySelectorAll("tbody tr th[data-sort-by]") ).forEach((row) => { row.addEventListener("click", function (e) { renderTable(records, e.target.dataset.sortBy); // only add callback when there's a sortBy attribute }); }); // mark currently active column recordElement .querySelector("tbody tr th[data-sort-by=" + sortState.sortBy + "]") .classList.add(sortState.sortOrder); } function apiResponseParsing(record) { record.sortName = titleCleaner(record.name); record.artists = record.artists.map((artist) => { return artist.replace(/ \([0-9]+\)$/, ""); }); record.label = record.label.replace(/ \([0-9]+\)$/, ""); record.sortArtist = record.artists.reduce((acc, curr) => { return ( acc + curr .replace(/^(An?|The)\s/i, "") .toLowerCase() .replaceAll('"', "") .replaceAll(":", "") .replaceAll("'", "") .replaceAll(" ", "") ); }, ""); return record; } function search(records, searchBy) { searchBy = searchCleaner(searchBy); if (searchBy !== "") { records = records.filter(({ name, artists, genre, label, year }) => { return Object.values({ name, artists: artists.join(" "), genre, label, year, }).find((field) => searchCleaner(field).indexOf(searchBy) !== -1); }); } return records; } function titleCleaner(title) { return title .replace('"', "") .replace(":", "") .replace(/^(An?|The)\s/i, ""); } function searchCleaner(str) { return str .toLowerCase() .replaceAll('"', "") .replaceAll(":", "") .replaceAll("'", "") .replaceAll(" ", ""); } function RecordTemplate({ name, artists, coverURL, format, genre, identifier, label, year, discogsURL, }) { return `${coverURL ? `` : ""}

${name}

${artists.join(", ")}

${identifier}
${genre}, ${label}, ${year}
${format}
Data provided by Discogs. `; } function TableRowTemplate({ name, coverURL, discogsURL }) { return `
${name} Data provided by Discogs.
`; } function TableTemplate(records) { return `
${records.reduce((acc, record) => { return acc.concat(TableRowTemplate(record)); }, "")}
`; }