Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(245)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/ViewportControl.js

Issue 2339293003: DevTools: Buffer ViewportController to prevent whitespace on scroll. (Closed)
Patch Set: Fix math error Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 // Text content needed for range intersection checks in _updateSelectionMode l. 47 // Text content needed for range intersection checks in _updateSelectionMode l.
48 // Use Unicode ZERO WIDTH NO-BREAK SPACE, which avoids contributing any heig ht to the element's layout overflow. 48 // Use Unicode ZERO WIDTH NO-BREAK SPACE, which avoids contributing any heig ht to the element's layout overflow.
49 this._topGapElement.textContent = "\uFEFF"; 49 this._topGapElement.textContent = "\uFEFF";
50 this._bottomGapElement.textContent = "\uFEFF"; 50 this._bottomGapElement.textContent = "\uFEFF";
51 51
52 this._provider = provider; 52 this._provider = provider;
53 this.element.addEventListener("scroll", this._onScroll.bind(this), false); 53 this.element.addEventListener("scroll", this._onScroll.bind(this), false);
54 this.element.addEventListener("copy", this._onCopy.bind(this), false); 54 this.element.addEventListener("copy", this._onCopy.bind(this), false);
55 this.element.addEventListener("dragstart", this._onDragStart.bind(this), fal se); 55 this.element.addEventListener("dragstart", this._onDragStart.bind(this), fal se);
56 56
57 this._firstVisibleIndex = 0; 57 this._firstActiveIndex = 0;
58 this._lastVisibleIndex = -1; 58 this._lastActiveIndex = -1;
59 this._renderedItems = []; 59 this._renderedItems = [];
60 this._anchorSelection = null; 60 this._anchorSelection = null;
61 this._headSelection = null; 61 this._headSelection = null;
62 this._itemCount = 0; 62 this._itemCount = 0;
63 63
64 // Listen for any changes to descendants and trigger a refresh. This ensures 64 // Listen for any changes to descendants and trigger a refresh. This ensures
65 // that items updated asynchronously will not break stick-to-bottom behavior 65 // that items updated asynchronously will not break stick-to-bottom behavior
66 // if they change the scroll height. 66 // if they change the scroll height.
67 this._observer = new MutationObserver(this.refresh.bind(this)); 67 this._observer = new MutationObserver(this.refresh.bind(this));
68 this._observerConfig = { childList: true, subtree: true }; 68 this._observerConfig = { childList: true, subtree: true };
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 223 }
224 return element; 224 return element;
225 }, 225 },
226 226
227 _rebuildCumulativeHeightsIfNeeded: function() 227 _rebuildCumulativeHeightsIfNeeded: function()
228 { 228 {
229 if (this._cumulativeHeights) 229 if (this._cumulativeHeights)
230 return; 230 return;
231 if (!this._itemCount) 231 if (!this._itemCount)
232 return; 232 return;
233 var firstVisibleIndex = this._firstVisibleIndex; 233 var firstActiveIndex = this._firstActiveIndex;
234 var lastVisibleIndex = this._lastVisibleIndex; 234 var lastActiveIndex = this._lastActiveIndex;
235 var height = 0; 235 var height = 0;
236 this._cumulativeHeights = new Int32Array(this._itemCount); 236 this._cumulativeHeights = new Int32Array(this._itemCount);
237 for (var i = 0; i < this._itemCount; ++i) { 237 for (var i = 0; i < this._itemCount; ++i) {
238 if (firstVisibleIndex <= i && i <= lastVisibleIndex) 238 if (firstActiveIndex <= i && i <= lastActiveIndex)
239 height += this._renderedItems[i - firstVisibleIndex].element().o ffsetHeight; 239 height += this._renderedItems[i - firstActiveIndex].element().of fsetHeight;
240 else 240 else
241 height += this._provider.fastHeight(i); 241 height += this._provider.fastHeight(i);
242 this._cumulativeHeights[i] = height; 242 this._cumulativeHeights[i] = height;
243 } 243 }
244 }, 244 },
245 245
246 /** 246 /**
247 * @param {number} index 247 * @param {number} index
248 * @return {number} 248 * @return {number}
249 */ 249 */
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 this._anchorSelection = null; 292 this._anchorSelection = null;
293 return false; 293 return false;
294 } 294 }
295 295
296 var firstSelected = Number.MAX_VALUE; 296 var firstSelected = Number.MAX_VALUE;
297 var lastSelected = -1; 297 var lastSelected = -1;
298 298
299 var hasVisibleSelection = false; 299 var hasVisibleSelection = false;
300 for (var i = 0; i < this._renderedItems.length; ++i) { 300 for (var i = 0; i < this._renderedItems.length; ++i) {
301 if (range.intersectsNode(this._renderedItems[i].element())) { 301 if (range.intersectsNode(this._renderedItems[i].element())) {
302 var index = i + this._firstVisibleIndex; 302 var index = i + this._firstActiveIndex;
303 firstSelected = Math.min(firstSelected, index); 303 firstSelected = Math.min(firstSelected, index);
304 lastSelected = Math.max(lastSelected, index); 304 lastSelected = Math.max(lastSelected, index);
305 hasVisibleSelection = true; 305 hasVisibleSelection = true;
306 } 306 }
307 } 307 }
308 if (hasVisibleSelection) { 308 if (hasVisibleSelection) {
309 firstSelected = this._createSelectionModel(firstSelected, /** @type {!Node} */(range.startContainer), range.startOffset); 309 firstSelected = this._createSelectionModel(firstSelected, /** @type {!Node} */(range.startContainer), range.startOffset);
310 lastSelected = this._createSelectionModel(lastSelected, /** @type {! Node} */(range.endContainer), range.endOffset); 310 lastSelected = this._createSelectionModel(lastSelected, /** @type {! Node} */(range.endContainer), range.endOffset);
311 } 311 }
312 var topOverlap = range.intersectsNode(this._topGapElement) && this._topG apElement._active; 312 var topOverlap = range.intersectsNode(this._topGapElement) && this._topG apElement._active;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 return true; 348 return true;
349 }, 349 },
350 350
351 /** 351 /**
352 * @param {?Selection} selection 352 * @param {?Selection} selection
353 */ 353 */
354 _restoreSelection: function(selection) 354 _restoreSelection: function(selection)
355 { 355 {
356 var anchorElement = null; 356 var anchorElement = null;
357 var anchorOffset; 357 var anchorOffset;
358 if (this._firstVisibleIndex <= this._anchorSelection.item && this._ancho rSelection.item <= this._lastVisibleIndex) { 358 if (this._firstActiveIndex <= this._anchorSelection.item && this._anchor Selection.item <= this._lastActiveIndex) {
359 anchorElement = this._anchorSelection.node; 359 anchorElement = this._anchorSelection.node;
360 anchorOffset = this._anchorSelection.offset; 360 anchorOffset = this._anchorSelection.offset;
361 } else { 361 } else {
362 if (this._anchorSelection.item < this._firstVisibleIndex) 362 if (this._anchorSelection.item < this._firstActiveIndex)
363 anchorElement = this._topGapElement; 363 anchorElement = this._topGapElement;
364 else if (this._anchorSelection.item > this._lastVisibleIndex) 364 else if (this._anchorSelection.item > this._lastActiveIndex)
365 anchorElement = this._bottomGapElement; 365 anchorElement = this._bottomGapElement;
366 anchorOffset = this._selectionIsBackward ? 1 : 0; 366 anchorOffset = this._selectionIsBackward ? 1 : 0;
367 } 367 }
368 368
369 var headElement = null; 369 var headElement = null;
370 var headOffset; 370 var headOffset;
371 if (this._firstVisibleIndex <= this._headSelection.item && this._headSel ection.item <= this._lastVisibleIndex) { 371 if (this._firstActiveIndex <= this._headSelection.item && this._headSele ction.item <= this._lastActiveIndex) {
372 headElement = this._headSelection.node; 372 headElement = this._headSelection.node;
373 headOffset = this._headSelection.offset; 373 headOffset = this._headSelection.offset;
374 } else { 374 } else {
375 if (this._headSelection.item < this._firstVisibleIndex) 375 if (this._headSelection.item < this._firstActiveIndex)
376 headElement = this._topGapElement; 376 headElement = this._topGapElement;
377 else if (this._headSelection.item > this._lastVisibleIndex) 377 else if (this._headSelection.item > this._lastActiveIndex)
378 headElement = this._bottomGapElement; 378 headElement = this._bottomGapElement;
379 headOffset = this._selectionIsBackward ? 0 : 1; 379 headOffset = this._selectionIsBackward ? 0 : 1;
380 } 380 }
381 381
382 selection.setBaseAndExtent(anchorElement, anchorOffset, headElement, hea dOffset); 382 selection.setBaseAndExtent(anchorElement, anchorOffset, headElement, hea dOffset);
383 }, 383 },
384 384
385 refresh: function() 385 refresh: function()
386 { 386 {
387 this._observer.disconnect(); 387 this._observer.disconnect();
388 this._innerRefresh(); 388 this._innerRefresh();
389 if (this._stickToBottom) 389 if (this._stickToBottom)
390 this._observer.observe(this._contentElement, this._observerConfig); 390 this._observer.observe(this._contentElement, this._observerConfig);
391 }, 391 },
392 392
393 _innerRefresh: function() 393 _innerRefresh: function()
394 { 394 {
395 if (!this._visibleHeight()) 395 if (!this._visibleHeight())
396 return; // Do nothing for invisible controls. 396 return; // Do nothing for invisible controls.
397 397
398 if (!this._itemCount) { 398 if (!this._itemCount) {
399 for (var i = 0; i < this._renderedItems.length; ++i) 399 for (var i = 0; i < this._renderedItems.length; ++i)
400 this._renderedItems[i].willHide(); 400 this._renderedItems[i].willHide();
401 this._renderedItems = []; 401 this._renderedItems = [];
402 this._contentElement.removeChildren(); 402 this._contentElement.removeChildren();
403 this._topGapElement.style.height = "0px"; 403 this._topGapElement.style.height = "0px";
404 this._bottomGapElement.style.height = "0px"; 404 this._bottomGapElement.style.height = "0px";
405 this._firstVisibleIndex = -1; 405 this._firstActiveIndex = -1;
406 this._lastVisibleIndex = -1; 406 this._lastActiveIndex = -1;
407 return; 407 return;
408 } 408 }
409 409
410 var selection = this.element.getComponentSelection(); 410 var selection = this.element.getComponentSelection();
411 var shouldRestoreSelection = this._updateSelectionModel(selection); 411 var shouldRestoreSelection = this._updateSelectionModel(selection);
412 412
413 var visibleFrom = this.element.scrollTop; 413 var visibleFrom = this.element.scrollTop;
414 var visibleHeight = this._visibleHeight(); 414 var visibleHeight = this._visibleHeight();
415 var isInvalidating = !this._cumulativeHeights; 415 var isInvalidating = !this._cumulativeHeights;
416 416
417 for (var i = 0; i < this._renderedItems.length; ++i) { 417 for (var i = 0; i < this._renderedItems.length; ++i) {
418 // Tolerate 1-pixel error due to double-to-integer rounding errors. 418 // Tolerate 1-pixel error due to double-to-integer rounding errors.
419 if (this._cumulativeHeights && Math.abs(this._cachedItemHeight(this. _firstVisibleIndex + i) - this._renderedItems[i].element().offsetHeight) > 1) 419 if (this._cumulativeHeights && Math.abs(this._cachedItemHeight(this. _firstActiveIndex + i) - this._renderedItems[i].element().offsetHeight) > 1)
420 delete this._cumulativeHeights; 420 delete this._cumulativeHeights;
421 } 421 }
422 this._rebuildCumulativeHeightsIfNeeded(); 422 this._rebuildCumulativeHeightsIfNeeded();
423 var oldFirstVisibleIndex = this._firstVisibleIndex; 423 var oldFirstActiveIndex = this._firstActiveIndex;
424 var oldLastVisibleIndex = this._lastVisibleIndex; 424 var oldLastActiveIndex = this._lastActiveIndex;
425 425 var activeHeight = visibleHeight * 2;
426 // When the viewport is scrolled to the bottom, using the cumulative hei ghts estimate is not 426 // When the viewport is scrolled to the bottom, using the cumulative hei ghts estimate is not
427 // precise enough to determine next visible indices. This stickToBottom check avoids extra 427 // precise enough to determine next visible indices. This stickToBottom check avoids extra
428 // calls to refresh in those cases. 428 // calls to refresh in those cases.
429 if (this._stickToBottom) { 429 if (this._stickToBottom) {
430 this._firstVisibleIndex = Math.max(this._itemCount - Math.ceil(visib leHeight / this._provider.minimumRowHeight()), 0); 430 this._firstActiveIndex = Math.max(this._itemCount - Math.ceil(active Height / this._provider.minimumRowHeight()), 0);
431 this._lastVisibleIndex = this._itemCount - 1; 431 this._lastActiveIndex = this._itemCount - 1;
432 } else { 432 } else {
433 this._firstVisibleIndex = Math.max(Array.prototype.lowerBound.call(t his._cumulativeHeights, visibleFrom + 1), 0); 433 this._firstActiveIndex = Math.max(Array.prototype.lowerBound.call(th is._cumulativeHeights, visibleFrom + 1 - (activeHeight - visibleHeight) / 2), 0) ;
434 // Proactively render more rows in case some of them will be collaps ed without triggering refresh. @see crbug.com/390169 434 // Proactively render more rows in case some of them will be collaps ed without triggering refresh. @see crbug.com/390169
435 this._lastVisibleIndex = this._firstVisibleIndex + Math.ceil(visible Height / this._provider.minimumRowHeight()) - 1; 435 this._lastActiveIndex = this._firstActiveIndex + Math.ceil(activeHei ght / this._provider.minimumRowHeight()) - 1;
436 this._lastVisibleIndex = Math.min(this._lastVisibleIndex, this._item Count - 1); 436 this._lastActiveIndex = Math.min(this._lastActiveIndex, this._itemCo unt - 1);
437 } 437 }
438 438
439 var topGapHeight = this._cumulativeHeights[this._firstVisibleIndex - 1] || 0; 439 var topGapHeight = this._cumulativeHeights[this._firstActiveIndex - 1] | | 0;
440 var bottomGapHeight = this._cumulativeHeights[this._cumulativeHeights.le ngth - 1] - this._cumulativeHeights[this._lastVisibleIndex]; 440 var bottomGapHeight = this._cumulativeHeights[this._cumulativeHeights.le ngth - 1] - this._cumulativeHeights[this._lastActiveIndex];
441 441
442 /** 442 /**
443 * @this {WebInspector.ViewportControl} 443 * @this {WebInspector.ViewportControl}
444 */ 444 */
445 function prepare() 445 function prepare()
446 { 446 {
447 this._topGapElement.style.height = topGapHeight + "px"; 447 this._topGapElement.style.height = topGapHeight + "px";
448 this._bottomGapElement.style.height = bottomGapHeight + "px"; 448 this._bottomGapElement.style.height = bottomGapHeight + "px";
449 this._topGapElement._active = !!topGapHeight; 449 this._topGapElement._active = !!topGapHeight;
450 this._bottomGapElement._active = !!bottomGapHeight; 450 this._bottomGapElement._active = !!bottomGapHeight;
451 this._contentElement.style.setProperty("height", "10000000px"); 451 this._contentElement.style.setProperty("height", "10000000px");
452 } 452 }
453 453
454 if (isInvalidating) 454 if (isInvalidating)
455 this._fullViewportUpdate(prepare.bind(this)); 455 this._fullViewportUpdate(prepare.bind(this));
456 else 456 else
457 this._partialViewportUpdate(oldFirstVisibleIndex, oldLastVisibleInde x, prepare.bind(this)); 457 this._partialViewportUpdate(oldFirstActiveIndex, oldLastActiveIndex, prepare.bind(this));
458 this._contentElement.style.removeProperty("height"); 458 this._contentElement.style.removeProperty("height");
459 // Should be the last call in the method as it might force layout. 459 // Should be the last call in the method as it might force layout.
460 if (shouldRestoreSelection) 460 if (shouldRestoreSelection)
461 this._restoreSelection(selection); 461 this._restoreSelection(selection);
462 if (this._stickToBottom) 462 if (this._stickToBottom)
463 this.element.scrollTop = 10000000; 463 this.element.scrollTop = 10000000;
464 }, 464 },
465 465
466 /** 466 /**
467 * @param {function()} prepare 467 * @param {function()} prepare
468 */ 468 */
469 _fullViewportUpdate: function(prepare) 469 _fullViewportUpdate: function(prepare)
470 { 470 {
471 for (var i = 0; i < this._renderedItems.length; ++i) 471 for (var i = 0; i < this._renderedItems.length; ++i)
472 this._renderedItems[i].willHide(); 472 this._renderedItems[i].willHide();
473 prepare(); 473 prepare();
474 this._renderedItems = []; 474 this._renderedItems = [];
475 this._contentElement.removeChildren(); 475 this._contentElement.removeChildren();
476 for (var i = this._firstVisibleIndex; i <= this._lastVisibleIndex; ++i) { 476 for (var i = this._firstActiveIndex; i <= this._lastActiveIndex; ++i) {
477 var viewportElement = this._providerElement(i); 477 var viewportElement = this._providerElement(i);
478 this._contentElement.appendChild(viewportElement.element()); 478 this._contentElement.appendChild(viewportElement.element());
479 this._renderedItems.push(viewportElement); 479 this._renderedItems.push(viewportElement);
480 } 480 }
481 for (var i = 0; i < this._renderedItems.length; ++i) 481 for (var i = 0; i < this._renderedItems.length; ++i)
482 this._renderedItems[i].wasShown(); 482 this._renderedItems[i].wasShown();
483 }, 483 },
484 484
485 /** 485 /**
486 * @param {number} oldFirstVisibleIndex 486 * @param {number} oldFirstActiveIndex
487 * @param {number} oldLastVisibleIndex 487 * @param {number} oldLastActiveIndex
488 * @param {function()} prepare 488 * @param {function()} prepare
489 */ 489 */
490 _partialViewportUpdate: function(oldFirstVisibleIndex, oldLastVisibleIndex, prepare) 490 _partialViewportUpdate: function(oldFirstActiveIndex, oldLastActiveIndex, pr epare)
491 { 491 {
492 var willBeHidden = []; 492 var willBeHidden = [];
493 for (var i = 0; i < this._renderedItems.length; ++i) { 493 for (var i = 0; i < this._renderedItems.length; ++i) {
494 var index = oldFirstVisibleIndex + i; 494 var index = oldFirstActiveIndex + i;
495 if (index < this._firstVisibleIndex || this._lastVisibleIndex < inde x) 495 if (index < this._firstActiveIndex || this._lastActiveIndex < index)
496 willBeHidden.push(this._renderedItems[i]); 496 willBeHidden.push(this._renderedItems[i]);
497 } 497 }
498 for (var i = 0; i < willBeHidden.length; ++i) 498 for (var i = 0; i < willBeHidden.length; ++i)
499 willBeHidden[i].willHide(); 499 willBeHidden[i].willHide();
500 prepare(); 500 prepare();
501 for (var i = 0; i < willBeHidden.length; ++i) 501 for (var i = 0; i < willBeHidden.length; ++i)
502 willBeHidden[i].element().remove(); 502 willBeHidden[i].element().remove();
503 503
504 this._renderedItems = []; 504 this._renderedItems = [];
505 var anchor = this._contentElement.firstChild; 505 var anchor = this._contentElement.firstChild;
506 var wasShown = []; 506 var wasShown = [];
507 for (var i = this._firstVisibleIndex; i <= this._lastVisibleIndex; ++i) { 507 for (var i = this._firstActiveIndex; i <= this._lastActiveIndex; ++i) {
508 var viewportElement = this._providerElement(i); 508 var viewportElement = this._providerElement(i);
509 var element = viewportElement.element(); 509 var element = viewportElement.element();
510 if (element !== anchor) { 510 if (element !== anchor) {
511 this._contentElement.insertBefore(element, anchor); 511 this._contentElement.insertBefore(element, anchor);
512 wasShown.push(viewportElement); 512 wasShown.push(viewportElement);
513 } else { 513 } else {
514 anchor = anchor.nextSibling; 514 anchor = anchor.nextSibling;
515 } 515 }
516 this._renderedItems.push(viewportElement); 516 this._renderedItems.push(viewportElement);
517 } 517 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 _onScroll: function(event) 578 _onScroll: function(event)
579 { 579 {
580 this.refresh(); 580 this.refresh();
581 }, 581 },
582 582
583 /** 583 /**
584 * @return {number} 584 * @return {number}
585 */ 585 */
586 firstVisibleIndex: function() 586 firstVisibleIndex: function()
587 { 587 {
588 return this._firstVisibleIndex; 588 var firstVisibleIndex;
589 if (this._stickToBottom)
590 firstVisibleIndex = Math.max(this._itemCount - Math.ceil(this._visib leHeight() / this._provider.minimumRowHeight()), 0);
591 else
592 firstVisibleIndex = Math.max(Array.prototype.lowerBound.call(this._c umulativeHeights, this.element.scrollTop + 1), 0);
593 return Math.max(firstVisibleIndex, this._firstActiveIndex);
589 }, 594 },
590 595
591 /** 596 /**
592 * @return {number} 597 * @return {number}
593 */ 598 */
594 lastVisibleIndex: function() 599 lastVisibleIndex: function()
595 { 600 {
596 return this._lastVisibleIndex; 601 var lastVisibleIndex;
602 if (this._stickToBottom)
603 lastVisibleIndex = this._itemCount - 1;
604 else
605 lastVisibleIndex = this.firstVisibleIndex() + Math.ceil(this._visibl eHeight() / this._provider.minimumRowHeight()) - 1;
606 return Math.min(lastVisibleIndex, this._lastActiveIndex);
597 }, 607 },
598 608
599 /** 609 /**
600 * @return {?Element} 610 * @return {?Element}
601 */ 611 */
602 renderedElementAt: function(index) 612 renderedElementAt: function(index)
603 { 613 {
604 if (index < this._firstVisibleIndex) 614 if (index < this._firstActiveIndex)
605 return null; 615 return null;
606 if (index > this._lastVisibleIndex) 616 if (index > this._lastActiveIndex)
607 return null; 617 return null;
608 return this._renderedItems[index - this._firstVisibleIndex].element(); 618 return this._renderedItems[index - this._firstActiveIndex].element();
609 }, 619 },
610 620
611 /** 621 /**
612 * @param {number} index 622 * @param {number} index
613 * @param {boolean=} makeLast 623 * @param {boolean=} makeLast
614 */ 624 */
615 scrollItemIntoView: function(index, makeLast) 625 scrollItemIntoView: function(index, makeLast)
616 { 626 {
617 if (index > this._firstVisibleIndex && index < this._lastVisibleIndex) 627 if (index > this._firstActiveIndex && index < this._lastActiveIndex)
618 return; 628 return;
619 if (makeLast) 629 if (makeLast)
620 this.forceScrollItemToBeLast(index); 630 this.forceScrollItemToBeLast(index);
621 else if (index <= this._firstVisibleIndex) 631 else if (index <= this._firstActiveIndex)
622 this.forceScrollItemToBeFirst(index); 632 this.forceScrollItemToBeFirst(index);
623 else if (index >= this._lastVisibleIndex) 633 else if (index >= this._lastActiveIndex)
624 this.forceScrollItemToBeLast(index); 634 this.forceScrollItemToBeLast(index);
625 }, 635 },
626 636
627 /** 637 /**
628 * @param {number} index 638 * @param {number} index
629 */ 639 */
630 forceScrollItemToBeFirst: function(index) 640 forceScrollItemToBeFirst: function(index)
631 { 641 {
632 this.setStickToBottom(false); 642 this.setStickToBottom(false);
633 this._rebuildCumulativeHeightsIfNeeded(); 643 this._rebuildCumulativeHeightsIfNeeded();
(...skipping 18 matching lines...) Expand all
652 662
653 /** 663 /**
654 * @return {number} 664 * @return {number}
655 */ 665 */
656 _visibleHeight: function() 666 _visibleHeight: function()
657 { 667 {
658 // Use offsetHeight instead of clientHeight to avoid being affected by h orizontal scroll. 668 // Use offsetHeight instead of clientHeight to avoid being affected by h orizontal scroll.
659 return this.element.offsetHeight; 669 return this.element.offsetHeight;
660 } 670 }
661 } 671 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698