ngx-scroll-position-restoration
Version:
Scroll position restoration in Angular.
2 lines • 10.1 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@angular/core"),require("@angular/common"),require("@angular/router"),require("rxjs"),require("rxjs/operators"),require("@medv/finder")):"function"==typeof define&&define.amd?define("ngx-scroll-position-restoration",["exports","@angular/core","@angular/common","@angular/router","rxjs","rxjs/operators","@medv/finder"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["ngx-scroll-position-restoration"]={},t.ng.core,t.ng.common,t.ng.router,t.rxjs,t.rxjs.operators,t.finder)}(this,(function(t,e,o,r,i,n,a){"use strict";Object.create;function s(t){var e="function"==typeof Symbol&&Symbol.iterator,o=e&&t[e],r=0;if(o)return o.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function l(t,e){var o="function"==typeof Symbol&&t[Symbol.iterator];if(!o)return t;var r,i,n=o.call(t),a=[];try{for(;(void 0===e||e-- >0)&&!(r=n.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(o=n.return)&&o.call(n)}finally{if(i)throw i.error}}return a}Object.create;var c="__window-selector__";function u(t){return t instanceof Window?window.scrollY:t.scrollTop}function d(t){return t instanceof Window?c:document.body.contains(t)?a.finder(t):null}function p(t,e){return t instanceof Window?(t.scrollTo(0,e),t.scrollY):t instanceof Element?(t.scrollTop=e,t.scrollTop):null}function g(t){return t===c?window:document.querySelector(t)}var f=new e.InjectionToken("ngx_scroll_position_restoration_config_injection_token"),h=function(){function t(t,e,o,r){this.router=t,this.zone=e,this.platformId=o,this.config=r,this.applyStateToDomTimer=0,this.currentPageState={},this.lastNavigationStartAt=0,this.navigationIDs=[],this.pageStates={},this.scrolledElements=new Set,this.maximumNumberOfCachedPageStates=20,this.serviceDestroyed$=new i.Subject}return t.prototype.initialize=function(){var t=this;o.isPlatformServer(this.platformId)||(this.setupScrollBinding(),this.router.events.pipe(n.takeUntil(this.serviceDestroyed$)).subscribe((function(e){e instanceof r.NavigationStart?t.handleNavigationStart(e):e instanceof r.NavigationEnd&&t.handleNavigationEnd()})),this.disableBrowserDefaultScrollRestoration())},t.prototype.ngOnDestroy=function(){this.serviceDestroyed$.next(),this.serviceDestroyed$.complete()},t.prototype.clearSavedWindowScrollTopInLastNavigation=function(){var t=this.navigationIDs[this.navigationIDs.length-1];t&&(this.config.debug&&this.pageStates[t][c]&&console.log('Navigation in a "secondary" router-outlet - Remove window scroll position from recorded scroll positions.'),delete this.pageStates[t][c])},t.prototype.applyPageStateToDom=function(t){var e=this;if(this.config.debug&&this.debugPageState(t,"Attempting to reapply scroll positions after a popstate navigation (backward or forward)."),!this.objectIsEmpty(t)){var o=Object.assign({},t);this.zone.runOutsideAngular((function(){var t=Date.now();e.applyStateToDomTimer=setInterval((function(){for(var r in o){var i=g(r);if(i)if(e.scrolledElements.has(i))delete o[r];else{var n=o[r];p(i,n)===n&&delete o[r]}}(e.objectIsEmpty(o)||Date.now()-t>=e.config.pollDuration)&&(clearTimeout(e.applyStateToDomTimer),e.config.debug&&(e.objectIsEmpty(o)?console.log("%c Successfully reapplied all recorded scroll positions to the DOM.","color: #2ecc71"):(console.warn("Could not reapply following recorded scroll positions to the DOM after a poll duration of: "+e.config.pollDuration+" milliseconds:"),e.debugPageState(o))))}),e.config.pollCadence)}))}},t.prototype.getPageStateFromNodes=function(t){var e={};return t.forEach((function(t){var o=d(t);o&&(e[o]=u(t))})),e},t.prototype.objectIsEmpty=function(t){for(var e in t)return!1;return!0},t.prototype.handleNavigationStart=function(t){this.lastNavigationStartAt=Date.now(),this.navigationID=t.id,this.restoredNavigationID=t.restoredState?t.restoredState.navigationId:null,clearTimeout(this.applyStateToDomTimer),Object.assign(this.currentPageState,this.getPageStateFromNodes(this.scrolledElements)),this.scrolledElements.clear(),this.config.debug&&this.debugPageState(this.currentPageState,"Recorded scroll positions.")},t.prototype.handleNavigationEnd=function(){var t=this.currentPageState;if(this.currentPageState=this.pageStates[this.navigationID]={},this.restoredNavigationID)this.restoredNavigationID&&this.pageStates[this.restoredNavigationID]&&this.applyPageStateToDom(Object.assign(this.currentPageState,this.pageStates[this.restoredNavigationID]));else for(var e in t){var o=g(e);o&&(u(o)===t[e]&&(this.currentPageState[e]=t[e],this.config.debug&&(console.group("Pulling scroll position from previous page state in current page state."),console.log({selector:e,scrollPosition:this.currentPageState[e]}),console.groupEnd())))}for(this.navigationIDs.push(this.navigationID);this.navigationIDs.length>this.maximumNumberOfCachedPageStates;)delete this.pageStates[this.navigationIDs.shift()]},t.prototype.setupScrollBinding=function(){var t=this;this.zone.runOutsideAngular((function(){var e;window.addEventListener("scroll",(function(o){Date.now()-t.lastNavigationStartAt<100||(e=function(t){var e=t.target;return e instanceof HTMLDocument?window:e instanceof Element?e:null}(o))&&t.scrolledElements.add(e)}),!0)}))},t.prototype.debugPageState=function(t,e){var o,r;if(!this.objectIsEmpty(t)){console.group(e||"");try{for(var i=s(Object.entries(t)),n=i.next();!n.done;n=i.next()){var a=l(n.value,2),c=a[0],u=a[1];console.log({selector:c,scrollPosition:u})}}catch(t){o={error:t}}finally{try{n&&!n.done&&(r=i.return)&&r.call(i)}finally{if(o)throw o.error}}console.groupEnd()}},t.prototype.disableBrowserDefaultScrollRestoration=function(){"scrollRestoration"in history&&(history.scrollRestoration="manual")},t}();h.decorators=[{type:e.Injectable}],h.ctorParameters=function(){return[{type:r.Router},{type:e.NgZone},{type:String,decorators:[{type:e.Inject,args:[e.PLATFORM_ID]}]},{type:void 0,decorators:[{type:e.Inject,args:[f]}]}]};var v="primary",y=function(){function t(t,e,o,r,n,a){this.elementRef=t,this.router=e,this.routerOutlet=o,this.ngxScrollPositionRestorationService=r,this.platformId=n,this.config=a,this.recordedScrollPositions=[],this.directiveDestroyed$=new i.Subject}return t.prototype.ngOnInit=function(){var t=this;o.isPlatformServer(this.platformId)||(this.routerOutlet.activateEvents.pipe(n.takeUntil(this.directiveDestroyed$)).subscribe((function(){return t.handleActivateEvent()})),this.routerOutlet.deactivateEvents.pipe(n.takeUntil(this.directiveDestroyed$)).subscribe((function(){return t.handleDectivateEvent()})),this.router.events.pipe(n.takeUntil(this.directiveDestroyed$)).subscribe((function(e){return t.handleNavigationEvent(e)})))},t.prototype.ngOnDestroy=function(){this.directiveDestroyed$.next(),this.directiveDestroyed$.complete()},t.prototype.handleActivateEvent=function(){var t,e,o,r=this.routerOutlet.activatedRoute.outlet,i="function"==typeof this.router.getCurrentNavigation?this.router.getCurrentNavigation():null;if(r===v||(null===(o=null==i?void 0:i.extras)||void 0===o?void 0:o.skipLocationChange)||this.ngxScrollPositionRestorationService.clearSavedWindowScrollTopInLastNavigation(),this.isRootRouterOutlet(this.routerOutlet.activatedRoute)&&"imperative"===this.navigationTrigger&&this.routerOutlet.activatedRoute.outlet===v)p(window,0),this.config.debug&&console.log("Imperative navigation: scrolled to the top (scrollTop = 0) of the window.");else{if(this.config.debug&&(console.group('router-outlet ("'+(this.elementRef.nativeElement.getAttribute("name")||v)+'") - Reapply recorded scroll positions.'),console.log(this.recordedScrollPositions.slice()),console.groupEnd()),0===this.recordedScrollPositions.length)return;try{for(var n=s(this.recordedScrollPositions),a=n.next();!a.done;a=n.next()){var l=a.value,c=l.elementSelector,u=l.scrollPosition;if(c){var d=g(c);d&&p(d,u)}}}catch(e){t={error:e}}finally{try{a&&!a.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}this.recordedScrollPositions=[]}},t.prototype.handleDectivateEvent=function(){for(var t=this.elementRef.nativeElement.parentNode;t&&"BODY"!==t.tagName;){if(1===t.nodeType){var e=u(t),o=d(t);this.recordedScrollPositions.push({elementSelector:o,target:t,scrollPosition:e})}t=t.parentNode}this.config.debug&&(console.group('router-outlet ("'+(this.elementRef.nativeElement.getAttribute("name")||v)+'") - Recorded scroll positions.'),console.log(this.recordedScrollPositions.slice()),console.groupEnd())},t.prototype.handleNavigationEvent=function(t){t instanceof r.NavigationStart&&(this.navigationTrigger=t.navigationTrigger),t instanceof r.NavigationEnd&&(this.recordedScrollPositions=[])},t.prototype.isRootRouterOutlet=function(t){var e,o,r,i,n=t.component,a=null===(i=null===(r=t.parent)||void 0===r?void 0:r.routeConfig)||void 0===i?void 0:i.children;if(!Array.isArray(a))return!0;try{for(var l=s(a),c=l.next();!c.done;c=l.next()){if(c.value.component===n)return!1}}catch(t){e={error:t}}finally{try{c&&!c.done&&(o=l.return)&&o.call(l)}finally{if(e)throw e.error}}return!0},t}();y.decorators=[{type:e.Directive,args:[{selector:"router-outlet"}]}],y.ctorParameters=function(){return[{type:e.ElementRef},{type:r.Router},{type:r.RouterOutlet},{type:h},{type:String,decorators:[{type:e.Inject,args:[e.PLATFORM_ID]}]},{type:void 0,decorators:[{type:e.Inject,args:[f]}]}]};var m={pollDuration:3e3,pollCadence:50,debug:!1},S=function(){function t(e){t.serviceInitialized||(e.initialize(),t.serviceInitialized=!0)}return t.forRoot=function(e){return{ngModule:t,providers:[{provide:f,useValue:Object.assign(m,e)}]}},t}();S.serviceInitialized=!1,S.decorators=[{type:e.NgModule,args:[{declarations:[y],exports:[y],providers:[h]}]}],S.ctorParameters=function(){return[{type:h}]},t.CustomRouterOutletDirective=y,t.NgxScrollPositionRestorationModule=S,t["ɵa"]=f,t["ɵb"]=h,t["ɵc"]=m,Object.defineProperty(t,"__esModule",{value:!0})}));
//# sourceMappingURL=ngx-scroll-position-restoration.umd.min.js.map