ng2-ui / scrollable

Angular2 Automatic Scroll Detection With Animation
17 stars 10 forks source link

Universal support for this library #5

Open rsach opened 7 years ago

rsach commented 7 years ago

i'm trying to use this lib in a universal project . can you work around with the use of window object?

ReferenceError: window is not defined

allenhwkim commented 7 years ago

@rsach thanks for reporting this However, I have no idea at this moment. Is it the same kind of issue like this, https://github.com/ng2-ui/map/issues/49?

I would be very appreciated if you make a pull request for this.

rsach commented 7 years ago

the error is kind of the same

rsach commented 7 years ago

hi, i did some changes in the directive to make it universal friendly

`import { Directive, ElementRef, Input, Output, EventEmitter,Renderer,HostListener } from '@angular/core'; import { elementVisible } from '@ngui/utils'; import { isPlatformBrowser } from '@angular/common'; import { PLATFORM_ID,Inject } from '@angular/core';

@Directive({ selector: '[ngui-scrollable]' }) export class NguiScrollableDirective {

@Input() horizontal: boolean; @Output() elementVisible = new EventEmitter();

sections: Element[] = []; el: HTMLElement; visible: any = elementVisible; private isBrowser: boolean = isPlatformBrowser(this.platform_id);

constructor(el: ElementRef ,private renderer: Renderer,@Inject(PLATFORM_ID) private platform_id) { this.el = el.nativeElement;

renderer.setElementStyle(el.nativeElement,'position','relative');

}

// setup list of sections // ngOnInit(): void { // for (var i = 0; i< this.el.children.length; i++) { // let childEl = this.el.children[i]; // childEl.id && this.sections.push(childEl); // }

// }

ngAfterViewInit(): void{ for (var i = 0; i< this.el.children.length; i++) { let childEl = this.el.children[i]; childEl.id && this.sections.push(childEl); }

let elToListenScroll = this.el;
if(this.isBrowser){
  let thisElStyle = window.getComputedStyle(this.el);
  let elToListenScroll = thisElStyle.overflow === 'auto' ? this.el : window;
}
this.listenScrollOn(elToListenScroll);  

}

private listenScrollOn(el: HTMLElement | Window): void {

    this.renderer.listen(<HTMLElement>el, 'scroll', (event) => {
  let elScrolledToVisible: HTMLElement = null;
  for (let i = 0; i< this.sections.length; i++) {
    let section = <HTMLElement>this.sections[i];
    let visible = this.visible(section, <HTMLElement>el);
    if (this.horizontal && (visible.left || visible.right)) {
      elScrolledToVisible = section;
      break;
    } else if (!this.horizontal && (visible.top || visible.bottom)) {
      elScrolledToVisible = section;
      break;
    }
  }
  elScrolledToVisible && this.elementVisible.emit(elScrolledToVisible)
});

}

static scrollTo( selector: string, parentSelector?: string, horizontal? : boolean, distance? : number ): void { // argument validation let parentEl: HTMLElement, targetEl: HTMLElement; parentSelector = parentSelector || 'body'; targetEl = document.querySelector(selector); if (!targetEl) { throw Invalid selector ${selector}; } parentEl = document.querySelector(parentSelector); if (!parentEl) { throw Invalid parent selector ${parentSelector}; }

// detect the current environment
let parentElStyle = window.getComputedStyle(parentEl);
let scrollContainerEl = parentElStyle.overflow === 'auto' ?
  parentEl : document.body;
let currentScrollTop = scrollContainerEl.scrollTop;
let currentScrollLeft = scrollContainerEl.scrollLeft;

// determine targetOffsetTop(or Left);
let targetOffsetTop: number;
let targetOffsetLeft: number;
if (scrollContainerEl === document.body) {
  let bodyRect = document.body.getBoundingClientRect();
  let targetRect = targetEl.getBoundingClientRect();
  targetOffsetTop = targetRect.top - bodyRect.top;
  targetOffsetLeft = targetRect.left - bodyRect.left;
} else {
  targetOffsetTop = targetEl.offsetTop;
  targetOffsetLeft = targetEl.offsetLeft;
}
if (distance) {
  currentScrollTop += distance;
  currentScrollLeft += distance;
}

// start scrolling
let step = horizontal ?
  Math.ceil((targetOffsetLeft - currentScrollLeft) / 10) :
  Math.ceil((targetOffsetTop - currentScrollTop) / 10);
let scrollProp = horizontal ? 'scrollLeft' : 'scrollTop';
(function loop(i: number, prop: any): void {
  setTimeout(function main() {
    scrollContainerEl[prop] += step;
    i > 1 && loop(i - 1, prop);
  }, 50);
}(10, scrollProp));

}

} `

allenhwkim commented 7 years ago

@rsach can you make a PR, Pull Request, with that code?