Skip to content

Commit 1fe64a6

Browse files
committed
fix(table-strategy): move buffer elements outside of table
Fixes #46
1 parent cb23200 commit 1fe64a6

File tree

2 files changed

+68
-27
lines changed

2 files changed

+68
-27
lines changed

src/template-strategy.js

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import {inject, Container} from 'aurelia-dependency-injection';
12
import {DOM} from 'aurelia-pal';
23
import {View} from 'aurelia-templating';
34
import {insertBeforeNode} from './utilities';
5+
import {DomHelper} from './dom-helper';
46

57
interface TemplateStrategy {
68
getScrollContainer(element: Element): Element;
@@ -11,17 +13,25 @@ interface TemplateStrategy {
1113
removeBufferElements(element: Element, topBuffer: Element, bottomBuffer: Element): void;
1214
getFirstElement(topBuffer: Element): Element;
1315
getLastView(bottomBuffer: Element): Element;
16+
getTopBufferDistance(topBuffer: Element): number;
1417
}
1518

19+
@inject(Container)
1620
export class TemplateStrategyLocator {
21+
22+
constructor(container: Container) {
23+
this.container = container;
24+
}
25+
1726
getStrategy(element: Element): TemplateStrategy {
1827
if (element.parentNode && element.parentNode.localName === 'tbody') {
19-
return new TableStrategy();
28+
return this.container.get(TableStrategy);
2029
}
21-
return new DefaultTemplateStrategy();
30+
return this.container.get(DefaultTemplateStrategy);
2231
}
2332
}
2433

34+
@inject(DomHelper)
2535
export class TableStrategy {
2636
tableCssReset = '\
2737
display: block;\
@@ -36,52 +46,76 @@ export class TableStrategy {
3646
-webkit-border-horizontal-spacing: 0;\
3747
-webkit-border-vertical-spacing: 0;';
3848

49+
constructor(domHelper) {
50+
this.domHelper = domHelper;
51+
}
52+
3953
getScrollContainer(element: Element): Element {
4054
return element.parentNode;
4155
}
4256

4357
moveViewFirst(view: View, topBuffer: Element): void {
44-
insertBeforeNode(view, DOM.nextElementSibling(topBuffer.parentNode));
58+
const tbody = this._getTbodyElement(topBuffer.nextSibling);
59+
const tr = tbody.firstChild;
60+
const firstElement = DOM.nextElementSibling(tr);
61+
insertBeforeNode(view, firstElement);
4562
}
4663

4764
moveViewLast(view: View, bottomBuffer: Element): void {
48-
let previousSibling = bottomBuffer.parentNode.previousSibling;
49-
let referenceNode = previousSibling.nodeType === 8 && previousSibling.data === 'anchor' ? previousSibling : bottomBuffer.parentNode;
65+
const lastElement = this.getLastElement(bottomBuffer).nextSibling;
66+
const referenceNode = lastElement.nodeType === 8 && lastElement.data === 'anchor' ? lastElement : lastElement;
5067
insertBeforeNode(view, referenceNode);
5168
}
5269

5370
createTopBufferElement(element: Element): Element {
54-
let tr = DOM.createElement('tr');
55-
tr.setAttribute('style', this.tableCssReset);
56-
let buffer = DOM.createElement('td');
57-
buffer.setAttribute('style', this.tableCssReset);
58-
tr.appendChild(buffer);
59-
element.parentNode.insertBefore(tr, element);
71+
const elementName = element.parentNode.localName === 'ul' ? 'li' : 'div';
72+
const buffer = DOM.createElement(elementName);
73+
const tableElement = element.parentNode.parentNode;
74+
tableElement.parentNode.insertBefore(buffer, tableElement);
75+
buffer.innerHTML = ' ';
6076
return buffer;
6177
}
6278

6379
createBottomBufferElement(element: Element): Element {
64-
let tr = DOM.createElement('tr');
65-
tr.setAttribute('style', this.tableCssReset);
66-
let buffer = DOM.createElement('td');
67-
buffer.setAttribute('style', this.tableCssReset);
68-
tr.appendChild(buffer);
69-
element.parentNode.insertBefore(tr, element.nextSibling);
80+
const elementName = element.parentNode.localName === 'ul' ? 'li' : 'div';
81+
const buffer = DOM.createElement(elementName);
82+
const tableElement = element.parentNode.parentNode;
83+
tableElement.parentNode.insertBefore(buffer, tableElement.nextSibling);
7084
return buffer;
7185
}
7286

7387
removeBufferElements(element: Element, topBuffer: Element, bottomBuffer: Element): void {
74-
element.parentNode.removeChild(topBuffer.parentNode);
75-
element.parentNode.removeChild(bottomBuffer.parentNode);
88+
topBuffer.parentNode.removeChild(topBuffer);
89+
bottomBuffer.parentNode.removeChild(bottomBuffer);
7690
}
7791

7892
getFirstElement(topBuffer: Element): Element {
79-
let tr = topBuffer.parentNode;
93+
const tbody = this._getTbodyElement(DOM.nextElementSibling(topBuffer));
94+
const tr = tbody.firstChild;
8095
return DOM.nextElementSibling(tr);
8196
}
8297

8398
getLastElement(bottomBuffer: Element): Element {
84-
return bottomBuffer.parentNode.previousElementSibling;
99+
const tbody = this._getTbodyElement(bottomBuffer.previousSibling);
100+
const trs = tbody.children;
101+
return trs[trs.length - 1];
102+
}
103+
104+
getTopBufferDistance(topBuffer: Element): number {
105+
const tbody = this._getTbodyElement(topBuffer.nextSibling);
106+
return this.domHelper.getElementDistanceToTopOfDocument(tbody) - this.domHelper.getElementDistanceToTopOfDocument(topBuffer);
107+
}
108+
109+
_getTbodyElement(tableElement: Element): Element {
110+
let tbodyElement;
111+
const children = tableElement.children;
112+
for (let i = 0, ii = children.length; i < ii; ++i) {
113+
if (children[i].localName === 'tbody') {
114+
tbodyElement = children[i];
115+
break;
116+
}
117+
}
118+
return tbodyElement;
85119
}
86120
}
87121

@@ -95,21 +129,21 @@ export class DefaultTemplateStrategy {
95129
}
96130

97131
moveViewLast(view: View, bottomBuffer: Element): void {
98-
let previousSibling = bottomBuffer.previousSibling;
99-
let referenceNode = previousSibling.nodeType === 8 && previousSibling.data === 'anchor' ? previousSibling : bottomBuffer;
132+
const previousSibling = bottomBuffer.previousSibling;
133+
const referenceNode = previousSibling.nodeType === 8 && previousSibling.data === 'anchor' ? previousSibling : bottomBuffer;
100134
insertBeforeNode(view, referenceNode);
101135
}
102136

103137
createTopBufferElement(element: Element): Element {
104-
let elementName = element.parentNode.localName === 'ul' ? 'li' : 'div';
105-
let buffer = DOM.createElement(elementName);
138+
const elementName = element.parentNode.localName === 'ul' ? 'li' : 'div';
139+
const buffer = DOM.createElement(elementName);
106140
element.parentNode.insertBefore(buffer, element);
107141
return buffer;
108142
}
109143

110144
createBottomBufferElement(element: Element): Element {
111-
let elementName = element.parentNode.localName === 'ul' ? 'li' : 'div';
112-
let buffer = DOM.createElement(elementName);
145+
const elementName = element.parentNode.localName === 'ul' ? 'li' : 'div';
146+
const buffer = DOM.createElement(elementName);
113147
element.parentNode.insertBefore(buffer, element.nextSibling);
114148
return buffer;
115149
}
@@ -126,4 +160,8 @@ export class DefaultTemplateStrategy {
126160
getLastElement(bottomBuffer: Element): Element {
127161
return bottomBuffer.previousElementSibling;
128162
}
163+
164+
getTopBufferDistance(topBuffer: Element): number {
165+
return 0;
166+
}
129167
}

src/virtual-repeat.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,15 @@ export class VirtualRepeat extends AbstractRepeater {
9292
this.calcDistanceToTopInterval = setInterval(() => {
9393
let distanceToTop = this.distanceToTop;
9494
this.distanceToTop = this.domHelper.getElementDistanceToTopOfDocument(this.topBuffer);
95+
this.distanceToTop += this.topBufferDistance;
9596
if (distanceToTop !== this.distanceToTop) {
9697
this._handleScroll();
9798
}
9899
}, 500);
99100

100101
this.distanceToTop = this.domHelper.getElementDistanceToTopOfDocument(this.templateStrategy.getFirstElement(this.topBuffer));
102+
this.topBufferDistance = this.templateStrategy.getTopBufferDistance(this.topBuffer);
103+
101104
if (this.domHelper.hasOverflowScroll(this.scrollContainer)) {
102105
this._fixedHeightContainer = true;
103106
this.scrollContainer.addEventListener('scroll', this.scrollListener);

0 commit comments

Comments
 (0)