OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |