diff --git a/sample/sample-v-ui-app/src/non-issues/scroller-not-first-parent-div/sub-app.html b/sample/sample-v-ui-app/src/non-issues/scroller-not-first-parent-div/sub-app.html new file mode 100644 index 0000000..42f0d5c --- /dev/null +++ b/sample/sample-v-ui-app/src/non-issues/scroller-not-first-parent-div/sub-app.html @@ -0,0 +1,61 @@ + diff --git a/sample/sample-v-ui-app/src/non-issues/scroller-not-first-parent-div/sub-app.ts b/sample/sample-v-ui-app/src/non-issues/scroller-not-first-parent-div/sub-app.ts new file mode 100644 index 0000000..fd390ff --- /dev/null +++ b/sample/sample-v-ui-app/src/non-issues/scroller-not-first-parent-div/sub-app.ts @@ -0,0 +1,43 @@ +interface IScrollContext { + isAtTop: boolean; + isAtBottom: boolean; + topIndex: number; +} + +export interface Person { + fname: string; + lname: string; +} + +const fNames = [ + // tslint:disable-next-line:max-line-length + 'Ford', 'Arthur', 'Trillian', 'Sneezy', 'Sleepy', 'Dopey', 'Doc', 'Happy', 'Bashful', 'Grumpy', 'Mufasa', 'Jørgen', 'Simba', 'Nala', 'Kiara', 'Kovu', 'Timon', 'Pumbaa', 'Rafiki', 'Shenzi' +]; +const lNames = [ + // tslint:disable-next-line:max-line-length + 'Prefect', 'Dent', 'Astra', 'Adams', 'Baker', 'Clark', 'Davis', 'Evans', 'Frank', 'Ghosh', 'Hills', 'Irwin', 'Jones', 'Klein', 'Lopez', 'Mason', 'Nalty', 'Ochoa', 'Patel', 'Quinn', 'Reily', 'Smith', 'Trott', 'Usman', 'Valdo', 'White', 'Xiang', 'Yakub', 'Zafar' +]; +export class PromiseGetMoreApp { + private people: Person[]; + + constructor() { + this.people = [ + { fname: fNames[0], lname: lNames[0] }, + { fname: fNames[1], lname: lNames[1] }, + { fname: fNames[2], lname: lNames[2] } + ]; + this.push30(undefined, 0); + } + + public async push30(scrollContext?: IScrollContext, count = 30) { + if (this.people.length < 200 && (!scrollContext || scrollContext.isAtBottom)) { + for (let i = 0; i < count; i++) { + this.people.push({ + fname: fNames[Math.floor(Math.random() * fNames.length)], + lname: lNames[Math.floor(Math.random() * lNames.length)] + }); + } + } + console.log('Population size:', this.people.length); + } +} diff --git a/sample/sample-v-ui-app/src/non-issues/sub-app.ts b/sample/sample-v-ui-app/src/non-issues/sub-app.ts index 6b42c32..12059cd 100644 --- a/sample/sample-v-ui-app/src/non-issues/sub-app.ts +++ b/sample/sample-v-ui-app/src/non-issues/sub-app.ts @@ -31,6 +31,12 @@ export class PromiseGetMoreApp { moduleId: PLATFORM.moduleName('./scroller-table-multiple-repeats/sub-app'), nav: true, title: 'Scroller + Table + Position Relative + Multiple Repeats' + }, + { + route: 'scroller-not-first-parent-div', + moduleId: PLATFORM.moduleName('./scroller-not-first-parent-div/sub-app'), + nav: true, + title: 'Scroller (not first parent) + Div' } ]).mapUnknownRoutes({ redirect: '', diff --git a/src/template-strategy-default.ts b/src/template-strategy-default.ts index f4597ee..8c3421a 100644 --- a/src/template-strategy-default.ts +++ b/src/template-strategy-default.ts @@ -1,11 +1,11 @@ import { IView, ITemplateStrategy } from './interfaces'; -import { insertBeforeNode } from './utilities-dom'; +import { insertBeforeNode, getScrollContainer } from './utilities-dom'; import { DOM } from 'aurelia-pal'; export class DefaultTemplateStrategy implements ITemplateStrategy { getScrollContainer(element: Element): HTMLElement { - return element.parentNode as HTMLElement; + return getScrollContainer(element); } moveViewFirst(view: IView, topBuffer: Element): void { diff --git a/src/utilities-dom.ts b/src/utilities-dom.ts index ed1d124..5818ccf 100644 --- a/src/utilities-dom.ts +++ b/src/utilities-dom.ts @@ -7,10 +7,10 @@ import { IView } from './interfaces'; * If none is found, return `document.documentElement` */ export const getScrollContainer = (element: Node): HTMLElement => { - let current = element.parentNode as HTMLElement; - while (current !== null) { + let current = element.parentNode; + while (current !== null && current !== document) { if (hasOverflowScroll(current)) { - return current; + return current as HTMLElement; } current = current.parentNode as HTMLElement; } @@ -30,11 +30,11 @@ export const getElementDistanceToTopOfDocument = (element: Element): number => { }; /** - * Check if an element has inline style scroll/auto for overflow/overflowY + * Check if an element has style scroll/auto for overflow/overflowY */ -export const hasOverflowScroll = (element: HTMLElement): boolean => { - let style = element.style; - return style.overflowY === 'scroll' || style.overflow === 'scroll' || style.overflowY === 'auto' || style.overflow === 'auto'; +export const hasOverflowScroll = (element): boolean => { + const style = window.getComputedStyle(element); + return style && (style.overflowY === 'scroll' || style.overflow === 'scroll' || style.overflowY === 'auto' || style.overflow === 'auto'); }; /**