From b43a87d6275e7323a98de3766d242c9c2bba7d95 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 14 Feb 2017 14:39:03 +0200 Subject: [PATCH] feat: autoscroll menu implements #88 --- lib/components/SideMenu/side-menu.ts | 9 ++------ lib/polyfills.ts | 32 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/components/SideMenu/side-menu.ts b/lib/components/SideMenu/side-menu.ts index fbe3d7e7..306afbed 100644 --- a/lib/components/SideMenu/side-menu.ts +++ b/lib/components/SideMenu/side-menu.ts @@ -51,8 +51,6 @@ export class SideMenu extends BaseComponent implements OnInit, OnDestroy { private $resourcesNav: any; private $scrollParent: any; - private firstChange = true; - constructor(specMgr:SpecManager, elementRef:ElementRef, private scrollService:ScrollService, private menuService:MenuService, optionsService:OptionsService, private detectorRef:ChangeDetectorRef, private marker:Marker) { @@ -84,15 +82,12 @@ export class SideMenu extends BaseComponent implements OnInit, OnDestroy { //safari doesn't update bindings if not run changeDetector manually :( this.detectorRef.detectChanges(); - if (this.firstChange) { - this.scrollActiveIntoView(); - this.firstChange = false; - } + this.scrollActiveIntoView(); } scrollActiveIntoView() { let $item = this.$element.querySelector('li.active, label.active'); - if ($item) $item.scrollIntoView(); + if ($item) $item.scrollIntoViewIfNeeded(); } activateAndScroll(item) { diff --git a/lib/polyfills.ts b/lib/polyfills.ts index e3f69e14..7f830a8f 100644 --- a/lib/polyfills.ts +++ b/lib/polyfills.ts @@ -28,3 +28,35 @@ if (!IS_PRODUCTION) { Error.stackTraceLimit = Infinity; require('zone.js/dist/long-stack-trace-zone'); } + +interface Element { + scrollIntoViewIfNeeded(centerIfNeeded?: boolean): void; +}; + +if (!(Element).prototype.scrollIntoViewIfNeeded) { + (Element).prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) { + centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded; + + var parent = this.parentNode, + parentComputedStyle = window.getComputedStyle(parent, null), + parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')), + parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')), + overTop = this.offsetTop - parent.offsetTop < parent.scrollTop, + overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight), + overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft, + overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth), + alignWithTop = overTop && !overBottom; + + if ((overTop || overBottom) && centerIfNeeded) { + parent.scrollTop = this.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2; + } + + if ((overLeft || overRight) && centerIfNeeded) { + parent.scrollLeft = this.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2; + } + + if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) { + this.scrollIntoView(alignWithTop); + } + }; +}