From c396713859fc2e9e6227f6c349a4a8f76bed67ed Mon Sep 17 00:00:00 2001 From: dhilt Date: Wed, 6 May 2020 20:55:15 +0300 Subject: [PATCH 1/5] issue-173 naming and destructuring --- src/component/classes/state.ts | 4 +-- src/component/classes/viewport.ts | 2 +- src/component/interfaces/state.ts | 2 +- src/component/processes/adjust.ts | 54 +++++++++++++++---------------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/component/classes/state.ts b/src/component/classes/state.ts index 330ceb2e..06b93c8d 100644 --- a/src/component/classes/state.ts +++ b/src/component/classes/state.ts @@ -32,7 +32,7 @@ export class State implements IState { startIndex: number; lastPosition: number; preFetchPosition: number; - bwdPaddingAverageSizeItemsCount: number; + bwdAverageSizeItemsCount: number; scrollState: IScrollState; @@ -63,7 +63,7 @@ export class State implements IState { this.fetch = new FetchModel(); this.clip = new ClipModel(); this.render = new RenderModel(); - this.bwdPaddingAverageSizeItemsCount = 0; + this.bwdAverageSizeItemsCount = 0; this.scrollState = new ScrollState(); } diff --git a/src/component/classes/viewport.ts b/src/component/classes/viewport.ts index 3fafa8a8..29035a29 100644 --- a/src/component/classes/viewport.ts +++ b/src/component/classes/viewport.ts @@ -54,7 +54,7 @@ export class Viewport { if (negativeSize) { newPosition = negativeSize; const { itemSize } = this.settings; - this.state.bwdPaddingAverageSizeItemsCount = itemSize ? negativeSize / itemSize : 0; + this.state.bwdAverageSizeItemsCount = itemSize ? negativeSize / itemSize : 0; } this.scrollPosition = newPosition; this.state.scrollState.reset(); diff --git a/src/component/interfaces/state.ts b/src/component/interfaces/state.ts index 680e6052..411dd3ae 100644 --- a/src/component/interfaces/state.ts +++ b/src/component/interfaces/state.ts @@ -48,7 +48,7 @@ export interface State { startIndex: number; lastPosition: number; preFetchPosition: number; - bwdPaddingAverageSizeItemsCount: number; + bwdAverageSizeItemsCount: number; scrollState: ScrollState; diff --git a/src/component/processes/adjust.ts b/src/component/processes/adjust.ts index cba87f9a..fc35efac 100644 --- a/src/component/processes/adjust.ts +++ b/src/component/processes/adjust.ts @@ -56,20 +56,20 @@ export default class Adjust { const lastIndex = lastItem.$index; const minIndex = isFinite(buffer.absMinIndex) ? buffer.absMinIndex : buffer.minIndex; const maxIndex = isFinite(buffer.absMaxIndex) ? buffer.absMaxIndex : buffer.maxIndex; - const hasAverageItemSizeChanged = fetch.hasAverageItemSizeChanged; - let index, bwdSize = 0, fwdSize = 0, bwdPaddingAverageSizeItemsCount = 0; + const { hasAverageItemSizeChanged, firstIndexBuffer } = fetch; + let index, bwdSize = 0, fwdSize = 0, bwdAverageSizeItemsCount = 0; // new backward padding for (index = minIndex; index < firstIndex; index++) { const item = buffer.cache.get(index); bwdSize += item ? item.size : buffer.cache.averageSize; if (hasAverageItemSizeChanged) { - bwdPaddingAverageSizeItemsCount += !item ? 1 : 0; + bwdAverageSizeItemsCount += !item ? 1 : 0; } } if (hasAverageItemSizeChanged) { - for (index = firstIndex; index < (fetch.firstIndexBuffer as number); index++) { - bwdPaddingAverageSizeItemsCount += !buffer.cache.get(index) ? 1 : 0; + for (index = firstIndex; index < (firstIndexBuffer as number); index++) { + bwdAverageSizeItemsCount += !buffer.cache.get(index) ? 1 : 0; } } @@ -97,14 +97,15 @@ export default class Adjust { backwardPadding.size = bwdSize; scroller.logger.stat('after paddings adjustments'); - return bwdPaddingAverageSizeItemsCount; + return bwdAverageSizeItemsCount; } - static fixScrollPosition(scroller: Scroller, bwdPaddingAverageSizeItemsCount: number, preAdjustPosition: number) { - const { viewport, buffer, state, state: { fetch, fetch: { items } } } = scroller; + static fixScrollPosition(scroller: Scroller, bwdAverageSizeItemsCountPrev: number, preAdjustPosition: number) { + const { viewport, buffer, state } = scroller; + const { fetch, render, bwdAverageSizeItemsCount } = state; const newPosition = viewport.scrollPosition; const posDiff = preAdjustPosition - newPosition; - let { negativeSize } = fetch; + let negative = fetch.negativeSize; if (viewport.scrollAnchoring && posDiff) { const winState = state.scrollState.window; @@ -118,15 +119,14 @@ export default class Adjust { } // if backward padding has been changed due to average item size change - const bwdAverageItemsCountDiff = fetch.isReplace ? 0 : - state.bwdPaddingAverageSizeItemsCount - bwdPaddingAverageSizeItemsCount; - const hasBwdParamsChanged = bwdPaddingAverageSizeItemsCount > 0 || bwdAverageItemsCountDiff > 0; + const bwdAverageItemsCountDiff = fetch.isReplace ? 0 : bwdAverageSizeItemsCount - bwdAverageSizeItemsCountPrev; + const hasBwdParamsChanged = bwdAverageSizeItemsCountPrev > 0 || bwdAverageItemsCountDiff > 0; if (fetch.hasAverageItemSizeChanged && hasBwdParamsChanged) { - const _bwdPaddingAverageSize = bwdPaddingAverageSizeItemsCount * buffer.averageSize; - const bwdPaddingAverageSize = bwdPaddingAverageSizeItemsCount * fetch.averageItemSize; - const bwdPaddingAverageSizeDiff = _bwdPaddingAverageSize - bwdPaddingAverageSize; + const _bwdAverageSize = bwdAverageSizeItemsCountPrev * buffer.averageSize; + const bwdAverageSize = bwdAverageSizeItemsCountPrev * fetch.averageItemSize; + const bwdAverageSizeDiff = _bwdAverageSize - bwdAverageSize; const bwdAverageItemsSizeDiff = bwdAverageItemsCountDiff * fetch.averageItemSize; - const bwdDiff = bwdPaddingAverageSizeDiff - bwdAverageItemsSizeDiff; + const bwdDiff = bwdAverageSizeDiff - bwdAverageItemsSizeDiff; const positionDiff = posDiff + bwdDiff; if (positionDiff) { if (scroller.settings.changeOverflow) { @@ -135,32 +135,32 @@ export default class Adjust { Adjust.setScroll(scroller, positionDiff); scroller.logger.stat('after scroll position adjustment (average)'); } - state.bwdPaddingAverageSizeItemsCount = bwdPaddingAverageSizeItemsCount; + state.bwdAverageSizeItemsCount = bwdAverageSizeItemsCountPrev; } // no negative area items - if (!items.length || items[0].$index >= fetch.minIndex) { + if (!fetch.items.length || fetch.items[0].$index >= fetch.minIndex) { return; } // if scrollable area size has not been changed during this cycle - if (viewport.getScrollableSize() === state.render.sizeBefore) { + if (viewport.getScrollableSize() === render.sizeBefore) { return; } // to fill forward padding gap in case of no minIndex if (!isFinite(buffer.absMinIndex)) { - const fwdBefore = Math.max(0, state.render.fwdPaddingBefore - viewport.offset); + const fwdBefore = Math.max(0, render.fwdPaddingBefore - viewport.offset); const fwdPaddingSizeDiff = fwdBefore - viewport.paddings.forward.size; - const diff = negativeSize - fwdPaddingSizeDiff; - negativeSize = diff < 0 ? negativeSize : Math.min(negativeSize, diff); + const diff = negative - fwdPaddingSizeDiff; + negative = diff < 0 ? negative : Math.min(negative, diff); } - if (negativeSize > 0) { - Adjust.setScroll(scroller, negativeSize); - } else if (negativeSize < 0) { - viewport.paddings.forward.size -= negativeSize; - viewport.scrollPosition -= negativeSize; + if (negative > 0) { + Adjust.setScroll(scroller, negative); + } else if (negative < 0) { + viewport.paddings.forward.size -= negative; + viewport.scrollPosition -= negative; } scroller.logger.stat('after scroll position adjustment (negative)'); } From dac4d432534c83a3ece583897da98b1faeae4d3c Mon Sep 17 00:00:00 2001 From: dhilt Date: Thu, 7 May 2020 08:38:45 +0300 Subject: [PATCH 2/5] issue-173 adjust sub-state --- src/component/classes/state.ts | 4 +- src/component/classes/state/adjust.ts | 15 ++++++++ src/component/classes/state/fetch.ts | 5 ++- src/component/interfaces/state.ts | 4 +- src/component/processes/adjust.ts | 54 +++++++++++++-------------- src/component/processes/preFetch.ts | 7 ++-- 6 files changed, 55 insertions(+), 34 deletions(-) create mode 100644 src/component/classes/state/adjust.ts diff --git a/src/component/classes/state.ts b/src/component/classes/state.ts index 06b93c8d..37208633 100644 --- a/src/component/classes/state.ts +++ b/src/component/classes/state.ts @@ -11,6 +11,7 @@ import { Logger } from './logger'; import { FetchModel } from './state/fetch'; import { ClipModel } from './state/clip'; import { RenderModel } from './state/render'; +import { AdjustModel } from './state/adjust'; import { ScrollState } from './state/scroll'; export class State implements IState { @@ -29,9 +30,9 @@ export class State implements IState { fetch: FetchModel; clip: ClipModel; render: RenderModel; + adjust: AdjustModel; startIndex: number; lastPosition: number; - preFetchPosition: number; bwdAverageSizeItemsCount: number; scrollState: IScrollState; @@ -63,6 +64,7 @@ export class State implements IState { this.fetch = new FetchModel(); this.clip = new ClipModel(); this.render = new RenderModel(); + this.adjust = new AdjustModel(); this.bwdAverageSizeItemsCount = 0; this.scrollState = new ScrollState(); diff --git a/src/component/classes/state/adjust.ts b/src/component/classes/state/adjust.ts new file mode 100644 index 00000000..df1670d1 --- /dev/null +++ b/src/component/classes/state/adjust.ts @@ -0,0 +1,15 @@ +export class AdjustModel { + positionBefore: number; + bwdAverageSizeItemsCount: number; + bwdPaddingBefore: number; + + constructor() { + this.reset(); + } + + reset() { + this.positionBefore = 0; + this.bwdAverageSizeItemsCount = 0; + this.bwdPaddingBefore = 0; + } +} diff --git a/src/component/classes/state/fetch.ts b/src/component/classes/state/fetch.ts index 2d3c7c9b..2068e194 100644 --- a/src/component/classes/state/fetch.ts +++ b/src/component/classes/state/fetch.ts @@ -3,7 +3,9 @@ import { Item } from '../item'; export class FetchModel { private _newItemsData: any[] | null; + items: Item[]; + positionBefore: number | null; firstIndexBuffer: number | null; lastIndexBuffer: number | null; firstIndex: number | null; @@ -27,14 +29,15 @@ export class FetchModel { reset() { this._newItemsData = null; - this.simulate = false; this.items = []; + this.positionBefore = null; this.firstIndex = this.firstIndexBuffer = null; this.lastIndex = this.lastIndexBuffer = null; this.hasAnotherPack = false; this.negativeSize = 0; this.hasAverageItemSizeChanged = false; this.direction = null; + this.simulate = false; this.isPrepend = false; this.isReplace = false; } diff --git a/src/component/interfaces/state.ts b/src/component/interfaces/state.ts index 411dd3ae..4d4388ef 100644 --- a/src/component/interfaces/state.ts +++ b/src/component/interfaces/state.ts @@ -4,6 +4,7 @@ import { Direction, ItemAdapter } from './index'; import { FetchModel } from '../classes/state/fetch'; import { ClipModel } from '../classes/state/clip'; import { RenderModel } from '../classes/state/render'; +import { AdjustModel } from '../classes/state/adjust'; export interface WindowScrollState { delta: number; @@ -45,10 +46,9 @@ export interface State { fetch: FetchModel; clip: ClipModel; render: RenderModel; + adjust: AdjustModel; startIndex: number; lastPosition: number; - preFetchPosition: number; - bwdAverageSizeItemsCount: number; scrollState: ScrollState; diff --git a/src/component/processes/adjust.ts b/src/component/processes/adjust.ts index fc35efac..2aecf608 100644 --- a/src/component/processes/adjust.ts +++ b/src/component/processes/adjust.ts @@ -6,14 +6,11 @@ export default class Adjust { static MAX_SCROLL_ADJUSTMENTS_COUNT = 10; static run(scroller: Scroller) { - const { workflow, state, viewport } = scroller; - const preAdjustPosition = viewport.scrollPosition; + const { workflow, state: { adjust }, viewport } = scroller; + adjust.positionBefore = viewport.scrollPosition; // padding-elements adjustments - const setPaddingsResult = - Adjust.setPaddings(scroller); - - if (setPaddingsResult === null) { + if (!Adjust.setPaddings(scroller)) { workflow.call({ process: Process.adjust, status: ProcessStatus.error, @@ -23,11 +20,11 @@ export default class Adjust { } // scroll position adjustments - Adjust.fixScrollPosition(scroller, setPaddingsResult, preAdjustPosition); + Adjust.fixScrollPosition(scroller); // re-set scroll position (if changed) via animation frame const { scrollPosition, previousPosition } = viewport; - if (preAdjustPosition !== scrollPosition && previousPosition !== scrollPosition) { + if (adjust.positionBefore !== scrollPosition && previousPosition !== scrollPosition) { viewport.setPositionSafe(previousPosition, scrollPosition, () => workflow.call({ process: Process.adjust, @@ -43,12 +40,12 @@ export default class Adjust { }); } - static setPaddings(scroller: Scroller): null | number { - const { viewport, buffer, state: { fetch }, settings: { inverse } } = scroller; + static setPaddings(scroller: Scroller): boolean { + const { viewport, buffer, state: { adjust, fetch }, settings: { inverse } } = scroller; const firstItem = buffer.getFirstVisibleItem(); const lastItem = buffer.getLastVisibleItem(); if (!firstItem || !lastItem) { - return null; + return false; } const forwardPadding = viewport.paddings.forward; const backwardPadding = viewport.paddings.backward; @@ -57,21 +54,23 @@ export default class Adjust { const minIndex = isFinite(buffer.absMinIndex) ? buffer.absMinIndex : buffer.minIndex; const maxIndex = isFinite(buffer.absMaxIndex) ? buffer.absMaxIndex : buffer.maxIndex; const { hasAverageItemSizeChanged, firstIndexBuffer } = fetch; - let index, bwdSize = 0, fwdSize = 0, bwdAverageSizeItemsCount = 0; + let index, bwdSize = 0, fwdSize = 0, itemsCount = 0; + adjust.bwdPaddingBefore = backwardPadding.size; // new backward padding for (index = minIndex; index < firstIndex; index++) { const item = buffer.cache.get(index); bwdSize += item ? item.size : buffer.cache.averageSize; if (hasAverageItemSizeChanged) { - bwdAverageSizeItemsCount += !item ? 1 : 0; + itemsCount += !item ? 1 : 0; } } if (hasAverageItemSizeChanged) { for (index = firstIndex; index < (firstIndexBuffer as number); index++) { - bwdAverageSizeItemsCount += !buffer.cache.get(index) ? 1 : 0; + itemsCount += !buffer.cache.get(index) ? 1 : 0; } } + adjust.bwdAverageSizeItemsCount = itemsCount; // new forward padding for (index = lastIndex + 1; index <= maxIndex; index++) { @@ -80,7 +79,7 @@ export default class Adjust { } // lack of items case - const bufferSize = viewport.getScrollableSize() - forwardPadding.size - backwardPadding.size; + const bufferSize = viewport.getScrollableSize() - forwardPadding.size - adjust.bwdPaddingBefore; const viewportSizeDiff = viewport.getSize() - (bwdSize + bufferSize + fwdSize); if (viewportSizeDiff > 0) { if (inverse) { @@ -97,21 +96,22 @@ export default class Adjust { backwardPadding.size = bwdSize; scroller.logger.stat('after paddings adjustments'); - return bwdAverageSizeItemsCount; + return true; } - static fixScrollPosition(scroller: Scroller, bwdAverageSizeItemsCountPrev: number, preAdjustPosition: number) { + static fixScrollPosition(scroller: Scroller) { const { viewport, buffer, state } = scroller; - const { fetch, render, bwdAverageSizeItemsCount } = state; - const newPosition = viewport.scrollPosition; - const posDiff = preAdjustPosition - newPosition; + const { adjust, fetch, render } = state; + const { bwdAverageSizeItemsCount } = adjust; + const positionNew = viewport.scrollPosition; + const posDiff = adjust.positionBefore - positionNew; let negative = fetch.negativeSize; if (viewport.scrollAnchoring && posDiff) { const winState = state.scrollState.window; - if (newPosition === winState.positionToUpdate) { + if (positionNew === winState.positionToUpdate) { winState.reset(); - scroller.logger.log(() => `process window scroll preventive: sum(${newPosition}, ${posDiff})`); + scroller.logger.log(() => `process window scroll preventive: sum(${positionNew}, ${posDiff})`); Adjust.setScroll(scroller, posDiff); scroller.logger.stat('after scroll position adjustment (window)'); return; @@ -119,11 +119,11 @@ export default class Adjust { } // if backward padding has been changed due to average item size change - const bwdAverageItemsCountDiff = fetch.isReplace ? 0 : bwdAverageSizeItemsCount - bwdAverageSizeItemsCountPrev; - const hasBwdParamsChanged = bwdAverageSizeItemsCountPrev > 0 || bwdAverageItemsCountDiff > 0; + const bwdAverageItemsCountDiff = fetch.isReplace ? 0 : state.bwdAverageSizeItemsCount - bwdAverageSizeItemsCount; + const hasBwdParamsChanged = bwdAverageSizeItemsCount > 0 || bwdAverageItemsCountDiff > 0; if (fetch.hasAverageItemSizeChanged && hasBwdParamsChanged) { - const _bwdAverageSize = bwdAverageSizeItemsCountPrev * buffer.averageSize; - const bwdAverageSize = bwdAverageSizeItemsCountPrev * fetch.averageItemSize; + const _bwdAverageSize = bwdAverageSizeItemsCount * buffer.averageSize; + const bwdAverageSize = bwdAverageSizeItemsCount * fetch.averageItemSize; const bwdAverageSizeDiff = _bwdAverageSize - bwdAverageSize; const bwdAverageItemsSizeDiff = bwdAverageItemsCountDiff * fetch.averageItemSize; const bwdDiff = bwdAverageSizeDiff - bwdAverageItemsSizeDiff; @@ -135,7 +135,7 @@ export default class Adjust { Adjust.setScroll(scroller, positionDiff); scroller.logger.stat('after scroll position adjustment (average)'); } - state.bwdAverageSizeItemsCount = bwdAverageSizeItemsCountPrev; + state.bwdAverageSizeItemsCount = bwdAverageSizeItemsCount; } // no negative area items diff --git a/src/component/processes/preFetch.ts b/src/component/processes/preFetch.ts index bb9210bc..0e9e5557 100644 --- a/src/component/processes/preFetch.ts +++ b/src/component/processes/preFetch.ts @@ -5,7 +5,7 @@ export default class PreFetch { static run(scroller: Scroller, process: Process) { const { workflow, buffer, state: { fetch } } = scroller; - scroller.state.preFetchPosition = scroller.viewport.scrollPosition; + fetch.positionBefore = scroller.viewport.scrollPosition; fetch.minIndex = buffer.minIndex; fetch.averageItemSize = buffer.averageSize || 0; @@ -60,9 +60,10 @@ export default class PreFetch { } static setFetchIndexes(scroller: Scroller) { - const { state, viewport } = scroller; + const { state: { fetch }, viewport } = scroller; const paddingDelta = viewport.getBufferPadding(); - const relativePosition = state.preFetchPosition - viewport.startDelta; + const positionBefore = fetch.positionBefore as number; + const relativePosition = positionBefore - viewport.startDelta; const startPosition = relativePosition - paddingDelta; const endPosition = relativePosition + viewport.getSize() + paddingDelta; const firstIndexPosition = From 0a39188f5ed0e2435f0bbad0064aee44b71ad9f3 Mon Sep 17 00:00:00 2001 From: dhilt Date: Sat, 16 May 2020 02:47:02 +0300 Subject: [PATCH 3/5] issue-173 support native scroll-anchoring --- src/component/classes/state/adjust.ts | 2 -- src/component/processes/adjust.ts | 27 +++++++++++---------------- src/component/processes/start.ts | 3 ++- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/component/classes/state/adjust.ts b/src/component/classes/state/adjust.ts index df1670d1..74c3ac58 100644 --- a/src/component/classes/state/adjust.ts +++ b/src/component/classes/state/adjust.ts @@ -1,7 +1,6 @@ export class AdjustModel { positionBefore: number; bwdAverageSizeItemsCount: number; - bwdPaddingBefore: number; constructor() { this.reset(); @@ -10,6 +9,5 @@ export class AdjustModel { reset() { this.positionBefore = 0; this.bwdAverageSizeItemsCount = 0; - this.bwdPaddingBefore = 0; } } diff --git a/src/component/processes/adjust.ts b/src/component/processes/adjust.ts index 2aecf608..971f8ef6 100644 --- a/src/component/processes/adjust.ts +++ b/src/component/processes/adjust.ts @@ -47,15 +47,13 @@ export default class Adjust { if (!firstItem || !lastItem) { return false; } - const forwardPadding = viewport.paddings.forward; - const backwardPadding = viewport.paddings.backward; + const { forward, backward } = viewport.paddings; const firstIndex = firstItem.$index; const lastIndex = lastItem.$index; const minIndex = isFinite(buffer.absMinIndex) ? buffer.absMinIndex : buffer.minIndex; const maxIndex = isFinite(buffer.absMaxIndex) ? buffer.absMaxIndex : buffer.maxIndex; const { hasAverageItemSizeChanged, firstIndexBuffer } = fetch; let index, bwdSize = 0, fwdSize = 0, itemsCount = 0; - adjust.bwdPaddingBefore = backwardPadding.size; // new backward padding for (index = minIndex; index < firstIndex; index++) { @@ -79,7 +77,7 @@ export default class Adjust { } // lack of items case - const bufferSize = viewport.getScrollableSize() - forwardPadding.size - adjust.bwdPaddingBefore; + const bufferSize = viewport.getScrollableSize() - forward.size - backward.size; const viewportSizeDiff = viewport.getSize() - (bwdSize + bufferSize + fwdSize); if (viewportSizeDiff > 0) { if (inverse) { @@ -92,8 +90,8 @@ export default class Adjust { ); } - forwardPadding.size = fwdSize; - backwardPadding.size = bwdSize; + backward.size = bwdSize; + forward.size = fwdSize; scroller.logger.stat('after paddings adjustments'); return true; @@ -103,19 +101,16 @@ export default class Adjust { const { viewport, buffer, state } = scroller; const { adjust, fetch, render } = state; const { bwdAverageSizeItemsCount } = adjust; - const positionNew = viewport.scrollPosition; - const posDiff = adjust.positionBefore - positionNew; + let positionNew = viewport.scrollPosition; + let posDiff = adjust.positionBefore - positionNew; let negative = fetch.negativeSize; + // if scroll anchoring is in game if (viewport.scrollAnchoring && posDiff) { - const winState = state.scrollState.window; - if (positionNew === winState.positionToUpdate) { - winState.reset(); - scroller.logger.log(() => `process window scroll preventive: sum(${positionNew}, ${posDiff})`); - Adjust.setScroll(scroller, posDiff); - scroller.logger.stat('after scroll position adjustment (window)'); - return; - } + Adjust.setScroll(scroller, posDiff); + positionNew = viewport.scrollPosition; + posDiff = adjust.positionBefore - positionNew; + scroller.logger.stat('after scroll position adjustment (anchoring)'); } // if backward padding has been changed due to average item size change diff --git a/src/component/processes/start.ts b/src/component/processes/start.ts index 16a47970..35ecf8f9 100644 --- a/src/component/processes/start.ts +++ b/src/component/processes/start.ts @@ -4,7 +4,7 @@ import { Process, ProcessStatus } from '../interfaces/index'; export default class Start { static run(scroller: Scroller, process: Process, payload?: { process: Process }) { - const { state, state: { scrollState, fetch, clip, render }, adapter } = scroller; + const { state, state: { scrollState, fetch, clip, render, adjust }, adapter } = scroller; const processToPass = payload && payload.process || process; adapter.loopPending = true; @@ -15,6 +15,7 @@ export default class Start { clip.reset(); } render.reset(); + adjust.reset(); scroller.workflow.call({ process: Process.start, From 0b3d0251524c24eb992f75ae52d1f3b87869f44b Mon Sep 17 00:00:00 2001 From: dhilt Date: Sat, 16 May 2020 02:57:34 +0300 Subject: [PATCH 4/5] issue-173 cleanup --- src/component/classes/state/render.ts | 2 -- src/component/classes/state/scroll.ts | 20 +------------------- src/component/interfaces/index.ts | 3 +-- src/component/interfaces/state.ts | 8 -------- src/component/processes/render.ts | 24 ------------------------ 5 files changed, 2 insertions(+), 55 deletions(-) diff --git a/src/component/classes/state/render.ts b/src/component/classes/state/render.ts index 57d56fd0..a05b80df 100644 --- a/src/component/classes/state/render.ts +++ b/src/component/classes/state/render.ts @@ -1,5 +1,4 @@ export class RenderModel { - positionBefore: number; sizeBefore: number; sizeAfter: number; fwdPaddingBefore: number; @@ -13,7 +12,6 @@ export class RenderModel { } reset() { - this.positionBefore = 0; this.sizeBefore = 0; this.sizeAfter = 0; this.fwdPaddingBefore = 0; diff --git a/src/component/classes/state/scroll.ts b/src/component/classes/state/scroll.ts index 86c04bba..66402f3a 100644 --- a/src/component/classes/state/scroll.ts +++ b/src/component/classes/state/scroll.ts @@ -1,39 +1,22 @@ import { Direction, ScrollEventData as IScrollEventData, - ScrollState as IScrollState, - WindowScrollState as IWindowScrollState + ScrollState as IScrollState } from '../../interfaces/index'; import { Logger } from '../logger'; -class WindowScrollState implements IWindowScrollState { - positionToUpdate: number; - delta: number; - - constructor() { - this.reset(); - } - - reset() { - this.delta = 0; - this.positionToUpdate = 0; - } -} - export class ScrollState implements IScrollState { previous: IScrollEventData | null; current: IScrollEventData | null; scrollTimer: ReturnType | null; - window: IWindowScrollState; syntheticPosition: number | null; syntheticFulfill: boolean; animationFrameId: number; constructor() { - this.window = new WindowScrollState(); this.reset(); } @@ -44,6 +27,5 @@ export class ScrollState implements IScrollState { this.syntheticPosition = null; this.syntheticFulfill = false; this.animationFrameId = 0; - this.window.reset(); } } diff --git a/src/component/interfaces/index.ts b/src/component/interfaces/index.ts index 981629e2..47235936 100644 --- a/src/component/interfaces/index.ts +++ b/src/component/interfaces/index.ts @@ -21,7 +21,7 @@ import { } from './adapter'; import { Settings, DevSettings } from './settings'; import { Direction } from './direction'; -import { WindowScrollState, ScrollEventData, ScrollState, State } from './state'; +import { ScrollEventData, ScrollState, State } from './state'; import { Process, ProcessStatus, ProcessSubject } from './process'; import { ValidatorType, @@ -56,7 +56,6 @@ export { Settings, DevSettings, Direction, - WindowScrollState, ScrollEventData, ScrollState, State, diff --git a/src/component/interfaces/state.ts b/src/component/interfaces/state.ts index 4d4388ef..54654208 100644 --- a/src/component/interfaces/state.ts +++ b/src/component/interfaces/state.ts @@ -6,13 +6,6 @@ import { ClipModel } from '../classes/state/clip'; import { RenderModel } from '../classes/state/render'; import { AdjustModel } from '../classes/state/adjust'; -export interface WindowScrollState { - delta: number; - positionToUpdate: number; - - reset: Function; -} - export interface ScrollEventData { time: number; position: number; @@ -24,7 +17,6 @@ export interface ScrollState { current: ScrollEventData | null; scrollTimer: ReturnType | null; - window: WindowScrollState; syntheticPosition: number | null; syntheticFulfill: boolean; diff --git a/src/component/processes/render.ts b/src/component/processes/render.ts index a2c79777..7d7103e4 100644 --- a/src/component/processes/render.ts +++ b/src/component/processes/render.ts @@ -28,9 +28,6 @@ export default class Render { static processElements(scroller: Scroller): boolean { const { state: { fetch, render }, viewport, buffer, logger } = scroller; - if (fetch.isPrepend) { - render.positionBefore = viewport.scrollPosition; - } if (!fetch.isReplace) { render.sizeBefore = viewport.getScrollableSize(); render.fwdPaddingBefore = viewport.paddings.forward.size; @@ -43,9 +40,6 @@ export default class Render { } fetch.hasAverageItemSizeChanged = buffer.checkAverageSize(); render.sizeAfter = viewport.getScrollableSize(); - if (viewport.scrollAnchoring && fetch.isPrepend && !render.noSize) { - Render.processWindowScrollBackJump(scroller); - } logger.stat('after new items render'); logger.log(() => render.noSize ? 'viewport size has not been changed' : void 0); return true; @@ -69,22 +63,4 @@ export default class Render { return true; } - static processWindowScrollBackJump({ state, viewport, logger }: Scroller) { - const { scrollState: { window }, render: { positionBefore, sizeAfter, sizeBefore } } = state; - // if new items have been rendered in the area that is before current scroll position - // then this position will be updated silently in case of entire window scrollable - // so we need to remember the delta and to update scroll position manually right after it is changed silently - const inc = positionBefore >= viewport.paddings.backward.size ? 1 : -1; - const delta = inc * Math.abs(sizeAfter - sizeBefore); - const positionToUpdate = positionBefore - delta; - if (delta && positionToUpdate > 0) { - window.positionToUpdate = positionToUpdate; - window.delta = delta; - logger.log(() => { - const token = delta < 0 ? 'reduced' : 'increased'; - return [`next scroll position (if ${positionToUpdate}) should be ${token} by`, Math.abs(delta)]; - }); - } - } - } From d664a2c3a70ccfa6cce449f0c613a7597a05bfee Mon Sep 17 00:00:00 2001 From: dhilt Date: Sat, 16 May 2020 20:50:41 +0300 Subject: [PATCH 5/5] issue-173 remove "overflow-anchor: none" requirement --- README.md | 3 +-- .../adapter/append-prepend-sync.component.ts | 1 - .../samples/adapter/append-prepend.component.ts | 1 - demo/app/samples/adapter/bof-eof.component.ts | 1 - demo/app/samples/adapter/check-size.component.ts | 1 - demo/app/samples/adapter/clip.component.ts | 1 - .../adapter/first-last-visible-items.component.ts | 1 - .../adapter/is-loading-extended.component.ts | 1 - demo/app/samples/adapter/is-loading.component.ts | 1 - demo/app/samples/adapter/items-count.component.ts | 1 - demo/app/samples/adapter/reload.component.ts | 1 - demo/app/samples/adapter/remove.component.ts | 1 - demo/app/samples/common/basic.component.ts | 1 - demo/app/samples/common/buffer-size.component.ts | 1 - .../samples/common/different-heights.component.ts | 1 - demo/app/samples/common/horizontal.component.ts | 1 - demo/app/samples/common/infinite.component.ts | 1 - demo/app/samples/common/item-size.component.ts | 1 - .../samples/common/min-max-indexes.component.ts | 1 - demo/app/samples/common/padding.component.ts | 1 - demo/app/samples/common/start-index.component.ts | 1 - .../samples/common/window-viewport.component.html | 14 ++------------ .../samples/common/window-viewport.component.ts | 6 +----- demo/app/samples/home.component.ts | 1 - demo/styles.css | 6 ------ tests/miscellaneous/styles.css | 6 ------ 26 files changed, 4 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 217155c5..c3c4744e 100644 --- a/README.md +++ b/README.md @@ -77,11 +77,10 @@ where the viewport is a scrollable area of finite height: .viewport { height: 300px; overflow-y: auto; - overflow-anchor: none; } ``` -If the height of the viewport is not constrained, it will pull the entire content of the datasource and no scrollbar will appear. Also, in order to support Safari and IE browsers, the library got its own implementation of scroll anchoring feature applicable to the case of virtual scrolling. Currently this implementation may conflict with native "overflow-anchor" in browsers that support it, so it is highly recommended to turn native anchoring off. +If the height of the viewport is not constrained, it will pull the entire content of the datasource and no scrollbar will appear. Also, in order to support Safari and IE browsers, the library has its own implementation of the scroll anchoring feature applicable to the case of virtual scrolling. Previous versions of the library (prior to 1.6.4) had the requirement that the value of "overflow-anchor" css property should be set to "none" for the viewport element. \*uiScroll acts like \*ngFor, but the datasource is an object of special type (IDatasource). It implements method _get_ to be used by the \*uiScroll directive to access the data by _index_ and _count_ parameters. The directive calls `Datasource.get` method each time a user scrolls to the edge of visible element list. That's the API provided by the \*uiScroll. diff --git a/demo/app/samples/adapter/append-prepend-sync.component.ts b/demo/app/samples/adapter/append-prepend-sync.component.ts index ab7b558c..433fe99a 100644 --- a/demo/app/samples/adapter/append-prepend-sync.component.ts +++ b/demo/app/samples/adapter/append-prepend-sync.component.ts @@ -123,7 +123,6 @@ doPrepend() { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/append-prepend.component.ts b/demo/app/samples/adapter/append-prepend.component.ts index ff3750a6..8d2eddfe 100644 --- a/demo/app/samples/adapter/append-prepend.component.ts +++ b/demo/app/samples/adapter/append-prepend.component.ts @@ -95,7 +95,6 @@ doAppend() { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/bof-eof.component.ts b/demo/app/samples/adapter/bof-eof.component.ts index f4051e60..c94d7bc2 100644 --- a/demo/app/samples/adapter/bof-eof.component.ts +++ b/demo/app/samples/adapter/bof-eof.component.ts @@ -88,7 +88,6 @@ BOF / EOF changes counter: {{edgeCounter}} width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/check-size.component.ts b/demo/app/samples/adapter/check-size.component.ts index fd6134d1..33782719 100644 --- a/demo/app/samples/adapter/check-size.component.ts +++ b/demo/app/samples/adapter/check-size.component.ts @@ -167,7 +167,6 @@ First visible item's index: {{datasource.adapter.firstVisible.$index}} width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/clip.component.ts b/demo/app/samples/adapter/clip.component.ts index c23ff26e..471169ee 100644 --- a/demo/app/samples/adapter/clip.component.ts +++ b/demo/app/samples/adapter/clip.component.ts @@ -61,7 +61,6 @@ doClip() { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/first-last-visible-items.component.ts b/demo/app/samples/adapter/first-last-visible-items.component.ts index 54e7fc6c..572e4f12 100644 --- a/demo/app/samples/adapter/first-last-visible-items.component.ts +++ b/demo/app/samples/adapter/first-last-visible-items.component.ts @@ -83,7 +83,6 @@ Visible items counter: {{visibleCount}} width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/is-loading-extended.component.ts b/demo/app/samples/adapter/is-loading-extended.component.ts index 85872db7..8498de47 100644 --- a/demo/app/samples/adapter/is-loading-extended.component.ts +++ b/demo/app/samples/adapter/is-loading-extended.component.ts @@ -73,7 +73,6 @@ counter: {{innerLoopCounter}} width: 150px; height: 175px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/is-loading.component.ts b/demo/app/samples/adapter/is-loading.component.ts index dd466e4b..7f613adf 100644 --- a/demo/app/samples/adapter/is-loading.component.ts +++ b/demo/app/samples/adapter/is-loading.component.ts @@ -67,7 +67,6 @@ for {{isLoadingCounter}} times. width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/items-count.component.ts b/demo/app/samples/adapter/items-count.component.ts index b67fae72..df059e89 100644 --- a/demo/app/samples/adapter/items-count.component.ts +++ b/demo/app/samples/adapter/items-count.component.ts @@ -52,7 +52,6 @@ export class DemoItemsCountComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/reload.component.ts b/demo/app/samples/adapter/reload.component.ts index b6a24655..1fbe4c60 100644 --- a/demo/app/samples/adapter/reload.component.ts +++ b/demo/app/samples/adapter/reload.component.ts @@ -58,7 +58,6 @@ by index width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/adapter/remove.component.ts b/demo/app/samples/adapter/remove.component.ts index e01ad528..a05549d9 100644 --- a/demo/app/samples/adapter/remove.component.ts +++ b/demo/app/samples/adapter/remove.component.ts @@ -106,7 +106,6 @@ doRemove(id: number) { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/basic.component.ts b/demo/app/samples/common/basic.component.ts index caa7727f..7bad5fe7 100644 --- a/demo/app/samples/common/basic.component.ts +++ b/demo/app/samples/common/basic.component.ts @@ -48,7 +48,6 @@ export class DemoBasicComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/buffer-size.component.ts b/demo/app/samples/common/buffer-size.component.ts index 1443954e..ff445a5d 100644 --- a/demo/app/samples/common/buffer-size.component.ts +++ b/demo/app/samples/common/buffer-size.component.ts @@ -54,7 +54,6 @@ export class DemoBufferSizeComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/different-heights.component.ts b/demo/app/samples/common/different-heights.component.ts index b642524a..ed0cc7c9 100644 --- a/demo/app/samples/common/different-heights.component.ts +++ b/demo/app/samples/common/different-heights.component.ts @@ -55,7 +55,6 @@ export class DemoDifferentHeightsComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/horizontal.component.ts b/demo/app/samples/common/horizontal.component.ts index 65c843ab..6de15720 100644 --- a/demo/app/samples/common/horizontal.component.ts +++ b/demo/app/samples/common/horizontal.component.ts @@ -54,7 +54,6 @@ export class DemoHorizontalComponent { text: `.viewport.horizontal { width: 250px; height: 100px; - overflow-anchor: none; overflow-x: scroll; overflow-y: hidden; white-space: nowrap; diff --git a/demo/app/samples/common/infinite.component.ts b/demo/app/samples/common/infinite.component.ts index bc9cf00b..b8837eb4 100644 --- a/demo/app/samples/common/infinite.component.ts +++ b/demo/app/samples/common/infinite.component.ts @@ -54,7 +54,6 @@ export class DemoInfiniteComponent { width: 150px; height: 175px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/item-size.component.ts b/demo/app/samples/common/item-size.component.ts index 0759b656..07b5a146 100644 --- a/demo/app/samples/common/item-size.component.ts +++ b/demo/app/samples/common/item-size.component.ts @@ -54,7 +54,6 @@ export class DemoItemSizeComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/min-max-indexes.component.ts b/demo/app/samples/common/min-max-indexes.component.ts index 8d17ae03..9456cd70 100644 --- a/demo/app/samples/common/min-max-indexes.component.ts +++ b/demo/app/samples/common/min-max-indexes.component.ts @@ -56,7 +56,6 @@ export class DemoMinMaxIndexesComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/padding.component.ts b/demo/app/samples/common/padding.component.ts index ac9eafac..9360c655 100644 --- a/demo/app/samples/common/padding.component.ts +++ b/demo/app/samples/common/padding.component.ts @@ -56,7 +56,6 @@ export class DemoPaddingComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/start-index.component.ts b/demo/app/samples/common/start-index.component.ts index 1844e97c..29bcdb9e 100644 --- a/demo/app/samples/common/start-index.component.ts +++ b/demo/app/samples/common/start-index.component.ts @@ -54,7 +54,6 @@ export class DemoStartIndexComponent { width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/app/samples/common/window-viewport.component.html b/demo/app/samples/common/window-viewport.component.html index 9f2e13de..9ca9d678 100644 --- a/demo/app/samples/common/window-viewport.component.html +++ b/demo/app/samples/common/window-viewport.component.html @@ -11,18 +11,8 @@

The entire window might work as a Viewport if windowViewport setting is set to true. - To provide most stable experience in this case, - the overflow-anchor css property should be disabled on the top level of the DOM tree. - This is what the doc says: -

-

- - In order to support Safari and IE browsers, - the library got its own implementation of scroll anchoring feature - applicable to the case of virtual scrolling. - Currently this implementation may conflict with native "overflow-anchor" in browsers that support it, - so it is highly recommended to turn native anchoring off. - + Previous versions of the library (prior to 1.6.4) required the "overflow-anchor" css property + to be disabled at the top level of the DOM tree (body or html tag). Today it is not necessary.

diff --git a/demo/app/samples/common/window-viewport.component.ts b/demo/app/samples/common/window-viewport.component.ts index ab8e6db5..d7909c9b 100644 --- a/demo/app/samples/common/window-viewport.component.ts +++ b/demo/app/samples/common/window-viewport.component.ts @@ -39,11 +39,7 @@ export class DemoWindowViewportComponent { ` }, { name: DemoSourceType.Styles, - text: `body { - overflow-anchor: none; -} - -.item { + text: `.item { font-weight: bold; height: 25px; }` diff --git a/demo/app/samples/home.component.ts b/demo/app/samples/home.component.ts index a7f0cd90..62d09df2 100644 --- a/demo/app/samples/home.component.ts +++ b/demo/app/samples/home.component.ts @@ -94,7 +94,6 @@ Index to reload: width: 150px; height: 250px; overflow-y: auto; - overflow-anchor: none; } .item { font-weight: bold; diff --git a/demo/styles.css b/demo/styles.css index 6515575f..64dfe407 100644 --- a/demo/styles.css +++ b/demo/styles.css @@ -2,10 +2,6 @@ body { line-height: 1.4; } -.entire-window { - overflow-anchor: none; -} - h1 { font-size: 42px; letter-spacing: -.015em; @@ -205,7 +201,6 @@ input[type=checkbox], input[type=radio] { .demo .work .viewport, .viewport { width: 150px; height: 250px; - overflow-anchor: none; overflow-y: auto; margin-bottom: 15px; } @@ -213,7 +208,6 @@ input[type=checkbox], input[type=radio] { .demo .work .viewport.horizontal { width: 250px; height: 100px; - overflow-anchor: none; overflow-x: scroll; overflow-y: hidden; white-space: nowrap; diff --git a/tests/miscellaneous/styles.css b/tests/miscellaneous/styles.css index e6e79b3d..ace763c1 100644 --- a/tests/miscellaneous/styles.css +++ b/tests/miscellaneous/styles.css @@ -8,14 +8,9 @@ html { line-height: 20px; } -body { - overflow-anchor: none; -} - .viewport { width: 200px; height: 200px; - overflow-anchor: none; overflow-y: auto; display: block; } @@ -23,7 +18,6 @@ body { .viewport-horizontal { width: 200px; height: 100px; - overflow-anchor: none; overflow-x: scroll; overflow-y: hidden; white-space: nowrap;