client/general: improve scrolling
This commit is contained in:
		
							parent
							
								
									5d8dd9cb05
								
							
						
					
					
						commit
						394e51ed21
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ class EmptyView {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._hostNode = document.getElementById('content-holder');
 | 
			
		||||
        views.replaceContent(this._hostNode, template());
 | 
			
		||||
        views.syncScrollPosition();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    showError(message) {
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -59,7 +59,7 @@ class HelpView {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        views.replaceContent(this._hostNode, sourceNode);
 | 
			
		||||
        views.scrollToHash();
 | 
			
		||||
        views.syncScrollPosition();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ class HomeView {
 | 
			
		||||
 | 
			
		||||
        const sourceNode = template(ctx);
 | 
			
		||||
        views.replaceContent(this._hostNode, sourceNode);
 | 
			
		||||
        views.syncScrollPosition();
 | 
			
		||||
 | 
			
		||||
        if (this._formNode) {
 | 
			
		||||
            this._tagAutoCompleteControl = new TagAutoCompleteControl(
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ class NotFoundView {
 | 
			
		||||
 | 
			
		||||
        const sourceNode = template({path: path});
 | 
			
		||||
        views.replaceContent(this._hostNode, sourceNode);
 | 
			
		||||
        views.syncScrollPosition();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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', {
 | 
			
		||||
 | 
			
		||||
@ -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 =
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,8 @@ class TagView extends events.EventTarget {
 | 
			
		||||
        } else {
 | 
			
		||||
            this._view = new TagSummaryView(ctx);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        views.syncScrollPosition();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clearMessages() {
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,8 @@ class UserView extends events.EventTarget {
 | 
			
		||||
        } else {
 | 
			
		||||
            this._view = new UserSummaryView(ctx);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        views.syncScrollPosition();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clearMessages() {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user