(function (global, factory) {
(typeof exports === 'object' && typeof module !== 'undefined') ? module.exports = factory() : (global.Vlist = factory());
}(this, function () {
function Vlist(param) {
this.locker = false;
this.itemHeight = param.itemHeight;
this.container = param.container;
this.containerUL = this.container.querySelector("ul");
this.maxHeight = param.maxHeight ? param.maxHeight : document.documentElement.clientHeight;
this.showItemCount = Math.ceil(this.maxHeight / this.itemHeight) + 1;
this.items = [];
this.startIndex = 0;
this.render = param.render;
this.data = [];
if (param.initData) {
this.addData(param.initData);
}
if (param.loadData) {
this.loadData = function () {
if (this.locker) return;
this.locker = true;
param.loadData()
};
if (!Array.isArray(param.initData) || param.initData.length == 0) {
this.loadData();
}
}
this.scrollEventBind = this.scrollEvent.bind(this);
this.container.addEventListener("scroll", this.scrollEventBind, false);
}
Vlist.prototype.renderItem = function (item) {
var index = item.index;
var itemDom = item.dom ? item.dom : document.createElement("LI");
var itemData = this.data[index];
itemDom.innerHTML = this.render(itemData, index);
itemDom.style.position = "absolute";
itemDom.style.top = (index * this.itemHeight) + "px";
itemDom.style.height = this.itemHeight + "px";
itemDom.style.width = "100%";
itemDom.style.overflow = "hidden";
item.dom = itemDom;
item.dom.setAttribute("index", index);
item.top = index * this.itemHeight;
return item;
}
Vlist.prototype.initList = function () {
var count = this.data.length < this.showItemCount ? this.data.length : this.showItemCount;
for (var i = 0; i < count; i++) {
var item = this.renderItem({
index: i
});
this.containerUL.appendChild(item.dom);
this.items.push(item);
}
}
Vlist.prototype.destroy = function () {
this.containerUL.innerHTML = '';
this.data = [];
this.items = [];
this.locker = false;
this.startIndex = 0;
this.container.removeEventListener("scroll", this.scrollEventBind, false)
}
Vlist.prototype.reloadData = function (data) {
this.destroy();
this.addData(data);
}
Vlist.prototype.addData = function (data) {
this.locker = false;
let isInit = this.data.length == 0;
this.data = this.data.concat(data);
var realHeight = parseInt(this.data.length * this.itemHeight);
if (realHeight > this.maxHeight) {
this.container.style.height = this.maxHeight + 'px';
this.showItemCount = Math.ceil(this.maxHeight / this.itemHeight) + 1;
} else {
this.container.style.height = realHeight + 'px';
this.showItemCount = this.data.length + 1;
}
this.containerUL.style.height = realHeight + 'px';
if (isInit) {
this.initList();
}
this.closeLoading();
}
Vlist.prototype.showLoading = function () {
if (!this.loadingDom) {
this.loadingDom = document.createElement("LI");
this.loadingDom.setAttribute("class", "loading");
this.loadingDom.innerText = "加载中...";
}
this.loadingDom.style.position = "absolute";
this.loadingDom.style.top = (this.items[this.items.length - 1].top + this.itemHeight) + 'px';
this.containerUL.appendChild(this.loadingDom);
}
Vlist.prototype.closeLoading = function () {
if (this.loadingDom)
this.containerUL.removeChild(this.loadingDom);
}
Vlist.prototype.diffRender = function (startIndex, startIndexNew) {
var showItemCount = this.showItemCount;
var items = this.items;
var moveCount = Math.abs(startIndex - startIndexNew);
if (moveCount >= showItemCount) {
items.forEach((item, idx) => {
item.index = startIndexNew + idx;
this.renderItem(item);
})
} else {
if (startIndex - startIndexNew > 0) {
for (var i = 1; i <= moveCount; i++) {
var item = items[showItemCount - i];
item.index = item.index - showItemCount;
this.renderItem(item);
}
this.items = items.splice(showItemCount - moveCount, moveCount).concat(items);
} else {
for (var i = 0; i < moveCount; i++) {
var item = items[i];
item.index = item.index + showItemCount;
this.renderItem(item);
}
this.items = items.concat(items.splice(0, moveCount));
}
}
}
Vlist.prototype.scrollEvent = function () {
var containerScrollTop = this.container.scrollTop;
var itemHeight = this.itemHeight;
var startIndex = this.startIndex;
if (containerScrollTop < 0) return;
var startIndexNew = Math.floor(containerScrollTop / itemHeight);
var maxStartIndex = this.data.length - this.showItemCount + 1;
startIndexNew = startIndexNew > maxStartIndex ? maxStartIndex : startIndexNew;
if (startIndexNew === startIndex) return;
var scrollOver = startIndexNew + this.showItemCount - 1 >= this.data.length;
var renderOver = startIndexNew - startIndex === 1;
if (scrollOver && renderOver) {
if (this.loadData) {
this.showLoading();
this.loadData();
}
return;
}
if (scrollOver && renderOver === false) {
startIndexNew--;
}
this.diffRender(startIndex, startIndexNew);
this.startIndex = startIndexNew;
}
return Vlist;
}));