From 03860ebc2e0624ecd0cf094498ac3bfc2df18183 Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Tue, 28 Jul 2020 12:54:40 -0400 Subject: [kona-web] Implement infinite scroll. --- README.md | 5 ++- static/js/infinite_scroll.js | 91 ++++++++++++++++++++++++++++++++++++++++++++ templates/index.hbs | 9 ++++- 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 static/js/infinite_scroll.js diff --git a/README.md b/README.md index f756061..ec73e72 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ the general public. - A command-line tool for interacting with the tag database. - A web interface for querying and viewing files in the tag database. + - Works with JavaScript disabled. + - Infinite scroll when JavaScript is enabled. ## Usage @@ -142,7 +144,7 @@ to the following endpoint with the following fields: `tags`, a comma-separated list of tags for the files, and `image`, the file to be uploaded. ``` -POST /api/posts/[filename] +POST /api/posts ``` ## TODO @@ -152,5 +154,4 @@ for me right now. - [kona-cli] Improve the `kona-cli add` interface, allowing multiple files to be indexed and tagged in the same invocation. -- [kona-web js] Implement a dynamic "endless scroll" view. - [kona-web js] Implement a mass-tagger tool in the web interface. diff --git a/static/js/infinite_scroll.js b/static/js/infinite_scroll.js new file mode 100644 index 0000000..15df7ae --- /dev/null +++ b/static/js/infinite_scroll.js @@ -0,0 +1,91 @@ +// Copyright © 2020 Jakob L. Kreuze +// +// This file is part of Kona. +// +// Kona is free software; you can redistribute it and/or modify it under +// the terms of the GNU Affero General Public License as published by +// the Free Software Foundation; either version 3 of the License, or (at +// your option) any later version. +// +// Kona is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public +// License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with Kona. If not, see . + +let searchQuery = /query=[^\&]*/.exec(window.location)[0]; +let searchLast = 0; + +// Calculate the `last` parameter for the 'posts' endpoint from the images +// currently displayed. +function lastId() { + let children = document.getElementById("main").children; + + if (children.length === 0) { + return 0; + } + + let lastChild = children[children.length - 1]; + return parseInt(/image-([\d]*)/.exec(lastChild.id)[1]); +} + +function scrollHandler() { + if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { + // Remove ourselves so we don't get triggered while we're loading. + window.removeEventListener("scroll", scrollHandler); + + let xhr = new XMLHttpRequest(); + xhr.open("GET", searchQuery ? + `/api/posts?${searchQuery}&last=${searchLast}` : + `/api/posts?query=&last=${searchLast}`); + xhr.onload = () => { + let results = JSON.parse(xhr.response); + + // Add ourselves iff there's more to load. + if (results.length > 0) { + window.addEventListener("scroll", scrollHandler); + } + + results.forEach((image) => { + let div = document.createElement("div"); + div.id = `image-${image.id}`; + div.classList.add("image-container"); + + let a = document.createElement("a"); + a.href = `/posts/${image.id}`; + + let img = document.createElement("img"); + img.src = `/image/${image.thumb_filename}`; + + div.appendChild(a); + a.appendChild(img); + document.getElementById("main").appendChild(div); + }); + + // Update the `searchLast` global. + searchLast = lastId(); + }; + xhr.send(); + } +}; + +window.addEventListener("scroll", scrollHandler); + +window.addEventListener("load", () => { + // Remove the "next" link. + let main = document.getElementById("main"); + let lastChild = main.children[main.children.length - 1]; + if (lastChild && lastChild.nodeName === "P") { + main.removeChild(lastChild); + } + + // Initialize `searchLast'. + searchLast = lastId(); + + // Simulate a scroll if we have the space to load more images. + if (window.innerHeight >= document.body.offsetHeight) { + scrollHandler(); + } +}); diff --git a/templates/index.hbs b/templates/index.hbs index db2202d..9f85a85 100644 --- a/templates/index.hbs +++ b/templates/index.hbs @@ -9,9 +9,13 @@

Kona

-
+
{{#each images}} - +
+ + + +
{{/each}} {{#if next_page}}

next

@@ -35,5 +39,6 @@ + -- cgit v1.3