257 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						||
<html>
 | 
						||
  <head>
 | 
						||
    <title>Library</title>
 | 
						||
    <script type="text/javascript" src="js/jquery.js"></script>
 | 
						||
    <script type="text/javascript" src="js/mustache.js"></script>
 | 
						||
    <script type="text/javascript" src="js/lodash.min.js"></script>
 | 
						||
    <script src="https://cdnjs.cloudflare.com/ajax/libs/tabletop.js/1.5.1/tabletop.min.js"></script>
 | 
						||
    <link
 | 
						||
      rel="stylesheet"
 | 
						||
      href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
 | 
						||
    />
 | 
						||
    <link rel="stylesheet" href="css/reset.css" />
 | 
						||
    <link rel="stylesheet" href="css/style.css" />
 | 
						||
    <link rel="icon" href="favicon.ico" type="image/x-icon" />
 | 
						||
    <link
 | 
						||
      href="https://fonts.googleapis.com/css?family=Libre+Baskerville:400,700"
 | 
						||
      rel="stylesheet"
 | 
						||
    />
 | 
						||
    <script type="text/javascript">
 | 
						||
      var publicSpreadsheetUrl =
 | 
						||
        "https://docs.google.com/spreadsheets/d/1w5Dc57wV0_rrKFsG7KM-qdPWEpqYk6lFu3JzAA0cSv0/pubhtml";
 | 
						||
      var sortState = {
 | 
						||
        sortBy: "authorLast",
 | 
						||
        sortOrder: "asc",
 | 
						||
      };
 | 
						||
 | 
						||
      function init() {
 | 
						||
        Tabletop.init({
 | 
						||
          key: publicSpreadsheetUrl,
 | 
						||
          callback: showInfo,
 | 
						||
          simpleSheet: true,
 | 
						||
        });
 | 
						||
      }
 | 
						||
 | 
						||
      function showInfo(data, tabletop) {
 | 
						||
        $("#reloadLink").unbind("click");
 | 
						||
        $("#reloadLink").on("click", function () {
 | 
						||
          init();
 | 
						||
        });
 | 
						||
 | 
						||
        $("#search").unbind("input");
 | 
						||
        $("#search").on("input", function (e) {
 | 
						||
          search(data, e.target.value);
 | 
						||
        });
 | 
						||
 | 
						||
        $.each(data, function (key, value) {
 | 
						||
          value.sortTitle = titleCleaner(value.title);
 | 
						||
          if (!value["isbn-10"] && value["isbn-13"]) {
 | 
						||
            value["isbn-10"] = generateISBNfromEAN(value["isbn-13"]);
 | 
						||
          }
 | 
						||
          if (!value.coverurl && value["isbn-10"]) {
 | 
						||
            value.coverurl = generateAmazonCoverUrl(value["isbn-10"]);
 | 
						||
          }
 | 
						||
        });
 | 
						||
 | 
						||
        renderTable(data);
 | 
						||
      }
 | 
						||
 | 
						||
      function search(data, searchString) {
 | 
						||
        searchBy = searchString
 | 
						||
          .toLowerCase()
 | 
						||
          .replace('"', "")
 | 
						||
          .replace(":", "")
 | 
						||
          .replace("'", "")
 | 
						||
          .replace(" ", "");
 | 
						||
        relevantFields = [
 | 
						||
          "title",
 | 
						||
          "author",
 | 
						||
          "genre",
 | 
						||
          "publisher",
 | 
						||
          "series",
 | 
						||
          "year",
 | 
						||
        ];
 | 
						||
 | 
						||
        if (!searchString) {
 | 
						||
          renderTable(data);
 | 
						||
          return false;
 | 
						||
        }
 | 
						||
 | 
						||
        renderTable(
 | 
						||
          _.filter(data, function (book) {
 | 
						||
            return _.find(_.pick(book, relevantFields), function (field) {
 | 
						||
              return (
 | 
						||
                field
 | 
						||
                  .toLowerCase()
 | 
						||
                  .replace('"', "")
 | 
						||
                  .replace(":", "")
 | 
						||
                  .replace("'", "")
 | 
						||
                  .replace(" ", "")
 | 
						||
                  .indexOf(searchBy) !== -1
 | 
						||
              );
 | 
						||
            });
 | 
						||
          })
 | 
						||
        );
 | 
						||
      }
 | 
						||
 | 
						||
      function renderTable(data, sortField) {
 | 
						||
        if (sortField) {
 | 
						||
          if (sortState.sortBy === sortField) {
 | 
						||
            sortState.sortOrder =
 | 
						||
              sortState.sortOrder === "asc" ? "desc" : "asc"; // swap if we're looping
 | 
						||
          } else {
 | 
						||
            sortState.sortOrder = "asc"; // reset if we've changed columns
 | 
						||
          }
 | 
						||
          sortState.sortBy = sortField;
 | 
						||
        }
 | 
						||
        data = _.orderBy(
 | 
						||
          data,
 | 
						||
          function (o) {
 | 
						||
            return (
 | 
						||
              o[sortState.sortBy].toLowerCase() + o["sortTitle"].toLowerCase()
 | 
						||
            );
 | 
						||
          },
 | 
						||
          sortState.sortOrder
 | 
						||
        );
 | 
						||
 | 
						||
        $.each(data, function (key, value) {
 | 
						||
          value.rowNumber = key; // re-key for new sort
 | 
						||
        });
 | 
						||
 | 
						||
        var template = $("#Table").html();
 | 
						||
        var rendered = Mustache.render(template, { books: data });
 | 
						||
        $("#books").html(rendered);
 | 
						||
        $("#books tbody tr")
 | 
						||
          .not(":first")
 | 
						||
          .on("click", function () {
 | 
						||
            updateCurrentBook(data[$(this)[0].id]); // ignore the headers
 | 
						||
          });
 | 
						||
        $("#books tbody tr th[data-sort-by]").on("click", function () {
 | 
						||
          renderTable(data, $(this).data("sortBy")); // only add callback when there's a sortBy attribute
 | 
						||
        });
 | 
						||
        $("#books tbody tr th[data-sort-by=" + sortState.sortBy + "]").addClass(
 | 
						||
          sortState.sortOrder
 | 
						||
        );
 | 
						||
      }
 | 
						||
 | 
						||
      function updateCurrentBook(book) {
 | 
						||
        var template = $("#View").html();
 | 
						||
        var rendered = Mustache.render(template, { book: book });
 | 
						||
        $("#current").html(rendered);
 | 
						||
      }
 | 
						||
 | 
						||
      function titleCleaner(title) {
 | 
						||
        return title
 | 
						||
          .replace('"', "")
 | 
						||
          .replace(":", "")
 | 
						||
          .replace(/^(An?|The)\s/i, "");
 | 
						||
      }
 | 
						||
 | 
						||
      function generateAmazonCoverUrl(ISBN) {
 | 
						||
        return (
 | 
						||
          "https://images-na.ssl-images-amazon.com/images/P/" +
 | 
						||
          ISBN +
 | 
						||
          ".01.LZZ.jpg"
 | 
						||
        );
 | 
						||
      }
 | 
						||
 | 
						||
      function generateISBNfromEAN(EAN) {
 | 
						||
        ISBN = EAN.slice(3, 12);
 | 
						||
        var checkdigit =
 | 
						||
          (11 -
 | 
						||
            (_.reduce(
 | 
						||
              ISBN.split(""),
 | 
						||
              function (sum, num, key) {
 | 
						||
                return sum + num * (10 - key);
 | 
						||
              },
 | 
						||
              0
 | 
						||
            ) %
 | 
						||
              11)) %
 | 
						||
          11;
 | 
						||
        return ISBN + (checkdigit == 10 ? "X" : checkdigit);
 | 
						||
      }
 | 
						||
 | 
						||
      window.addEventListener("DOMContentLoaded", init);
 | 
						||
    </script>
 | 
						||
  </head>
 | 
						||
  <body>
 | 
						||
    <div class="wrapper">
 | 
						||
      <div id="header">
 | 
						||
        <h1>Library</h1>
 | 
						||
        <a target="_blank" href="https://git.yetaga.in/alazyreader/library"
 | 
						||
          >git</a
 | 
						||
        >
 | 
						||
        <a id="reloadLink" href="#">reload</a>
 | 
						||
        <div id="searchBox">
 | 
						||
          <input
 | 
						||
            id="search"
 | 
						||
            type="text"
 | 
						||
            name="search"
 | 
						||
            placeholder="Search..."
 | 
						||
          />
 | 
						||
        </div>
 | 
						||
      </div>
 | 
						||
      <div id="current">No Book Selected</div>
 | 
						||
      <div id="books"></div>
 | 
						||
      <!-- Table goes here -->
 | 
						||
    </div>
 | 
						||
 | 
						||
    <script id="Table" type="text/html">
 | 
						||
      <table class="bookTable">
 | 
						||
        <tr>
 | 
						||
          <th data-sort-by="sortTitle" class="tHeader title">Title</th>
 | 
						||
          <th data-sort-by="authorLast" class="tHeader author">Author</th>
 | 
						||
          <th data-sort-by="publisher" class="tHeader publisher">Publisher</th>
 | 
						||
          <th data-sort-by="year" class="tHeader year">Year</th>
 | 
						||
          <th class="tHeader isbn">ISBN</th>
 | 
						||
        </tr>
 | 
						||
        {{#books}}
 | 
						||
        <tr class="tRow {{#onLoan}}onLoan{{/onLoan}}" id="{{rowNumber}}">
 | 
						||
          <td class="title">
 | 
						||
            {{title}} {{#signed}}<span
 | 
						||
              class="signed"
 | 
						||
              title="Signed by the author"
 | 
						||
              >✒</span
 | 
						||
            >︎{{/signed}}
 | 
						||
          </td>
 | 
						||
          <td class="author">{{author}}</td>
 | 
						||
          <td class="publisher">{{publisher}}</td>
 | 
						||
          <td class="year">{{year}}</td>
 | 
						||
          <td class="isbn">{{isbn-13}}</td>
 | 
						||
        </tr>
 | 
						||
        {{/books}}
 | 
						||
      </table>
 | 
						||
    </script>
 | 
						||
 | 
						||
    <script id="View" type="text/html">
 | 
						||
      {{#book}}
 | 
						||
        {{#coverurl}}
 | 
						||
        <img src="{{coverurl}}"/>
 | 
						||
        {{/coverurl}}
 | 
						||
        <h1 {{#onLoan}}class="onLoan" {{/onLoan}}>{{title}}</h1>
 | 
						||
        <h2>{{author}}</h2>
 | 
						||
        <span>{{isbn-13}}</span><br/>
 | 
						||
        <span>{{publisher}}, {{year}}</span><br/>
 | 
						||
        {{#series}}
 | 
						||
          <span>{{series}}{{#volume}}, Volume {{volume}}</span>{{/volume}}<br/>
 | 
						||
        {{/series}}
 | 
						||
        {{#signed}}
 | 
						||
          <span>Signed by the author ✒</span><br/>
 | 
						||
        {{/signed}}
 | 
						||
        <span>{{format}}</span>
 | 
						||
        {{#onLoan}}
 | 
						||
        <h2 class="onLoan">On loan to {{onLoan}}</h2>
 | 
						||
        {{/onLoan}}
 | 
						||
        <div class="description">
 | 
						||
          <p>{{description}}</p>
 | 
						||
          {{#notes}}
 | 
						||
            <span>Notes:</span>
 | 
						||
            <p>{{notes}}</p>
 | 
						||
          {{/notes}}
 | 
						||
        </div>
 | 
						||
      {{/book}}
 | 
						||
    </script>
 | 
						||
  </body>
 | 
						||
</html>
 |