diff --git a/lib/Router.ts b/lib/Router.ts index 4fc279c..ec67a1d 100644 --- a/lib/Router.ts +++ b/lib/Router.ts @@ -11,6 +11,7 @@ export class Router { events = new $EventManager().register('notfound', 'load'); basePath: string; static currentPath: URL = new URL(location.href); + static readonly SCROLL_HISTORY_KEY = '$router_scroll_history'; constructor(basePath: string, view?: $View) { this.basePath = basePath; this.$view = view ?? new $View(); @@ -50,6 +51,7 @@ export class Router { history.pushState(routeData, '', url); Router.currentPath = new URL(location.href); $.routers.forEach(router => router.resolvePath()) + Router.recoveryScrollPosition(); Router.events.fire('pathchange', {prevURL: prevPath, nextURL: Router.currentPath, navigation: 'Forward'}); return this; } @@ -91,6 +93,7 @@ export class Router { const prevPath = Router.currentPath; Router.index = history.state.index; this.resolvePath(); + Router.recoveryScrollPosition(); Router.currentPath = new URL(location.href); Router.events.fire('pathchange', {prevURL: prevPath, nextURL: Router.currentPath, navigation: 'Forward'}); }).bind(this) @@ -170,6 +173,48 @@ export class Router { } } + static recoveryScrollPosition() { + const history = this.getScrollHistory(this.index, location.href); + if (!history) { + document.documentElement.scrollTop = 0; + this.setScrollHistory(this.index, location.href, 0); + } + else document.documentElement.scrollTop = history.scroll; + } + + static getScrollHistory(pageIndex: number, href: string) { + const data = this.scrollHistoryData; + if (!data || !data[pageIndex]) return null; + return data[pageIndex].href === href ? data[pageIndex] : null; + } + + static setScrollHistory(pageIndex: number, href: string, scroll: number) { + let history = this.scrollHistoryData; + if (!history) { + history = {[pageIndex]: {href, scroll}}; + sessionStorage.setItem(this.SCROLL_HISTORY_KEY, JSON.stringify(history)); + } + else { + const data = history[pageIndex]; + if (data && data.href !== href) { + let i = 0; + while (history[pageIndex + i]) { + delete history[pageIndex + i]; + i++; + } + } + history[pageIndex] = {href, scroll} + sessionStorage.setItem(this.SCROLL_HISTORY_KEY, JSON.stringify(history)); + } + return history[pageIndex]; + } + + static get scrollHistoryData() { + const json = sessionStorage.getItem(this.SCROLL_HISTORY_KEY) + if (!json) return null; + return JSON.parse(json) as {[key: number]: RouteScrollHistoryData}; + } + static on(type: K, callback: (...args: RouterGlobalEventMap[K]) => any) { this.events.on(type, callback); return this } static off(type: K, callback: (...args: RouterGlobalEventMap[K]) => any) { this.events.off(type, callback); return this } static once(type: K, callback: (...args: RouterGlobalEventMap[K]) => any) { this.events.once(type, callback); return this } @@ -187,4 +232,13 @@ interface RouterGlobalEventMap { type RouteData = { index: number; data: {[key: string]: any}; -} \ No newline at end of file +} + +type RouteScrollHistoryData = { + href: string; + scroll: number; +} + +window.addEventListener('scroll', () => { + Router.setScrollHistory(Router.index, location.href, document.documentElement.scrollTop); +}) \ No newline at end of file diff --git a/package.json b/package.json index 80a356a..3fe6546 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,21 @@ { "name": "@elexis/router", "description": "A simple router for ElexisJS", - "version": "0.1.0", + "version": "0.1.1", "author": { "name": "defaultkavy", "email": "defaultkavy@gmail.com", - "url": "https://github.com/defaultkavy" + "url": "https://git.defaultkavy.com/defaultkavy" }, "repository": { "type": "git", - "url": "git+https://github.com/elexis/router.git" + "url": "git+https://git.defaultkavy.com/elexis/router.git" }, "module": "index.ts", "bugs": { - "url": "https://github.com/elexis/router/issues" + "url": "https://git.defaultkavy.com/elexis/router/issues" }, - "homepage": "https://github.com/elexis/router", + "homepage": "https://git.defaultkavy.com/elexis/router", "keywords": ["router", "web", "front-end", "lib", "fluent", "framework"], "license": "ISC", "type": "module",