Skip to content

Commit ad039eb

Browse files
committed
Refactor Viewport
1 parent 33495c7 commit ad039eb

File tree

1 file changed

+108
-95
lines changed

1 file changed

+108
-95
lines changed

src/ui-scroll.js

Lines changed: 108 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -234,120 +234,133 @@ angular.module('ui.scroll', [])
234234
return viewport.outerHeight() * Math.max(0.1, +attrs.padding || 0.1); // some extra space to initiate preload
235235
}
236236

237-
viewport.createPaddingElements = function (template) {
238-
topPadding = new Padding(template);
239-
bottomPadding = new Padding(template);
240-
element.before(topPadding);
241-
return element.after(bottomPadding);
242-
};
237+
angular.extend(viewport, {
238+
createPaddingElements(template) {
239+
topPadding = new Padding(template);
240+
bottomPadding = new Padding(template);
241+
element.before(topPadding);
242+
element.after(bottomPadding);
243+
},
243244

244-
viewport.bottomDataPos = function () {
245-
var ref;
246-
return ((ref = viewport[0].scrollHeight) != null ? ref : viewport[0].document.documentElement.scrollHeight) - bottomPadding.height();
247-
};
245+
bottomDataPos() {
246+
let scrollHeight = viewport[0].scrollHeight;
247+
scrollHeight = scrollHeight !== null ? scrollHeight : viewport[0].document.documentElement.scrollHeight;
248248

249-
viewport.topDataPos = function () {
250-
return topPadding.height();
251-
};
249+
return scrollHeight - bottomPadding.height();
250+
},
252251

253-
viewport.bottomVisiblePos = function () {
254-
return viewport.scrollTop() + viewport.outerHeight();
255-
};
252+
topDataPos() {
253+
return topPadding.height();
254+
},
256255

257-
viewport.topVisiblePos = function () {
258-
return viewport.scrollTop();
259-
};
256+
bottomVisiblePos() {
257+
return viewport.scrollTop() + viewport.outerHeight();
258+
},
260259

261-
viewport.insertElement = function (e, sibling) {
262-
return insertElement(e, sibling || topPadding);
263-
};
260+
topVisiblePos() {
261+
return viewport.scrollTop();
262+
},
264263

265-
viewport.insertElementAnimated = function (e, sibling) {
266-
return insertElementAnimated(e, sibling || topPadding);
267-
};
264+
insertElement(e, sibling) {
265+
return insertElement(e, sibling || topPadding);
266+
},
268267

269-
viewport.shouldLoadBottom = function () {
270-
return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding();
271-
};
268+
insertElementAnimated(e, sibling) {
269+
return insertElementAnimated(e, sibling || topPadding);
270+
},
271+
272+
shouldLoadBottom() {
273+
return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding();
274+
},
275+
276+
clipBottom() {
277+
// clip the invisible items off the bottom
278+
let overage = 0;
279+
let i = buffer.length - 1;
272280

273-
viewport.clipBottom = function () {
274-
// clip the invisible items off the bottom
275-
var i, item, j, overage, ref;
276-
overage = 0;
277-
for (i = j = ref = buffer.length - 1; ref <= 0 ? j <= 0 : j >= 0; i = ref <= 0 ? ++j : --j) {
278-
item = buffer[i];
279-
if (item.element.offset().top - viewportOffset().top > viewport.outerHeight() + bufferPadding()) {
281+
while (i >= 0) {
282+
if (buffer[i].element.offset().top - viewportOffset().top <= viewport.outerHeight() + bufferPadding()) {
283+
break;
284+
}
280285
overage++;
281-
} else {
282-
break;
286+
i--;
283287
}
284-
}
285-
if (overage > 0) {
286-
buffer.eof = false;
287-
buffer.remove(buffer.length - overage, buffer.length);
288-
buffer.next -= overage;
289-
return viewport.adjustPadding();
290-
}
291-
};
292288

293-
viewport.shouldLoadTop = function () {
294-
return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding());
295-
};
289+
if (overage > 0) {
290+
buffer.eof = false;
291+
buffer.remove(buffer.length - overage, buffer.length);
292+
buffer.next -= overage;
293+
viewport.adjustPadding();
294+
}
295+
},
296296

297-
viewport.clipTop = function () {
298-
// clip the invisible items off the top
299-
var item, j, len, overage, overageHeight;
300-
overage = 0;
301-
overageHeight = 0;
302-
for (j = 0, len = buffer.length; j < len; j++) {
303-
item = buffer[j];
304-
if (item.element.offset().top - viewportOffset().top + item.element.outerHeight(true) < (-1) * bufferPadding()) {
297+
shouldLoadTop() {
298+
return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding());
299+
},
300+
301+
clipTop() {
302+
// clip the invisible items off the top
303+
let overage = 0;
304+
let overageHeight = 0;
305+
306+
buffer.some((item) => {
307+
if (item.element.offset().top - viewportOffset().top + item.element.outerHeight(true) >= (-1) * bufferPadding()) {
308+
// break the loop
309+
return true;
310+
}
305311
overageHeight += item.element.outerHeight(true);
306312
overage++;
307-
} else {
308-
break;
313+
});
314+
315+
if (overage > 0) {
316+
// we need to adjust top padding element before items are removed from top
317+
// to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom
318+
topPadding.height(topPadding.height() + overageHeight);
319+
buffer.bof = false;
320+
buffer.remove(0, overage);
321+
buffer.first += overage;
309322
}
310-
}
311-
if (overage > 0) {
312-
// we need to adjust top padding element before items are removed from top
313-
// to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom
314-
topPadding.height(topPadding.height() + overageHeight);
315-
buffer.bof = false;
316-
buffer.remove(0, overage);
317-
return buffer.first += overage;
318-
}
319-
};
323+
},
320324

321-
viewport.adjustPadding = function () {
322-
if (!buffer.length) {
323-
return;
324-
}
325-
averageItemHeight = (buffer[buffer.length - 1].element.offset().top + buffer[buffer.length - 1].element.outerHeight(true) - buffer[0].element.offset().top) / buffer.length;
326-
topPadding.height((buffer.first - buffer.minIndex) * averageItemHeight);
327-
return bottomPadding.height((buffer.maxIndex - buffer.next + 1) * averageItemHeight);
328-
};
325+
adjustPadding() {
326+
if (!buffer.length) {
327+
return;
328+
}
329329

330-
viewport.syncDatasource = function (datasource) {
331-
var delta;
332-
if (!buffer.length) {
333-
return;
334-
}
335-
delta = buffer.syncDatasource(datasource) * averageItemHeight;
336-
topPadding.height(topPadding.height() + delta);
337-
viewport.scrollTop(viewport.scrollTop() + delta);
338-
return viewport.adjustPadding();
339-
};
330+
const bufferFirstEl = buffer[0].element;
331+
const bufferLastEl = buffer[buffer.length - 1].element;
340332

341-
viewport.adjustScrollTop = function (height) {
342-
var paddingHeight;
343-
paddingHeight = topPadding.height() - height;
344-
if (paddingHeight >= 0) {
345-
return topPadding.height(paddingHeight);
346-
} else {
347-
topPadding.height(0);
348-
return viewport.scrollTop(viewport.scrollTop() - paddingHeight);
333+
averageItemHeight = (bufferLastEl.offset().top + bufferLastEl.outerHeight(true) - bufferFirstEl.offset().top) / buffer.length;
334+
topPadding.height((buffer.first - buffer.minIndex) * averageItemHeight);
335+
336+
return bottomPadding.height((buffer.maxIndex - buffer.next + 1) * averageItemHeight);
337+
},
338+
339+
syncDatasource(datasource) {
340+
if (!buffer.length) {
341+
return;
342+
}
343+
344+
const delta = buffer.syncDatasource(datasource) * averageItemHeight;
345+
346+
topPadding.height(topPadding.height() + delta);
347+
348+
viewport.scrollTop(viewport.scrollTop() + delta);
349+
350+
viewport.adjustPadding();
351+
},
352+
353+
adjustScrollTop(height) {
354+
const paddingHeight = topPadding.height() - height;
355+
356+
if (paddingHeight >= 0) {
357+
topPadding.height(paddingHeight);
358+
} else {
359+
topPadding.height(0);
360+
viewport.scrollTop(viewport.scrollTop() - paddingHeight);
361+
}
349362
}
350-
};
363+
});
351364

352365
return viewport;
353366
}

0 commit comments

Comments
 (0)