author | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
commit | 541bb378ddece2eab135a8066a16994e94436dea (patch) (unidiff) | |
tree | ff160ea3e26f7fe07fcfd401387c5a0232ca715e /frontend/beta/js/YUI-extensions/grid/GridView.js | |
parent | 1bf431fd3d45cbdf4afa3e12afefe5d24f4d3bc7 (diff) | |
parent | ecad5e895831337216544e81f1a467e0c68c4a6a (diff) | |
download | clipperz-541bb378ddece2eab135a8066a16994e94436dea.zip clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.gz clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.bz2 |
Merge pull request #1 from gcsolaroli/master
First version of the restructured repository
Diffstat (limited to 'frontend/beta/js/YUI-extensions/grid/GridView.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/YUI-extensions/grid/GridView.js | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/grid/GridView.js b/frontend/beta/js/YUI-extensions/grid/GridView.js new file mode 100644 index 0000000..dbd47e3 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/grid/GridView.js | |||
@@ -0,0 +1,790 @@ | |||
1 | /** | ||
2 | * @class YAHOO.ext.grid.GridView | ||
3 | * Default UI code used internally by the Grid. This is the object returned by {@link YAHOO.ext.grid.Grid#getView}. | ||
4 | * @constructor | ||
5 | */ | ||
6 | YAHOO.ext.grid.GridView = function(){ | ||
7 | this.grid = null; | ||
8 | this.lastFocusedRow = null; | ||
9 | this.onScroll = new YAHOO.util.CustomEvent('onscroll'); | ||
10 | this.adjustScrollTask = new YAHOO.ext.util.DelayedTask(this._adjustForScroll, this); | ||
11 | this.ensureVisibleTask = new YAHOO.ext.util.DelayedTask(); | ||
12 | }; | ||
13 | |||
14 | YAHOO.ext.grid.GridView.prototype = { | ||
15 | init: function(grid){ | ||
16 | this.grid = grid; | ||
17 | }, | ||
18 | |||
19 | fireScroll: function(scrollLeft, scrollTop){ | ||
20 | this.onScroll.fireDirect(this.grid, scrollLeft, scrollTop); | ||
21 | }, | ||
22 | |||
23 | /** | ||
24 | * @private | ||
25 | * Utility method that gets an array of the cell renderers | ||
26 | */ | ||
27 | getColumnRenderers : function(){ | ||
28 | var renderers = []; | ||
29 | var cm = this.grid.colModel; | ||
30 | var colCount = cm.getColumnCount(); | ||
31 | for(var i = 0; i < colCount; i++){ | ||
32 | renderers.push(cm.getRenderer(i)); | ||
33 | } | ||
34 | return renderers; | ||
35 | }, | ||
36 | |||
37 | buildIndexMap : function(){ | ||
38 | var colToData = {}; | ||
39 | var dataToCol = {}; | ||
40 | var cm = this.grid.colModel; | ||
41 | for(var i = 0, len = cm.getColumnCount(); i < len; i++){ | ||
42 | var di = cm.getDataIndex(i); | ||
43 | colToData[i] = di; | ||
44 | dataToCol[di] = i; | ||
45 | } | ||
46 | return {'colToData': colToData, 'dataToCol': dataToCol}; | ||
47 | }, | ||
48 | |||
49 | getDataIndexes : function(){ | ||
50 | if(!this.indexMap){ | ||
51 | this.indexMap = this.buildIndexMap(); | ||
52 | } | ||
53 | return this.indexMap.colToData; | ||
54 | }, | ||
55 | |||
56 | getColumnIndexByDataIndex : function(dataIndex){ | ||
57 | if(!this.indexMap){ | ||
58 | this.indexMap = this.buildIndexMap(); | ||
59 | } | ||
60 | return this.indexMap.dataToCol[dataIndex]; | ||
61 | }, | ||
62 | |||
63 | updateHeaders : function(){ | ||
64 | var colModel = this.grid.colModel; | ||
65 | var hcells = this.headers; | ||
66 | var colCount = colModel.getColumnCount(); | ||
67 | for(var i = 0; i < colCount; i++){ | ||
68 | hcells[i].textNode.innerHTML = colModel.getColumnHeader(i); | ||
69 | } | ||
70 | }, | ||
71 | |||
72 | adjustForScroll : function(disableDelay){ | ||
73 | if(!disableDelay){ | ||
74 | this.adjustScrollTask.delay(50); | ||
75 | }else{ | ||
76 | this._adjustForScroll(); | ||
77 | } | ||
78 | }, | ||
79 | |||
80 | /** | ||
81 | * Returns the rowIndex/columnIndex of the cell found at the passed page coordinates | ||
82 | * @param {Number} x | ||
83 | * @param {Number} y | ||
84 | * @return {Array} [rowIndex, columnIndex] | ||
85 | */ | ||
86 | getCellAtPoint : function(x, y){ | ||
87 | var colIndex = null; | ||
88 | var rowIndex = null; | ||
89 | |||
90 | // translate page coordinates to local coordinates | ||
91 | var xy = YAHOO.util.Dom.getXY(this.wrap); | ||
92 | x = (x - xy[0]) + this.wrap.scrollLeft; | ||
93 | y = (y - xy[1]) + this.wrap.scrollTop; | ||
94 | |||
95 | var colModel = this.grid.colModel; | ||
96 | var pos = 0; | ||
97 | var colCount = colModel.getColumnCount(); | ||
98 | for(var i = 0; i < colCount; i++){ | ||
99 | if(colModel.isHidden(i)) continue; | ||
100 | var width = colModel.getColumnWidth(i); | ||
101 | if(x >= pos && x < pos+width){ | ||
102 | colIndex = i; | ||
103 | break; | ||
104 | } | ||
105 | pos += width; | ||
106 | } | ||
107 | if(colIndex != null){ | ||
108 | rowIndex = (y == 0 ? 0 : Math.floor(y / this.getRowHeight())); | ||
109 | if(rowIndex >= this.grid.dataModel.getRowCount()){ | ||
110 | return null; | ||
111 | } | ||
112 | return [colIndex, rowIndex]; | ||
113 | } | ||
114 | return null; | ||
115 | }, | ||
116 | |||
117 | /** @private */ | ||
118 | _adjustForScroll : function(){ | ||
119 | this.forceScrollUpdate(); | ||
120 | if(this.scrollbarMode == YAHOO.ext.grid.GridView.SCROLLBARS_OVERLAP){ | ||
121 | var adjustment = 0; | ||
122 | if(this.wrap.clientWidth && this.wrap.clientWidth !== 0){ | ||
123 | adjustment = this.wrap.offsetWidth - this.wrap.clientWidth; | ||
124 | } | ||
125 | this.hwrap.setWidth(this.wrap.offsetWidth-adjustment); | ||
126 | }else{ | ||
127 | this.hwrap.setWidth(this.wrap.offsetWidth); | ||
128 | } | ||
129 | this.bwrap.setWidth(Math.max(this.grid.colModel.getTotalWidth(), this.wrap.clientWidth)); | ||
130 | }, | ||
131 | |||
132 | /** | ||
133 | * Focuses the specified row. The preferred way to scroll to a row is {@link #ensureVisible}. | ||
134 | * @param {Number/HTMLElement} row The index of a row or the row itself | ||
135 | */ | ||
136 | focusRow : function(row){ | ||
137 | if(typeof row == 'number'){ | ||
138 | row = this.getBodyTable().childNodes[row]; | ||
139 | } | ||
140 | if(!row) return; | ||
141 | var left = this.wrap.scrollLeft; | ||
142 | try{ // try catch for IE occasional focus bug | ||
143 | row.childNodes.item(0).hideFocus = true; | ||
144 | row.childNodes.item(0).focus(); | ||
145 | }catch(e){} | ||
146 | this.ensureVisible(row); | ||
147 | this.wrap.scrollLeft = left; | ||
148 | this.handleScroll(); | ||
149 | this.lastFocusedRow = row; | ||
150 | }, | ||
151 | |||
152 | /** | ||
153 | * Scrolls the specified row into view. This call is automatically buffered (delayed), to disable | ||
154 | * the delay, pass true for disableDelay. | ||
155 | * @param {Number/HTMLElement} row The index of a row or the row itself | ||
156 | * @param {Boolean} disableDelay | ||
157 | */ | ||
158 | ensureVisible : function(row, disableDelay){ | ||
159 | if(!disableDelay){ | ||
160 | this.ensureVisibleTask.delay(50, this._ensureVisible, this, [row]); | ||
161 | }else{ | ||
162 | this._ensureVisible(row); | ||
163 | } | ||
164 | }, | ||
165 | |||
166 | /** @ignore */ | ||
167 | _ensureVisible : function(row){ | ||
168 | if(typeof row == 'number'){ | ||
169 | row = this.getBodyTable().childNodes[row]; | ||
170 | } | ||
171 | if(!row) return; | ||
172 | var left = this.wrap.scrollLeft; | ||
173 | var rowTop = parseInt(row.offsetTop, 10); // parseInt for safari bug | ||
174 | var rowBottom = rowTop + row.offsetHeight; | ||
175 | var clientTop = parseInt(this.wrap.scrollTop, 10); // parseInt for safari bug | ||
176 | var clientBottom = clientTop + this.wrap.clientHeight; | ||
177 | if(rowTop < clientTop){ | ||
178 | this.wrap.scrollTop = rowTop; | ||
179 | }else if(rowBottom > clientBottom){ | ||
180 | this.wrap.scrollTop = rowBottom-this.wrap.clientHeight; | ||
181 | } | ||
182 | this.wrap.scrollLeft = left; | ||
183 | this.handleScroll(); | ||
184 | }, | ||
185 | |||
186 | updateColumns : function(){ | ||
187 | this.grid.stopEditing(); | ||
188 | var colModel = this.grid.colModel; | ||
189 | var hcols = this.headers; | ||
190 | var colCount = colModel.getColumnCount(); | ||
191 | var pos = 0; | ||
192 | var totalWidth = colModel.getTotalWidth(); | ||
193 | for(var i = 0; i < colCount; i++){ | ||
194 | if(colModel.isHidden(i)) continue; | ||
195 | var width = colModel.getColumnWidth(i); | ||
196 | hcols[i].style.width = width + 'px'; | ||
197 | hcols[i].style.left = pos + 'px'; | ||
198 | hcols[i].split.style.left = (pos+width-3) + 'px'; | ||
199 | this.setCSSWidth(i, width, pos); | ||
200 | pos += width; | ||
201 | } | ||
202 | this.lastWidth = totalWidth; | ||
203 | if(this.grid.autoWidth){ | ||
204 | this.grid.container.setWidth(totalWidth+this.grid.container.getBorderWidth('lr')); | ||
205 | this.grid.autoSize(); | ||
206 | } | ||
207 | this.bwrap.setWidth(Math.max(totalWidth, this.wrap.clientWidth)); | ||
208 | if(!YAHOO.ext.util.Browser.isIE){ // fix scrolling prob in gecko and opera | ||
209 | this.wrap.scrollLeft = this.hwrap.dom.scrollLeft; | ||
210 | } | ||
211 | this.syncScroll(); | ||
212 | this.forceScrollUpdate(); | ||
213 | if(this.grid.autoHeight){ | ||
214 | this.autoHeight(); | ||
215 | this.updateWrapHeight(); | ||
216 | } | ||
217 | }, | ||
218 | |||
219 | setCSSWidth : function(colIndex, width, pos){ | ||
220 | var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex]; | ||
221 | YAHOO.ext.util.CSS.updateRule(selector, 'width', width + 'px'); | ||
222 | if(typeof pos == 'number'){ | ||
223 | YAHOO.ext.util.CSS.updateRule(selector, 'left', pos + 'px'); | ||
224 | } | ||
225 | }, | ||
226 | |||
227 | /** | ||
228 | * Set a css style for a column dynamically. | ||
229 | * @param {Number} colIndex The index of the column | ||
230 | * @param {String} name The css property name | ||
231 | * @param {String} value The css value | ||
232 | */ | ||
233 | setCSSStyle : function(colIndex, name, value){ | ||
234 | var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex]; | ||
235 | YAHOO.ext.util.CSS.updateRule(selector, name, value); | ||
236 | }, | ||
237 | |||
238 | handleHiddenChange : function(colModel, colIndex, hidden){ | ||
239 | if(hidden){ | ||
240 | this.hideColumn(colIndex); | ||
241 | }else{ | ||
242 | this.unhideColumn(colIndex); | ||
243 | } | ||
244 | this.updateColumns(); | ||
245 | }, | ||
246 | |||
247 | hideColumn : function(colIndex){ | ||
248 | var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex]; | ||
249 | YAHOO.ext.util.CSS.updateRule(selector, 'position', 'absolute'); | ||
250 | YAHOO.ext.util.CSS.updateRule(selector, 'visibility', 'hidden'); | ||
251 | |||
252 | this.headers[colIndex].style.display = 'none'; | ||
253 | this.headers[colIndex].split.style.display = 'none'; | ||
254 | }, | ||
255 | |||
256 | unhideColumn : function(colIndex){ | ||
257 | var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex]; | ||
258 | YAHOO.ext.util.CSS.updateRule(selector, 'position', ''); | ||
259 | YAHOO.ext.util.CSS.updateRule(selector, 'visibility', 'visible'); | ||
260 | |||
261 | this.headers[colIndex].style.display = ''; | ||
262 | this.headers[colIndex].split.style.display = ''; | ||
263 | }, | ||
264 | |||
265 | getBodyTable : function(){ | ||
266 | return this.bwrap.dom; | ||
267 | }, | ||
268 | |||
269 | updateRowIndexes : function(firstRow, lastRow){ | ||
270 | var stripeRows = this.grid.stripeRows; | ||
271 | var bt = this.getBodyTable(); | ||
272 | var nodes = bt.childNodes; | ||
273 | firstRow = firstRow || 0; | ||
274 | lastRow = lastRow || nodes.length-1; | ||
275 | var re = /^(?:ygrid-row ygrid-row-alt|ygrid-row)/; | ||
276 | for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){ | ||
277 | var node = nodes[rowIndex]; | ||
278 | if(stripeRows && (rowIndex+1) % 2 == 0){ | ||
279 | node.className = node.className.replace(re, 'ygrid-row ygrid-row-alt'); | ||
280 | }else{ | ||
281 | node.className = node.className.replace(re, 'ygrid-row'); | ||
282 | } | ||
283 | node.rowIndex = rowIndex; | ||
284 | nodes[rowIndex].style.top = (rowIndex * this.rowHeight) + 'px'; | ||
285 | } | ||
286 | }, | ||
287 | |||
288 | insertRows : function(dataModel, firstRow, lastRow){ | ||
289 | this.updateBodyHeight(); | ||
290 | this.adjustForScroll(true); | ||
291 | var renderers = this.getColumnRenderers(); | ||
292 | var dindexes = this.getDataIndexes(); | ||
293 | var colCount = this.grid.colModel.getColumnCount(); | ||
294 | var beforeRow = null; | ||
295 | var bt = this.getBodyTable(); | ||
296 | if(firstRow < bt.childNodes.length){ | ||
297 | beforeRow = bt.childNodes[firstRow]; | ||
298 | } | ||
299 | for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){ | ||
300 | var row = document.createElement('span'); | ||
301 | row.className = 'ygrid-row'; | ||
302 | row.style.top = (rowIndex * this.rowHeight) + 'px'; | ||
303 | this.renderRow(dataModel, row, rowIndex, colCount, renderers, dindexes); | ||
304 | if(beforeRow){ | ||
305 | bt.insertBefore(row, beforeRow); | ||
306 | }else{ | ||
307 | bt.appendChild(row); | ||
308 | } | ||
309 | } | ||
310 | this.updateRowIndexes(firstRow); | ||
311 | this.adjustForScroll(true); | ||
312 | }, | ||
313 | |||
314 | renderRow : function(dataModel, row, rowIndex, colCount, renderers, dindexes){ | ||
315 | for(var colIndex = 0; colIndex < colCount; colIndex++){ | ||
316 | var td = document.createElement('span'); | ||
317 | td.className = 'ygrid-col ygrid-col-' + colIndex + (colIndex == colCount-1 ? ' ygrid-col-last' : ''); | ||
318 | td.columnIndex = colIndex; | ||
319 | td.tabIndex = 0; | ||
320 | var span = document.createElement('span'); | ||
321 | span.className = 'ygrid-cell-text'; | ||
322 | td.appendChild(span); | ||
323 | var val = renderers[colIndex](dataModel.getValueAt(rowIndex, dindexes[colIndex]), rowIndex, colIndex, td, dataModel); | ||
324 | if(typeof val == 'undefined' || val === '') val = ' '; | ||
325 | span.innerHTML = val; | ||
326 | row.appendChild(td); | ||
327 | } | ||
328 | }, | ||
329 | |||
330 | deleteRows : function(dataModel, firstRow, lastRow){ | ||
331 | this.updateBodyHeight(); | ||
332 | // first make sure they are deselected | ||
333 | this.grid.selModel.deselectRange(firstRow, lastRow); | ||
334 | var bt = this.getBodyTable(); | ||
335 | var rows = []; // get references because the rowIndex will change | ||
336 | for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){ | ||
337 | rows.push(bt.childNodes[rowIndex]); | ||
338 | } | ||
339 | for(var i = 0; i < rows.length; i++){ | ||
340 | bt.removeChild(rows[i]); | ||
341 | rows[i] = null; | ||
342 | } | ||
343 | rows = null; | ||
344 | this.updateRowIndexes(firstRow); | ||
345 | this.adjustForScroll(); | ||
346 | }, | ||
347 | |||
348 | updateRows : function(dataModel, firstRow, lastRow){ | ||
349 | var bt = this.getBodyTable(); | ||
350 | var dindexes = this.getDataIndexes(); | ||
351 | var renderers = this.getColumnRenderers(); | ||
352 | var colCount = this.grid.colModel.getColumnCount(); | ||
353 | for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){ | ||
354 | var row = bt.rows[rowIndex]; | ||
355 | var cells = row.childNodes; | ||
356 | for(var colIndex = 0; colIndex < colCount; colIndex++){ | ||
357 | var td = cells[colIndex]; | ||
358 | var val = renderers[colIndex](dataModel.getValueAt(rowIndex, dindexes[colIndex]), rowIndex, colIndex, td, dataModel); | ||
359 | if(typeof val == 'undefined' || val === '') val = ' '; | ||
360 | td.firstChild.innerHTML = val; | ||
361 | } | ||
362 | } | ||
363 | }, | ||
364 | |||
365 | handleSort : function(dataModel, sortColumnIndex, sortDir, noRefresh){ | ||
366 | varselectedRows; | ||
367 | this.grid.selModel.syncSelectionsToIds(); | ||
368 | if(!noRefresh){ | ||
369 | this.updateRows(dataModel, 0, dataModel.getRowCount()-1); | ||
370 | } | ||
371 | this.updateHeaderSortState(); | ||
372 | selectedRows = this.grid.selModel.getSelectedRows(); | ||
373 | if (selectedRows.length > 0) { | ||
374 | this.focusRow(selectedRows[0]); | ||
375 | } | ||
376 | }, | ||
377 | |||
378 | syncScroll : function(){ | ||
379 | this.hwrap.dom.scrollLeft = this.wrap.scrollLeft; | ||
380 | }, | ||
381 | |||
382 | handleScroll : function(){ | ||
383 | this.syncScroll(); | ||
384 | this.fireScroll(this.wrap.scrollLeft, this.wrap.scrollTop); | ||
385 | this.grid.fireEvent('bodyscroll', this.wrap.scrollLeft, this.wrap.scrollTop); | ||
386 | }, | ||
387 | |||
388 | getRowHeight : function(){ | ||
389 | if(!this.rowHeight){ | ||
390 | var rule = YAHOO.ext.util.CSS.getRule(["#" + this.grid.id + " .ygrid-row", ".ygrid-row"]); | ||
391 | if(rule && rule.style.height){ | ||
392 | this.rowHeight = parseInt(rule.style.height, 10); | ||
393 | }else{ | ||
394 | this.rowHeight = 21; | ||
395 | } | ||
396 | } | ||
397 | return this.rowHeight; | ||
398 | }, | ||
399 | |||
400 | renderRows : function(dataModel){ | ||
401 | this.grid.stopEditing(); | ||
402 | if(this.grid.selModel){ | ||
403 | this.grid.selModel.clearSelections(); | ||
404 | } | ||
405 | var bt = this.getBodyTable(); | ||
406 | bt.innerHTML = ''; | ||
407 | this.rowHeight = this.getRowHeight(); | ||
408 | this.insertRows(dataModel, 0, dataModel.getRowCount()-1); | ||
409 | }, | ||
410 | |||
411 | updateCell : function(dataModel, rowIndex, dataIndex){ | ||
412 | var colIndex = this.getColumnIndexByDataIndex(dataIndex); | ||
413 | if(typeof colIndex == 'undefined'){ // not present in grid | ||
414 | return; | ||
415 | } | ||
416 | var bt = this.getBodyTable(); | ||
417 | var row = bt.childNodes[rowIndex]; | ||
418 | var cell = row.childNodes[colIndex]; | ||
419 | var renderer = this.grid.colModel.getRenderer(colIndex); | ||
420 | var val = renderer(dataModel.getValueAt(rowIndex, dataIndex), rowIndex, colIndex, cell, dataModel); | ||
421 | if(typeof val == 'undefined' || val === '') val = ' '; | ||
422 | cell.firstChild.innerHTML = val; | ||
423 | }, | ||
424 | |||
425 | calcColumnWidth : function(colIndex, maxRowsToMeasure){ | ||
426 | var maxWidth = 0; | ||
427 | var bt = this.getBodyTable(); | ||
428 | var rows = bt.childNodes; | ||
429 | var stopIndex = Math.min(maxRowsToMeasure || rows.length, rows.length); | ||
430 | if(this.grid.autoSizeHeaders){ | ||
431 | var h = this.headers[colIndex]; | ||
432 | var curWidth = h.style.width; | ||
433 | h.style.width = this.grid.minColumnWidth+'px'; | ||
434 | maxWidth = Math.max(maxWidth, h.scrollWidth); | ||
435 | h.style.width = curWidth; | ||
436 | } | ||
437 | for(var i = 0; i < stopIndex; i++){ | ||
438 | var cell = rows[i].childNodes[colIndex].firstChild; | ||
439 | maxWidth = Math.max(maxWidth, cell.scrollWidth); | ||
440 | } | ||
441 | return maxWidth + /*margin for error in IE*/ 5; | ||
442 | }, | ||
443 | |||
444 | /** | ||
445 | * Autofit a column to it's content. | ||
446 | * @param {Number} colIndex | ||
447 | * @param {Boolean} forceMinSize true to force the column to go smaller if possible | ||
448 | */ | ||
449 | autoSizeColumn : function(colIndex, forceMinSize){ | ||
450 | if(forceMinSize){ | ||
451 | this.setCSSWidth(colIndex, this.grid.minColumnWidth); | ||
452 | } | ||
453 | var newWidth = this.calcColumnWidth(colIndex); | ||
454 | this.grid.colModel.setColumnWidth(colIndex, | ||
455 | Math.max(this.grid.minColumnWidth, newWidth)); | ||
456 | this.grid.fireEvent('columnresize', colIndex, newWidth); | ||
457 | }, | ||
458 | |||
459 | /** | ||
460 | * Autofits all columns to their content and then expands to fit any extra space in the grid | ||
461 | */ | ||
462 | autoSizeColumns : function(){ | ||
463 | var colModel = this.grid.colModel; | ||
464 | var colCount = colModel.getColumnCount(); | ||
465 | var wrap = this.wrap; | ||
466 | for(var i = 0; i < colCount; i++){ | ||
467 | this.setCSSWidth(i, this.grid.minColumnWidth); | ||
468 | colModel.setColumnWidth(i, this.calcColumnWidth(i, this.grid.maxRowsToMeasure), true); | ||
469 | } | ||
470 | if(colModel.getTotalWidth() < wrap.clientWidth){ | ||
471 | var diff = Math.floor((wrap.clientWidth - colModel.getTotalWidth()) / colCount); | ||
472 | for(var i = 0; i < colCount; i++){ | ||
473 | colModel.setColumnWidth(i, colModel.getColumnWidth(i) + diff, true); | ||
474 | } | ||
475 | } | ||
476 | this.updateColumns(); | ||
477 | }, | ||
478 | |||
479 | /** | ||
480 | * Autofits all columns to the grid's width proportionate with their current size | ||
481 | */ | ||
482 | fitColumns : function(){ | ||
483 | var cm = this.grid.colModel; | ||
484 | var colCount = cm.getColumnCount(); | ||
485 | var cols = []; | ||
486 | var width = 0; | ||
487 | var i, w; | ||
488 | for (i = 0; i < colCount; i++){ | ||
489 | if(!cm.isHidden(i) && !cm.isFixed(i)){ | ||
490 | w = cm.getColumnWidth(i); | ||
491 | cols.push(i); | ||
492 | cols.push(w); | ||
493 | width += w; | ||
494 | } | ||
495 | } | ||
496 | var frac = (this.wrap.clientWidth - cm.getTotalWidth())/width; | ||
497 | while (cols.length){ | ||
498 | w = cols.pop(); | ||
499 | i = cols.pop(); | ||
500 | cm.setColumnWidth(i, Math.floor(w + w*frac), true); | ||
501 | } | ||
502 | this.updateColumns(); | ||
503 | }, | ||
504 | |||
505 | onWindowResize : function(){ | ||
506 | if(this.grid.monitorWindowResize){ | ||
507 | this.adjustForScroll(); | ||
508 | this.updateWrapHeight(); | ||
509 | this.adjustForScroll(); | ||
510 | } | ||
511 | }, | ||
512 | |||
513 | updateWrapHeight : function(){ | ||
514 | this.grid.container.beginMeasure(); | ||
515 | this.autoHeight(); | ||
516 | var box = this.grid.container.getSize(true); | ||
517 | this.wrapEl.setHeight(box.height-this.footerHeight-parseInt(this.wrap.offsetTop, 10)); | ||
518 | this.pwrap.setSize(box.width, box.height); | ||
519 | this.grid.container.endMeasure(); | ||
520 | }, | ||
521 | |||
522 | forceScrollUpdate : function(){ | ||
523 | var wrap = this.wrapEl; | ||
524 | wrap.setWidth(wrap.getWidth(true)); | ||
525 | setTimeout(function(){ // set timeout so FireFox works | ||
526 | wrap.setWidth(''); | ||
527 | }, 1); | ||
528 | }, | ||
529 | |||
530 | updateHeaderSortState : function(){ | ||
531 | var state = this.grid.dataModel.getSortState(); | ||
532 | if(!state || typeof state.column == 'undefined') return; | ||
533 | var sortColumn = this.getColumnIndexByDataIndex(state.column); | ||
534 | var sortDir = state.direction; | ||
535 | for(var i = 0, len = this.headers.length; i < len; i++){ | ||
536 | var h = this.headers[i]; | ||
537 | if(i != sortColumn){ | ||
538 | h.sortDesc.style.display = 'none'; | ||
539 | h.sortAsc.style.display = 'none'; | ||
540 | YAHOO.util.Dom.removeClass(h, 'ygrid-sort-col'); | ||
541 | }else{ | ||
542 | h.sortDesc.style.display = sortDir == 'DESC' ? 'block' : 'none'; | ||
543 | h.sortAsc.style.display = sortDir == 'ASC' ? 'block' : 'none'; | ||
544 | YAHOO.util.Dom.addClass(h, 'ygrid-sort-col'); | ||
545 | } | ||
546 | } | ||
547 | }, | ||
548 | |||
549 | unplugDataModel : function(dm){ | ||
550 | dm.removeListener('cellupdated', this.updateCell, this); | ||
551 | dm.removeListener('datachanged', this.renderRows, this); | ||
552 | dm.removeListener('rowsdeleted', this.deleteRows, this); | ||
553 | dm.removeListener('rowsinserted', this.insertRows, this); | ||
554 | dm.removeListener('rowsupdated', this.updateRows, this); | ||
555 | dm.removeListener('rowssorted', this.handleSort, this); | ||
556 | }, | ||
557 | |||
558 | plugDataModel : function(dm){ | ||
559 | dm.on('cellupdated', this.updateCell, this, true); | ||
560 | dm.on('datachanged', this.renderRows, this, true); | ||
561 | dm.on('rowsdeleted', this.deleteRows, this, true); | ||
562 | dm.on('rowsinserted', this.insertRows, this, true); | ||
563 | dm.on('rowsupdated', this.updateRows, this, true); | ||
564 | dm.on('rowssorted', this.handleSort, this, true); | ||
565 | }, | ||
566 | |||
567 | destroy : function(){ | ||
568 | this.unplugDataModel(this.grid.dataModel); | ||
569 | var sp = this.splitters; | ||
570 | if(sp){ | ||
571 | for(var i in sp){ | ||
572 | if(sp[i] && typeof sp[i] != 'function'){ | ||
573 | sp[i].destroy(true); | ||
574 | } | ||
575 | } | ||
576 | } | ||
577 | }, | ||
578 | |||
579 | render : function(){ | ||
580 | var grid = this.grid; | ||
581 | var container = grid.container.dom; | ||
582 | var dataModel = grid.dataModel; | ||
583 | this.plugDataModel(dataModel); | ||
584 | |||
585 | var colModel = grid.colModel; | ||
586 | colModel.onWidthChange.subscribe(this.updateColumns, this, true); | ||
587 | colModel.onHeaderChange.subscribe(this.updateHeaders, this, true); | ||
588 | colModel.onHiddenChange.subscribe(this.handleHiddenChange, this, true); | ||
589 | |||
590 | if(grid.monitorWindowResize === true){ | ||
591 | YAHOO.ext.EventManager.onWindowResize(this.onWindowResize, this, true); | ||
592 | } | ||
593 | var autoSizeDelegate = this.autoSizeColumn.createDelegate(this); | ||
594 | |||
595 | var colCount = colModel.getColumnCount(); | ||
596 | |||
597 | var dh = YAHOO.ext.DomHelper; | ||
598 | this.pwrap = dh.append(container, | ||
599 | {tag: 'div', cls: 'ygrid-positioner', | ||
600 | style: 'position:relative;width:100%;height:100%;left:0;top:0;overflow:hidden;'}, true); | ||
601 | var pos = this.pwrap.dom; | ||
602 | |||
603 | //create wrapper elements that handle offsets and scrolling | ||
604 | var wrap = dh.append(pos, {tag: 'div', cls: 'ygrid-wrap'}); | ||
605 | this.wrap = wrap; | ||
606 | this.wrapEl = getEl(wrap, true); | ||
607 | YAHOO.ext.EventManager.on(wrap, 'scroll', this.handleScroll, this, true); | ||
608 | |||
609 | var hwrap = dh.append(pos, {tag: 'div', cls: 'ygrid-wrap-headers'}); | ||
610 | this.hwrap = getEl(hwrap, true); | ||
611 | |||
612 | var bwrap = dh.append(wrap, {tag: 'div', cls: 'ygrid-wrap-body', id: container.id + '-body'}); | ||
613 | this.bwrap = getEl(bwrap, true); | ||
614 | this.bwrap.setWidth(colModel.getTotalWidth()); | ||
615 | bwrap.rows = bwrap.childNodes; | ||
616 | |||
617 | this.footerHeight = 0; | ||
618 | var foot = this.appendFooter(this.pwrap.dom); | ||
619 | if(foot){ | ||
620 | this.footer = getEl(foot, true); | ||
621 | this.footerHeight = this.footer.getHeight(); | ||
622 | } | ||
623 | this.updateWrapHeight(); | ||
624 | |||
625 | var hrow = dh.append(hwrap, {tag: 'span', cls: 'ygrid-hrow'}); | ||
626 | this.hrow = hrow; | ||
627 | |||
628 | if(!YAHOO.ext.util.Browser.isGecko){ | ||
629 | // IE doesn't like iframes, we will leave this alone | ||
630 | var iframe = document.createElement('iframe'); | ||
631 | iframe.className = 'ygrid-hrow-frame'; | ||
632 | iframe.frameBorder = 0; | ||
633 | iframe.src = YAHOO.ext.SSL_SECURE_URL; | ||
634 | hwrap.appendChild(iframe); | ||
635 | } | ||
636 | this.headerCtrl = new YAHOO.ext.grid.HeaderController(this.grid); | ||
637 | this.headers = []; | ||
638 | this.cols = []; | ||
639 | this.splitters = []; | ||
640 | |||
641 | var htemplate = dh.createTemplate({ | ||
642 | tag: 'span', cls: 'ygrid-hd ygrid-header-{0}', children: [{ | ||
643 | tag: 'span', | ||
644 | cls: 'ygrid-hd-body', | ||
645 | html: '<table border="0" cellpadding="0" cellspacing="0" title="{2}">' + | ||
646 | '<tbody><tr><td><span>{1}</span></td>' + | ||
647 | '<td><span class="sort-desc"></span><span class="sort-asc"></span></td>' + | ||
648 | '</tr></tbody></table>' | ||
649 | }] | ||
650 | }); | ||
651 | htemplate.compile(); | ||
652 | |||
653 | var ruleBuf = []; | ||
654 | |||
655 | for(var i = 0; i < colCount; i++){ | ||
656 | var hd = htemplate.append(hrow, [i, colModel.getColumnHeader(i), colModel.getColumnTooltip(i) || '']); | ||
657 | var spans = hd.getElementsByTagName('span'); | ||
658 | hd.textNode = spans[1]; | ||
659 | hd.sortDesc = spans[2]; | ||
660 | hd.sortAsc = spans[3]; | ||
661 | hd.columnIndex = i; | ||
662 | this.headers.push(hd); | ||
663 | if(colModel.isSortable(i)){ | ||
664 | this.headerCtrl.register(hd); | ||
665 | } | ||
666 | var split = dh.append(hrow, {tag: 'span', cls: 'ygrid-hd-split'}); | ||
667 | hd.split = split; | ||
668 | |||
669 | if(colModel.isResizable(i) && !colModel.isFixed(i)){ | ||
670 | YAHOO.util.Event.on(split, 'dblclick', autoSizeDelegate.createCallback(i+0, true)); | ||
671 | var sb = new YAHOO.ext.SplitBar(split, hd, null, YAHOO.ext.SplitBar.LEFT); | ||
672 | sb.columnIndex = i; | ||
673 | sb.minSize = grid.minColumnWidth; | ||
674 | sb.onMoved.subscribe(this.onColumnSplitterMoved, this, true); | ||
675 | YAHOO.util.Dom.addClass(sb.proxy, 'ygrid-column-sizer'); | ||
676 | YAHOO.util.Dom.setStyle(sb.proxy, 'background-color', ''); | ||
677 | sb.dd._resizeProxy = function(){ | ||
678 | var el = this.getDragEl(); | ||
679 | YAHOO.util.Dom.setStyle(el, 'height', (hwrap.clientHeight+wrap.clientHeight-2) +'px'); | ||
680 | }; | ||
681 | this.splitters[i] = sb; | ||
682 | }else{ | ||
683 | split.style.cursor = 'default'; | ||
684 | } | ||
685 | ruleBuf.push('#', container.id, ' .ygrid-col-', i, ' {\n}\n'); | ||
686 | } | ||
687 | |||
688 | YAHOO.ext.util.CSS.createStyleSheet(ruleBuf.join('')); | ||
689 | |||
690 | if(grid.autoSizeColumns){ | ||
691 | this.renderRows(dataModel); | ||
692 | this.autoSizeColumns(); | ||
693 | }else{ | ||
694 | this.updateColumns(); | ||
695 | this.renderRows(dataModel); | ||
696 | } | ||
697 | |||
698 | for(var i = 0; i < colCount; i++){ | ||
699 | if(colModel.isHidden(i)){ | ||
700 | this.hideColumn(i); | ||
701 | } | ||
702 | } | ||
703 | this.updateHeaderSortState(); | ||
704 | return this.bwrap; | ||
705 | }, | ||
706 | |||
707 | onColumnSplitterMoved : function(splitter, newSize){ | ||
708 | this.grid.colModel.setColumnWidth(splitter.columnIndex, newSize); | ||
709 | this.grid.fireEvent('columnresize', splitter.columnIndex, newSize); | ||
710 | }, | ||
711 | |||
712 | appendFooter : function(parentEl){ | ||
713 | return null; | ||
714 | }, | ||
715 | |||
716 | autoHeight : function(){ | ||
717 | if(this.grid.autoHeight){ | ||
718 | var h = this.getBodyHeight(); | ||
719 | var c = this.grid.container; | ||
720 | var total = h + (parseInt(this.wrap.offsetTop, 10)||0) + | ||
721 | this.footerHeight + c.getBorderWidth('tb') + c.getPadding('tb') | ||
722 | + (this.wrap.offsetHeight - this.wrap.clientHeight); | ||
723 | c.setHeight(total); | ||
724 | |||
725 | } | ||
726 | }, | ||
727 | |||
728 | getBodyHeight : function(){ | ||
729 | return this.grid.dataModel.getRowCount() * this.getRowHeight();; | ||
730 | }, | ||
731 | |||
732 | updateBodyHeight : function(){ | ||
733 | this.getBodyTable().style.height = this.getBodyHeight() + 'px'; | ||
734 | if(this.grid.autoHeight){ | ||
735 | this.autoHeight(); | ||
736 | this.updateWrapHeight(); | ||
737 | } | ||
738 | } | ||
739 | }; | ||
740 | YAHOO.ext.grid.GridView.SCROLLBARS_UNDER = 0; | ||
741 | YAHOO.ext.grid.GridView.SCROLLBARS_OVERLAP = 1; | ||
742 | YAHOO.ext.grid.GridView.prototype.scrollbarMode = YAHOO.ext.grid.GridView.SCROLLBARS_UNDER; | ||
743 | |||
744 | YAHOO.ext.grid.GridView.prototype.fitColumnsToContainer = YAHOO.ext.grid.GridView.prototype.fitColumns; | ||
745 | |||
746 | YAHOO.ext.grid.HeaderController = function(grid){ | ||
747 | this.grid = grid; | ||
748 | this.headers = []; | ||
749 | }; | ||
750 | |||
751 | YAHOO.ext.grid.HeaderController.prototype = { | ||
752 | register : function(header){ | ||
753 | this.headers.push(header); | ||
754 | YAHOO.ext.EventManager.on(header, 'selectstart', this.cancelTextSelection, this, true); | ||
755 | YAHOO.ext.EventManager.on(header, 'mousedown', this.cancelTextSelection, this, true); | ||
756 | YAHOO.ext.EventManager.on(header, 'mouseover', this.headerOver, this, true); | ||
757 | YAHOO.ext.EventManager.on(header, 'mouseout', this.headerOut, this, true); | ||
758 | YAHOO.ext.EventManager.on(header, 'click', this.headerClick, this, true); | ||
759 | }, | ||
760 | |||
761 | headerClick : function(e){ | ||
762 | var grid = this.grid, cm = grid.colModel, dm = grid.dataModel; | ||
763 | grid.stopEditing(); | ||
764 | var header = grid.getHeaderFromChild(e.getTarget()); | ||
765 | var state = dm.getSortState(); | ||
766 | var direction = header.sortDir || 'ASC'; | ||
767 | if(typeof state.column != 'undefined' && | ||
768 | grid.getView().getColumnIndexByDataIndex(state.column) == header.columnIndex){ | ||
769 | direction = (state.direction == 'ASC' ? 'DESC' : 'ASC'); | ||
770 | } | ||
771 | header.sortDir = direction; | ||
772 | dm.sort(cm, cm.getDataIndex(header.columnIndex), direction); | ||
773 | }, | ||
774 | |||
775 | headerOver : function(e){ | ||
776 | var header = this.grid.getHeaderFromChild(e.getTarget()); | ||
777 | YAHOO.util.Dom.addClass(header, 'ygrid-hd-over'); | ||
778 | //YAHOO.ext.util.CSS.applyFirst(header, this.grid.id, '.ygrid-hd-over'); | ||
779 | }, | ||
780 | |||
781 | headerOut : function(e){ | ||
782 | var header = this.grid.getHeaderFromChild(e.getTarget()); | ||
783 | YAHOO.util.Dom.removeClass(header, 'ygrid-hd-over'); | ||
784 | //YAHOO.ext.util.CSS.revertFirst(header, this.grid.id, '.ygrid-hd-over'); | ||
785 | }, | ||
786 | |||
787 | cancelTextSelection : function(e){ | ||
788 | e.preventDefault(); | ||
789 | } | ||
790 | }; \ No newline at end of file | ||