client/general: improve scrolling

This commit is contained in:
rr- 2016-07-13 17:18:28 +02:00
parent 5d8dd9cb05
commit 394e51ed21
16 changed files with 57 additions and 38 deletions

View file

@ -24,12 +24,6 @@ router.enter(
(ctx, next) => {
mousetrap.reset();
next();
window.requestAnimationFrame(
() => {
window.scrollTo(
ctx.state.scrollX || 0,
ctx.state.scrollY || 0);
});
});
// register controller routes

View file

@ -390,17 +390,15 @@ function replaceContent(target, source) {
}
}
function scrollToHash() {
window.setTimeout(() => {
if (!window.location.hash) {
return;
}
const el = document.getElementById(
window.location.hash.replace(/#/, ''));
if (el) {
el.scrollIntoView();
}
}, 10);
function syncScrollPosition() {
window.requestAnimationFrame(
() => {
if (history.state.hasOwnProperty('scrollX')) {
window.scrollTo(history.state.scrollX, history.state.scrollY);
} else {
window.scrollTo(0, 0);
}
});
}
function slideDown(element) {
@ -470,7 +468,7 @@ module.exports = {
decorateValidator: decorateValidator,
makeVoidElement: makeVoidElement,
makeNonVoidElement: makeNonVoidElement,
scrollToHash: scrollToHash,
syncScrollPosition: syncScrollPosition,
slideDown: slideDown,
slideUp: slideUp,
monitorNodeRemoval: monitorNodeRemoval,

View file

@ -11,6 +11,7 @@ class EmptyView {
constructor() {
this._hostNode = document.getElementById('content-holder');
views.replaceContent(this._hostNode, template());
views.syncScrollPosition();
}
showError(message) {

View file

@ -11,7 +11,7 @@ class EndlessPageView {
this._hostNode = document.getElementById('content-holder');
this._active = true;
this._working = 0;
this._init = true;
this._init = false;
this.threshold = window.innerHeight / 3;
this.minPageShown = null;
@ -30,7 +30,11 @@ class EndlessPageView {
ctx.headerRenderer(ctx.headerContext);
}
this._loadPage(ctx, ctx.parameters.page, true);
this._loadPage(ctx, ctx.parameters.page, true).then(pageNode => {
if (ctx.parameters.page !== 1) {
pageNode.scrollIntoView();
}
});
this._probePageLoad(ctx);
}
@ -87,26 +91,32 @@ class EndlessPageView {
_loadPage(ctx, pageNumber, append) {
this._working++;
ctx.requestPage(pageNumber).then(response => {
if (!this._active) {
this._working--;
return Promise.reject();
}
this.totalPages = Math.ceil(response.total / response.pageSize);
window.requestAnimationFrame(() => {
this._renderPage(
ctx, pageNumber, append, response);
return new Promise((resolve, reject) => {
ctx.requestPage(pageNumber).then(response => {
if (!this._active) {
this._working--;
return Promise.reject();
}
this.totalPages = Math.ceil(response.total / response.pageSize);
window.requestAnimationFrame(() => {
let pageNode = this._renderPage(
ctx, pageNumber, append, response);
this._working--;
resolve(pageNode);
});
}, response => {
this.showError(response.description);
this._working--;
reject();
});
}, response => {
this.showError(response.description);
this._working--;
});
}
_renderPage(ctx, pageNumber, append, response) {
let pageNode = null;
if (response.total) {
const pageNode = pageTemplate({
pageNode = pageTemplate({
page: pageNumber,
totalPages: this.totalPages,
});
@ -128,7 +138,7 @@ class EndlessPageView {
if (append) {
this._pagesHolderNode.appendChild(pageNode);
if (this._init && pageNumber !== 1) {
if (!this._init && pageNumber !== 1) {
window.scroll(0, pageNode.getBoundingClientRect().top);
}
} else {
@ -141,7 +151,9 @@ class EndlessPageView {
} else if (response.total <= (pageNumber - 1) * response.pageSize) {
this.showInfo('No data to show');
}
this._init = false;
this._init = true;
return pageNode;
}
showSuccess(message) {

View file

@ -59,7 +59,7 @@ class HelpView {
}
views.replaceContent(this._hostNode, sourceNode);
views.scrollToHash();
views.syncScrollPosition();
}
}

View file

@ -20,6 +20,7 @@ class HomeView {
const sourceNode = template(ctx);
views.replaceContent(this._hostNode, sourceNode);
views.syncScrollPosition();
if (this._formNode) {
this._tagAutoCompleteControl = new TagAutoCompleteControl(

View file

@ -16,6 +16,7 @@ class LoginView extends events.EventTarget {
passwordPattern: config.passwordRegex,
canSendMails: config.canSendMails,
}));
views.syncScrollPosition();
views.decorateValidator(this._formNode);
this._userNameFieldNode.setAttribute('pattern', config.userNameRegex);

View file

@ -107,6 +107,8 @@ class ManualPageView {
if (response.total <= (currentPage - 1) * response.pageSize) {
this.showInfo('No data to show');
}
views.syncScrollPosition();
}, response => {
this.showError(response.description);
});

View file

@ -11,6 +11,7 @@ class NotFoundView {
const sourceNode = template({path: path});
views.replaceContent(this._hostNode, sourceNode);
views.syncScrollPosition();
}
}

View file

@ -11,8 +11,9 @@ class PasswordResetView extends events.EventTarget {
this._hostNode = document.getElementById('content-holder');
views.replaceContent(this._hostNode, template());
views.decorateValidator(this._formNode);
views.syncScrollPosition();
views.decorateValidator(this._formNode);
this._hostNode.addEventListener('submit', e => {
e.preventDefault();
this.dispatchEvent(new CustomEvent('submit', {

View file

@ -23,6 +23,7 @@ class PostView {
const postContainerNode = sourceNode.querySelector('.post-container');
const sidebarNode = sourceNode.querySelector('.sidebar');
views.replaceContent(this._hostNode, sourceNode);
views.syncScrollPosition();
const postViewNode = document.body.querySelector('.content-wrapper');
const topNavigationNode =

View file

@ -14,6 +14,7 @@ class RegistrationView extends events.EventTarget {
userNamePattern: config.userNameRegex,
passwordPattern: config.passwordRegex,
}));
views.syncScrollPosition();
views.decorateValidator(this._formNode);
this._formNode.addEventListener('submit', e => this._evtSubmit(e));
}

View file

@ -12,8 +12,9 @@ class SettingsView extends events.EventTarget {
this._hostNode = document.getElementById('content-holder');
views.replaceContent(
this._hostNode, template({browsingSettings: ctx.settings}));
views.decorateValidator(this._formNode);
views.syncScrollPosition();
views.decorateValidator(this._formNode);
this._formNode.addEventListener('submit', e => this._evtSubmit(e));
}

View file

@ -14,6 +14,7 @@ class TagCategoriesView extends events.EventTarget {
this._hostNode = document.getElementById('content-holder');
views.replaceContent(this._hostNode, template(ctx));
views.syncScrollPosition();
views.decorateValidator(this._formNode);
const categoriesToAdd = Array.from(ctx.tagCategories);

View file

@ -52,6 +52,8 @@ class TagView extends events.EventTarget {
} else {
this._view = new TagSummaryView(ctx);
}
views.syncScrollPosition();
}
clearMessages() {

View file

@ -47,6 +47,8 @@ class UserView extends events.EventTarget {
} else {
this._view = new UserSummaryView(ctx);
}
views.syncScrollPosition();
}
clearMessages() {