mirror of https://github.com/kiwix/libkiwix.git
Merge pull request #530 from kiwix/adding_dynamic_and_subset_loading
Kiwix Serve welcome page dynamic and subset loading (OPDS based)
This commit is contained in:
commit
672b4fc907
|
@ -4,3 +4,4 @@ subprojects/googletest-release*
|
||||||
*.class
|
*.class
|
||||||
build/
|
build/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
builddir/
|
||||||
|
|
|
@ -658,7 +658,7 @@ std::vector<std::string>
|
||||||
InternalServer::search_catalog(const RequestContext& request,
|
InternalServer::search_catalog(const RequestContext& request,
|
||||||
kiwix::OPDSDumper& opdsDumper)
|
kiwix::OPDSDumper& opdsDumper)
|
||||||
{
|
{
|
||||||
auto filter = kiwix::Filter().valid(true).local(true).remote(true);
|
auto filter = kiwix::Filter().valid(true).local(true);
|
||||||
string query("<Empty query>");
|
string query("<Empty query>");
|
||||||
size_t count(10);
|
size_t count(10);
|
||||||
size_t startIndex(0);
|
size_t startIndex(0);
|
||||||
|
|
|
@ -19,6 +19,7 @@ skin/jquery-ui/jquery-ui.theme.min.css
|
||||||
skin/jquery-ui/jquery-ui.min.css
|
skin/jquery-ui/jquery-ui.min.css
|
||||||
skin/caret.png
|
skin/caret.png
|
||||||
skin/taskbar.js
|
skin/taskbar.js
|
||||||
|
skin/index.js
|
||||||
skin/taskbar.css
|
skin/taskbar.css
|
||||||
skin/block_external.js
|
skin/block_external.js
|
||||||
templates/search_result.html
|
templates/search_result.html
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
(function() {
|
||||||
|
const root = $(`link[type='root']`).attr('href');
|
||||||
|
let isFetching = false;
|
||||||
|
const incrementalLoadingParams = {
|
||||||
|
start: 0,
|
||||||
|
count: viewPortToCount()
|
||||||
|
};
|
||||||
|
|
||||||
|
function queryUrlBuilder() {
|
||||||
|
let url = `${root}/catalog/search?`;
|
||||||
|
url += Object.keys(incrementalLoadingParams).map(key => `${key}=${incrementalLoadingParams[key]}`).join("&");
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewPortToCount(){
|
||||||
|
return Math.floor(window.innerHeight/100 + 1)*(window.innerWidth>1000 ? 3 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInnerHtml(node, query) {
|
||||||
|
return node.querySelector(query).innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateBookHtml(book) {
|
||||||
|
const link = book.querySelector('link').getAttribute('href');
|
||||||
|
const title = getInnerHtml(book, 'title');
|
||||||
|
const description = getInnerHtml(book, 'summary');
|
||||||
|
const id = getInnerHtml(book, 'id');
|
||||||
|
const iconUrl = getInnerHtml(book, 'icon');
|
||||||
|
const articleCount = getInnerHtml(book, 'articleCount');
|
||||||
|
const mediaCount = getInnerHtml(book, 'mediaCount');
|
||||||
|
|
||||||
|
return `<a href='${link}' data-id='${id}'><div class='book'>
|
||||||
|
<div class='book__background' style="background-image: url('${iconUrl}');">
|
||||||
|
<div class='book__title' title='${title}'>${title}</div>
|
||||||
|
<div class='book__description' title='${description}'>${description}</div>
|
||||||
|
<div class='book__info'>${articleCount} articles, ${mediaCount} medias</div>
|
||||||
|
</div>
|
||||||
|
</div></a>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadAndDisplayBooks() {
|
||||||
|
isFetching = true;
|
||||||
|
fetch(queryUrlBuilder()).then(async (resp) => {
|
||||||
|
const data = new window.DOMParser().parseFromString(await resp.text(), 'application/xml');
|
||||||
|
const books = data.querySelectorAll('entry');
|
||||||
|
let bookHtml = '';
|
||||||
|
books.forEach((book) => {bookHtml += generateBookHtml(book)});
|
||||||
|
document.querySelector('.book__list').innerHTML += bookHtml;
|
||||||
|
incrementalLoadingParams.start += books.length;
|
||||||
|
if (books.length < incrementalLoadingParams.count) {
|
||||||
|
incrementalLoadingParams.count = 0;
|
||||||
|
}
|
||||||
|
isFetching = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadSubset() {
|
||||||
|
if (!isFetching &&
|
||||||
|
incrementalLoadingParams.count &&
|
||||||
|
window.innerHeight + window.scrollY >= document.body.offsetHeight
|
||||||
|
) {
|
||||||
|
loadAndDisplayBooks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('resize', async () => {
|
||||||
|
incrementalLoadingParams.count = incrementalLoadingParams.count && viewPortToCount();
|
||||||
|
loadSubset();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('scroll', loadSubset);
|
||||||
|
|
||||||
|
window.onload = async () => {
|
||||||
|
loadAndDisplayBooks();
|
||||||
|
}
|
||||||
|
})();
|
|
@ -1,66 +1,96 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>Welcome to Kiwix Server</title>
|
<title>Welcome to Kiwix Server</title>
|
||||||
<script type="text/javascript" src="{{root}}/skin/jquery-ui/external/jquery/jquery.js"></script>
|
<script
|
||||||
<script type="text/javascript" src="{{root}}/skin/jquery-ui/jquery-ui.min.js"></script>
|
type="text/javascript"
|
||||||
<link type="text/css" href="{{root}}/skin/jquery-ui/jquery-ui.min.css" rel="Stylesheet" />
|
src="{{root}}/skin/jquery-ui/external/jquery/jquery.js"
|
||||||
<link type="text/css" href="{{root}}/skin/jquery-ui/jquery-ui.theme.min.css" rel="Stylesheet" />
|
></script>
|
||||||
<style>
|
<script
|
||||||
body {
|
type="text/javascript"
|
||||||
background:
|
src="{{root}}/skin/jquery-ui/jquery-ui.min.js"
|
||||||
radial-gradient(#EEEEEE 15%, transparent 16%) 0 0,
|
></script>
|
||||||
radial-gradient(#EEEEEE 15%, transparent 16%) 8px 8px,
|
<link
|
||||||
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
|
type="text/css"
|
||||||
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
|
href="{{root}}/skin/jquery-ui/jquery-ui.min.css"
|
||||||
background-color:#E8E8E8;
|
rel="Stylesheet"
|
||||||
background-size:16px 16px;
|
/>
|
||||||
margin-left: auto;
|
<link
|
||||||
margin-right: auto;
|
type="text/css"
|
||||||
max-width: 1100px;
|
href="{{root}}/skin/jquery-ui/jquery-ui.theme.min.css"
|
||||||
}
|
rel="Stylesheet"
|
||||||
.book__list { text-align: center; }
|
/>
|
||||||
.book {
|
<style>
|
||||||
display: inline-block; vertical-align: bottom; margin: 8px; padding: 12px 15px; width: 300px;
|
body {
|
||||||
border: 1px solid #ccc; border-radius: 8px;
|
background: radial-gradient(#eeeeee 15%, transparent 16%) 0 0,
|
||||||
text-align: left; color: #000; font-family: sans-serif; font-size: 13px;
|
radial-gradient(#eeeeee 15%, transparent 16%) 8px 8px,
|
||||||
background-color:#F1F1F1;
|
radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 0 1px,
|
||||||
box-shadow: 2px 2px 5px 0px #ccc;
|
radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 8px 9px;
|
||||||
}
|
background-color: #e8e8e8;
|
||||||
.book:hover { background-color: #F9F9F9; box-shadow: none;}
|
background-size: 16px 16px;
|
||||||
.book__background { background-repeat: no-repeat; background-size: 48px 48px; background-position: top right; }
|
margin-left: auto;
|
||||||
.book__title {
|
margin-right: auto;
|
||||||
padding: 0 55px 0 0;overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
max-width: 1100px;
|
||||||
font-size: 18px; color: #0645ad; line-height: 1em;
|
}
|
||||||
}
|
.book__list {
|
||||||
.book__description {
|
text-align: center;
|
||||||
padding: 5px 55px 5px 0px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
}
|
||||||
font-size: 15px; line-height: 1em;
|
.book {
|
||||||
}
|
display: inline-block;
|
||||||
.book__info { color: #777; font-weight: bold; font-size: 13px; line-height: 1em; }
|
vertical-align: bottom;
|
||||||
</style>
|
margin: 8px;
|
||||||
<script type="text/javascript" src="{{root}}/skin/taskbar.js" async></script>
|
padding: 12px 15px;
|
||||||
</head>
|
width: 300px;
|
||||||
<body class="kiwix">
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: left;
|
||||||
|
color: #000;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
box-shadow: 2px 2px 5px 0px #ccc;
|
||||||
|
}
|
||||||
|
.book:hover {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.book__background {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 48px 48px;
|
||||||
|
background-position: top right;
|
||||||
|
}
|
||||||
|
.book__title {
|
||||||
|
padding: 0 55px 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #0645ad;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
.book__description {
|
||||||
|
padding: 5px 55px 5px 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
.book__info {
|
||||||
|
color: #777;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript" src="{{root}}/skin/index.js" async></script>
|
||||||
|
</head>
|
||||||
|
<body class="kiwix">
|
||||||
|
<div class="kiwix">
|
||||||
|
<div class="book__list"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="kiwix">
|
<div id="kiwixfooter">Powered by <a href="https://kiwix.org">Kiwix</a></div>
|
||||||
<div class='book__list'>
|
</body>
|
||||||
{{#books}}
|
|
||||||
<a href="{{root}}/{{name}}"><div class='book'>
|
|
||||||
<div class='book__background' style="background-image: url('{{root}}/meta?content={{#urlencoded}}{{{name}}}{{/urlencoded}}&name=favicon');">
|
|
||||||
<div class='book__title' title='{{title}}'>{{title}}</div>
|
|
||||||
<div class='book__description' title='{{description}}'>{{description}}</div>
|
|
||||||
<div class='book__info'>{{articleCount}} articles, {{mediaCount}} medias</div>
|
|
||||||
</div>
|
|
||||||
</div></a>
|
|
||||||
{{/books}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="kiwixfooter">
|
|
||||||
Powered by <a href="https://kiwix.org">Kiwix</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue