UNPKG

nscomponentsreact

Version:

React Wrapper Components for NSComponents

818 lines (772 loc) 27.2 kB
var nsModuleExport = function(root,name,prototype) { if(typeof exports === 'object' && typeof module === 'object') { module.exports[name] = prototype; } else if (typeof define === "function" && define.amd) { define(name,[], function () {return prototype;}); } else if(typeof exports === 'object') { exports[name] = prototype; } else { root[name] = prototype; } };var nsIsWeb = function(root) { if(typeof exports === 'object' && typeof module === 'object') { return false; } else if (typeof define === "function" && define.amd) { return false; } else if(typeof exports === 'object') { return false; } else { return true; } };if(!nsIsWeb()) { var nsutilRef = require('./nsUtil.min.js'); var NSUtil = nsutilRef.NSUtil; } "use strict"; var NSVirtualScroll = (function() { function NSVirtualScroll(setting) { this.__setting = setting; this.util = null; this.__config = null; this.__internal = {}; this.__objProp = {}; this.__objSelectedProp = {}; this.__domVariables = null; this.__doc = null; this.__win = null; this.__scrollHandlerRef = null; this.__resizeHandlerRef = null; this.__initialize(); } NSVirtualScroll.prototype.dataSource = function(paramItems) { if(!this.util.isUndefinedOrNull(paramItems)) { var reInit = false; if(!this.__internal.itemDimension) { reInit = true; } if(this.util.isNumber(paramItems)) { this.__config.totalLength = parseInt(paramItems); } else if(this.util.isArray(paramItems)) { this.__config.items = paramItems; } else { this.__config.totalLength = null; this.__config.items = [paramItems]; } this.__internal.objItemComp = {}; this.__internal.arrItem = []; if(reInit) { var item = this.__getItemAt(0); this.__internal.isItemHtml = this.util.isString(item); this.__setSize(); } var scrollElement = this.__config.scrollElement; var scrollPos = scrollElement[this.__objSelectedProp.scroll]; if(this.__internal.items && (this.__internal.items.length * this.__internal.itemDimension < scrollPos)) { scrollElement[this.__objSelectedProp.scroll] = 0; this.__internal.lastPageNum = 0; } this.__addItems(); scrollElement[this.__objSelectedProp.scroll] = scrollPos; } }; NSVirtualScroll.prototype.refresh = function(isReset) { var currItemSize = this.__internal.itemDimension; this.__setSize(); var newItemSize = this.__internal.itemDimension; if((currItemSize != newItemSize) || isReset) { var criteria = null; if(this.__config.totalLength) { criteria = this.__config.totalLength; } else if(this.util.isArray(this.__config.items) && this.__config.items && this.__config.items.length) { criteria = this.__config.items; } else { criteria = 0; } this.dataSource(criteria); } }; NSVirtualScroll.prototype.getScrollProgress = function() { var scrollPos = this.__internal.scrollPos; var itemSize = this.__internal.itemDimension; var totalSize = this.__internal.arrItem.length * itemSize; var progress = ((scrollPos / totalSize) * 100) || 0; return progress; }; NSVirtualScroll.prototype.appendItems = function(arrItem) { this.__addNewItems(arrItem,false); }; NSVirtualScroll.prototype.prependItems = function(arrItem) { this.__addNewItems(arrItem,true); }; //assuming that size of all rows are same //if not same add offset //if variable Row size and utility user has original scroll Position then set scrollPosition and pass index as null NSVirtualScroll.prototype.scrollToIndex = function(index,animationRequired,offset,scrollPosition) { var arrItem = this.__internal.arrItem; if(arrItem && arrItem.length) { var scrollPos = null; if(!this.util.isUndefinedOrNull(index) && index > -1 && index < arrItem.length) { offset = this.util.isUndefinedOrNull(offset) ? 0 : parseInt(offset); scrollPos = (this.__internal.itemDimension * index) + offset; } else if(!this.util.isUndefinedOrNull(scrollPosition)) { offset = 0; scrollPos = scrollPosition; } if(!this.util.isUndefinedOrNull(scrollPos)) { var scrollElement = this.__config.scrollElement; if(animationRequired) { var animation = new this.util.animation(scrollElement,[ { time: 500, property:this.__objSelectedProp.scroll, target: scrollPos, } ]); animation.animate(); } else { scrollElement[this.__objSelectedProp.scroll] = scrollPos; } } } }; //this function is used for updating items(dom elements) already generated NSVirtualScroll.prototype.updateItems = function(updateCallback) { if(this.__internal.arrItem && this.__internal.arrItem.length && updateCallback) { var arrItem = this.__internal.arrItem; for(var count = 0;count < arrItem.length;count++) { var item = arrItem[count]; item = updateCallback(item); arrItem[count] = item; } this.__internal.arrItem = arrItem; this.__internal.origArrItem = this.__internal.arrItem; } } NSVirtualScroll.prototype.destroy = function() { var scrollElement = this.__config.scrollElement; var contentElement = this.__config.contentElement; if(this.__internal.contentTabIndex) { contentElement.setAttribute("tabindex",this.__internal.contentTabIndex); } this.util.removeStyleClass(scrollElement,"nsVirtualScrollElement nsVirtualScrollElement" + this.util.toCamelCase(this.__config.direction,true)); this.util.removeStyleClass(contentElement,"nsVirtualScrollContent nsVirtualScrollContent" + this.util.toCamelCase(this.__config.direction,true)); if(this.__scrollHandlerRef) { this.util.removeEvent(scrollElement,"scroll",this.__scrollHandlerRef); this.__scrollHandlerRef = null; } if(this.__resizeHandlerRef) { this.util.removeEvent(this.__win,"resize",this.__resizeHandlerRef); this.__resizeHandlerRef = null; } if(this.__internal.divLoader) { this.__internal.divLoader.parentNode.removeChild(this.__internal.divLoader); } }; NSVirtualScroll.prototype.__initialize = function() { this.util = new NSUtil(); if(this.__setting) { this.__config = { scrollElement: this.util.getElement(this.__setting["scrollElement"]), contentElement: this.util.getElement(this.__setting["contentElement"]), direction: this.__setting["direction"] || NSVirtualScroll.DIRECTION_VERTICAL, itemTag: this.__setting["itemTag"], pageSize: parseInt(this.__setting["pageSize"]) || 30,//number of items after the cache will be refreshed pagesRendered: parseInt(this.__setting["pagesRendered"]) || 3,//number of items(pageSize * pagesRendered) to be rendered items: this.__setting["items"],//array of items, can be html or nodes totalLength: parseInt(this.__setting["totalLength"]) || 0,//either mention items or totalLength and itemCreateCallback getItemComponent: this.__setting["getItemComponent"], getEmptyItemComponent: this.__setting["getEmptyItemComponent"], enableScrollDelay: Boolean.parse(this.__setting["enableScrollDelay"]),//for Mobile device which are slow in rendering scrollInterval: this.__setting["scrollInterval"], enableLoader: Boolean.parse(this.__setting["enableLoader"]), getLoaderComponent: this.__setting["getLoaderComponent"], resizeInterval: parseInt(this.__setting["resizeInterval"]) || 150, scrollingProgress: this.__setting["scrollingProgress"], //scrollingProgress callback while scrolling like scrollingProgress(progress) pageWillChange: this.__setting["pageWillChange"], //pageWillChange callback before page change like pageWillChange(oldPage,newPage) pageChanged: this.__setting["pageChanged"], //pageChanged callback before page change like pageChanged(page) }; if(!this.__config.scrollElement) { this.util.throwNSError("NSVirtualScroll","scrollElement is not valid"); } if(!this.__config.contentElement) { this.util.throwNSError("NSVirtualScroll","contentElement is not valid"); } this.__domVariables = this.util.getDomVariables(); this.__doc = this.__domVariables.doc; this.__win = this.__domVariables.win; if((!this.__config.items || this.__config.items.length == 0) && !this.__config.totalLength) { this.__config.items = this.__fetchChildren(contentElement); } this.__setProps(); this.__setInternalVars(); this.__create(); this.__addListeners(); } }; NSVirtualScroll.prototype.__setProps = function() { this.__objProp = { vertical: { direction:NSVirtualScroll.DIRECTION_VERTICAL,size: "height",offset: "offsetHeight", scroll: "scrollTop", scrollSize: "scrollHeight",paddingStart:"paddingTop", paddingEnd:"paddingBottom",marginStart:"marginTop",marginEnd:"marginBottom" }, horizontal: { direction:NSVirtualScroll.DIRECTION_HORIZONTAL,size: "width",offset: "offsetWidth", scroll: "scrollLeft", scrollSize: "scrollWidth",paddingStart:"paddingLeft", paddingEnd:"paddingRight",marginStart:"marginLeft",marginEnd:"marginRight" } }; this.__objSelectedProp = this.__objProp["vertical"]; if(this.__config.direction == NSVirtualScroll.DIRECTION_HORIZONTAL) { this.__objSelectedProp = this.__objProp["horizontal"]; } }; //call this function only with init is needed NSVirtualScroll.prototype.__setInternalVars = function() { if(!this.__internal.itemDimension) { if(this.__config.contentElement.hasAttribute("tabindex")) { this.__internal.contentTabIndex = this.__config.contentElement.getAttribute("tabindex"); } this.__internal.scrollIntervalID = -1; this.__internal.resizeIntervalID = -1; this.__internal.scrollPos = -1; this.__internal.lastPageNum = -1; this.__internal.objItemComp = {}; this.__internal.objCache = {}; this.__internal.cssExtraItem = "nsVirtualExtraItem" + this.util.toCamelCase(this.__objSelectedProp.direction,true); this.__internal.isMobile = this.util.isMobile().any; if(this.__config.enableScrollDelay && this.util.isUndefinedOrNull(this.__config.scrollInterval)) { this.__config.scrollInterval = this.__internal.isMobile ? 300 : 0; } this.__internal.divLoader = null; this.__addLoader(); this.__internal.pageSize = this.__config.pageSize; this.__internal.pagesRendered = this.__config.pagesRendered; var item = this.__getItemAt(0); if(item) { this.__internal.isItemHtml = this.util.isString(item); this.__setSize(); } else { this.__internal.itemDimension = 0; this.__internal.pageDimension = 0; this.__internal.itemsRendered = 0; this.__internal.renderedSize = 0; } } }; NSVirtualScroll.prototype.__setSize = function() { this.__internal.itemDimension = this.__getItemSize(); this.__internal.pageDimension = this.__internal.itemDimension * this.__internal.pageSize; this.__internal.itemsRendered = this.__internal.pageSize * this.__internal.pagesRendered; this.__internal.renderedSize = this.__internal.pagesRendered * this.__internal.pageDimension; }; NSVirtualScroll.prototype.__create = function() { var scrollElement = this.__config.scrollElement; var contentElement = this.__config.contentElement; this.util.addStyleClass(scrollElement,"nsVirtualScrollElement nsVirtualScrollElement" + this.util.toCamelCase(this.__config.direction,true)); this.util.addStyleClass(contentElement,"nsVirtualScrollContent nsVirtualScrollContent" + this.util.toCamelCase(this.__config.direction,true)); contentElement.setAttribute("tabindex",0); if((this.__config.items && this.__config.items.length) || this.__config.totalLength) { var scrollPos = scrollElement[this.__objSelectedProp.scroll]; this.__addItems(); scrollElement[this.__objSelectedProp.scroll] = scrollPos; } }; NSVirtualScroll.prototype.__addListeners = function() { if(!this.__scrollHandlerRef) { this.__scrollHandlerRef = this.__config.enableScrollDelay ? this.__scrollHandlerWithDelay.bind(this) : this.__scrollHandler.bind(this); this.util.addEvent(this.__config.scrollElement,"scroll",this.__scrollHandlerRef); } if(!this.__resizeHandlerRef) { this.__resizeHandlerRef = this.__resizeHandler.bind(this); this.util.addEvent(this.__win,"resize",this.__resizeHandlerRef); } }; NSVirtualScroll.prototype.__scrollHandlerWithDelay = function(event) { var self = this; clearTimeout(this.__internal.scrollIntervalID); this.__internal.scrollIntervalID = setTimeout(function(){ self.__scrollHandler.call(self,event); },this.__config.scrollInterval); }; NSVirtualScroll.prototype.__scrollHandler = function(event) { this.__internal.scrollIntervalID = -1; event = this.util.getEvent(event); var pageNumber = this.__getCurrentPageNum(); var lastPageNum = this.__internal.lastPageNum; this.__internal.lastPageNum = pageNumber; /*console.log("lastPageNum::" + lastPageNum + " pageNumber::" + pageNumber);*/ if(lastPageNum != pageNumber) { //console.log("In Scroll"); this.__addItems(); this.__fireCallback("scrollingProgress",this.getScrollProgress()); } }; //not used for now NSVirtualScroll.prototype.__isScrollingDown = function() { var isScrollingDown = false; var currentScrollPos = this.__config.scrollElement[this.__objSelectedProp.scroll]; if (currentScrollPos > this.__internal.prevScrollPos) { isScrollingDown = true; } else { isScrollingDown = false; } this.__internal.prevScrollPos = currentScrollPos; return isScrollingDown; }; NSVirtualScroll.prototype.__resizeHandler = function(event) { event = this.util.getEvent(event); clearTimeout(this.__internal.resizeIntervalID); var self = this; this.__internal.resizeIntervalID = setTimeout(self.refresh.bind(self), this.__config.resizeInterval); }; NSVirtualScroll.prototype.__getItemSize = function() { var contentElement = this.__config.contentElement; var isAdded = false; var size = null; if(!contentElement.children.length) { var itemHtml = this.__getItemAt(0); this.__setItemsInDom(itemHtml); isAdded = true; } var item = null; var length = contentElement.children.length; for(var count = 0;count < length;count++) { item = contentElement.children[count]; if(!this.util.hasStyleClass(item,this.__internal.cssExtraItem)) { break; } } if(!this.__config.itemTag) { this.__config.itemTag = item.tagName.toLowerCase(); } size = item[this.__objSelectedProp.offset]; if(this.__config.itemTag == "tr") { var border = this.util.getStyleValue(contentElement,"borderCollapse"); if(border != "collapse") { var borderSpacing = this.util.getStyleValue(contentElement,"borderSpacing"); size += this.__getInt(borderSpacing); } } else { var marginStart = this.util.getStyleValue(item,this.__objSelectedProp.marginStart); var marginEnd = this.util.getStyleValue(item,this.__objSelectedProp.marginEnd); marginStart = this.__getInt(marginStart); marginEnd = this.__getInt(marginEnd); size += Math.max(marginStart, marginEnd); } if(isAdded) { this.__setItemsInDom(null); } return size; }; NSVirtualScroll.prototype.__addItems = function() { var arrItem = this.__internal.arrItem || []; var itemPage = this.__getPageData(arrItem,this.__getCurrentPageNum()); var hasPageContentChanged = this.__hasCacheChanged("data",itemPage.arrItem); var hasStartOffsetChanged = this.__hasCacheChanged("top",itemPage.startOffset); var hasEndOffsetChanged = this.__hasCacheChanged("bottom",itemPage.endOffset); var contentElement = this.__config.contentElement; var arrSource = []; if(hasPageContentChanged || hasStartOffsetChanged) { if(itemPage.startOffset) { arrSource.push(this.__getExtraItem("nsVirtualTopItem",itemPage.startOffset)); } arrSource.push.apply(arrSource,itemPage.arrItem); if(itemPage.endOffset) { arrSource.push(this.__getExtraItem("nsVirtualBottomItem",itemPage.endOffset)); } this.__fireCallback("pageWillChange",[this.__internal.currentItemPage,itemPage]); this.__setItemsInDom(arrSource); this.__handleTagAfterRender(itemPage); this.__fireCallback("pageChanged",[itemPage]); this.__internal.currentItemPage = itemPage; } else if(hasEndOffsetChanged) { contentElement.lastChild.style[this.__objSelectedProp.size] = itemPage.endOffset + "px"; } }; NSVirtualScroll.prototype.__setItemsInDom = function(arrItem,isAdd) { this.__setLoaderVisibility(true); var contentElement = this.__config.contentElement; if(this.__internal.isItemHtml) { if(arrItem) { var html = this.__convertArrayToString(arrItem); isAdd ? contentElement.innerHTML += html : contentElement.innerHTML = html; } else { isAdd ? null : contentElement.innerHTML = ""; } } else { if(!isAdd) { //IE Bug that when Html elements are added(i.e. when this.__internal.isItemHtml is false) you do contentElement.innerHTML = "" //then the items being rendered in this.__internal.arrItem also becomes empty if(this.__internal.isItemHtml) { contentElement.innerHTML = ""; } else { while(contentElement.firstChild) { contentElement.removeChild(contentElement.lastChild); } } } if(arrItem) { arrItem = this.util.isArray(arrItem) ? arrItem : [arrItem]; var item = null; var length = arrItem.length; for(var count =0;count < length;count++) { if(arrItem[count]) { item = arrItem[count]; this.util.isString(item) ? contentElement.innerHTML += item : contentElement.appendChild(item); } } } } this.__setLoaderVisibility(false); }; NSVirtualScroll.prototype.__getAllItems = function(fromIndex,toIndex) { if(this.__config.items && this.__config.items.length && this.__config.items.length > fromIndex) { toIndex = this.__config.items.length > toIndex ? toIndex : this.__config.items.length - 1; var arrCloned = this.__config.items.slice(); var arrItem = arrCloned.splice(fromIndex,toIndex - fromIndex); return arrItem; } else if(this.__config.totalLength && this.__config.getItemComponent) { fromIndex = this.__config.totalLength > fromIndex ? fromIndex : this.__config.totalLength - 1; toIndex = this.__config.totalLength > toIndex ? toIndex : this.__config.totalLength - 1; if(!this.__internal.arrItem) { this.__internal.arrItem = []; } var arrItem = this.__internal.arrItem; var arrRet = []; for(var count = fromIndex;count < toIndex + 1;count++) { if(arrItem.length > count && arrItem[count]) { arrRet.push(arrItem[count]); } else { var item = this.__getItemFromComponent(count); arrItem[count] = item; arrRet.push(item); } } return arrRet; } return []; }; NSVirtualScroll.prototype.__getItemAt = function(index) { if(this.__config.items && this.__config.items.length && this.__config.items.length > index) { return this.__config.items[index]; } else if(this.__config.arrItem && this.__config.arrItem.length && this.__config.arrItem.length > index && this.__config.arrItem[index]) { return this.__config.arrItem[index]; } else if(this.__config.totalLength > index && this.__config.getItemComponent) { return this.__getItemFromComponent(index); } return null; }; NSVirtualScroll.prototype.__getItemFromComponent = function(index) { var item = null; if(this.__config.totalLength > index) { var comp = new this.__config.getItemComponent(index); item = comp.getElement(); this.__internal.objItemComp[index.toString()] = comp; } return item; }; NSVirtualScroll.prototype.__getPageData = function(arrItem,pageNum) { var internal = this.__internal; var retItem = null; if(this.__config.totalLength === 0) { retItem = {startOffset: 0,endOffset: 0,itemsBefore: 0,arrItem:[this.__getEmptyItem()]}; } /*else if(arrItem.length < internal.pageSize) { var startIndex = 0; var endIndex = internal.pageSize; var arrRet = this.__getAllItems(startIndex,endIndex); retItem = {startOffset: 0,endOffset: 0,itemsBefore: 0,arrItem:arrRet}; }*/ else { var startIndex = Math.max((internal.itemsRendered - internal.pageSize) * pageNum, 0); var endIndex = startIndex + internal.itemsRendered; var totalLength = this.__getTotalLength(); var startOffset = Math.max(startIndex * internal.itemDimension, 0); var endOffset = Math.max((totalLength - endIndex) * internal.itemDimension, 0); var itemsBefore = startIndex; if(startOffset < 1) { itemsBefore++; } var arrRet = this.__getAllItems(startIndex,endIndex);//arrItem.slice(startIndex,endIndex); retItem = {startOffset: startOffset,endOffset: endOffset,itemsBefore: itemsBefore,arrItem:arrRet}; } console.log(retItem); return retItem; }; NSVirtualScroll.prototype.__getTotalLength = function() { if(this.__config.items && this.__config.items.length) { return this.__config.items.length; } else if(this.__config.totalLength && this.__config.getItemComponent) { return this.__config.totalLength; } return 0; }; NSVirtualScroll.prototype.__addNewItems = function(arrNewItem,isPrepend) { if(!this.util.isUndefinedOrNull(arrNewItem)) { arrNewItem = this.util.isArray(arrNewItem) ? arrNewItem : [arrNewItem]; if(arrNewItem && arrNewItem.length) { var arrItem = []; for(var count = 0;count < arrNewItem.length;count++) { arrItem.push(arrNewItem.items[count]); } var arrExisting = this.__internal.arrItem; this.__internal.arrItem = isPrepend ? arrItem.concat(arrExisting) : arrExisting.concat(arrItem); this.__addItems(); } } }; NSVirtualScroll.prototype.__handleTagAfterRender = function(itemPage) { var contentElement = this.__config.contentElement; if(this.__config.itemTag == "ol") { contentElement.setAttribute("start", itemPage.itemsBefore); } }; NSVirtualScroll.prototype.__fetchChildren = function(element) { if(element) { var arrChildren = element.children; var arrRet = []; var length = arrChildren.length; var child = null; for(var count = 0;count < length;count++) { child = arrChildren[count]; arrRet.push(this.__getItemHtml(child)); } return arrRet; } return null; }; NSVirtualScroll.prototype.__fireCallback = function(callbackName,args) { if(this.__config[callbackName]) { this.__config[callbackName](args); } }; NSVirtualScroll.prototype.__hasCacheChanged = function(key,value) { var changed = (value != this.__internal.objCache[key]); this.__internal.objCache[key] = value; return changed; }; NSVirtualScroll.prototype.__getCurrentPageNum = function() { this.__internal.scrollPos = this.__config.scrollElement[this.__objSelectedProp.scroll]; var pageNum = Math.floor(this.__internal.scrollPos / (this.__internal.renderedSize - this.__internal.pageDimension)) || 0; //console.log(this.__internal.scrollPos + "," + this.__internal.renderedSize + "," + this.__internal.pageDimension + "," + pageNum); return pageNum; }; NSVirtualScroll.prototype.__getExtraItem = function(cssClass,size) { var item = this.util.createElement(this.__config.itemTag,null,this.__internal.cssExtraItem,this.__doc); cssClass && this.util.addStyleClass(item,cssClass); size && (item.style[this.__objSelectedProp.size] = size + "px"); return (this.__internal.isItemHtml ? this.__getItemHtml(item) : item); }; NSVirtualScroll.prototype.__getEmptyItem = function() { if(this.__config.getEmptyItemComponent) { var comp = new this.__config.getEmptyItemComponent(); return (this.__internal.isItemHtml ? this.__getItemHtml(comp.getElement()) : comp.getElement()); } var item = this.util.createElement(this.__config.itemTag,null,null,this.__doc); if(this.__config.itemTag == "tr") { item.innerHTML = "<td colSpan='1000'></td>"; } return (this.__internal.isItemHtml ? this.__getItemHtml(item) : item); }; NSVirtualScroll.prototype.__getItemHtml = function(item) { if(item) { return this.util.isString(item) ? item : item.outerHTML; } return ""; }; NSVirtualScroll.prototype.__addLoader = function() { if(this.__config.enableLoader) { this.__internal.divLoader = this.util.createDiv(null,"nsVirtualScrollLoader"); var divText = null; if(this.__config.getLoaderComponent) { var comp = new this.__config.getLoaderComponent(); divText = comp.getElement(); } else { divText = this.util.createDiv(null,"nsVirtualScrollLoaderTextCon"); divText.innerHTML = "<b class=\"nsVirtualScrollLoaderText\">Rendering...</b>"; } this.__internal.divLoader.appendChild(divText); this.__setLoaderVisibility(false); this.__config.scrollElement.appendChild(this.__internal.divLoader); } }; NSVirtualScroll.prototype.__setLoaderVisibility = function(isShow) { if(this.__internal.divLoader) { this.__internal.divLoader.style.display = isShow ? "" : "none"; } }; NSVirtualScroll.prototype.__convertArrayToString = function(arrItem,separator) { if(arrItem) { separator = separator ? separator : ""; return this.util.isArray(arrItem) ? arrItem.join(separator) : arrItem; } return ""; }; NSVirtualScroll.prototype.__getInt = function(value) { return parseInt(value,10) || 0; }; NSVirtualScroll.DIRECTION_VERTICAL = "vertical"; NSVirtualScroll.DIRECTION_HORIZONTAL = "horizontal"; return NSVirtualScroll; })(); nsModuleExport(this,"NSVirtualScroll",NSVirtualScroll);