Changeset 6
- Timestamp:
- 08/25/08 01:42:48 (4 years ago)
- Location:
- trunk
- Files:
-
- 3 modified
-
CHANGELOG (modified) (2 diffs)
-
src/BufferedGridToolbar.js (modified) (12 diffs)
-
src/BufferedGridView.js (modified) (86 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/CHANGELOG
r4 r6 1 1 Version 0.1.1 2 25-August-2008 3 4 - fixes: 5 - BufferedGridView: grid would not be repainted correctly if a column was moved: 6 method "onColumnMove()" with appropriate implementation added (fixes google issue 9); 7 "onRemove()" would not work properly if the end of the data was reached in the visible 8 rect and rows from within that rect are removed. Adjusted "lastRowIndex" to be equal to 9 "rowIndex", and skipped implicit "processRows()" call in "replaceLiveRows()" via passing 10 a new third argument "processRows", which will only call "processRows()" if the argument 11 was not set to false; removed call to "selections.add()" in "processRows()" since selections 12 are already in the "bufferedSelections" property of the selection model, and previously 13 selected records are still part of the "selections"-property of the selection model. 14 15 16 - enhancements: 17 - BufferedGridView: Added functionality for listening to erroneous responses from 18 buffer-requests. Event "bufferfailure" will now be fired if the store indicated that 19 the proxy's response was erroneous; added "options" parameter to be passed to 20 "buffer"-event 21 22 - BufferedGridToolbar: Toolbar is now listening to "bufferfailure"-event and resets 23 the reload-button to "enabled" if necessary. 24 2 25 Version 0.1 3 26 16-June-2008 … … 7 30 the passed argument to the appropriate index in the model; updated sources to take 8 31 overriden method into account 9 - added cfg option "scrollDelay" in BufferedGridView for buffering calls to onLiveScroll 32 - added cfg option "scrollDelay" in BufferedGridView for buffering calls to onLiveScroll 10 33 when scroll-event gets fired (thanks to Rich Waters) 11 34 - BufferedStore: removed custom applySort() implementation due to changes in findInsertIndex 12 - BufferedStore: changed findInsertIndex to use parent implementation first, then check 35 - BufferedStore: changed findInsertIndex to use parent implementation first, then check 13 36 return value and adjust the index if needed 14 37 - BufferedStore/BufferedGridView: moved bufferRange-member to BufferedStore 15 38 - BufferedStore: optimized insert() method in BufferedStore 16 39 - allowed to add records at position "0" in grid (existing records get shifted down) 17 40 18 41 - fixes: 19 - wrong calculation in BufferedGridView.onLiveScroll (based on lastScrollPosition and actual 42 - wrong calculation in BufferedGridView.onLiveScroll (based on lastScrollPosition and actual 20 43 scrollPosition) caused the view sometimes to not re-render some rows 21 44 - provided bug fix for "ensureVisible: returned x-coordinate does not take the x-position -
trunk/src/BufferedGridToolbar.js
r2 r6 2 2 * Ext.ux.BufferedGridToolbar V1.0 3 3 * Copyright(c) 2007, http://www.siteartwork.de 4 * 4 * 5 5 * Licensed under the terms of the Open Source LGPL 3.0 6 6 * http://www.gnu.org/licenses/lgpl.html … … 13 13 * @class Ext.ux.BufferedGridToolbar 14 14 * @extends Ext.Toolbar 15 * A specialized toolbar that is bound to a {@link Ext.ux.grid.BufferedGridView} 16 * and provides information about the indexes of the requested data and the buffer 15 * A specialized toolbar that is bound to a {@link Ext.ux.grid.BufferedGridView} 16 * and provides information about the indexes of the requested data and the buffer 17 17 * state. 18 18 * @constructor … … 26 26 * True to display the displayMsg (defaults to false) 27 27 */ 28 28 29 29 /** 30 30 * @cfg {String} displayMsg … … 32 32 */ 33 33 displayMsg : 'Displaying {0} - {1} of {2}', 34 34 35 35 /** 36 36 * @cfg {String} emptyMsg … … 44 44 * @param {String} 45 45 */ 46 refreshText : "Refresh", 47 46 refreshText : "Refresh", 47 48 48 initComponent : function() 49 49 { … … 58 58 var msg = totalCount == 0 ? 59 59 this.emptyMsg : 60 String.format(this.displayMsg, rowIndex+1, 60 String.format(this.displayMsg, rowIndex+1, 61 61 rowIndex+visibleRows, totalCount); 62 62 this.displayEl.update(msg); 63 } 63 } 64 64 }, 65 65 … … 70 70 unbind : function(view) 71 71 { 72 view.un('rowremoved', this.onRowRemoved, this); 73 view.un('rowsinserted', this.onRowsInserted, this); 74 view.un('beforebuffer', this.beforeBuffer, this); 75 view.un('cursormove', this.onCursorMove, this); 76 view.un('buffer', this.onBuffer, this); 72 view.un('rowremoved', this.onRowRemoved, this); 73 view.un('rowsinserted', this.onRowsInserted, this); 74 view.un('beforebuffer', this.beforeBuffer, this); 75 view.un('cursormove', this.onCursorMove, this); 76 view.un('buffer', this.onBuffer, this); 77 view.un('bufferfailure', this.onBufferFailure, this); 77 78 this.view = undefined; 78 79 }, … … 84 85 bind : function(view) 85 86 { 86 view.on('rowremoved', this.onRowRemoved, this); 87 view.on('rowsinserted', this.onRowsInserted, this); 88 view.on('beforebuffer', this.beforeBuffer, this); 89 view.on('cursormove', this.onCursorMove, this); 90 view.on('buffer', this.onBuffer, this); 87 view.on('rowremoved', this.onRowRemoved, this); 88 view.on('rowsinserted', this.onRowsInserted, this); 89 view.on('beforebuffer', this.beforeBuffer, this); 90 view.on('cursormove', this.onCursorMove, this); 91 view.on('buffer', this.onBuffer, this); 92 view.on('bufferfailure', this.onBufferFailure, this); 91 93 this.view = view; 92 }, 93 94 // ----------------------------------- Listeners ------------------------------- 94 }, 95 96 // ----------------------------------- Listeners ------------------------------- 95 97 onCursorMove : function(view, rowIndex, visibleRows, totalCount) 96 98 { … … 98 100 }, 99 101 100 // private 102 // private 101 103 onRowsInserted : function(view, start, end) 102 104 { 103 this.updateInfo(view.rowIndex, Math.min(view.ds.totalLength, view.visibleRows), 105 this.updateInfo(view.rowIndex, Math.min(view.ds.totalLength, view.visibleRows), 104 106 view.ds.totalLength); 105 }, 107 }, 106 108 107 // private 109 // private 108 110 onRowRemoved : function(view, index, record) 109 111 { 110 this.updateInfo(view.rowIndex, Math.min(view.ds.totalLength, view.visibleRows), 112 this.updateInfo(view.rowIndex, Math.min(view.ds.totalLength, view.visibleRows), 111 113 view.ds.totalLength); 112 }, 114 }, 113 115 114 116 // private … … 118 120 this.updateInfo(rowIndex, visibleRows, totalCount); 119 121 }, 120 122 123 // priate 124 onBufferFailure : function(view, store, options) 125 { 126 this.loading.enable(); 127 }, 128 121 129 // private 122 130 onBuffer : function(view, store, rowIndex, visibleRows, totalCount) … … 124 132 this.loading.enable(); 125 133 this.updateInfo(rowIndex, visibleRows, totalCount); 126 }, 134 }, 127 135 128 // private 136 // private 129 137 onClick : function(type) 130 138 { … … 147 155 handler : this.onClick.createDelegate(this, ["refresh"]) 148 156 }); 149 157 150 158 this.addSeparator(); 151 159 152 160 if(this.displayInfo){ 153 161 this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'}); -
trunk/src/BufferedGridView.js
r4 r6 2 2 * Ext.ux.grid.BufferedGridView V0.1 3 3 * Copyright(c) 2007, http://www.siteartwork.de 4 * 4 * 5 5 * Licensed under the terms of the Open Source LGPL 3.0 6 6 * http://www.gnu.org/licenses/lgpl.html … … 19 19 Ext.namespace('Ext.ux.grid'); 20 20 Ext.ux.grid.BufferedGridView = function(config) { 21 21 22 22 this.addEvents({ 23 23 /** … … 39 39 * @param {Number} visibleRows 40 40 * @param {Number} totalCount 41 * @param {Object} options 41 42 */ 42 43 'buffer' : true, 44 /** 45 * @event bufferfailure 46 * Fires when buffering failed. 47 * @param {Ext.ux.BufferedGridView} this 48 * @param {Ext.data.Store} store The store 49 * @param {Object} options The options the buffer-request was initiated with 50 */ 51 'bufferfailure' : true, 43 52 /** 44 53 * @event cursormove … … 48 57 * grid absolute to it's position in the model. 49 58 * @param {Number} visibleRows The number of rows visible in the grid. 50 * @param {Number} totalCount 59 * @param {Number} totalCount 51 60 */ 52 61 'cursormove' : true 53 54 }); 55 56 /** 57 * @cfg {Number} scrollDelay The number of microseconds a call to the 62 63 }); 64 65 /** 66 * @cfg {Number} scrollDelay The number of microseconds a call to the 58 67 * onLiveScroll-lisener should be delayed when the scroll event fires 59 68 */ 60 61 /** 62 * @cfg {Number} bufferSize The number of records that will at least always 69 70 /** 71 * @cfg {Number} bufferSize The number of records that will at least always 63 72 * be available in the store for rendering. This value will be send to the 64 73 * server as the <tt>limit</tt> parameter and should not change during the 65 * lifetime of a grid component. Note: In a paging grid, this number would 74 * lifetime of a grid component. Note: In a paging grid, this number would 66 75 * indicate the page size. 67 * The value should be set high enough to make a userfirendly scrolling 68 * possible and should be greater than the sum of {nearLimit} and 76 * The value should be set high enough to make a userfirendly scrolling 77 * possible and should be greater than the sum of {nearLimit} and 69 78 * {visibleRows}. Usually, a value in between 150 and 200 is good enough. 70 79 * A lesser value will more often make the store re-request new data, while 71 80 * a larger number will make loading times higher. 72 81 */ 73 82 74 83 /** 75 84 * @cfg {Number} nearLimit This value represents a near value that is responsible 76 * for deciding if a request for new data is needed. The lesser the number, the 85 * for deciding if a request for new data is needed. The lesser the number, the 77 86 * more often new data will be requested. The number should be set to a value 78 87 * that lies in between 1/4 to 1/2 of the {bufferSize}. 79 88 */ 80 81 /** 82 * @cfg {Number} horizontalScrollOffset The height of a horizontal aligned 83 * scrollbar. The scrollbar is shown if the total width of all visible 84 * columns exceeds the width of the grid component. 89 90 /** 91 * @cfg {Number} horizontalScrollOffset The height of a horizontal aligned 92 * scrollbar. The scrollbar is shown if the total width of all visible 93 * columns exceeds the width of the grid component. 85 94 * On Windows XP (IE7, FF2), this value defaults to 16. 86 95 */ 87 this.horizontalScrollOffset = 16; 88 96 this.horizontalScrollOffset = 16; 97 89 98 /** 90 99 * @cfg {Object} loadMaskConfig The config of the load mask that will be shown … … 92 101 */ 93 102 this.loadMask = false; 94 103 95 104 Ext.apply(this, config); 96 105 … … 109 118 '<div class="x-grid3-resize-proxy"> </div>', 110 119 "</div>" 111 ); 112 120 ); 121 113 122 Ext.ux.grid.BufferedGridView.superclass.constructor.call(this); 114 123 }; … … 117 126 Ext.extend(Ext.ux.grid.BufferedGridView, Ext.grid.GridView, { 118 127 119 // {{{ --------------------------properties------------------------------------- 128 // {{{ --------------------------properties------------------------------------- 120 129 /** 121 130 * This is the actual y-scroller that does control sending request to the server … … 124 133 */ 125 134 liveScroller : null, 126 135 127 136 /** 128 137 * This is the panel that represents the amount of data in a given repository. … … 132 141 */ 133 142 liveScrollerInset : null, 134 135 /** 136 * The <b>fixed</b> row height for <b>every</b> row in the grid. The value is 143 144 /** 145 * The <b>fixed</b> row height for <b>every</b> row in the grid. The value is 137 146 * computed once the store has been loaded for the first time and used for 138 147 * various calculations during the lifetime of the grid component, such as … … 141 150 */ 142 151 rowHeight : -1, 143 152 144 153 /** 145 154 * Stores the number of visible rows that have to be rendered. … … 147 156 */ 148 157 visibleRows : 1, 149 150 /** 151 * Stores the last offset relative to a previously scroll action. This is 158 159 /** 160 * Stores the last offset relative to a previously scroll action. This is 152 161 * needed for deciding wether the user scrolls up or down. 153 162 * @param {Number} 154 163 */ 155 164 lastIndex : -1, 156 165 157 166 /** 158 167 * Stores the last visible row at position "0" in the table view before … … 161 170 */ 162 171 lastRowIndex : 0, 163 164 /** 165 * Stores the value of the <tt>liveScroller</tt>'s <tt>scrollTop</tt> DOM 172 173 /** 174 * Stores the value of the <tt>liveScroller</tt>'s <tt>scrollTop</tt> DOM 166 175 * property. 167 176 * @param {Number} 168 177 */ 169 178 lastScrollPos : 0, 170 171 /** 172 * The current index of the row in the model that is displayed as the first 179 180 /** 181 * The current index of the row in the model that is displayed as the first 173 182 * visible row in the view. 174 183 * @param {Number} 175 184 */ 176 rowIndex : 0, 177 185 rowIndex : 0, 186 178 187 /** 179 188 * Set to <tt>true</tt> if the store is busy with loading new data. … … 181 190 */ 182 191 isBuffering : false, 183 192 184 193 /** 185 194 * If a request for new data was made and the user scrolls to a new position 186 * that lays not within the requested range of the new data, the queue will 195 * that lays not within the requested range of the new data, the queue will 187 196 * hold the latest requested position. If the buffering succeeds and the value 188 197 * of requestQueue is not within the range of the current buffer, data may be … … 192 201 */ 193 202 requestQueue : -1, 194 203 195 204 /** 196 205 * The view's own load mask that will be shown when a request to data was made … … 200 209 */ 201 210 loadMask : null, 202 211 203 212 /** 204 213 * Set to <tt>true</tt> if a request for new data has been made while there … … 213 222 214 223 /** 215 * Resets the view to display the first row in the data model. This will 224 * Resets the view to display the first row in the data model. This will 216 225 * change the scrollTop property of the scroller and may trigger a request 217 226 * to buffer new data, if the row index "0" is not within the buffer range and … … 234 243 this.refresh(true); 235 244 //this.replaceLiveRows(0, true); 236 this.fireEvent('cursormove', this, 0, 237 Math.min(this.ds.totalLength, this.visibleRows), 245 this.fireEvent('cursormove', this, 0, 246 Math.min(this.ds.totalLength, this.visibleRows), 238 247 this.ds.totalLength); 239 248 } else { 240 249 241 250 var params = { 242 start : 0, 251 start : 0, 243 252 limit : this.ds.bufferSize 244 253 }; 245 254 246 255 var sInfo = this.ds.sortInfo; 247 256 248 257 if (sInfo) { 249 258 params.dir = sInfo.direction; 250 259 params.sort = sInfo.field; 251 260 } 252 261 253 262 this.ds.load({ 254 263 callback : function(){this.reset(false);}, 255 scope : this, 264 scope : this, 256 265 params : params 257 266 }); 258 267 } 259 268 260 269 }, 261 270 … … 266 275 * 267 276 * Since detaching a previously created DragZone from a grid panel seems to 268 * be impossible, a little workaround will tell the parent implementation 277 * be impossible, a little workaround will tell the parent implementation 269 278 * that drad/drop is not enabled for this view's grid, and right after that 270 279 * the custom DragZone will be created, if neccessary. … … 274 283 var g = this.grid; 275 284 var dEnabled = g.enableDragDrop || g.enableDrag; 276 285 277 286 g.enableDragDrop = false; 278 287 g.enableDrag = false; 279 288 280 289 Ext.ux.grid.BufferedGridView.superclass.renderUI.call(this); 281 290 282 291 var g = this.grid; 283 292 284 293 g.enableDragDrop = dEnabled; 285 294 g.enableDrag = dEnabled; 286 295 287 296 if(dEnabled){ 288 297 var dd = new Ext.ux.grid.BufferedGridDragZone(g, { … … 290 299 }); 291 300 } 292 293 301 302 294 303 if (this.loadMask) { 295 304 this.loadMask = new Ext.LoadMask( 296 this.mainBody.dom.parentNode.parentNode, 305 this.mainBody.dom.parentNode.parentNode, 297 306 this.loadMask 298 ); 307 ); 299 308 } 300 309 }, … … 312 321 { 313 322 Ext.ux.grid.BufferedGridView.superclass.init.call(this, grid); 314 323 315 324 this.ds.on('beforeload', this.onBeforeLoad, this); 316 }, 317 318 325 }, 326 327 319 328 /** 320 329 * Only render the viewable rect of the table. The number of rows visible to … … 328 337 return this.templates.body.apply({rows: markup}); 329 338 }, 330 331 /** 332 * Inits the DOM native elements for this component. 339 340 /** 341 * Inits the DOM native elements for this component. 333 342 * The properties <tt>liveScroller</tt> and <tt>liveScrollerInset</tt> will 334 343 * be respected as provided by the master template. 335 * The <tt>scroll</tt> listener for the <tt>liverScroller</tt> will also be 344 * The <tt>scroll</tt> listener for the <tt>liverScroller</tt> will also be 336 345 * added here as the <tt>mousewheel</tt> listener. 337 346 * This method overwrites the parents implementation. … … 348 357 349 358 this.mainWrap = new E(cs[1]); 350 359 351 360 // liveScroller and liveScrollerInset 352 361 this.liveScroller = new E(cs[0]); 353 362 this.liveScrollerInset = this.liveScroller.dom.firstChild; 354 363 this.liveScroller.on('scroll', this.onLiveScroll, this, {buffer : this.scrollDelay}); 355 364 356 365 this.mainHd = new E(this.mainWrap.dom.firstChild); 357 366 this.innerHd = this.mainHd.dom.firstChild; … … 364 373 // addd the mousewheel event to the table's body 365 374 this.mainBody.on('mousewheel', this.handleWheel, this); 366 375 367 376 this.focusEl = new E(this.scroller.dom.childNodes[1]); 368 377 this.focusEl.swallowEvent("click", true); … … 371 380 this.resizeProxy = new E(cs[3]); 372 381 373 }, 374 382 }, 383 375 384 /** 376 385 * Layouts the grid's view taking the scroller into account. The height … … 378 387 * The width of the grid view will be adjusted so the header and the rows do 379 388 * not overlap the scroller. 380 * This method will also compute the row-height based on the first row this 381 * grid displays and will adjust the number of visible rows if a resize 389 * This method will also compute the row-height based on the first row this 390 * grid displays and will adjust the number of visible rows if a resize 382 391 * of the grid component happened. 383 392 * This method overwrites the parents implementation. 384 393 */ 385 //private 394 //private 386 395 layout : function() 387 396 { … … 395 404 396 405 var csize = c.getSize(true); 397 406 398 407 // set vw to 19 to take scrollbar width into account! 399 408 var vw = csize.width-this.scrollOffset; 400 409 401 410 if(vw < 20 || csize.height < 20){ // display: none? 402 411 return; … … 416 425 } 417 426 } 418 427 419 428 if(this.forceFit){ 420 429 if(this.lastViewWidth != vw){ … … 425 434 this.autoExpand(); 426 435 } 427 428 436 437 429 438 // adjust the number of visible rows and the height of the scroller. 430 439 this.adjustVisibleRows(); 431 440 this.adjustBufferInset(); 432 433 441 442 434 443 this.onLayout(vw, vh); 435 }, 444 }, 436 445 437 446 // {{{ ----------------------dom/mouse listeners-------------------------------- 447 448 // private 449 onColumnMove : function(cm, oldIndex, newIndex) 450 { 451 this.indexMap = null; 452 this.replaceLiveRows(this.rowIndex, true); 453 this.updateHeaders(); 454 this.updateHeaderSortState(); 455 this.afterMove(newIndex); 456 }, 457 458 438 459 /** 439 460 * Called when a column width has been updated. Adjusts the scroller height … … 444 465 { 445 466 this.adjustVisibleRows(); 446 this.adjustBufferInset(); 447 }, 448 449 /** 450 * Called when the width of all columns has been updated. Adjusts the scroller 467 this.adjustBufferInset(); 468 }, 469 470 /** 471 * Called when the width of all columns has been updated. Adjusts the scroller 451 472 * height and the number of visible rows wether the horizontal scrollbar is shown 452 473 * or not. … … 456 477 this.adjustVisibleRows(); 457 478 this.adjustBufferInset(); 458 }, 459 460 /** 461 * Callback for selecting a row. The index of the row is the absolute index 479 }, 480 481 /** 482 * Callback for selecting a row. The index of the row is the absolute index 462 483 * in the datamodel and gets translated to the index in the view. 463 484 * Overwrites the parent's implementation. 464 */ 485 */ 465 486 // private 466 487 onRowSelect : function(row) … … 469 490 return; 470 491 } 471 492 472 493 var viewIndex = row-this.rowIndex; 473 494 474 495 this.addRowClass(viewIndex, "x-grid3-row-selected"); 475 496 }, 476 497 477 498 /** 478 * Callback for deselecting a row. The index of the row is the absolute index 499 * Callback for deselecting a row. The index of the row is the absolute index 479 500 * in the datamodel and gets translated to the index in the view. 480 501 * Overwrites the parent's implementation. 481 */ 502 */ 482 503 // private 483 504 onRowDeselect : function(row) … … 486 507 return; 487 508 } 488 509 489 510 var viewIndex = row-this.rowIndex; 490 511 491 512 this.removeRowClass(viewIndex, "x-grid3-row-selected"); 492 513 }, 493 514 494 515 /** 495 * Callback for selecting a cell. The index of the row is the absolute index 516 * Callback for selecting a cell. The index of the row is the absolute index 496 517 * in the datamodel and gets translated to the index in the view. 497 518 * Overwrites the parent's implementation. 498 */ 519 */ 499 520 // private 500 521 onCellSelect : function(row, col) … … 503 524 return; 504 525 } 505 526 506 527 var viewIndex = row-this.rowIndex; 507 528 508 529 var cell = this.getCell(viewIndex, col); 509 530 if(cell){ … … 513 534 514 535 /** 515 * Callback for deselecting a cell. The index of the row is the absolute index 536 * Callback for deselecting a cell. The index of the row is the absolute index 516 537 * in the datamodel and gets translated to the index in the view. 517 538 * Overwrites the parent's implementation. 518 */ 539 */ 519 540 // private 520 541 onCellDeselect : function(row, col) … … 523 544 return; 524 545 } 525 546 526 547 var viewIndex = row-this.rowIndex; 527 548 528 549 var cell = this.getCell(viewIndex, col); 529 550 if(cell){ … … 537 558 * view. 538 559 * Overwrites the parent's implementation. 539 */ 560 */ 540 561 // private 541 562 onRowOver : function(e, t) … … 562 583 this.removeRowClass(viewIndex, "x-grid3-row-over"); 563 584 } 564 }, 585 }, 565 586 566 587 … … 577 598 }, 578 599 579 580 /** 581 * Callback for the underlying store's remove method. The current 582 * implementation does only remove the selected row which record is in the 600 601 /** 602 * Callback for the underlying store's remove method. The current 603 * implementation does only remove the selected row which record is in the 583 604 * current store. 584 605 * … … 587 608 onRemove : function(ds, record, index, isUpdate) 588 609 { 610 589 611 if (index == Number.MIN_VALUE || index == Number.MAX_VALUE) { 590 612 this.fireEvent("beforerowremoved", this, index, record); … … 597 619 this.fireEvent("beforerowremoved", this, viewIndex, record); 598 620 } 599 621 600 622 var domLength = this.getRows().length; 601 623 602 624 if (viewIndex < this.rowIndex) { 603 // if the according row is not displayed within the visible rect of 625 // if the according row is not displayed within the visible rect of 604 626 // the grid, just adjust the row index and the liveScroller 605 627 this.rowIndex--; 606 628 this.lastRowIndex = this.rowIndex; 607 629 this.adjustScrollerPos(-this.rowHeight, true); 608 this.fireEvent('cursormove', this, this.rowIndex, 609 Math.min(this.ds.totalLength, this.visibleRows), 630 this.fireEvent('cursormove', this, this.rowIndex, 631 Math.min(this.ds.totalLength, this.visibleRows), 610 632 this.ds.totalLength); 611 633 612 634 } else if (viewIndex >= this.rowIndex && viewIndex < this.rowIndex+domLength) { 613 635 614 636 var lastPossibleRIndex = ((this.rowIndex-this.ds.bufferRange[0])+this.visibleRows)-1; 615 637 616 638 var cInd = viewIndex-this.rowIndex; 617 639 var rec = this.ds.getAt(this.rowIndex+this.visibleRows-1); 618 640 619 641 // did we reach the end of the buffer range? 620 642 if (rec == null) { … … 625 647 } 626 648 this.updateLiveRows(this.rowIndex, true, true); 627 649 628 650 return; 629 651 } else { … … 631 653 // nor in the data store 632 654 if (this.rowIndex == 0) { 633 // simply remove the row from the dom655 // simply remove the row from the end of the dom dom 634 656 this.removeRows(cInd, cInd); 635 657 636 658 } else { 637 // scroll a new row in the rect so the whole rect is filled 659 // scroll a new row in the rect so the whole rect is filled 638 660 // with rows 639 661 this.rowIndex--; 662 this.lastRowIndex = this.rowIndex; 640 663 if (this.rowIndex < this.ds.bufferRange[0]) { 641 664 // buffer range is invalid! request new data … … 644 667 } 645 668 this.updateLiveRows(this.rowIndex); 646 669 647 670 return; 648 671 } else { 649 // still records in the store, simply update the dom 650 this.replaceLiveRows(this.rowIndex); 651 672 // still records in the store, simply update the dom, 673 //but leave processing to this method after the event rowremoved 674 // was fired so the selection store can update properly 675 this.replaceLiveRows(this.rowIndex, true, false); 652 676 } 653 677 } 654 678 } 655 679 } else { 656 680 657 681 // the record is right within the visible rect of the grid. 658 682 // remove the row that represents the record and append another … … 662 686 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html); 663 687 } 664 } 665 688 } 689 666 690 // a record within the bufferrange was removed, so adjust the buffer 667 691 // range … … 671 695 this.fireEvent("rowremoved", this, viewIndex, record); 672 696 } 673 697 674 698 this.processRows(0, undefined, true); 675 699 }, 676 700 677 701 /** 678 * The callback for the underlying data store when new data was added. 679 * If <tt>index</tt> equals to <tt>Number.MIN_VALUE</tt> or <tt>Number.MAX_VALUE</tt>, the 702 * The callback for the underlying data store when new data was added. 703 * If <tt>index</tt> equals to <tt>Number.MIN_VALUE</tt> or <tt>Number.MAX_VALUE</tt>, the 680 704 * method can't tell at which position in the underlying data model the 681 * records where added. However, if <tt>index</tt> equals to <tt>Number.MIN_VALUE</tt>, 705 * records where added. However, if <tt>index</tt> equals to <tt>Number.MIN_VALUE</tt>, 682 706 * the <tt>rowIndex</tt> property will be adjusted to <tt>rowIndex+records.length</tt>, 683 707 * and the <tt>liveScroller</tt>'s properties get adjusted so it matches the … … 685 709 * The same will happen to any records that get added at the store index which 686 710 * is currently represented by the first visible row in the view. 687 * Any other value will cause the method to compute the number of rows that 711 * Any other value will cause the method to compute the number of rows that 688 712 * have to be (re-)painted and calling the <tt>insertRows</tt> method, if 689 713 * neccessary. 690 714 * 691 715 * This method triggers the <tt>beforerowsinserted</tt> and <tt>rowsinserted</tt> 692 * event, passing the indexes of the records as they may default to the 693 * positions in the underlying data model. However, due to the fact that 716 * event, passing the indexes of the records as they may default to the 717 * positions in the underlying data model. However, due to the fact that 694 718 * any sort algorithm may have computed the indexes of the records, it is 695 * not guaranteed that the computed indexes equal to the indexes of the 719 * not guaranteed that the computed indexes equal to the indexes of the 696 720 * underlying data model. 697 721 * 698 722 * @param {Ext.ux.grid.BufferedStore} ds The datastore that buffers records 699 723 * from the underlying data model 700 * @param {Array} records An array containing the newly added 701 * {@link Ext.data.Record}s 724 * @param {Array} records An array containing the newly added 725 * {@link Ext.data.Record}s 702 726 * @param {Number} index The index of the position in the underlying 703 727 * {@link Ext.ux.grid.BufferedStore} where the rows … … 708 732 { 709 733 var recordLen = records.length; 710 711 // values of index which equal to Number.MIN_VALUE or Number.MAX_VALUE 712 // indicate that the records were not added to the store. The component 734 735 // values of index which equal to Number.MIN_VALUE or Number.MAX_VALUE 736 // indicate that the records were not added to the store. The component 713 737 // does not know which index those records do have in the underlying 714 738 // data model 715 739 if (index == Number.MAX_VALUE || index == Number.MIN_VALUE) { 716 740 this.fireEvent("beforerowsinserted", this, index, index); 717 741 718 742 // if index equals to Number.MIN_VALUE, shift rows! 719 743 if (index == Number.MIN_VALUE) { 720 744 721 745 this.rowIndex = this.rowIndex + recordLen; 722 746 this.lastRowIndex = this.rowIndex; 723 724 this.adjustBufferInset(); 747 748 this.adjustBufferInset(); 725 749 this.adjustScrollerPos(this.rowHeight*recordLen, true); 726 750 727 751 this.fireEvent("rowsinserted", this, index, index); 728 752 this.processRows(); 729 753 // the cursor did virtually move 730 this.fireEvent('cursormove', this, this.rowIndex, 731 Math.min(this.ds.totalLength, this.visibleRows), 754 this.fireEvent('cursormove', this, this.rowIndex, 755 Math.min(this.ds.totalLength, this.visibleRows), 732 756 this.ds.totalLength); 733 757 734 758 return; 735 759 } 736 760 737 761 this.adjustBufferInset(); 738 762 this.fireEvent("rowsinserted", this, index, index); 739 return; 740 } 741 763 return; 764 } 765 742 766 // only insert the rows which affect the current view. 743 767 var start = index+this.ds.bufferRange[0]; 744 768 var end = start + (recordLen-1); 745 769 var len = this.getRows().length; 746 770 747 771 var firstRow = 0; 748 772 var lastRow = 0; 749 750 // rows would be added at the end of the rows which are currently 773 774 // rows would be added at the end of the rows which are currently 751 775 // displayed, so fire the evnt and return 752 776 if (index >= (this.rowIndex-this.ds.bufferRange[0])+len && len == this.visibleRows) { 753 this.fireEvent("beforerowsinserted", this, start, end); 754 this.fireEvent("rowsinserted", this, start, end); 755 777 this.fireEvent("beforerowsinserted", this, start, end); 778 this.fireEvent("rowsinserted", this, start, end); 779 756 780 this.adjustVisibleRows(); 757 781 this.adjustBufferInset(); 758 759 } 760 782 783 } 784 761 785 // we are all up in the grid, first row is first record, 762 786 // prepend! … … 767 791 this.rowIndex = 0; 768 792 this.insertRows(ds, firstRow, lastRow); 769 793 770 794 this.adjustVisibleRows(); 771 795 this.adjustBufferInset(); 772 796 } 773 797 774 798 // rows get added before the first row in the view 775 799 else if (len == this.visibleRows && index <= this.rowIndex-this.ds.bufferRange[0]) { 776 777 this.fireEvent("beforerowsinserted", this, start, end); 800 801 this.fireEvent("beforerowsinserted", this, start, end); 778 802 this.liveScroller.un('scroll', this.onLiveScroll, this); 779 803 this.rowIndex = this.rowIndex+recordLen; 780 804 this.lastRowIndex = this.rowIndex; 781 805 782 806 this.adjustVisibleRows(); 783 807 this.adjustBufferInset(); 784 808 785 809 this.adjustScrollerPos(this.rowHeight*recordLen, true); 786 787 this.fireEvent("rowsinserted", this, start, end); 810 811 this.fireEvent("rowsinserted", this, start, end); 788 812 this.processRows(); 789 this.fireEvent('cursormove', this, this.rowIndex, 790 Math.min(this.ds.totalLength, this.visibleRows), 791 this.ds.totalLength); 792 } 793 813 this.fireEvent('cursormove', this, this.rowIndex, 814 Math.min(this.ds.totalLength, this.visibleRows), 815 this.ds.totalLength); 816 } 817 794 818 // rows get added somewhere IN the current view 795 819 else if ((len < this.visibleRows ) || index > this.rowIndex-this.ds.bufferRange[0]) { 796 820 firstRow = index; 797 821 lastRow = Math.min(end, this.rowIndex+this.visibleRows-1) - this.ds.bufferRange[0]; 798 this.insertRows(ds, firstRow, lastRow); 799 822 this.insertRows(ds, firstRow, lastRow); 823 800 824 this.adjustVisibleRows(); 801 825 this.adjustBufferInset(); 802 803 } 804 805 806 807 808 }, 809 810 // {{{ ----------------------store listeners------------------------------------ 826 827 } 828 829 830 831 832 }, 833 834 // {{{ ----------------------store listeners------------------------------------ 811 835 /** 812 836 * This callback for the store's "beforeload" event will adjust the start 813 837 * position and the limit of the data in the model to fetch. It is guaranteed 814 * that this method will only be called when the store initially loads, 838 * that this method will only be called when the store initially loads, 815 839 * remeote-sorts or reloads. 816 840 * All other load events will be suspended when the view requests buffer data. … … 824 848 { 825 849 if (!options.params) { 826 options.params = {start : 0, limit : this.ds.bufferSize}; 850 options.params = {start : 0, limit : this.ds.bufferSize}; 827 851 } else { 828 852 options.params.start = 0; 829 853 options.params.limit = this.ds.bufferSize; 830 854 } 831 855 832 856 options.scope = this; 833 857 options.callback = function(){this.reset(false);}; 834 858 835 859 return true; 836 860 }, 837 861 838 862 /** 839 863 * Method is used as a callback for the load-event of the attached data store. 840 * Adjusts the buffer inset based upon the <tt>totalCount</tt> property 864 * Adjusts the buffer inset based upon the <tt>totalCount</tt> property 841 865 * returned by the response. 842 866 * Overwrites the parent's implementation. … … 846 870 this.adjustBufferInset(); 847 871 }, 848 849 /** 850 * This will be called when the data in the store has changed, i.e. a 851 * re-buffer has occured. If the table was not rendered yet, a call to 852 * <tt>refresh</tt> will initially render the table, which DOM elements will 872 873 /** 874 * This will be called when the data in the store has changed, i.e. a 875 * re-buffer has occured. If the table was not rendered yet, a call to 876 * <tt>refresh</tt> will initially render the table, which DOM elements will 853 877 * then be used to re-render the table upon scrolling. 854 878 * … … 858 882 { 859 883 this.updateHeaderSortState(); 860 }, 861 884 }, 885 862 886 /** 863 887 * A callback for the store when new data has been buffered successfully. 864 * If the current row index is not within the range of the newly created 865 * data buffer or another request to new data has been made while the store 888 * If the current row index is not within the range of the newly created 889 * data buffer or another request to new data has been made while the store 866 890 * was loading, new data will be re-requested. 867 891 * … … 869 893 * in the data store, the method will request the pending selections from 870 894 * the grid's selection model and add them to the selections if available. 871 * This is because the component assumes that a user who scrolls through the 872 * rows and updates the view's buffer during scrolling, can check the selected 873 * rows which come into the view for integrity. It is up to the user to 895 * This is because the component assumes that a user who scrolls through the 896 * rows and updates the view's buffer during scrolling, can check the selected 897 * rows which come into the view for integrity. It is up to the user to 874 898 * deselect those rows not matchuing the selection. 875 899 * Additionally, if the version of the store changes during various requests 876 * and selections are still pending, the versionchange event of the store 877 * can delete the pending selections after a re-bufer happened and before this 900 * and selections are still pending, the versionchange event of the store 901 * can delete the pending selections after a re-bufer happened and before this 878 902 * method was called. 879 903 * 880 904 */ 881 905 // private 882 liveBufferUpdate : function(o1, options, o2) 883 { 884 this.fireEvent('buffer', this, this.ds, this.rowIndex, 885 Math.max(this.visibleRows, this.getRows().length), 886 this.ds.getTotalCount()); 906 liveBufferUpdate : function(records, options, success) 907 { 908 if (success === true) { 909 this.fireEvent('buffer', this, this.ds, this.rowIndex, 910 Math.max(this.visibleRows, this.getRows().length), 911 this.ds.getTotalCount(), 912 options 913 ); 914 915 this.isBuffering = false; 916 this.isPrebuffering = false; 917 this.showLoadMask(false); 918 919 var pendingSelections = this.grid.selModel.getPendingSelections(false); 920 921 for (var i = 0, max_i = pendingSelections.length; i < max_i; i++) { 922 this.grid.selModel.clearPendingSelection(pendingSelections[i]); 923 } 924 925 if (this.isInRange(this.rowIndex)) { 926 this.replaceLiveRows(this.rowIndex); 927 } else { 928 this.updateLiveRows(this.rowIndex); 929 } 930 931 if (this.requestQueue >= 0) { 932 var offset = this.requestQueue; 933 this.requestQueue = -1; 934 this.updateLiveRows(offset); 935 } 936 937 return; 938 } else { 939 this.fireEvent('bufferfailure', this, this.ds, options); 940 } 941 942 this.requestQueue = -1; 887 943 this.isBuffering = false; 888 944 this.isPrebuffering = false; 889 945 this.showLoadMask(false); 890 891 var pendingSelections = this.grid.selModel.getPendingSelections(false); 892 893 for (var i = 0, max_i = pendingSelections.length; i < max_i; i++) { 894 this.grid.selModel.clearPendingSelection(pendingSelections[i]); 895 } 896 897 if (this.isInRange(this.rowIndex)) { 898 this.replaceLiveRows(this.rowIndex); 899 } else { 900 this.updateLiveRows(this.rowIndex); 901 } 902 903 if (this.requestQueue >= 0) { 904 var offset = this.requestQueue; 905 this.requestQueue = -1; 906 this.updateLiveRows(offset); 907 } 908 }, 909 910 911 // {{{ ----------------------scroll listeners------------------------------------ 946 }, 947 948 949 // {{{ ----------------------scroll listeners------------------------------------ 912 950 /** 913 951 * Handles mousewheel event on the table's body. This is neccessary since the … … 919 957 { 920 958 if (this.rowHeight == -1) { 921 e.stopEvent(); 959 e.stopEvent(); 922 960 return; 923 961 } 924 962 var d = e.getWheelDelta(); 925 963 926 964 this.adjustScrollerPos(-(d*this.rowHeight)); 927 928 e.stopEvent(); 929 }, 930 965 966 e.stopEvent(); 967 }, 968 931 969 /** 932 970 * Handles scrolling through the grid. Since the grid is fixed and rows get … … 938 976 onLiveScroll : function() 939 977 { 940 var scrollTop = this.liveScroller.dom.scrollTop; 941 978 var scrollTop = this.liveScroller.dom.scrollTop; 979 942 980 var cursor = Math.floor((scrollTop)/this.rowHeight); 943 981 this.rowIndex = cursor; … … 946 984 return; 947 985 } 948 986 949 987 this.updateLiveRows(cursor); 950 this.lastScrollPos = this.liveScroller.dom.scrollTop; 951 }, 952 953 954 988 this.lastScrollPos = this.liveScroller.dom.scrollTop; 989 }, 990 991 992 955 993 // {{{ --------------------------helpers---------------------------------------- 956 994 … … 965 1003 index = ds.indexOf(record); 966 1004 } 967 1005 968 1006 var viewIndex = index + this.ds.bufferRange[0]; 969 1007 970 1008 if (viewIndex < this.rowIndex || viewIndex >= this.rowIndex + this.visibleRows) { 971 1009 this.fireEvent("rowupdated", this, viewIndex, record); 972 1010 return; 973 1011 } 974 1012 975 1013 this.insertRows(ds, index, index, true); 976 1014 //this.getRow(index).rowIndex = index; … … 994 1032 var cls = ' x-grid3-row-alt '; 995 1033 var cursor = this.rowIndex; 996 1034 997 1035 var index = 0; 998 1036 var selections = this.grid.selModel.selections; … … 1003 1041 // changed! 1004 1042 row.rowIndex = index; 1005 1043 1006 1044 if (paintSelections == true) { 1007 1045 if (this.grid.selModel.bufferedSelections[index] === true) { 1008 1046 this.addRowClass(i, "x-grid3-row-selected"); 1009 selections.add(ds.getAt(index));1010 1047 } 1011 1048 this.fly(row).removeClass("x-grid3-row-over"); 1012 1049 } 1013 1050 1014 1051 if(!skipStripe){ 1015 1052 var isAlt = ((i+1) % 2 == 0); … … 1029 1066 /** 1030 1067 * API only, since the passed arguments are the indexes in the buffer store. 1031 * However, the method will try to compute the indexes so they might match 1068 * However, the method will try to compute the indexes so they might match 1032 1069 * the indexes of the records in the underlying data model. 1033 1070 * … … 1038 1075 var viewIndexFirst = firstRow + this.ds.bufferRange[0]; 1039 1076 var viewIndexLast = lastRow + this.ds.bufferRange[0]; 1040 1077 1041 1078 if (!isUpdate) { 1042 1079 this.fireEvent("beforerowsinserted", this, viewIndexFirst, viewIndexLast); 1043 1080 } 1044 1045 // first off, remove the rows at the bottom of the view to match the 1081 1082 // first off, remove the rows at the bottom of the view to match the 1046 1083 // visibleRows value and to not cause any spill in the DOM 1047 1084 if (isUpdate !== true && this.getRows().length == this.visibleRows) { 1048 1085 this.removeRows((this.visibleRows-1)-(lastRow-firstRow), this.visibleRows-1); 1049 1086 } 1050 1087 1051 1088 if (isUpdate) { 1052 1089 this.removeRows(viewIndexFirst-this.rowIndex, viewIndexLast-this.rowIndex); 1053 1090 } 1054 1091 1055 1092 var html = this.renderRows(firstRow, lastRow); 1056 1093 1057 1094 var before = this.getRow(firstRow-(this.rowIndex-this.ds.bufferRange[0])); 1058 1095 1059 1096 if (before) { 1060 1097 Ext.DomHelper.insertHtml('beforeBegin', before, html); … … 1062 1099 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html); 1063 1100 } 1064 1065 1066 1101 1102 1103 1067 1104 if (isUpdate === true) { 1068 1105 var rows = this.getRows(); 1069 1106 var cursor = this.rowIndex; 1070 1107 for (var i = 0, max_i = rows.length; i < max_i; i++) { 1071 rows[i].rowIndex = cursor+i; 1072 } 1073 } 1074 1108 rows[i].rowIndex = cursor+i; 1109 } 1110 } 1111 1075 1112 if (!isUpdate) { 1076 1113 this.fireEvent("rowsinserted", this, viewIndexFirst, viewIndexLast); … … 1078 1115 } 1079 1116 }, 1080 1117 1081 1118 /** 1082 1119 * Focuses the specified cell. … … 1091 1128 } 1092 1129 this.focusEl.setXY(xy); 1093 1130 1094 1131 if(Ext.isGecko){ 1095 1132 this.focusEl.focus(); … … 1097 1134 this.focusEl.focus.defer(1, this.focusEl); 1098 1135 } 1099 1136 1100 1137 }, 1101 1138 … … 1112 1149 row = row.rowIndex; 1113 1150 } 1114 1151 1115 1152 if(row < 0 || row >= this.ds.totalLength){ 1116 1153 return; 1117 1154 } 1118 1155 1119 1156 col = (col !== undefined ? col : 0); 1120 1157 1121 1158 var rowInd = row-this.rowIndex; 1122 1159 if (row >= this.rowIndex+this.visibleRows) { … … 1124 1161 } else if (row <= this.rowIndex) { 1125 1162 this.adjustScrollerPos((rowInd)*this.rowHeight); 1126 } 1163 } 1127 1164 var rowInd = rowInd < 0 ? row : rowInd; 1128 1165 var rowEl = this.getRow(rowInd), cellEl; 1129 1166 1130 1167 if(!(hscroll === false && col === 0)){ 1131 1168 while(this.cm.isHidden(col)){ … … 1137 1174 return; 1138 1175 } 1139 1176 1140 1177 var c = this.scroller.dom; 1141 1142 return cellEl ? 1143 Ext.fly(cellEl).getXY() : 1178 1179 return cellEl ? 1180 Ext.fly(cellEl).getXY() : 1144 1181 [c.scrollLeft+this.el.getX(), Ext.fly(rowEl).getY()]; 1145 }, 1146 1147 1148 /** 1149 * Checks if the passed argument <tt>cursor</tt> lays within a renderable 1150 * area. The area is renderable, if the sum of cursor and the visibleRows 1182 }, 1183 1184 1185 /** 1186 * Checks if the passed argument <tt>cursor</tt> lays within a renderable 1187 * area. The area is renderable, if the sum of cursor and the visibleRows 1151 1188 * property does not exceed the current upper buffer limit. 1152 1189 * … … 1163 1200 isInRange : function(rowIndex) 1164 1201 { 1165 var lastRowIndex = Math.min(this.ds.totalLength-1, 1202 var lastRowIndex = Math.min(this.ds.totalLength-1, 1166 1203 rowIndex + this.visibleRows); 1167 return (rowIndex >= this.ds.bufferRange[0]) && 1168 (lastRowIndex <= this.ds.bufferRange[1]); 1169 }, 1170 1171 /** 1172 * Calculates the bufferRange start index for a buffer request 1204 return (rowIndex >= this.ds.bufferRange[0]) && 1205 (lastRowIndex <= this.ds.bufferRange[1]); 1206 }, 1207 1208 /** 1209 * Calculates the bufferRange start index for a buffer request 1173 1210 * 1174 1211 * @param {Boolean} inRange If the index is within the current buffer range … … 1184 1221 return Math.max(0, (index-this.ds.bufferSize)+this.visibleRows); 1185 1222 } 1186 1223 1187 1224 if (down) { 1188 1225 return Math.max(0, Math.min(index, this.ds.totalLength-this.ds.bufferSize)); 1189 1226 } 1190 1227 }, 1191 1192 1193 /** 1194 * Updates the table view. Removes/appends rows as needed and fetches the 1228 1229 1230 /** 1231 * Updates the table view. Removes/appends rows as needed and fetches the 1195 1232 * cells content out of the available store. If the needed rows are not within 1196 1233 * the buffer, the method will advise the store to update it's contents. … … 1200 1237 * 1201 1238 * @param {Number} cursor The row's position, absolute to it's position in the 1202 * data model 1203 * 1204 */ 1205 updateLiveRows: function(index, forceRepaint, forceReload) 1206 { 1207 this.fireEvent('cursormove', this, index, 1208 Math.min(this.ds.totalLength, this.visibleRows), 1239 * data model 1240 * 1241 */ 1242 updateLiveRows: function(index, forceRepaint, forceReload) 1243 { 1244 this.fireEvent('cursormove', this, index, 1245 Math.min(this.ds.totalLength, this.visibleRows), 1209 1246 this.ds.totalLength); 1210 1247 1211 1248 var inRange = this.isInRange(index); 1212 1249 1213 1250 if (this.isBuffering && this.isPrebuffering) { 1214 1251 if (inRange) { 1215 this.replaceLiveRows(index); 1252 this.replaceLiveRows(index); 1216 1253 } else { 1217 1254 this.showLoadMask(true); … … 1222 1259 return; 1223 1260 } 1224 1261 1225 1262 var lastIndex = this.lastIndex; 1226 1263 this.lastIndex = index; 1227 1264 var inRange = this.isInRange(index); 1228 1265 1229 1266 var down = false; 1230 1267 1231 1268 if (inRange && forceReload !== true) { 1232 1233 // repaint the table's view 1269 1270 // repaint the table's view 1234 1271 this.replaceLiveRows(index, forceRepaint); 1235 1236 // lets decide if we can void this method or stay in here for 1272 1273 // lets decide if we can void this method or stay in here for 1237 1274 // requesting a buffer update 1238 1275 if (index > lastIndex) { // scrolling down 1239 1276 1240 1277 down = true; 1241 1278 var totalCount = this.ds.totalLength; 1242 1279 1243 1280 // while scrolling, we have not yet reached the row index 1244 1281 // that would trigger a re-buffer … … 1246 1283 return; 1247 1284 } 1248 1285 1249 1286 // If we have already buffered the last range we can ever get 1250 1287 // by the queried data repository, we don't need to buffer again. … … 1255 1292 } 1256 1293 } else if (index < lastIndex) { // scrolling up 1257 1294 1258 1295 down = false; 1259 1296 // We are scrolling up in the first buffer range we can ever get … … 1262 1299 return; 1263 1300 } 1264 1265 // if we are scrolling up and we are moving in an acceptable 1266 // buffer range, lets return. 1301 1302 // if we are scrolling up and we are moving in an acceptable 1303 // buffer range, lets return. 1267 1304 if (index - this.nearLimit > this.ds.bufferRange[0]) { 1268 1305 return; … … 1271 1308 return; 1272 1309 } 1273 1310 1274 1311 this.isPrebuffering = true; 1275 1312 } 1276 1313 1277 1314 // prepare for rebuffering 1278 1315 this.isBuffering = true 1279 1316 1280 1317 var bufferOffset = this.getPredictedBufferIndex(index, inRange, down); 1281 1318 var fetchSize = this.ds.bufferSize; 1282 1319 1283 1320 if (!inRange) { 1284 1321 this.showLoadMask(true); 1285 1322 } 1286 1287 this.fireEvent('beforebuffer', this, this.ds, index, 1323 1324 this.fireEvent('beforebuffer', this, this.ds, index, 1288 1325 this.visibleRows, this.ds.totalLength); 1289 1326 1290 1327 this.ds.suspendEvents(); 1291 1328 var sInfo = this.ds.sortInfo; 1292 1329 1293 1330 var params = {}; 1294 1331 if (this.ds.lastOptions) { … … 1297 1334 params.start = bufferOffset; 1298 1335 params.limit = this.ds.bufferSize; 1299 1336 1300 1337 if (sInfo) { 1301 1338 params.dir = sInfo.direction; … … 1308 1345 }); 1309 1346 this.ds.resumeEvents(); 1310 }, 1311 1347 }, 1348 1312 1349 /** 1313 1350 * Shows this' view own load mask to indicate that a large amount of buffer … … 1320 1357 if (this.loadMask == null) { 1321 1358 if (show) { 1322 this.loadMask = new Ext.LoadMask(this.mainBody.dom.parentNode.parentNode, 1323 this.loadMaskConfig); 1359 this.loadMask = new Ext.LoadMask(this.mainBody.dom.parentNode.parentNode, 1360 this.loadMaskConfig); 1324 1361 } else { 1325 1362 return; 1326 1363 } 1327 } 1328 1364 } 1365 1329 1366 if (show) { 1330 1367 this.loadMask.show(); … … 1333 1370 } 1334 1371 }, 1335 1336 /** 1337 * Renders the table body with the contents of the model. The method will 1372 1373 /** 1374 * Renders the table body with the contents of the model. The method will 1338 1375 * prepend/ append rows after removing from either the end or the beginning 1339 1376 * of the table DOM to reduce expensive DOM calls. … … 1343 1380 * Instead of calling this method directly, the <tt>updateLiveRows</tt> method 1344 1381 * should be called which takes care of rebuffering if needed, since this method 1345 * will behave erroneous if data of the buffer is requested which may not be 1382 * will behave erroneous if data of the buffer is requested which may not be 1346 1383 * available. 1347 * 1348 * @param {Number} cursor The position of the data in the model to start 1384 * 1385 * @param {Number} cursor The position of the data in the model to start 1349 1386 * rendering. 1350 1387 * … … 1353 1390 */ 1354 1391 // private 1355 replaceLiveRows : function(cursor, forceReplace )1356 { 1392 replaceLiveRows : function(cursor, forceReplace, processRows) 1393 { 1357 1394 var spill = cursor-this.lastRowIndex; 1358 1395 1359 1396 if (spill == 0 && forceReplace !== true) { 1360 1397 return; 1361 } 1362 1398 } 1399 1363 1400 // decide wether to prepend or append rows 1364 // if spill is negative, we are scrolling up. Thus we have to prepend 1365 // rows. If spill is positive, we have to append the buffers data. 1401 // if spill is negative, we are scrolling up. Thus we have to prepend 1402 // rows. If spill is positive, we have to append the buffers data. 1366 1403 var append = spill > 0; 1367 1404 1368 1405 // abs spill for simplyfiying append/prepend calculations 1369 1406 spill = Math.abs(spill); 1370 1407 1371 1408 // adjust cursor to the buffered model index 1372 1409 var cursorBuffer = cursor-this.ds.bufferRange[0]; 1373 1410 1374 1411 // we can skip checking for append or prepend if the spill is larger than 1375 1412 // visibleRows. We can paint the whole rows new then- 1376 1413 if (spill >= this.visibleRows || spill == 0) { 1377 1414 this.mainBody.update(this.renderRows( 1378 cursorBuffer, 1415 cursorBuffer, 1379 1416 cursorBuffer+this.visibleRows-1 1380 )); 1417 )); 1381 1418 } else { 1382 1419 if (append) { 1383 1420 this.removeRows(0, spill-1); 1384 var html = this.renderRows(cursorBuffer+this.visibleRows-spill, 1421 var html = this.renderRows(cursorBuffer+this.visibleRows-spill, 1385 1422 cursorBuffer+this.visibleRows-1); 1386 1423 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html); 1387 1424 } else { 1388 this.removeRows(this.visibleRows-spill, this.visibleRows-1); 1425 this.removeRows(this.visibleRows-spill, this.visibleRows-1); 1389 1426 var html = this.renderRows(cursorBuffer, cursorBuffer+spill-1); 1390 1427 Ext.DomHelper.insertHtml('beforeBegin', this.mainBody.dom.firstChild, html); 1391 1428 } 1392 1429 } 1393 1394 this.processRows(0, undefined, true); 1430 1431 if (processRows !== false) { 1432 this.processRows(0, undefined, true); 1433 } 1395 1434 this.lastRowIndex = cursor; 1396 1435 }, 1397 1398 1399 1400 /** 1401 * Adjusts the scroller height to make sure each row in the dataset will be 1402 * can be displayed, no matter which value the current height of the grid 1436 1437 1438 1439 /** 1440 * Adjusts the scroller height to make sure each row in the dataset will be 1441 * can be displayed, no matter which value the current height of the grid 1403 1442 * component equals to. 1404 1443 */ … … 1407 1446 { 1408 1447 var g = this.grid, ds = g.store; 1409 1448 1410 1449 var c = g.getGridEl(); 1411 1450 1412 1451 var scrollbar = this.cm.getTotalWidth()+this.scrollOffset > c.getSize().width; 1413 1452 1414 1453 // adjust the height of the scrollbar 1415 this.liveScroller.dom.style.height = this.liveScroller.dom.parentNode.offsetHeight + 1416 (Ext.isGecko 1454 this.liveScroller.dom.style.height = this.liveScroller.dom.parentNode.offsetHeight + 1455 (Ext.isGecko 1417 1456 ? ((ds.totalLength > 0 && scrollbar) 1418 1457 ? - this.horizontalScrollOffset 1419 1458 : 0) 1420 1459 : (((ds.totalLength > 0 && scrollbar) 1421 ? 0 : this.horizontalScrollOffset)))+"px"; 1460 ? 0 : this.horizontalScrollOffset)))+"px"; 1422 1461 if (this.rowHeight == -1) { 1423 1462 return; 1424 1463 } 1425 1464 1426 1465 if (ds.totalLength <= this.visibleRows) { 1427 1466 this.liveScrollerInset.style.height = "0px"; 1428 1467 return; 1429 } 1430 1468 } 1469 1431 1470 var height = this.rowHeight*ds.totalLength; 1432 1471 1433 1472 height += (c.getSize().height-(this.visibleRows*this.rowHeight)); 1434 1473 1435 1474 if (scrollbar) { 1436 1475 height -= this.horizontalScrollOffset; 1437 1476 } 1438 1477 1439 1478 this.liveScrollerInset.style.height = (height)+"px"; 1440 1479 }, 1441 1480 1442 1481 /** 1443 1482 * Recomputes the number of visible rows in the table based upon the height 1444 * of the component. The method adjusts the <tt>rowIndex</tt> property as 1445 * needed, if the sum of visible rows and the current row index exceeds the 1483 * of the component. The method adjusts the <tt>rowIndex</tt> property as 1484 * needed, if the sum of visible rows and the current row index exceeds the 1446 1485 * number of total data available. 1447 1486 */ … … 1451 1490 if (this.rowHeight == -1) { 1452 1491 if (this.getRows()[0]) { 1453 this.rowHeight = this.getRows()[0].offsetHeight; 1492 this.rowHeight = this.getRows()[0].offsetHeight; 1454 1493 } else { 1455 1494 return; 1456 1495 } 1457 } 1458 1459 1496 } 1497 1498 1460 1499 var g = this.grid, ds = g.store; 1461 1500 1462 1501 var c = g.getGridEl(); 1463 1502 var cm = this.cm; 1464 1503 var size = c.getSize(true); 1465 var vh = size.height; 1466 1467 var vw = size.width-this.scrollOffset; 1504 var vh = size.height; 1505 1506 var vw = size.width-this.scrollOffset; 1468 1507 // horizontal scrollbar shown? 1469 1508 if (cm.getTotalWidth() > vw) { 1470 1509 // yes! 1471 1510 vh -= this.horizontalScrollOffset; 1472 } 1473 1511 } 1512 1474 1513 vh -= this.mainHd.getHeight(); 1475 1514 1476 1515 var visibleRows = Math.max(1, Math.floor(vh/this.rowHeight)); 1477 1516 1478 1517 var totalLength = ds.getTotalCount(); 1479 1518 1480 1519 if (totalLength < this.visibleRows || this.visibleRows == visibleRows) { 1481 1520 return; 1482 1521 } 1483 1522 1484 1523 this.visibleRows = visibleRows; 1485 1524 1486 1525 if (this.rowIndex + visibleRows > totalLength) { 1487 1526 this.rowIndex = Math.max(0, ds.totalLength-this.visibleRows); … … 1490 1529 } else { 1491 1530 this.updateLiveRows(this.rowIndex, true); 1492 } 1493 }, 1494 1495 1531 } 1532 }, 1533 1534 1496 1535 adjustScrollerPos : function(pixels, suspendEvent) 1497 1536 { … … 1501 1540 var liveScroller = this.liveScroller; 1502 1541 var scrollDom = liveScroller.dom; 1503 1542 1504 1543 if (suspendEvent === true) { 1505 1544 liveScroller.un('scroll', this.onLiveScroll, this); 1506 1545 } 1507 this.lastScrollPos = scrollDom.scrollTop; 1546 this.lastScrollPos = scrollDom.scrollTop; 1508 1547 scrollDom.scrollTop += pixels; 1509 1548 1510 1549 if (suspendEvent === true) { 1511 1550 scrollDom.scrollTop = scrollDom.scrollTop; 1512 1551 liveScroller.on('scroll', this.onLiveScroll, this, {buffer : this.scrollDelay}); 1513 1552 } 1514 1553 1515 1554 } 1516 1517 1518 1555 1556 1557 1519 1558 });
