Permalink
Browse files

fix(scroll-next): invoke get more items in init if items length small

fix #129
  • Loading branch information...
bigopon committed Jan 18, 2019
1 parent e1f75db commit fa6af8cc290cc5995339f58963b7860ddf202e27
@@ -30,9 +30,10 @@ export class App {
}

public push30(scrollContext?: IScrollContext, count = 30) {
if (scrollContext) {
console.log('Issue-129 getting more:', JSON.stringify(scrollContext, undefined, 2));
}
console.log('Issue-129 getting more...');
// if (scrollContext) {
// console.log('Issue-129 getting more:', JSON.stringify(scrollContext, undefined, 2));
// }
if (!scrollContext || scrollContext.isAtBottom) {
for (let i = 0; i < count; i++) {
this.people.push({
@@ -57,9 +57,7 @@ module.exports = {
]
},
plugins: [
new AureliaPlugin({
dist: 'es2015'
}),
new AureliaPlugin(),
// Standard plugin to build index.html
new HtmlWebpackPlugin({
template: 'index.ejs'
@@ -12,3 +12,7 @@ export {
VirtualRepeat,
InfiniteScrollNext
};

export {
IScrollNextScrollContext
} from './interfaces';
@@ -1,5 +1,3 @@
import { OverrideContext, Scope } from 'aurelia-binding';

// Placeholder attribute to prohibit use of this attribute name in other places
export class InfiniteScrollNext {

@@ -10,15 +8,4 @@ export class InfiniteScrollNext {
name: 'infinite-scroll-next'
};
}

/**@internal */
scope: Scope;

bind(bindingContext: any, overrideContext: OverrideContext): void {
this.scope = { bindingContext, overrideContext };
}

unbind() {
this.scope = undefined;
}
}
@@ -3,6 +3,12 @@ import { ViewSlot, View, ViewFactory, BoundViewFactory, Controller } from 'aurel
import { Scope, Binding, OverrideContext } from 'aurelia-binding';
import { TaskQueue } from 'aurelia-task-queue';

export interface IScrollNextScrollContext {
topIndex: number;
isAtBottom: boolean;
isAtTop: boolean;
}

/**@internal */
declare module 'aurelia-binding' {
interface ObserverLocator {
@@ -11,11 +17,7 @@ declare module 'aurelia-binding' {

interface OverrideContext {
$index: number;
$scrollContext: {
topIndex: number;
isAtBottom: boolean;
isAtTop: boolean;
};
$scrollContext: IScrollNextScrollContext;
$first: boolean;
$last: boolean;
$middle: boolean;
@@ -28,7 +28,8 @@ import {
IVirtualRepeat,
IVirtualRepeatStrategy,
ITemplateStrategy,
IView
IView,
IScrollNextScrollContext
} from './interfaces';
import { TaskQueue } from '../sample/sample-v-ui-app/node_modules/aurelia-framework/dist/aurelia-framework';

@@ -262,6 +263,9 @@ export class VirtualRepeat extends AbstractRepeater implements IVirtualRepeat {
} else {
document.addEventListener('scroll', scrollListener);
}
if (this.items.length < this.elementsInView && this.isLastIndex === undefined) {
this._getMore(true);
}
}

/**@override */
@@ -276,6 +280,7 @@ export class VirtualRepeat extends AbstractRepeater implements IVirtualRepeat {
} else {
document.removeEventListener('scroll', this.scrollListener);
}
this.isLastIndex = undefined;
this._fixedHeightContainer = false;
this._resetCalculation();
this._isAttached = false;
@@ -537,7 +542,7 @@ export class VirtualRepeat extends AbstractRepeater implements IVirtualRepeat {

/**@internal*/
_getMore(force?: boolean): void {
if (this.isLastIndex || this._first === 0 || force) {
if (this.isLastIndex || this._first === 0 || force === true) {
if (!this._calledGetMore) {
let executeGetMore = () => {
this._calledGetMore = true;
@@ -552,22 +557,28 @@ export class VirtualRepeat extends AbstractRepeater implements IVirtualRepeat {
let topIndex = this._first;
let isAtBottom = this._bottomBufferHeight === 0;
let isAtTop = this._isAtTop;
let scrollContext = {
let scrollContext: IScrollNextScrollContext = {
topIndex: topIndex,
isAtBottom: isAtBottom,
isAtTop: isAtTop
};

this.scope.overrideContext.$scrollContext = scrollContext;
let overrideContext = this.scope.overrideContext;
overrideContext.$scrollContext = scrollContext;

if (func === undefined) {
// Still reset `_calledGetMore` flag as if it was invoked
// though this should not happen as presence of infinite-scroll-next attribute
// will make the value at least be an empty string
// keeping this logic here for future enhancement/evolution
this._calledGetMore = false;
return null;
} else if (typeof func === 'string') {
let getMoreFuncName = (this.view(0).firstChild as Element).getAttribute(scrollNextAttrName);
let funcCall = this.scope.overrideContext.bindingContext[getMoreFuncName];
let getMoreFuncName = (firstView.firstChild as Element).getAttribute(scrollNextAttrName);
let funcCall = overrideContext.bindingContext[getMoreFuncName];

if (typeof funcCall === 'function') {
let result = funcCall.call(this.scope.overrideContext.bindingContext, topIndex, isAtBottom, isAtTop);
let result = funcCall.call(overrideContext.bindingContext, topIndex, isAtBottom, isAtTop);
if (!(result instanceof Promise)) {
// Reset for the next time
this._calledGetMore = false;
@@ -639,10 +650,10 @@ export class VirtualRepeat extends AbstractRepeater implements IVirtualRepeat {

/**@internal*/
_unsubscribeCollection(): void {
if (this.collectionObserver) {
this.collectionObserver.unsubscribe(this.callContext, this);
this.collectionObserver = null;
this.callContext = null;
let collectionObserver = this.collectionObserver;
if (collectionObserver) {
collectionObserver.unsubscribe(this.callContext, this);
this.collectionObserver = this.callContext = null;
}
}

@@ -815,10 +826,11 @@ export class VirtualRepeat extends AbstractRepeater implements IVirtualRepeat {

/**@internal*/
_observeCollection(): void {
this.collectionObserver = this.strategy.getCollectionObserver(this.observerLocator, this.items);
if (this.collectionObserver) {
let collectionObserver = this.strategy.getCollectionObserver(this.observerLocator, this.items);
if (collectionObserver) {
this.callContext = VirtualRepeatCallContext.handleCollectionMutated;
this.collectionObserver.subscribe(this.callContext, this);
this.collectionObserver = collectionObserver;
collectionObserver.subscribe(this.callContext, this);
}
}

@@ -67,7 +67,10 @@ export function validateScrolledState(virtualRepeat: VirtualRepeat, viewModel: a
let topBufferHeight = virtualRepeat.topBuffer.getBoundingClientRect().height;
let bottomBufferHeight = virtualRepeat.bottomBuffer.getBoundingClientRect().height;
let renderedItemsHeight = views.length * itemHeight;
expect(topBufferHeight + renderedItemsHeight + bottomBufferHeight).toBe(expectedHeight);
expect(topBufferHeight + renderedItemsHeight + bottomBufferHeight).toBe(
expectedHeight,
`Top buffer (${topBufferHeight}) + items height (${renderedItemsHeight}) + bottom buffer (${bottomBufferHeight}) should have been correct`
);

if (viewModel.items.length > views.length) {
expect(topBufferHeight + bottomBufferHeight).toBeGreaterThan(0);
@@ -91,3 +94,21 @@ export function validateScrolledState(virtualRepeat: VirtualRepeat, viewModel: a
expect(overrideContext.$even).toBe(even);
}
}

/**
* Manually dispatch a scroll event and validate scrolled state of virtual repeat
*
* Programatically set `scrollTop` of element specified with `elementSelector` query string
* (or `#scrollContainer` by default) to be equal with its `scrollHeight`
*/
export function validateScroll(virtualRepeat: VirtualRepeat, viewModel: any, itemHeight: number, element: Element, done: Function): void {
let event = new Event('scroll');
element.scrollTop = element.scrollHeight;
element.dispatchEvent(event);
window.setTimeout(() => {
window.requestAnimationFrame(() => {
validateScrolledState(virtualRepeat, viewModel, itemHeight);
done();
});
});
}
Oops, something went wrong.

0 comments on commit fa6af8c

Please sign in to comment.