3 * Copyright(c) 2006-2009 Ext JS, LLC
5 * http://www.extjs.com/license
10 * @class Ext.ux.grid.BufferView
11 * @extends Ext.grid.GridView
12 * A custom GridView which renders rows on an as-needed basis.
14 Ext.ux.grid.BufferView = Ext.extend(Ext.grid.GridView, {
16 * @cfg {Number} rowHeight
17 * The height of a row in the grid.
22 * @cfg {Number} borderHeight
23 * The combined height of border-top and border-bottom of a row.
28 * @cfg {Boolean/Number} scrollDelay
29 * The number of milliseconds before rendering rows out of the visible
30 * viewing area. Defaults to 100. Rows will render immediately with a config
36 * @cfg {Number} cacheSize
37 * The number of rows to look forward and backwards from the currently viewable
38 * area. The cache applies only to rows that have been rendered already.
43 * @cfg {Number} cleanDelay
44 * The number of milliseconds to buffer cleaning of extra rows not in the
49 initTemplates : function(){
50 Ext.ux.grid.BufferView.superclass.initTemplates.call(this);
51 var ts = this.templates;
52 // empty div to act as a place holder for a row
53 ts.rowHolder = new Ext.Template(
54 '<div class="x-grid3-row {alt}" style="{tstyle}"></div>'
56 ts.rowHolder.disableFormats = true;
57 ts.rowHolder.compile();
59 ts.rowBody = new Ext.Template(
60 '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
61 '<tbody><tr>{cells}</tr>',
62 (this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' : ''),
65 ts.rowBody.disableFormats = true;
69 getStyleRowHeight : function(){
70 return Ext.isBorderBox ? (this.rowHeight + this.borderHeight) : this.rowHeight;
73 getCalculatedRowHeight : function(){
74 return this.rowHeight + this.borderHeight;
77 getVisibleRowCount : function(){
78 var rh = this.getCalculatedRowHeight();
79 var visibleHeight = this.scroller.dom.clientHeight;
80 return (visibleHeight < 1) ? 0 : Math.ceil(visibleHeight / rh);
83 getVisibleRows: function(){
84 var count = this.getVisibleRowCount();
85 var sc = this.scroller.dom.scrollTop;
86 var start = (sc == 0 ? 0 : Math.floor(sc/this.getCalculatedRowHeight())-1);
88 first: Math.max(start, 0),
89 last: Math.min(start + count + 2, this.ds.getCount()-1)
93 doRender : function(cs, rs, ds, startRow, colCount, stripe, onlyBody){
94 var ts = this.templates, ct = ts.cell, rt = ts.row, rb = ts.rowBody, last = colCount-1;
95 var rh = this.getStyleRowHeight();
96 var vr = this.getVisibleRows();
97 var tstyle = 'width:'+this.getTotalWidth()+';height:'+rh+'px;';
99 var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
100 for (var j = 0, len = rs.length; j < len; j++) {
102 var rowIndex = (j+startRow);
103 var visible = rowIndex >= vr.first && rowIndex <= vr.last;
105 for (var i = 0; i < colCount; i++) {
108 p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
109 p.attr = p.cellAttr = "";
110 p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
112 if (p.value == undefined || p.value === "") {
115 if (r.dirty && typeof r.modified[c.name] !== 'undefined') {
116 p.css += ' x-grid3-dirty-cell';
118 cb[cb.length] = ct.apply(p);
122 if(stripe && ((rowIndex+1) % 2 == 0)){
123 alt[0] = "x-grid3-row-alt";
126 alt[1] = " x-grid3-dirty-row";
129 if(this.getRowClass){
130 alt[2] = this.getRowClass(r, rowIndex, rp, ds);
132 rp.alt = alt.join(" ");
133 rp.cells = cb.join("");
134 buf[buf.length] = !visible ? ts.rowHolder.apply(rp) : (onlyBody ? rb.apply(rp) : rt.apply(rp));
139 isRowRendered: function(index){
140 var row = this.getRow(index);
141 return row && row.childNodes.length > 0;
144 syncScroll: function(){
145 Ext.ux.grid.BufferView.superclass.syncScroll.apply(this, arguments);
149 // a (optionally) buffered method to update contents of gridview
151 if (this.scrollDelay) {
152 if (!this.renderTask) {
153 this.renderTask = new Ext.util.DelayedTask(this.doUpdate, this);
155 this.renderTask.delay(this.scrollDelay);
161 onRemove : function(ds, record, index, isUpdate){
162 Ext.ux.grid.BufferView.superclass.onRemove.apply(this, arguments);
163 if(isUpdate !== true){
168 doUpdate: function(){
169 if (this.getVisibleRowCount() > 0) {
170 var g = this.grid, cm = g.colModel, ds = g.store;
171 var cs = this.getColumnData();
173 var vr = this.getVisibleRows();
174 for (var i = vr.first; i <= vr.last; i++) {
175 // if row is NOT rendered and is visible, render it
176 if(!this.isRowRendered(i)){
177 var html = this.doRender(cs, [ds.getAt(i)], ds, i, cm.getColumnCount(), g.stripeRows, true);
178 this.getRow(i).innerHTML = html;
185 // a buffered method to clean rows
188 this.cleanTask = new Ext.util.DelayedTask(this.doClean, this);
190 this.cleanTask.delay(this.cleanDelay);
194 if (this.getVisibleRowCount() > 0) {
195 var vr = this.getVisibleRows();
196 vr.first -= this.cacheSize;
197 vr.last += this.cacheSize;
199 var i = 0, rows = this.getRows();
200 // if first is less than 0, all rows have been rendered
201 // so lets clean the end...
205 for(var len = this.ds.getCount(); i < len; i++){
206 // if current row is outside of first and last and
207 // has content, update the innerHTML to nothing
208 if ((i < vr.first || i > vr.last) && rows[i].innerHTML) {
209 rows[i].innerHTML = '';
216 Ext.ux.grid.BufferView.superclass.layout.call(this);