@syncfusion/ej2-lists
Version:
The listview control allows you to select an item or multiple items from a list-like interface and represents the data in interactive hierarchical structure across different layouts or views.
886 lines (885 loc) • 46.6 kB
JavaScript
import { classNames } from './list-view';
import { EventHandler, append, isNullOrUndefined, detach, compile, formatUnit, select } from '@syncfusion/ej2-base';
import { ListBase } from '../common/list-base';
import { DataManager } from '@syncfusion/ej2-data';
var listElementCount = 1.5;
var windowElementCount = 3;
var Virtualization = /** @class */ (function () {
function Virtualization(instance) {
this.elementDifference = 0;
this.listViewInstance = instance;
}
/**
* For internal use only.
*
* @private
*/
Virtualization.prototype.isNgTemplate = function () {
return !isNullOrUndefined(this.listViewInstance.templateRef) && typeof this.listViewInstance.templateRef !== 'string';
};
/**
* Checks if the platform is a Vue and its template property is a function type.
*
* @returns {boolean} indicating the result of the check
*/
Virtualization.prototype.isVueFunctionTemplate = function () {
return this.listViewInstance.isVue && typeof this.listViewInstance.template === 'function';
};
/**
* For internal use only.
*
* @private
*/
Virtualization.prototype.uiVirtualization = function () {
this.wireScrollEvent(false);
var curViewDS = this.listViewInstance.curViewDS;
var isRendered = this.listViewInstance.isRendered;
var firstIndex = isRendered && !isNullOrUndefined(this.uiFirstIndex) && this.uiLastIndex <= Object.keys(curViewDS).length
? this.uiFirstIndex : 0;
var firstDs = curViewDS.slice(firstIndex, firstIndex + 1);
this.listViewInstance.ulElement = this.listViewInstance.curUL = ListBase.createList(this.listViewInstance.createElement, firstDs, this.listViewInstance.listBaseOption, null, this.listViewInstance);
this.listViewInstance.contentContainer = this.listViewInstance.createElement('div', { className: classNames.container });
this.listViewInstance.element.appendChild(this.listViewInstance.contentContainer);
this.listViewInstance.contentContainer.appendChild(this.listViewInstance.ulElement);
this.listItemHeight = this.listViewInstance.ulElement.firstElementChild.getBoundingClientRect().height;
this.expectedDomItemCount = this.ValidateItemCount(10000);
this.updateDOMItemCount();
var lastIndex = isRendered && !isNullOrUndefined(this.uiLastIndex) && this.listDiff !== 0
? this.uiLastIndex : this.domItemCount - 1;
this.uiFirstIndex = firstIndex;
this.uiLastIndex = lastIndex;
var otherDs = curViewDS.slice(firstIndex + 1, lastIndex + 1);
var listItems = ListBase.createListItemFromJson(this.listViewInstance.createElement, otherDs, this.listViewInstance.listBaseOption, null, null, this.listViewInstance);
append(listItems, this.listViewInstance.ulElement);
this.listViewInstance.liCollection = this.listViewInstance.curUL.querySelectorAll('li');
this.topElement = this.listViewInstance.createElement('div');
this.listViewInstance.ulElement.insertBefore(this.topElement, this.listViewInstance.ulElement.firstElementChild);
this.bottomElement = this.listViewInstance.createElement('div');
this.listViewInstance.ulElement.insertBefore(this.bottomElement, null);
this.totalHeight = (Object.keys(curViewDS).length * this.listItemHeight) - (this.domItemCount * this.listItemHeight);
this.topElement.style.height = isRendered ? this.topElementHeight + 'px' : '0px';
this.bottomElement.style.height = isRendered ? (this.totalHeight - this.topElementHeight) + 'px' : this.totalHeight + 'px';
this.topElementHeight = isRendered ? this.topElementHeight : 0;
this.bottomElementHeight = isRendered ? (this.totalHeight - this.topElementHeight) : this.totalHeight;
this.listDiff = isRendered && Object.keys(curViewDS).length !== this.domItemCount ? this.listDiff : 0;
if (isRendered) {
this.listViewInstance.element.scrollTop = this.listViewInstance.previousScrollTop;
}
this.uiIndicesInitialization();
};
Virtualization.prototype.wireScrollEvent = function (destroy) {
if (!destroy) {
if (this.listViewInstance.isWindow) {
this.onVirtualScroll = this.onVirtualUiScroll.bind(this);
window.addEventListener('scroll', this.onVirtualScroll);
}
else {
EventHandler.add(this.listViewInstance.element, 'scroll', this.onVirtualUiScroll, this);
}
}
else {
if (this.listViewInstance.isWindow === true) {
window.removeEventListener('scroll', this.onVirtualScroll);
window.removeEventListener('scroll', this.updateUl);
}
else {
EventHandler.remove(this.listViewInstance.element, 'scroll', this.onVirtualUiScroll);
}
}
};
Virtualization.prototype.ValidateItemCount = function (dataSourceLength) {
var height = parseFloat(formatUnit(this.listViewInstance.height));
var itemCount;
if (this.listViewInstance.isWindow) {
itemCount = Math.round((window.innerHeight / this.listItemHeight) * windowElementCount);
}
else {
if (typeof this.listViewInstance.height === 'string' && this.listViewInstance.height.indexOf('%') !== -1) {
itemCount = Math.round((this.listViewInstance.element.getBoundingClientRect().height / this.listItemHeight) * listElementCount);
}
else {
itemCount = Math.round((height / this.listItemHeight) * listElementCount);
}
}
if (itemCount > dataSourceLength) {
itemCount = dataSourceLength;
}
return itemCount;
};
Virtualization.prototype.updateDOMItemCount = function () {
this.domItemCount = this.ValidateItemCount(Object.keys(this.listViewInstance.curViewDS).length);
};
Virtualization.prototype.uiIndicesInitialization = function () {
this.uiIndices = { 'activeIndices': [], 'disabledItemIndices': [], 'hiddenItemIndices': [] };
var data = this.listViewInstance.curViewDS;
for (var i = 0; i < data.length; i++) {
if (this.listViewInstance.showCheckBox && data[i][this.listViewInstance.fields.isChecked]) {
this.uiIndices.activeIndices.push(i);
}
if (!isNullOrUndefined(data[parseInt(i.toString(), 10)][this.listViewInstance.fields.enabled]) &&
!data[i][this.listViewInstance.fields.enabled]) {
(this.uiIndices.disabledItemIndices.push(i));
}
}
if (this.isNgTemplate()) {
var items = this.listViewInstance.element.querySelectorAll('.' + classNames.listItem);
for (var index = 0; index < items.length; index++) {
items[index].context = this.listViewInstance.viewContainerRef.get(index).context;
}
}
};
Virtualization.prototype.refreshItemHeight = function () {
if (this.listViewInstance.curViewDS.length) {
var curViewDS = this.listViewInstance.curViewDS;
this.listItemHeight = this.topElement.nextSibling.getBoundingClientRect().height;
this.totalHeight = (Object.keys(curViewDS).length * this.listItemHeight) - (this.domItemCount * this.listItemHeight);
this.bottomElementHeight = this.totalHeight;
this.bottomElement.style.height = this.totalHeight + 'px';
}
};
Virtualization.prototype.getscrollerHeight = function (startingHeight) {
return this.listViewInstance.isWindow ? (((pageYOffset - startingHeight) <= 0) ? 0 :
(pageYOffset - startingHeight)) : ((this.listViewInstance.element.scrollTop - startingHeight) <= 0) ? 0 :
(this.listViewInstance.element.scrollTop - startingHeight);
};
Virtualization.prototype.onVirtualUiScroll = function () {
var _a;
var startingHeight;
var curViewDS = this.listViewInstance.curViewDS;
this.listItemHeight = select('.e-list-item', this.listViewInstance.element).getBoundingClientRect().height;
this.totalHeight = (Object.keys(curViewDS).length * this.listItemHeight) - (this.domItemCount * this.listItemHeight);
if (this.listViewInstance.isWindow) {
startingHeight = this.listViewInstance.ulElement.getBoundingClientRect().top -
document.documentElement.getBoundingClientRect().top;
}
else {
startingHeight = this.listViewInstance.headerEle ? this.listViewInstance.headerEle.getBoundingClientRect().height : 0;
}
this.scrollPosition = isNullOrUndefined(this.scrollPosition) ? 0 : this.scrollPosition;
var scroll = this.getscrollerHeight(startingHeight);
this.topElementHeight = this.listItemHeight * Math.floor(scroll / this.listItemHeight);
this.bottomElementHeight = this.totalHeight - this.topElementHeight;
_a = scroll <= this.totalHeight ?
[this.topElementHeight, this.bottomElementHeight] : [this.totalHeight, 0], this.topElementHeight = _a[0], this.bottomElementHeight = _a[1];
if (this.topElementHeight !== parseFloat(this.topElement.style.height)) {
this.topElement.style.height = this.topElementHeight + 'px';
this.bottomElement.style.height = this.bottomElementHeight + 'px';
if (scroll > this.scrollPosition) {
var listDiff = Math.round(((this.topElementHeight / this.listItemHeight) - this.listDiff));
if (listDiff > (this.expectedDomItemCount + 5)) {
this.onLongScroll(listDiff, true);
}
else {
this.onNormalScroll(listDiff, true);
}
}
else {
var listDiff = Math.round((this.listDiff - (this.topElementHeight / this.listItemHeight)));
if (listDiff > (this.expectedDomItemCount + 5)) {
this.onLongScroll(listDiff, false);
}
else {
this.onNormalScroll(listDiff, false);
}
}
}
this.listDiff = Math.round(this.topElementHeight / this.listItemHeight);
if (typeof this.listViewInstance.onUIScrolled === 'function') {
this.listViewInstance.onUIScrolled();
}
this.scrollPosition = scroll;
};
Virtualization.prototype.onLongScroll = function (listDiff, isScrollingDown) {
var index = isScrollingDown ? (this.uiFirstIndex + listDiff) : (this.uiFirstIndex - listDiff);
var elements = this.listViewInstance.ulElement.querySelectorAll('li');
for (var i = 0; i < elements.length; i++) {
this.updateUI(elements[i], index);
index++;
}
this.uiLastIndex = isScrollingDown ? (this.uiLastIndex + listDiff) : (this.uiLastIndex - listDiff);
this.uiFirstIndex = isScrollingDown ? (this.uiFirstIndex + listDiff) : (this.uiFirstIndex - listDiff);
};
Virtualization.prototype.onNormalScroll = function (listDiff, isScrollingDown) {
if (isScrollingDown) {
for (var i = 0; i < listDiff; i++) {
var index = ++this.uiLastIndex;
this.updateUI(this.topElement.nextElementSibling, index, this.bottomElement);
this.uiFirstIndex++;
}
}
else {
for (var i = 0; i < listDiff; i++) {
var index = --this.uiFirstIndex;
var target = this.topElement.nextSibling;
this.updateUI(this.bottomElement.previousElementSibling, index, target);
this.uiLastIndex--;
}
}
};
Virtualization.prototype.updateUiContent = function (element, index) {
var curViewDs = this.listViewInstance.curViewDS;
if (typeof this.listViewInstance.dataSource[0] === 'string' ||
typeof this.listViewInstance.dataSource[0] === 'number') {
element.dataset.uid = ListBase.generateId();
element.getElementsByClassName(classNames.listItemText)[0].innerHTML =
this.listViewInstance.curViewDS[index].toString();
}
else {
element.dataset.uid = (curViewDs[parseInt(index.toString(), 10)][this.listViewInstance.fields.id]) ?
(curViewDs[parseInt(index.toString(), 10)][this.listViewInstance.fields.id]) : ListBase.generateId();
element.getElementsByClassName(classNames.listItemText)[0].innerHTML =
(curViewDs[parseInt(index.toString(), 10)][this.listViewInstance.fields.text]);
}
if (this.listViewInstance.showIcon) {
if (element.querySelector('.' + classNames.listIcon)) {
detach(element.querySelector('.' + classNames.listIcon));
}
if (this.listViewInstance.curViewDS[index][this.listViewInstance.fields.iconCss]) {
var textContent = element.querySelector('.' + classNames.textContent);
var curViewDS = this.listViewInstance.curViewDS[index];
var iconCss = curViewDS[this.listViewInstance.fields.iconCss].toString();
var target = this.listViewInstance.createElement('div', {
className: classNames.listIcon + ' ' + iconCss
});
textContent.insertBefore(target, element.querySelector('.' + classNames.listItemText));
}
}
if (this.listViewInstance.showCheckBox && this.listViewInstance.fields.groupBy) {
if (!this.checkListWrapper) {
this.checkListWrapper = this.listViewInstance.curUL.querySelector('.' + classNames.checkboxWrapper).cloneNode(true);
}
var textContent = element.querySelector('.' + classNames.textContent);
if (this.listViewInstance.curViewDS[index].isHeader) {
if (element.querySelector('.' + classNames.checkboxWrapper)) {
element.classList.remove(classNames.checklist);
textContent.classList.remove(classNames.checkbox);
detach(element.querySelector('.' + classNames.checkboxWrapper));
}
}
else {
if (!element.querySelector('.' + classNames.checkboxWrapper)) {
element.classList.add(classNames.checklist);
textContent.classList.add(classNames.checkbox);
if (this.listViewInstance.checkBoxPosition === 'Left') {
textContent.classList.add('e-checkbox-left');
}
else {
textContent.classList.add('e-checkbox-right');
}
textContent.append(this.checkListWrapper.cloneNode(true));
}
}
}
};
Virtualization.prototype.changeElementAttributes = function (element, index) {
element.classList.remove(classNames.disable);
if (this.uiIndices.disabledItemIndices.length && this.uiIndices.disabledItemIndices.indexOf(index) !== -1) {
element.classList.add(classNames.disable);
}
element.style.display = '';
if (this.uiIndices.hiddenItemIndices.length && this.uiIndices.hiddenItemIndices.indexOf(index) !== -1) {
element.style.display = 'none';
}
if (this.listViewInstance.showCheckBox) {
var checklistElement = element.querySelector('.' + classNames.checkboxWrapper);
element.classList.remove(classNames.selected);
element.classList.remove(classNames.focused);
if (checklistElement) {
checklistElement.removeAttribute('aria-checked');
checklistElement.firstElementChild.classList.remove(classNames.checked);
}
if (this.uiIndices.activeIndices.length && this.uiIndices.activeIndices.indexOf(index) !== -1 &&
!this.listViewInstance.curUL.querySelector(classNames.selected)) {
element.classList.add(classNames.selected);
checklistElement.firstElementChild.classList.add(classNames.checked);
checklistElement.setAttribute('aria-checked', 'true');
if (this.activeIndex === index) {
element.classList.add(classNames.focused);
}
}
}
else {
element.classList.remove(classNames.selected);
element.removeAttribute('aria-selected');
if (!isNullOrUndefined(this.activeIndex) && this.activeIndex === index &&
!this.listViewInstance.curUL.querySelector(classNames.selected)) {
element.classList.add(classNames.selected);
element.setAttribute('aria-selected', 'true');
}
}
if (this.listViewInstance.fields.groupBy) {
if (this.listViewInstance.curViewDS[index].isHeader) {
if (element.classList.contains(classNames.listItem)) {
element.classList.remove(classNames.listItem);
element.setAttribute('role', 'group');
element.classList.add(classNames.groupListItem);
}
}
else {
if (element.classList.contains(classNames.groupListItem)) {
element.classList.remove(classNames.groupListItem);
element.setAttribute('role', 'listitem');
element.classList.add(classNames.listItem);
}
}
}
};
Virtualization.prototype.findDSAndIndexFromId = function (ds, fields) {
var _this = this;
var resultJSON = {};
fields = this.listViewInstance.getElementUID(fields);
if (!isNullOrUndefined(fields)) {
ds.some(function (data, index) {
if ((fields[_this.listViewInstance.fields.id] &&
fields[_this.listViewInstance.fields.id]
=== (data[_this.listViewInstance.fields.id] && data[_this.listViewInstance.fields.id]) || fields === data)) {
resultJSON.index = index;
resultJSON.data = data;
return true;
}
else {
return false;
}
});
}
return resultJSON;
};
Virtualization.prototype.getSelectedItems = function () {
var _this = this;
if (!isNullOrUndefined(this.activeIndex) || (this.listViewInstance.showCheckBox && this.uiIndices.activeIndices.length)) {
var dataCollection = [];
var textCollection = [];
if (typeof this.listViewInstance.dataSource[0] === 'string' ||
typeof this.listViewInstance.dataSource[0] === 'number') {
var curViewDS_1 = this.listViewInstance.curViewDS;
if (this.listViewInstance.showCheckBox) {
var indices = this.uiIndices.activeIndices;
for (var i = 0; i < indices.length; i++) {
dataCollection.push(curViewDS_1[indices[i]]);
}
return {
text: dataCollection,
data: dataCollection,
index: this.uiIndices.activeIndices.map(function (index) {
return _this.listViewInstance.dataSource.indexOf(curViewDS_1[index]);
})
};
}
else {
return {
text: curViewDS_1[this.activeIndex],
data: curViewDS_1[this.activeIndex],
index: this.listViewInstance.dataSource.indexOf(curViewDS_1[this.activeIndex])
};
}
}
else {
var curViewDS_2 = this.listViewInstance.curViewDS;
var text = this.listViewInstance.fields.text;
if (this.listViewInstance.showCheckBox) {
var indexArray = this.uiIndices.activeIndices;
for (var i = 0; i < indexArray.length; i++) {
textCollection.push(curViewDS_2[indexArray[i]]["" + text]);
dataCollection.push(curViewDS_2[indexArray[parseInt(i.toString(), 10)]]);
}
var dataSource_1 = this.listViewInstance.dataSource instanceof DataManager
? curViewDS_2 : this.listViewInstance.dataSource;
return {
text: textCollection,
data: dataCollection,
index: this.uiIndices.activeIndices.map(function (index) {
return dataSource_1.indexOf(curViewDS_2[index]);
})
};
}
else {
var dataSource = this.listViewInstance.dataSource instanceof DataManager
? curViewDS_2 : this.listViewInstance.dataSource;
return {
text: curViewDS_2[this.activeIndex][this.listViewInstance.fields.text],
data: curViewDS_2[this.activeIndex],
index: dataSource.indexOf(curViewDS_2[this.activeIndex])
};
}
}
}
else {
return undefined;
}
};
Virtualization.prototype.selectItem = function (obj) {
var _this = this;
var resutJSON = this.findDSAndIndexFromId(this.listViewInstance.curViewDS, obj);
if (Object.keys(resutJSON).length) {
var isSelected = this.activeIndex === resutJSON.index;
var isChecked_1;
this.activeIndex = resutJSON.index;
if (this.listViewInstance.showCheckBox) {
if (this.uiIndices.activeIndices.indexOf(resutJSON.index) === -1) {
isChecked_1 = true;
this.uiIndices.activeIndices.push(resutJSON.index);
}
else {
isChecked_1 = false;
this.uiIndices.activeIndices.splice(this.uiIndices.activeIndices.indexOf(resutJSON.index), 1);
}
if (this.listViewInstance.curUL.querySelector('.' + classNames.focused)) {
this.listViewInstance.curUL.querySelector('.' + classNames.focused).classList.remove(classNames.focused);
}
}
if (this.listViewInstance.getLiFromObjOrElement(obj)) {
if (this.listViewInstance.showCheckBox) {
this.listViewInstance.setCheckboxLI(this.listViewInstance.getLiFromObjOrElement(obj));
}
else {
this.listViewInstance.setSelectLI(this.listViewInstance.getLiFromObjOrElement(obj));
}
}
else {
var eventArgs_1;
if (typeof this.listViewInstance.dataSource[0] === 'string' ||
typeof this.listViewInstance.dataSource[0] === 'number') {
eventArgs_1 = {
text: this.listViewInstance.curViewDS[this.activeIndex],
data: this.listViewInstance.curViewDS[this.activeIndex],
index: this.activeIndex
};
}
else {
var curViewDS = this.listViewInstance.curViewDS;
eventArgs_1 = {
text: curViewDS[this.activeIndex][this.listViewInstance.fields.text],
data: curViewDS[this.activeIndex],
index: this.activeIndex
};
}
if (this.listViewInstance.showCheckBox) {
this.listViewInstance.trigger('select', eventArgs_1, function (observedArgs) {
if (observedArgs.cancel) {
if (!isChecked_1) {
eventArgs_1.isChecked = isChecked_1;
_this.uiIndices.activeIndices.push(resutJSON.index);
}
else {
eventArgs_1.isChecked = !isChecked_1;
_this.uiIndices.activeIndices.splice(_this.uiIndices.activeIndices.indexOf(resutJSON.index), 1);
}
}
});
}
else if (!isSelected) {
this.listViewInstance.removeSelect();
this.listViewInstance.trigger('select', eventArgs_1, function (observedArgs) {
if (observedArgs.cancel) {
_this.activeIndex = undefined;
}
});
}
}
}
else if (isNullOrUndefined(obj) && !this.listViewInstance.showCheckBox) {
this.listViewInstance.removeSelect();
this.activeIndex = undefined;
}
};
Virtualization.prototype.enableItem = function (obj) {
var resutJSON = this.findDSAndIndexFromId(this.listViewInstance.curViewDS, obj);
if (Object.keys(resutJSON).length) {
this.uiIndices.disabledItemIndices.splice(this.uiIndices.disabledItemIndices.indexOf(resutJSON.index), 1);
}
};
Virtualization.prototype.disableItem = function (obj) {
var resutJSON = this.findDSAndIndexFromId(this.listViewInstance.curViewDS, obj);
if (Object.keys(resutJSON).length && this.uiIndices.disabledItemIndices.indexOf(resutJSON.index) === -1) {
this.uiIndices.disabledItemIndices.push(resutJSON.index);
}
};
Virtualization.prototype.showItem = function (obj) {
var resutJSON = this.findDSAndIndexFromId(this.listViewInstance.curViewDS, obj);
if (Object.keys(resutJSON).length) {
this.uiIndices.hiddenItemIndices.splice(this.uiIndices.hiddenItemIndices.indexOf(resutJSON.index), 1);
}
};
Virtualization.prototype.hideItem = function (obj) {
var resutJSON = this.findDSAndIndexFromId(this.listViewInstance.curViewDS, obj);
if (Object.keys(resutJSON).length && this.uiIndices.hiddenItemIndices.indexOf(resutJSON.index) === -1) {
this.uiIndices.hiddenItemIndices.push(resutJSON.index);
}
};
Virtualization.prototype.removeItem = function (obj) {
var dataSource;
var curViewDS = this.listViewInstance.curViewDS;
var resutJSON = this.findDSAndIndexFromId(curViewDS, obj);
if (Object.keys(resutJSON).length) {
dataSource = resutJSON.data;
if (curViewDS[resutJSON.index - 1] &&
curViewDS[resutJSON.index - 1].isHeader &&
(curViewDS[resutJSON.index - 1])
.items.length === 1) {
this.removeUiItem(resutJSON.index - 1);
this.removeUiItem(resutJSON.index - 1);
}
else {
this.removeUiItem(resutJSON.index);
}
}
var listDataSource = this.listViewInstance.dataSource instanceof DataManager
? this.listViewInstance.localData : this.listViewInstance.dataSource;
var index = listDataSource.indexOf(dataSource);
if (index !== -1) {
listDataSource.splice(index, 1);
this.listViewInstance.setViewDataSource(listDataSource);
}
// recollect all the list item into collection
this.listViewInstance.liCollection =
this.listViewInstance.curUL.querySelectorAll('li');
};
// eslint-disable-next-line
Virtualization.prototype.setCheckboxLI = function (li, e) {
var index = Array.prototype.indexOf.call(this.listViewInstance.curUL.querySelectorAll('li'), li) + this.uiFirstIndex;
this.activeIndex = Array.prototype.indexOf.call(this.listViewInstance.curUL.querySelectorAll('li'), li) + this.uiFirstIndex;
if (li.classList.contains(classNames.selected)) {
if (this.uiIndices.activeIndices.indexOf(index) === -1) {
this.uiIndices.activeIndices.push(index);
}
}
else {
this.uiIndices.activeIndices.splice(this.uiIndices.activeIndices.indexOf(index), 1);
}
};
// eslint-disable-next-line
Virtualization.prototype.setSelectLI = function (li, e) {
this.activeIndex = Array.prototype.indexOf.call(this.listViewInstance.curUL.querySelectorAll('li'), li) + this.uiFirstIndex;
};
Virtualization.prototype.checkedItem = function (checked) {
if (checked) {
this.uiIndices.activeIndices = [];
this.activeIndex = undefined;
var data = this.listViewInstance.curViewDS;
for (var index = 0; index < data.length; index++) {
if (!data[index].isHeader) {
this.uiIndices.activeIndices.push(index);
}
}
}
else {
this.activeIndex = undefined;
this.uiIndices.activeIndices = [];
}
};
Virtualization.prototype.addUiItem = function (index) {
// virtually new add list item based on the scollbar position
// if the scroll bar is at the top, just pretend the new item has been added since no UI
// change is required for the item that has been added at last but when scroll bar is at the bottom
// just detach top and inject into bottom to mimic new item is added
var curViewDs = this.listViewInstance.curViewDS;
this.changeUiIndices(index, true);
if (this.activeIndex && this.activeIndex >= index) {
this.activeIndex++;
}
if (this.listViewInstance.showCheckBox &&
curViewDs[index][this.listViewInstance.fields.isChecked]) {
this.uiIndices.activeIndices.push(index);
}
if (!parseFloat(this.bottomElement.style.height) && !parseFloat(this.topElement.style.height)) {
this.bottomElement.style.height = parseFloat(this.bottomElement.style.height) + this.listItemHeight + 'px';
}
if (parseFloat(this.bottomElement.style.height)) {
var liItem = this.listViewInstance.curUL.lastElementChild.previousSibling;
var target = this.listViewInstance.getLiFromObjOrElement(curViewDs[index + 1]) ||
this.listViewInstance.getLiFromObjOrElement(curViewDs[index + 2]);
if (target) {
this.bottomElement.style.height = parseFloat(this.bottomElement.style.height) + this.listItemHeight + 'px';
this.updateUI(liItem, index, target);
}
}
else {
var liItem = this.listViewInstance.curUL.firstElementChild.nextSibling;
var target = void 0;
if ((Object.keys(this.listViewInstance.curViewDS).length - 1) === index) {
target = this.listViewInstance.curUL.lastElementChild;
}
else {
target = this.listViewInstance.getLiFromObjOrElement(curViewDs[index + 1]) ||
this.listViewInstance.getLiFromObjOrElement(curViewDs[index + 2]);
}
this.topElement.style.height = parseFloat(this.topElement.style.height) + this.listItemHeight + 'px';
this.uiFirstIndex++;
this.uiLastIndex++;
if (target) {
this.updateUI(liItem, index, target);
if (this.listViewInstance.isWindow === true) {
window.scrollTo(0, (pageYOffset + this.listItemHeight));
}
else {
this.listViewInstance.element.scrollTop += this.listItemHeight;
}
}
}
this.totalHeight += this.listItemHeight;
this.listDiff = Math.round(parseFloat(this.topElement.style.height) / this.listItemHeight);
};
Virtualization.prototype.removeUiItem = function (index) {
this.totalHeight -= this.listItemHeight;
var curViewDS = this.listViewInstance.curViewDS[index];
var liItem = this.listViewInstance.getLiFromObjOrElement(curViewDS);
this.listViewInstance.curViewDS.splice(index, 1);
if (this.activeIndex && this.activeIndex >= index) {
this.activeIndex--;
}
if (liItem) {
if (this.domItemCount > Object.keys(this.listViewInstance.curViewDS).length) {
detach(liItem);
this.domItemCount--;
this.uiLastIndex--;
this.totalHeight = 0;
}
else {
if (liItem.classList.contains(classNames.disable)) {
liItem.classList.remove(classNames.disable);
this.uiIndices.disabledItemIndices.splice(this.uiIndices.disabledItemIndices.indexOf(index), 1);
}
if (liItem.style.display === 'none') {
liItem.style.display = '';
this.uiIndices.hiddenItemIndices.splice(this.uiIndices.hiddenItemIndices.indexOf(index), 1);
}
if (this.listViewInstance.showCheckBox && liItem.classList.contains(classNames.selected)) {
this.listViewInstance.removeSelect();
this.uiIndices.activeIndices.splice(this.uiIndices.activeIndices.indexOf(index), 1);
var checklistElement = liItem.querySelector('.' + classNames.checkboxWrapper);
checklistElement.removeAttribute('aria-checked');
checklistElement.firstElementChild.classList.remove(classNames.checked);
if (liItem.classList.contains(classNames.focused)) {
liItem.classList.remove(classNames.focused);
this.activeIndex = undefined;
}
}
else if (liItem.classList.contains(classNames.selected)) {
this.listViewInstance.removeSelect();
this.activeIndex = undefined;
}
if (!parseFloat(this.bottomElement.style.height) && !parseFloat(this.topElement.style.height)) {
this.updateUI(liItem, this.uiLastIndex, this.bottomElement);
}
else if (parseFloat(this.bottomElement.style.height)) {
this.bottomElement.style.height = parseFloat(this.bottomElement.style.height) - this.listItemHeight + 'px';
this.updateUI(liItem, this.uiLastIndex, this.bottomElement);
}
else {
this.topElement.style.height = parseFloat(this.topElement.style.height) - this.listItemHeight + 'px';
this.updateUI(liItem, (this.uiFirstIndex - 1), this.topElement.nextSibling);
this.uiLastIndex--;
this.uiFirstIndex--;
}
}
}
this.changeUiIndices(index, false);
this.listDiff = Math.round(parseFloat(this.topElement.style.height) / this.listItemHeight);
};
Virtualization.prototype.changeUiIndices = function (index, increment) {
var keys = Object.keys(this.uiIndices);
for (var ind = 0; ind < keys.length; ind++) {
this.uiIndices[keys[ind]] = this.uiIndices[keys[ind]].map(function (i) {
if (i >= index) {
return increment ? ++i : --i;
}
else {
return i;
}
});
}
};
Virtualization.prototype.addItem = function (data, fields, dataSource, index) {
for (var i = 0; i < data.length; i++) {
var currentItem = data[i];
// push the given data to main data array
dataSource = this.listViewInstance.addItemAtIndex(index, dataSource, currentItem);
// recalculate all the group data or other datasource related things
this.listViewInstance.setViewDataSource(dataSource);
// render list items for first time due to no datasource present earlier
if (!this.domItemCount) {
// fresh rendering for first time
if ((this.listViewInstance.template || this.listViewInstance.groupTemplate) && !this.isNgTemplate()) {
this.listViewInstance.listBaseOption.template = null;
this.listViewInstance.listBaseOption.groupTemplate = null;
this.listViewInstance.listBaseOption.itemCreated = this.createUIItem.bind(this);
}
this.uiVirtualization();
// when expected expected DOM count doesn't meet the condition we need to create and inject new item into DOM
}
else if (this.domItemCount < this.expectedDomItemCount) {
var ds = this.listViewInstance.findItemFromDS(dataSource, fields);
if (ds instanceof Array) {
if (this.listViewInstance.ulElement) {
var index_1 = this.listViewInstance.curViewDS.indexOf(currentItem);
// inject new list item into DOM
this.createAndInjectNewItem(currentItem, index_1);
// check for group header item
var curViewDS = this.listViewInstance.curViewDS[index_1 - 1];
if (curViewDS && curViewDS.isHeader && curViewDS.items.length === 1) {
// target group item index in datasource
--index_1;
// inject new group header into DOM for previously created list item
this.createAndInjectNewItem(curViewDS, index_1);
}
}
// recollect all the list item into collection
this.listViewInstance.liCollection =
this.listViewInstance.curUL.querySelectorAll('li');
}
}
else {
var index_2 = this.listViewInstance.curViewDS.indexOf(currentItem);
// virtually new add list item based on the scollbar position
this.addUiItem(index_2);
// check for group header item needs to be added
var curViewDS = this.listViewInstance.curViewDS[index_2 - 1];
if (curViewDS && curViewDS.isHeader && curViewDS.items.length === 1) {
this.addUiItem(index_2 - 1);
}
}
}
};
Virtualization.prototype.createAndInjectNewItem = function (itemData, index) {
// generate li item for given datasource
var target;
var li = ListBase.createListItemFromJson(this.listViewInstance.createElement, [itemData], this.listViewInstance.listBaseOption, null, null, this.listViewInstance);
// check for target element whether to insert before last item or group item
if ((Object.keys(this.listViewInstance.curViewDS).length - 1) === index) {
target = this.listViewInstance.curUL.lastElementChild;
}
else {
// target group header's first child item to append its header
target = this.listViewInstance.getLiFromObjOrElement(this.listViewInstance.curViewDS[index + 1]) ||
this.listViewInstance.getLiFromObjOrElement(this.listViewInstance.curViewDS[index + 2]);
}
if (this.listViewInstance.fields.groupBy
&& this.listViewInstance.curViewDS[index + 1]
&& this.listViewInstance.curViewDS[index + 1].isHeader) {
var targetEle = this.listViewInstance.getLiFromObjOrElement(this.listViewInstance.curViewDS[index - 1]);
if (targetEle) {
target = targetEle.nextElementSibling;
}
}
// insert before the target element
this.listViewInstance.ulElement.insertBefore(li[0], target);
// increment internal DOM count, last index count for new element
this.domItemCount++;
if (this.bottomElementHeight <= 0) {
this.uiLastIndex++;
}
// recalculate the current item height, to avoid jumpy scroller
this.refreshItemHeight();
};
Virtualization.prototype.createUIItem = function (args) {
if (!args.item.classList.contains('e-list-group-item')) {
this.templateData = args.curData.isHeader ? args.curData.items[0] :
args.curData;
if (this.listViewInstance.showCheckBox) {
this.listViewInstance.renderCheckbox(args);
if ((!isNullOrUndefined(this.listViewInstance.virtualCheckBox)) &&
(!isNullOrUndefined(this.listViewInstance.virtualCheckBox.outerHTML))) {
var div_1 = document.createElement('div');
var commonTemplate = '<div class="e-text-content" role="presentation"> ' +
'<span class="e-list-text"> ${' + this.listViewInstance.fields.text + '} </span></div>';
var templateFunction = compile(this.listViewInstance.template || commonTemplate, this.listViewInstance);
var nodes = templateFunction(this.templateData, this.listViewInstance);
if (this.listViewInstance.template && this.listViewInstance.isReact) {
this.listViewInstance.renderReactTemplates();
}
[].slice.call(nodes).forEach(function (ele) {
div_1.appendChild(ele);
});
if (div_1.children && div_1.children[0]) {
div_1.children[0].classList.add('e-checkbox');
if (this.listViewInstance.checkBoxPosition === 'Left') {
div_1.children[0].classList.add('e-checkbox-left');
}
else {
div_1.children[0].classList.add('e-checkbox-right');
}
if (this.listViewInstance.checkBoxPosition === 'Left') {
div_1.children[0].insertBefore(this.listViewInstance.virtualCheckBox, div_1.childNodes[0].children[0]);
}
else {
div_1.children[0].appendChild(this.listViewInstance.virtualCheckBox);
}
while (args.item.lastChild) {
args.item.removeChild(args.item.lastChild);
}
[].slice.call(div_1.children).forEach(function (ele) {
args.item.appendChild(ele);
});
}
}
}
}
};
Virtualization.prototype.reRenderUiVirtualization = function () {
this.wireScrollEvent(true);
if (this.listViewInstance.contentContainer) {
detach(this.listViewInstance.contentContainer);
}
this.listViewInstance.preRender();
// resetting the dom count to 0, to avoid edge case of dataSource suddenly becoming zero
// and then manually adding item using addItem API
this.domItemCount = 0;
this.listViewInstance.header();
this.listViewInstance.setLocalData();
};
Virtualization.prototype.updateUI = function (element, index, targetElement) {
var onChange = this.isNgTemplate() ? this.onNgChange : this.onChange;
if (this.listViewInstance.template || this.listViewInstance.groupTemplate) {
var curViewDS = this.listViewInstance.curViewDS[index];
element.dataset.uid = (curViewDS[this.listViewInstance.fields.id]) ?
(curViewDS[this.listViewInstance.fields.id]) : ListBase.generateId();
onChange(curViewDS, element, this);
}
else {
this.updateUiContent(element, index);
}
this.changeElementAttributes(element, index);
if (targetElement) {
this.listViewInstance.ulElement.insertBefore(element, targetElement);
}
};
/**
* Handles the UI change in vue for the list view.
*
* @param {DataSource} newData - The new data source for the list view.
* @param {ElementContext} listElement - The HTML element context for the list view.
* @param {Virtualization} virtualThis - The virtualization context for the list view.
* @returns {void}
*/
Virtualization.prototype.onChange = function (newData, listElement, virtualThis) {
var liItem = ListBase.createListItemFromJson(virtualThis.listViewInstance.createElement, [newData], virtualThis.listViewInstance.listBaseOption, null, null, virtualThis.listViewInstance);
if (virtualThis.listViewInstance.isReact) {
virtualThis.listViewInstance.renderReactTemplates();
}
while (listElement.lastChild) {
listElement.removeChild(listElement.lastChild);
}
[].slice.call(liItem[0].children).forEach(function (ele) {
listElement.appendChild(ele);
});
};
Virtualization.prototype.onNgChange = function (newData, listElement, virtualThis) {
// compile given target element with template for new data
var templateCompiler = compile(virtualThis.listViewInstance.template);
var resultElement = templateCompiler(newData);
while (listElement.lastChild) {
listElement.removeChild(listElement.lastChild);
}
listElement.appendChild(resultElement[0]);
};
Virtualization.prototype.getModuleName = function () {
return 'virtualization';
};
Virtualization.prototype.destroy = function () {
this.wireScrollEvent(true);
this.topElement = null;
this.bottomElement = null;
};
return Virtualization;
}());
export { Virtualization };