szurubooru/client/js/views/endless_page_view.js

143 lines
5.1 KiB
JavaScript
Raw Normal View History

2016-04-12 23:49:46 +02:00
'use strict';
const page = require('page');
2016-04-12 23:49:46 +02:00
const events = require('../events.js');
const misc = require('../util/misc.js');
const views = require('../util/views.js');
class EndlessPageView {
constructor() {
this.holderTemplate = views.getTemplate('endless-pager');
this.pageTemplate = views.getTemplate('endless-pager-page');
}
render(ctx) {
const target = document.getElementById('content-holder');
const source = this.holderTemplate();
const pagesHolder = source.querySelector('.pages-holder');
views.listenToMessages(target);
views.showView(target, source);
const threshold = window.innerHeight / 3;
if (ctx.state && ctx.state.html) {
console.log('Loading from state');
this.minPageShown = ctx.state.minPageShown;
this.maxPageShown = ctx.state.maxPageShown;
this.totalPages = ctx.state.totalPages;
this.currentPage = ctx.state.currentPage;
} else {
this.minPageShown = null;
this.maxPageShown = null;
this.totalPages = null;
this.currentPage = null;
}
2016-04-12 23:49:46 +02:00
this.fetching = false;
this.updater = () => {
let topPage = null;
let allPageNodes =
pagesHolder.querySelectorAll('.page');
for (let pageNode of allPageNodes) {
if (pageNode.getBoundingClientRect().bottom >= 0) {
topPage = parseInt(pageNode.getAttribute('data-page'));
break;
}
}
if (topPage !== this.currentPage) {
page.replace(
ctx.clientUrl.format({page: topPage}),
{
minPageShown: this.minPageShown,
maxPageShown: this.maxPageShown,
totalPages: this.totalPages,
currentPage: this.currentPage,
html: pagesHolder.innerHTML,
scrollX: window.scrollX,
scrollY: window.scrollY,
},
false,
false);
this.currentPage = topPage;
}
2016-04-12 23:49:46 +02:00
if (this.fetching || this.totalPages === null) {
return;
}
let scrollHeight =
document.documentElement.scrollHeight -
document.documentElement.clientHeight;
if (this.minPageShown > 1 && window.scrollY - threshold < 0) {
this.loadPage(pagesHolder, ctx, this.minPageShown - 1, false);
} else if (this.maxPageShown < this.totalPages &&
window.scrollY + threshold > scrollHeight) {
this.loadPage(pagesHolder, ctx, this.maxPageShown + 1, true);
}
};
if (ctx.state && ctx.state.html) {
pagesHolder.innerHTML = ctx.state.html;
window.scroll(ctx.state.scrollX, ctx.state.scrollY);
} else {
this.loadPage(pagesHolder, ctx, ctx.initialPage, true);
}
2016-04-12 23:49:46 +02:00
window.addEventListener('scroll', this.updater, true);
}
unrender() {
window.removeEventListener('scroll', this.updater, true);
}
loadPage(pagesHolder, ctx, pageNumber, append) {
2016-04-12 23:49:46 +02:00
this.fetching = true;
if (pageNumber < this.minPageShown || this.minPageShown === null) {
this.minPageShown = pageNumber;
2016-04-12 23:49:46 +02:00
}
if (pageNumber > this.maxPageShown || this.maxPageShown === null) {
this.maxPageShown = pageNumber;
2016-04-12 23:49:46 +02:00
}
ctx.requestPage(pageNumber).then(response => {
2016-04-12 23:49:46 +02:00
this.totalPages = Math.ceil(response.total / response.pageSize);
if (response.total) {
const pageNode = this.pageTemplate({
page: pageNumber,
2016-04-12 23:49:46 +02:00
totalPages: this.totalPages,
});
pageNode.setAttribute('data-page', pageNumber);
2016-04-12 23:49:46 +02:00
let pageRendererCtx = response;
pageRendererCtx.target = pageNode.querySelector(
2016-04-12 23:49:46 +02:00
'.page-content-holder');
ctx.pageRenderer.render(pageRendererCtx);
if (append) {
pagesHolder.appendChild(pageNode);
2016-04-12 23:49:46 +02:00
} else {
pagesHolder.prependChild(pageNode);
// note: with probability of 75%, if the user has scrolled
// with a mouse wheel, chrome 49 doesn't give a slightest
// fuck about this and loads all the way to page 1 at once
2016-04-12 23:49:46 +02:00
window.scroll(
window.scrollX,
window.scrollY + pageNode.offsetHeight);
2016-04-12 23:49:46 +02:00
}
}
this.fetching = false;
this.updater();
if (response.total <= (pageNumber - 1) * response.pageSize) {
2016-04-12 23:49:46 +02:00
events.notify(events.Info, 'No data to show');
}
}, response => {
events.notify(events.Error, response.description);
});
}
}
module.exports = EndlessPageView;