Skip to content

Commit

Permalink
feat(virtual-repeat): add support for iterating tables
Browse files Browse the repository at this point in the history
Also includes deferred scrolling when it scrolls faster than the binding and other optimizations
  • Loading branch information
martingust committed Dec 9, 2015
1 parent b8f23ea commit 54ad2fb
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 16 deletions.
14 changes: 7 additions & 7 deletions src/array-virtual-repeat-strategy.js
@@ -1,5 +1,5 @@
import {ArrayRepeatStrategy} from 'aurelia-templating-resources/array-repeat-strategy';
import {createFullOverrideContext, updateOverrideContexts, refreshBinding} from 'aurelia-templating-resources/repeat-utilities';
import {createFullOverrideContext, updateOverrideContexts, updateOverrideContext, refreshBinding} from 'aurelia-templating-resources/repeat-utilities';

/**
* A strategy for repeating a template over an array.
Expand Down Expand Up @@ -42,6 +42,7 @@ export class ArrayVirtualRepeatStrategy extends ArrayRepeatStrategy {
_inPlaceProcessItems(repeat, items) {
let itemsLength = items.length;
let viewsLength = repeat.viewSlot.children.length;
let first = repeat.first;
// remove unneeded views.
while (viewsLength > repeat.numberOfDomElements) {
viewsLength--;
Expand All @@ -55,14 +56,14 @@ export class ArrayVirtualRepeatStrategy extends ArrayRepeatStrategy {
let last = i === itemsLength - 1;
let middle = i !== 0 && !last;
// any changes to the binding context?
if (view.bindingContext[local] === items[i]
if (view.bindingContext[local] === items[i + first]
&& view.overrideContext.$middle === middle
&& view.overrideContext.$last === last) {
// no changes. continue...
continue;
}
// update the binding context and refresh the bindings.
view.bindingContext[local] = items[i];
view.bindingContext[local] = items[i + first];
view.overrideContext.$middle = middle;
view.overrideContext.$last = last;
let j = view.bindings.length;
Expand Down Expand Up @@ -100,8 +101,7 @@ export class ArrayVirtualRepeatStrategy extends ArrayRepeatStrategy {
this._standardProcessInstanceMutated(repeat, array, splices);
return;
}
repeat._updateViews(repeat.items, splices);
//this._inPlaceProcessItems(repeat, array);
this._updateViews(repeat, repeat.items, splices);
}

_standardProcessInstanceMutated(repeat, array, splices) {
Expand Down Expand Up @@ -137,12 +137,12 @@ export class ArrayVirtualRepeatStrategy extends ArrayRepeatStrategy {
if (rmPromises.length > 0) {
Promise.all(rmPromises).then(() => {
this._handleAddedSplices(array, splices);
repeat._updateViews(array, splices);
repeat._updateViews(repeat, array, splices);
repeat._updateSizes();
});
} else {
this._handleAddedSplices(array, splices);
repeat._updateViews(array, splices);
this._updateViews(repeat, array, splices);
repeat._updateSizes();
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/utilities.js
Expand Up @@ -22,10 +22,18 @@ function getStyleValue(element, style){
}

export function moveViewFirst(view, scrollView) {
// TODO Better support for table
if(scrollView.localName === 'table') {
scrollView = scrollView.firstElementChild;
}
insertBeforeNode(view, scrollView, scrollView.childNodes[1]);
}

export function moveViewLast(view, scrollView, numberOfDomElements) {
// TODO Better support for table
if(scrollView.localName === 'table') {
scrollView = scrollView.firstElementChild;
}
insertBeforeNode(view, scrollView, scrollView.children[numberOfDomElements]);
}

Expand Down
50 changes: 41 additions & 9 deletions src/virtual-repeat.js
Expand Up @@ -62,7 +62,13 @@ export class VirtualRepeat {

attached(){
this.isAttached = true;
this.virtualScrollInner = this.element.parentNode;

if (this.element.parentNode.localName === 'tbody') {
this.virtualScrollInner = this.element.parentNode.parentNode;
} else {
this.virtualScrollInner = this.element.parentNode;
}

this.virtualScroll = this.virtualScrollInner.parentElement;
this.virtualScroll.style.overflow = 'hidden';
this.virtualScroll.tabIndex = '-1';
Expand All @@ -76,6 +82,7 @@ export class VirtualRepeat {
});

this.itemsChanged();
this.scroll();
}

bind(bindingContext, overrideContext){
Expand Down Expand Up @@ -131,9 +138,6 @@ export class VirtualRepeat {
this.strategy.instanceChanged(this, items, this.numberOfDomElements);
this._calcScrollViewHeight();
this._calcIndicatorHeight();

// TODO Call this on scrolling
this.scroll();
}

unbind(){
Expand Down Expand Up @@ -176,6 +180,11 @@ export class VirtualRepeat {
ease = this.useEase ? 0.1 : 1,
element, viewStart, viewEnd, marginTop, translateStyle, view, first;

// TODO Better solution for table support - strategy?
if (scrollView.localName === 'table') {
childNodes = scrollView.childNodes.firstElementChild;
}

this.currentY += (this.targetY - this.currentY) * ease;
this.currentY = Math.round(this.currentY);

Expand All @@ -188,6 +197,11 @@ export class VirtualRepeat {
first = this.first = Math.ceil(this.currentY / itemHeight) * -1;

if(first > this.previousFirst && first + numberOfDomElements - 1 <= items.length){
if((first - this.previousFirst) > 1){
first = this.first = this.previousFirst + 1;
this.currentY = this.currentY + itemHeight;
}

this.previousFirst = first;

view = viewSlot.children[0];
Expand All @@ -199,7 +213,12 @@ export class VirtualRepeat {

marginTop = itemHeight * first + "px";
scrollView.style.marginTop = marginTop;
}else if (first < this.previousFirst && !Object.is(first, -0)){
}else if (first < this.previousFirst){
if((this.previousFirst - first) > 1){
first = this.first = this.previousFirst - 1;
this.currentY = this.currentY - itemHeight;
}

this.previousFirst = first;

view = viewSlot.children[numberOfDomElements - 1];
Expand Down Expand Up @@ -227,16 +246,16 @@ export class VirtualRepeat {
}

scrollIndicator(){
if(!this.indicator) {
if (!this.indicator) {
return;
}

var scrolledPercentage, indicatorTranslateStyle;

scrolledPercentage = (-this.currentY) / ((this.items.length * this.itemHeight) - this.virtualScrollHeight);
scrolledPercentage = -this.currentY / (this.items.length * this.itemHeight - this.virtualScrollHeight);
this.indicatorY = (this.virtualScrollHeight - this.indicatorHeight) * scrolledPercentage;

indicatorTranslateStyle = "translate3d(0px," + this.indicatorY + "px,0px)";
indicatorTranslateStyle = "translate3d(0px," + this.indicatorY + "px,0px)";
this.indicator.style.webkitTransform = indicatorTranslateStyle;
this.indicator.style.msTransform = indicatorTranslateStyle;
this.indicator.style.transform = indicatorTranslateStyle;
Expand Down Expand Up @@ -305,9 +324,19 @@ export class VirtualRepeat {
}

_createScrollIndicator(){
if(this.indicator) {
return;
}
var indicator;
indicator = this.indicator = document.createElement('div');
this.virtualScroll.appendChild(this.indicator);

// TODO Better table support - maybe strategy?
if (this.virtualScroll.localName === 'table') {
this.virtualScroll.firstElementChild.appendChild(this.indicator);
} else {
this.virtualScroll.appendChild(this.indicator);
}

indicator.classList.add('au-scroll-indicator');
indicator.style.backgroundColor = '#cccccc';
indicator.style.top = '0px';
Expand All @@ -325,6 +354,9 @@ export class VirtualRepeat {
}

_calcInitialHeights() {
if (this.numberOfDomElements > 0) {
return;
}
let listItems = this.virtualScrollInner.children;
this.itemHeight = calcOuterHeight(listItems[0]);
this.virtualScrollHeight = calcScrollHeight(this.virtualScroll);
Expand Down

0 comments on commit 54ad2fb

Please sign in to comment.