var sortState = { sortBy: "sortAuthor", sortOrder: "asc", }; function init() { fetch("/api/books") .then((response) => response.json()) .then((books) => { // prepare response books.forEach(apiResponseParsing); document.getElementById("search").addEventListener("input", (e) => { renderTable( search( books, e.target.value, document.getElementById("childrens").checked ) ); }); document.getElementById("childrens").addEventListener("change", (e) => { renderTable( search( books, document.getElementById("search").value, e.target.checked ) ); }); renderTable( search(books, "", document.getElementById("childrens").checked) ); }); } function renderTable(books, sortField) { if (sortField) { if (sortState.sortBy === sortField && sortState.sortOrder === "asc") { sortState.sortOrder = "desc"; } else { sortState.sortOrder = "asc"; } sortState.sortBy = sortField; } books.sort((one, two) => (one[sortState.sortBy] + one["sortTitle"]).localeCompare( two[sortState.sortBy] + two["sortTitle"] ) ); if (sortState.sortOrder === "desc") { books.reverse(); } books.forEach((e, i) => (e.rowNumber = i)); // re-key // rendering var bookElement = document.getElementById("books"); bookElement.innerHTML = TableTemplate(books); var bookCount = document.getElementById("bookCount"); bookCount.innerHTML = `${books.length} books`; // add listeners for selecting book to view Array.from(bookElement.querySelectorAll("tbody tr")) .slice(1) // remove header from Array .forEach((row) => { row.addEventListener("click", (e) => { // add listener to swap current book document.getElementById("current").innerHTML = BookTemplate( books[e.currentTarget.id] ); }); }); // add sorting callbacks Array.from(bookElement.querySelectorAll("tbody tr th[data-sort-by]")).forEach( (row) => { row.addEventListener("click", function (e) { renderTable(books, e.target.dataset.sortBy); // only add callback when there's a sortBy attribute }); } ); // mark currently active column bookElement .querySelector("tbody tr th[data-sort-by=" + sortState.sortBy + "]") .classList.add(sortState.sortOrder); } function apiResponseParsing(book) { book.sortTitle = titleCleaner(book.title); if (!book["isbn-10"] && book["isbn-13"]) { book["isbn-10"] = ISBNfromEAN(book["isbn-13"]); } if (!book.coverURL && book["isbn-10"]) { book.coverURL = `https://images-na.ssl-images-amazon.com/images/P/` + book["isbn-10"] + `.01.LZZ.jpg`; } return book; } function search(books, searchBy, includeChildrensBooks) { searchBy = searchCleaner(searchBy); books = books.filter( ({ title, authors, genre, publisher, series, year, childrens }) => { var inSearch = true; if (searchBy !== "") { inSearch = Object.values({ title, authors: authors.join(" "), genre, publisher, series, year, }).find((field) => searchCleaner(field).indexOf(searchBy) !== -1); } if (!includeChildrensBooks) { return inSearch && !childrens; } return inSearch; } ); return books; } function titleCleaner(title) { return title .replace('"', "") .replace(":", "") .replace(/^(An?|The)\s/i, ""); } function searchCleaner(str) { return str .toLowerCase() .replaceAll('"', "") .replaceAll(":", "") .replaceAll("'", "") .replaceAll(" ", ""); } function ISBNfromEAN(EAN) { ISBN = EAN.slice(3, 12); var checkdigit = (11 - (ISBN.split("").reduce((s, n, k) => s + n * (10 - k), 0) % 11)) % 11; return ISBN + (checkdigit === 10 ? "X" : checkdigit); } function BookTemplate({ "isbn-13": isbn13, "isbn-10": isbn10, authors, coverURL, description, format, notes, publisher, series, signed, title, volume, year, }) { return `
Title | Author | Publisher | Year | ISBN |
---|