vue-virtual-scroller
Version:
Smooth scrolling for any amount of data
2 lines (1 loc) • 13.4 kB
JavaScript
var VueVirtualScroller=function(e){"use strict";var t=void 0;function i(){i.init||(i.init=!0,t=-1!==function(){var e=window.navigator.userAgent,t=e.indexOf("MSIE ");if(t>0)return parseInt(e.substring(t+5,e.indexOf(".",t)),10);if(e.indexOf("Trident/")>0){var i=e.indexOf("rv:");return parseInt(e.substring(i+3,e.indexOf(".",i)),10)}var n=e.indexOf("Edge/");return n>0?parseInt(e.substring(n+5,e.indexOf(".",n)),10):-1}())}var n={render:function(){var e=this.$createElement;return(this._self._c||e)("div",{staticClass:"resize-observer",attrs:{tabindex:"-1"}})},staticRenderFns:[],_scopeId:"data-v-b329ee4c",name:"resize-observer",methods:{notify:function(){this.$emit("notify")},addResizeHandlers:function(){this._resizeObject.contentDocument.defaultView.addEventListener("resize",this.notify),this._w===this.$el.offsetWidth&&this._h===this.$el.offsetHeight||this.notify()},removeResizeHandlers:function(){this._resizeObject&&this._resizeObject.onload&&(!t&&this._resizeObject.contentDocument&&this._resizeObject.contentDocument.defaultView.removeEventListener("resize",this.notify),delete this._resizeObject.onload)}},mounted:function(){var e=this;i(),this.$nextTick(function(){e._w=e.$el.offsetWidth,e._h=e.$el.offsetHeight});var n=document.createElement("object");this._resizeObject=n,n.setAttribute("style","display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;"),n.setAttribute("aria-hidden","true"),n.onload=this.addResizeHandlers,n.type="text/html",t&&this.$el.appendChild(n),n.data="about:blank",t||this.$el.appendChild(n)},beforeDestroy:function(){this.removeResizeHandlers()}};var s={version:"0.4.3",install:function(e){e.component("resize-observer",n)}},o=null;function l(e){if(null!==e&&"function"!=typeof e)throw new Error("observe-visibility directive expects a function as the value")}"undefined"!=typeof window?o=window.Vue:"undefined"!=typeof global&&(o=global.Vue),o&&o.use(s);var r={bind:function(e,t,i){var n=t.value;if("undefined"==typeof IntersectionObserver)console.warn("[vue-observe-visibility] IntersectionObserver API is not available in your browser. Please install this polyfill: https://github.com/WICG/IntersectionObserver/tree/gh-pages/polyfill");else{l(n),e._vue_visibilityCallback=n;var s=e._vue_intersectionObserver=new IntersectionObserver(function(t){var i=t[0];e._vue_visibilityCallback&&e._vue_visibilityCallback.call(null,i.intersectionRatio>0,i)});i.context.$nextTick(function(){s.observe(e)})}},update:function(e,t){var i=t.value;l(i),e._vue_visibilityCallback=i},unbind:function(e){e._vue_intersectionObserver&&(e._vue_intersectionObserver.disconnect(),delete e._vue_intersectionObserver,delete e._vue_visibilityCallback)}};var a={version:"0.3.1",install:function(e){e.directive("observe-visibility",r)}},d=null;"undefined"!=typeof window?d=window.Vue:"undefined"!=typeof global&&(d=global.Vue),d&&d.use(a);var u=!1;if("undefined"!=typeof window){u=!1;try{var c=Object.defineProperty({},"passive",{get:function(){u=!0}});window.addEventListener("test",null,c)}catch(e){}}var h={components:{ResizeObserver:n},directives:{ObserveVisibility:r},props:{items:{type:Array,required:!0},itemHeight:{type:[Number,String],default:null},minItemHeight:{type:[Number,String],default:null},heightField:{type:String,default:"height"},typeField:{type:String,default:"type"},buffer:{type:[Number,String],default:200},pageMode:{type:Boolean,default:!1},prerender:{type:[Number,String],default:0},emitUpdate:{type:Boolean,default:!1}},computed:{cssClass:function(){return{"page-mode":this.pageMode}},heights:function(){if(null===this.itemHeight){for(var e={"-1":{accumulator:0}},t=this.items,i=this.heightField,n=this.minItemHeight,s=0,o=void 0,l=0,r=t.length;l<r;l++)s+=o=t[l][i]||n,e[l]={accumulator:s,height:o};return e}}},beforeDestroy:function(){this.removeWindowScroll()},methods:{getScroll:function(){var e=this.$el,t=void 0;if(this.pageMode){var i=e.getBoundingClientRect(),n=-i.top,s=window.innerHeight;n<0&&(s+=n,n=0),n+s>i.height&&(s=i.height-n),t={top:n,bottom:n+s}}else t={top:e.scrollTop,bottom:e.scrollTop+e.clientHeight};return t.bottom>=0&&t.top<=t.bottom?t:null},applyPageMode:function(){this.pageMode?this.addWindowScroll():this.removeWindowScroll()},addWindowScroll:function(){window.addEventListener("scroll",this.handleScroll,!!u&&{passive:!0}),window.addEventListener("resize",this.handleResize)},removeWindowScroll:function(){window.removeEventListener("scroll",this.handleScroll),window.removeEventListener("resize",this.handleResize)},scrollToItem:function(e){var t=void 0;t=null===this.itemHeight?e>0?this.heights[e-1].accumulator:0:e*this.itemHeight,this.scrollToPosition(t)},scrollToPosition:function(e){this.$el.scrollTop=e}}},f={render:function(){var e=this,t=e.$createElement,i=e._self._c||t;return i(e.mainTag,{directives:[{name:"observe-visibility",rawName:"v-observe-visibility",value:e.handleVisibilityChange,expression:"handleVisibilityChange"}],tag:"component",staticClass:"virtual-scroller",class:e.cssClass,on:{"&scroll":function(t){e.handleScroll(t)}}},[e._t("before-container"),e._v(" "),i(e.containerTag,{ref:"itemContainer",tag:"component",staticClass:"item-container",class:e.containerClass,style:e.itemContainerStyle},[e._t("before-content"),e._v(" "),i(e.contentTag,{ref:"items",tag:"component",staticClass:"items",class:e.contentClass,style:e.itemsStyle},[e.renderers?e._l(e.visibleItems,function(t,n){return i(e.renderers[t[e.typeField]],{key:e.keysEnabled&&t[e.keyField]||void 0,tag:"component",staticClass:"item",attrs:{item:t,"item-index":e.$_startIndex+n}})}):[e._l(e.visibleItems,function(t,i){return e._t("default",null,{item:t,itemIndex:e.$_startIndex+i,itemKey:e.keysEnabled&&t[e.keyField]||void 0})})]],2),e._v(" "),e._t("after-content")],2),e._v(" "),e._t("after-container"),e._v(" "),i("resize-observer",{on:{notify:e.handleResize}})],2)},staticRenderFns:[],_scopeId:"data-v-2b1f2e05",name:"virtual-scroller",mixins:[h],props:{renderers:{default:null},keyField:{type:String,default:"id"},mainTag:{type:String,default:"div"},containerTag:{type:String,default:"div"},containerClass:{default:null},contentTag:{type:String,default:"div"},contentClass:{default:null},poolSize:{type:[Number,String],default:2e3},delayPreviousItems:{type:Boolean,default:!1}},data:function(){return{visibleItems:[],itemContainerStyle:null,itemsStyle:null,keysEnabled:!0}},watch:{items:{handler:function(){this.updateVisibleItems(!0)},deep:!0},pageMode:function(){this.applyPageMode(),this.updateVisibleItems(!0)},itemHeight:"setDirty"},created:function(){this.$_ready=!1,this.$_startIndex=0,this.$_oldScrollTop=null,this.$_oldScrollBottom=null,this.$_offsetTop=0,this.$_height=0,this.$_scrollDirty=!1,this.$_updateDirty=!1;var e=parseInt(this.prerender);e>0?(this.visibleItems=this.items.slice(0,e),this.$_length=this.visibleItems.length,this.$_endIndex=this.$_length-1,this.$_skip=!0):(this.$_endIndex=0,this.$_length=0,this.$_skip=!1)},mounted:function(){var e=this;this.applyPageMode(),this.$nextTick(function(){e.updateVisibleItems(!0),e.$_ready=!0})},methods:{updateVisibleItems:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.$_updateDirty||(this.$_updateDirty=!0,this.$nextTick(function(){e.$_updateDirty=!1;var i=e.items.length,n=e.getScroll(),s=e.items,o=e.itemHeight,l=void 0,r=void 0;if(n){var a=-1,d=-1,u=parseInt(e.buffer),c=parseInt(e.poolSize),h=~~(n.top/c)*c-u,f=Math.ceil(n.bottom/c)*c+u;if(!t&&(h===e.$_oldScrollTop&&f===e.$_oldScrollBottom||e.$_skip))return void(e.$_skip=!1);if(e.$_oldScrollTop=h,e.$_oldScrollBottom=f,null===o){var v=e.heights,m=0,p=i-1,b=~~(i/2),y=void 0;do{y=b,v[b].accumulator<h?m=b:b<i-1&&v[b+1].accumulator>h&&(p=b),b=~~((m+p)/2)}while(b!==y);for(b<0&&(b=0),a=b,r=b>0?v[b-1].accumulator:0,l=v[i-1].accumulator,d=b;d<i&&v[d].accumulator<f;d++);-1===d?d=s.length-1:++d>i&&(d=i)}else a=~~(h/o),d=Math.ceil(f/o),a<0&&(a=0),d>i&&(d=i),r=a*o,l=i*o;(t||e.$_startIndex!==a||e.$_endIndex!==d||e.$_offsetTop!==r||e.$_height!==l||e.$_length!==i)&&(e.keysEnabled=!(a>e.$_endIndex||d<e.$_startIndex),e.itemContainerStyle={height:l+"px"},e.itemsStyle={marginTop:r+"px"},e.delayPreviousItems?(e.visibleItems=s.slice(e.$_startIndex,d),e.$nextTick(function(){e.visibleItems=s.slice(a,d)})):e.visibleItems=s.slice(a,d),e.emitUpdate&&e.$emit("update",a,d),e.$_startIndex=a,e.$_endIndex=d,e.$_length=i,e.$_offsetTop=r,e.$_height=l)}}))},setDirty:function(){this.$_oldScrollTop=null,this.$_oldScrollBottom=null},handleScroll:function(){var e=this;this.$_scrollDirty||(this.$_scrollDirty=!0,requestAnimationFrame(function(){e.$_scrollDirty=!1,e.updateVisibleItems()}))},handleResize:function(){this.$emit("resize"),this.$_ready&&this.updateVisibleItems()},handleVisibilityChange:function(e,t){var i=this;this.$_ready&&(e||0!==t.boundingClientRect.width||0!==t.boundingClientRect.height)&&(this.$emit("visible"),this.$nextTick(function(){i.updateVisibleItems()}))}}},v=0,m={render:function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{directives:[{name:"observe-visibility",rawName:"v-observe-visibility",value:e.handleVisibilityChange,expression:"handleVisibilityChange"}],staticClass:"recycle-list",class:e.cssClass,on:{"&scroll":function(t){e.handleScroll(t)}}},[i("div",{ref:"wrapper",staticClass:"item-wrapper",style:{height:e.totalHeight+"px"}},e._l(e.pool,function(t){return i("div",{key:t.nr.id,staticClass:"item-view",style:{transform:"translateY("+t.top+"px)"}},[e._t("default",null,{item:t.item,index:t.nr.index,active:t.nr.used})],2)})),e._v(" "),e._t("after-container"),e._v(" "),i("resize-observer",{on:{notify:e.handleResize}})],2)},staticRenderFns:[],_scopeId:"data-v-2277f571",name:"RecycleList",mixins:[h],props:{itemHeight:{type:Number,default:null},keyField:{type:String,default:null}},data:function(){return{pool:[],totalHeight:0}},watch:{items:{handler:function(){this.updateVisibleItems({checkItem:!0})}},pageMode:function(){this.applyPageMode(),this.updateVisibleItems({checkItem:!1})},heights:{handler:function(){this.updateVisibleItems({checkItem:!1})},deep:!0}},created:function(){this.$_ready=!1,this.$_startIndex=0,this.$_endIndex=0,this.$_views=new Map,this.$_unusedViews=new Map,this.$_scrollDirty=!1},mounted:function(){var e=this;this.applyPageMode(),this.$nextTick(function(){e.updateVisibleItems({checkItem:!0}),e.$_ready=!0})},methods:{addView:function(e,t,i,n,s){var o={item:i,top:0},l={id:v++,index:t,used:!0,key:n,type:s};return Object.defineProperty(o,"nr",{configurable:!1,value:l}),e.push(o),o},unuseView:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.$_unusedViews,n=e.nr.type,s=i.get(n);s||(s=[],i.set(n,s)),s.push(e),t||(e.nr.used=!1,e.top=-9999,this.$_views.delete(e.nr.key))},handleResize:function(){this.$emit("resize"),this.$_ready&&this.updateVisibleItems({checkItem:!1})},handleScroll:function(e){var t=this;this.$_scrollDirty||(this.$_scrollDirty=!0,requestAnimationFrame(function(){t.$_scrollDirty=!1,t.updateVisibleItems({checkItem:!1}).continuous||(clearTimeout(t.$_refreshTimout),t.$_refreshTimout=setTimeout(t.handleScroll,100))}))},handleVisibilityChange:function(e,t){var i=this;this.$_ready&&(e||0!==t.boundingClientRect.width||0!==t.boundingClientRect.height)&&(this.$emit("visible"),requestAnimationFrame(function(){i.updateVisibleItems({checkItem:!1})}))},updateVisibleItems:function(e){var t=e.checkItem,i=this.getScroll(),n=parseInt(this.buffer);i.top-=n,i.bottom+=n;var s=this.itemHeight,o=this.typeField,l=this.keyField,r=this.items,a=r.length,d=this.heights,u=this.$_views,c=this.$_unusedViews,h=this.pool,f=void 0,v=void 0,m=void 0;if(a)if(null===s){var p=0,b=a-1,y=~~(a/2),g=void 0;do{g=y,d[y].accumulator<i.top?p=y:y<a-1&&d[y+1].accumulator>i.top&&(b=y),y=~~((p+b)/2)}while(y!==g);for(y<0&&(y=0),f=y,m=d[a-1].accumulator,v=y;v<a&&d[v].accumulator<i.bottom;v++);-1===v?v=r.length-1:++v>a&&(v=a)}else f=~~(i.top/s),v=Math.ceil(i.bottom/s),f<0&&(f=0),v>a&&(v=a),m=a*s;else f=v=m=0;this.totalHeight=m;var _=void 0,$=f<=this.$_endIndex&&v>=this.$_startIndex,I=void 0;if(this.$_continuous!==$){if($){u.clear(),c.clear();for(var w=0,x=h.length;w<x;w++)_=h[w],this.unuseView(_)}this.$_continuous=$}else if($)for(var S=0,V=h.length;S<V;S++)(_=h[S]).nr.used&&(t&&(_.nr.index=r.findIndex(function(e){return l?e[l]==_.item[l]:e===_.item})),(-1===_.nr.index||_.nr.index<f||_.nr.index>v)&&this.unuseView(_));$||(I=new Map);for(var k=void 0,C=void 0,z=void 0,T=void 0,O=f;O<v;O++){k=r[O];var R=l?k[l]:k;_=u.get(R),s||d[O].height?(_?_.nr.used=!0:(C=k[o],$?(z=c.get(C))&&z.length?((_=z.pop()).item=k,_.nr.used=!0,_.nr.index=O,_.nr.key=R,_.nr.type=C):_=this.addView(h,O,k,R,C):(z=c.get(C),T=I.get(C)||0,z&&T<z.length?((_=z[T]).item=k,_.nr.used=!0,_.nr.index=O,_.nr.key=R,_.nr.type=C,I.set(C,T+1)):(_=this.addView(h,O,k,R,C),this.unuseView(_,!0)),T++),u.set(R,_)),_.top=null===s?d[O-1].accumulator:O*s):_&&this.unuseView(_)}return this.$_startIndex=f,this.$_endIndex=v,this.emitUpdate&&this.$emit("update",f,v),{continuous:$}}}};var p={version:"0.11.7",install:function(e,t){var i=Object.assign({},{installComponents:!0,componentsPrefix:""},t);i.installComponents&&function(e,t){e.component(t+"virtual-scroller",f),e.component(t+"recycle-list",m)}(e,i.componentsPrefix)}},b=null;return"undefined"!=typeof window?b=window.Vue:"undefined"!=typeof global&&(b=global.Vue),b&&b.use(p),e.VirtualScroller=f,e.RecycleList=m,e.default=p,e}({});