1 | /*! |
---|
2 | * Ext JS Library 3.0.0 |
---|
3 | * Copyright(c) 2006-2009 Ext JS, LLC |
---|
4 | * licensing@extjs.com |
---|
5 | * http://www.extjs.com/license |
---|
6 | */ |
---|
7 | Ext.ns('Ext.ux.grid'); |
---|
8 | |
---|
9 | /** |
---|
10 | * @class Ext.ux.grid.BufferView |
---|
11 | * @extends Ext.grid.GridView |
---|
12 | * A custom GridView which renders rows on an as-needed basis. |
---|
13 | */ |
---|
14 | Ext.ux.grid.BufferView = Ext.extend(Ext.grid.GridView, { |
---|
15 | /** |
---|
16 | * @cfg {Number} rowHeight |
---|
17 | * The height of a row in the grid. |
---|
18 | */ |
---|
19 | rowHeight: 19, |
---|
20 | |
---|
21 | /** |
---|
22 | * @cfg {Number} borderHeight |
---|
23 | * The combined height of border-top and border-bottom of a row. |
---|
24 | */ |
---|
25 | borderHeight: 2, |
---|
26 | |
---|
27 | /** |
---|
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 |
---|
31 | * of false. |
---|
32 | */ |
---|
33 | scrollDelay: 100, |
---|
34 | |
---|
35 | /** |
---|
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. |
---|
39 | */ |
---|
40 | cacheSize: 20, |
---|
41 | |
---|
42 | /** |
---|
43 | * @cfg {Number} cleanDelay |
---|
44 | * The number of milliseconds to buffer cleaning of extra rows not in the |
---|
45 | * cache. |
---|
46 | */ |
---|
47 | cleanDelay: 500, |
---|
48 | |
---|
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>' |
---|
55 | ); |
---|
56 | ts.rowHolder.disableFormats = true; |
---|
57 | ts.rowHolder.compile(); |
---|
58 | |
---|
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>' : ''), |
---|
63 | '</tbody></table>' |
---|
64 | ); |
---|
65 | ts.rowBody.disableFormats = true; |
---|
66 | ts.rowBody.compile(); |
---|
67 | }, |
---|
68 | |
---|
69 | getStyleRowHeight : function(){ |
---|
70 | return Ext.isBorderBox ? (this.rowHeight + this.borderHeight) : this.rowHeight; |
---|
71 | }, |
---|
72 | |
---|
73 | getCalculatedRowHeight : function(){ |
---|
74 | return this.rowHeight + this.borderHeight; |
---|
75 | }, |
---|
76 | |
---|
77 | getVisibleRowCount : function(){ |
---|
78 | var rh = this.getCalculatedRowHeight(); |
---|
79 | var visibleHeight = this.scroller.dom.clientHeight; |
---|
80 | return (visibleHeight < 1) ? 0 : Math.ceil(visibleHeight / rh); |
---|
81 | }, |
---|
82 | |
---|
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); |
---|
87 | return { |
---|
88 | first: Math.max(start, 0), |
---|
89 | last: Math.min(start + count + 2, this.ds.getCount()-1) |
---|
90 | }; |
---|
91 | }, |
---|
92 | |
---|
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;'; |
---|
98 | // buffers |
---|
99 | var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r; |
---|
100 | for (var j = 0, len = rs.length; j < len; j++) { |
---|
101 | r = rs[j]; cb = []; |
---|
102 | var rowIndex = (j+startRow); |
---|
103 | var visible = rowIndex >= vr.first && rowIndex <= vr.last; |
---|
104 | if (visible) { |
---|
105 | for (var i = 0; i < colCount; i++) { |
---|
106 | c = cs[i]; |
---|
107 | p.id = c.id; |
---|
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); |
---|
111 | p.style = c.style; |
---|
112 | if (p.value == undefined || p.value === "") { |
---|
113 | p.value = " "; |
---|
114 | } |
---|
115 | if (r.dirty && typeof r.modified[c.name] !== 'undefined') { |
---|
116 | p.css += ' x-grid3-dirty-cell'; |
---|
117 | } |
---|
118 | cb[cb.length] = ct.apply(p); |
---|
119 | } |
---|
120 | } |
---|
121 | var alt = []; |
---|
122 | if(stripe && ((rowIndex+1) % 2 == 0)){ |
---|
123 | alt[0] = "x-grid3-row-alt"; |
---|
124 | } |
---|
125 | if(r.dirty){ |
---|
126 | alt[1] = " x-grid3-dirty-row"; |
---|
127 | } |
---|
128 | rp.cols = colCount; |
---|
129 | if(this.getRowClass){ |
---|
130 | alt[2] = this.getRowClass(r, rowIndex, rp, ds); |
---|
131 | } |
---|
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)); |
---|
135 | } |
---|
136 | return buf.join(""); |
---|
137 | }, |
---|
138 | |
---|
139 | isRowRendered: function(index){ |
---|
140 | var row = this.getRow(index); |
---|
141 | return row && row.childNodes.length > 0; |
---|
142 | }, |
---|
143 | |
---|
144 | syncScroll: function(){ |
---|
145 | Ext.ux.grid.BufferView.superclass.syncScroll.apply(this, arguments); |
---|
146 | this.update(); |
---|
147 | }, |
---|
148 | |
---|
149 | // a (optionally) buffered method to update contents of gridview |
---|
150 | update: function(){ |
---|
151 | if (this.scrollDelay) { |
---|
152 | if (!this.renderTask) { |
---|
153 | this.renderTask = new Ext.util.DelayedTask(this.doUpdate, this); |
---|
154 | } |
---|
155 | this.renderTask.delay(this.scrollDelay); |
---|
156 | }else{ |
---|
157 | this.doUpdate(); |
---|
158 | } |
---|
159 | }, |
---|
160 | |
---|
161 | doUpdate: function(){ |
---|
162 | if (this.getVisibleRowCount() > 0) { |
---|
163 | var g = this.grid, cm = g.colModel, ds = g.store; |
---|
164 | var cs = this.getColumnData(); |
---|
165 | |
---|
166 | var vr = this.getVisibleRows(); |
---|
167 | for (var i = vr.first; i <= vr.last; i++) { |
---|
168 | // if row is NOT rendered and is visible, render it |
---|
169 | if(!this.isRowRendered(i)){ |
---|
170 | var html = this.doRender(cs, [ds.getAt(i)], ds, i, cm.getColumnCount(), g.stripeRows, true); |
---|
171 | this.getRow(i).innerHTML = html; |
---|
172 | } |
---|
173 | } |
---|
174 | this.clean(); |
---|
175 | } |
---|
176 | }, |
---|
177 | |
---|
178 | // a buffered method to clean rows |
---|
179 | clean : function(){ |
---|
180 | if(!this.cleanTask){ |
---|
181 | this.cleanTask = new Ext.util.DelayedTask(this.doClean, this); |
---|
182 | } |
---|
183 | this.cleanTask.delay(this.cleanDelay); |
---|
184 | }, |
---|
185 | |
---|
186 | doClean: function(){ |
---|
187 | if (this.getVisibleRowCount() > 0) { |
---|
188 | var vr = this.getVisibleRows(); |
---|
189 | vr.first -= this.cacheSize; |
---|
190 | vr.last += this.cacheSize; |
---|
191 | |
---|
192 | var i = 0, rows = this.getRows(); |
---|
193 | // if first is less than 0, all rows have been rendered |
---|
194 | // so lets clean the end... |
---|
195 | if(vr.first <= 0){ |
---|
196 | i = vr.last + 1; |
---|
197 | } |
---|
198 | for(var len = this.ds.getCount(); i < len; i++){ |
---|
199 | // if current row is outside of first and last and |
---|
200 | // has content, update the innerHTML to nothing |
---|
201 | if ((i < vr.first || i > vr.last) && rows[i].innerHTML) { |
---|
202 | rows[i].innerHTML = ''; |
---|
203 | } |
---|
204 | } |
---|
205 | } |
---|
206 | }, |
---|
207 | |
---|
208 | layout: function(){ |
---|
209 | Ext.ux.grid.BufferView.superclass.layout.call(this); |
---|
210 | this.update(); |
---|
211 | } |
---|
212 | }); |
---|