Index: third_party/WebKit/Source/devtools/front_end/ui/ViewportControl.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ViewportControl.js b/third_party/WebKit/Source/devtools/front_end/ui/ViewportControl.js |
index b3f40d42015177bbbe6e1656e481e50084bd295a..dbd36008c8a08dd7baf1be0f7679ec221d521a0e 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/ui/ViewportControl.js |
+++ b/third_party/WebKit/Source/devtools/front_end/ui/ViewportControl.js |
@@ -1,33 +1,6 @@ |
-/* |
- * Copyright (C) 2013 Google Inc. All rights reserved. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions are |
- * met: |
- * |
- * * Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * * Redistributions in binary form must reproduce the above |
- * copyright notice, this list of conditions and the following disclaimer |
- * in the documentation and/or other materials provided with the |
- * distribution. |
- * * Neither the name of Google Inc. nor the names of its |
- * contributors may be used to endorse or promote products derived from |
- * this software without specific prior written permission. |
- * |
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
/** |
* @unrestricted |
*/ |
@@ -38,490 +11,90 @@ UI.ViewportControl = class { |
constructor(provider) { |
this.element = createElement('div'); |
this.element.style.overflow = 'auto'; |
- this._topGapElement = this.element.createChild('div'); |
- this._topGapElement.style.height = '0px'; |
- this._topGapElement.style.color = 'transparent'; |
- this._contentElement = this.element.createChild('div'); |
- this._bottomGapElement = this.element.createChild('div'); |
- this._bottomGapElement.style.height = '0px'; |
- this._bottomGapElement.style.color = 'transparent'; |
- |
- // Text content needed for range intersection checks in _updateSelectionModel. |
- // Use Unicode ZERO WIDTH NO-BREAK SPACE, which avoids contributing any height to the element's layout overflow. |
- this._topGapElement.textContent = '\uFEFF'; |
- this._bottomGapElement.textContent = '\uFEFF'; |
+ this._innerElement = this.element.createChild('div'); |
+ this._innerElement.style.height = '0px'; |
+ this._innerElement.style.position = 'relative'; |
+ this._innerElement.style.overflow = 'hidden'; |
this._provider = provider; |
- this.element.addEventListener('scroll', this._onScroll.bind(this), false); |
- this.element.addEventListener('copy', this._onCopy.bind(this), false); |
- this.element.addEventListener('dragstart', this._onDragStart.bind(this), false); |
- |
- this._firstActiveIndex = 0; |
- this._lastActiveIndex = -1; |
- this._renderedItems = []; |
- this._anchorSelection = null; |
- this._headSelection = null; |
+ this.element.addEventListener('scroll', this._update.bind(this), false); |
this._itemCount = 0; |
- |
- // Listen for any changes to descendants and trigger a refresh. This ensures |
- // that items updated asynchronously will not break stick-to-bottom behavior |
- // if they change the scroll height. |
- this._observer = new MutationObserver(this.refresh.bind(this)); |
- this._observerConfig = {childList: true, subtree: true}; |
- } |
- |
- /** |
- * @return {boolean} |
- */ |
- stickToBottom() { |
- return this._stickToBottom; |
- } |
- |
- /** |
- * @param {boolean} value |
- */ |
- setStickToBottom(value) { |
- this._stickToBottom = value; |
- if (this._stickToBottom) |
- this._observer.observe(this._contentElement, this._observerConfig); |
- else |
- this._observer.disconnect(); |
- } |
- |
- /** |
- * @param {!Event} event |
- */ |
- _onCopy(event) { |
- var text = this._selectedText(); |
- if (!text) |
- return; |
- event.preventDefault(); |
- event.clipboardData.setData('text/plain', text); |
+ this._indexSymbol = Symbol('UI.ViewportControl._indexSymbol'); |
} |
- /** |
- * @param {!Event} event |
- */ |
- _onDragStart(event) { |
- var text = this._selectedText(); |
- if (!text) |
- return false; |
- event.dataTransfer.clearData(); |
- event.dataTransfer.setData('text/plain', text); |
- event.dataTransfer.effectAllowed = 'copy'; |
- return true; |
- } |
- |
- /** |
- * @return {!Element} |
- */ |
- contentElement() { |
- return this._contentElement; |
- } |
- |
- invalidate() { |
- delete this._cumulativeHeights; |
- delete this._cachedProviderElements; |
+ refresh() { |
this._itemCount = this._provider.itemCount(); |
- this.refresh(); |
- } |
+ this._innerElement.removeChildren(); |
- /** |
- * @param {number} index |
- * @return {?UI.ViewportElement} |
- */ |
- _providerElement(index) { |
- if (!this._cachedProviderElements) |
- this._cachedProviderElements = new Array(this._itemCount); |
- var element = this._cachedProviderElements[index]; |
- if (!element) { |
- element = this._provider.itemElement(index); |
- this._cachedProviderElements[index] = element; |
- } |
- return element; |
- } |
- |
- _rebuildCumulativeHeightsIfNeeded() { |
- if (this._cumulativeHeights) |
- return; |
- if (!this._itemCount) |
- return; |
- var firstActiveIndex = this._firstActiveIndex; |
- var lastActiveIndex = this._lastActiveIndex; |
var height = 0; |
this._cumulativeHeights = new Int32Array(this._itemCount); |
for (var i = 0; i < this._itemCount; ++i) { |
- if (firstActiveIndex <= i && i <= lastActiveIndex) |
- height += this._renderedItems[i - firstActiveIndex].element().offsetHeight; |
- else |
- height += this._provider.fastHeight(i); |
+ height += this._provider.fastItemHeight(i); |
this._cumulativeHeights[i] = height; |
} |
- } |
- |
- /** |
- * @param {number} index |
- * @return {number} |
- */ |
- _cachedItemHeight(index) { |
- return index === 0 ? this._cumulativeHeights[0] : |
- this._cumulativeHeights[index] - this._cumulativeHeights[index - 1]; |
- } |
- |
- /** |
- * @param {?Selection} selection |
- * @suppressGlobalPropertiesCheck |
- */ |
- _isSelectionBackwards(selection) { |
- if (!selection || !selection.rangeCount) |
- return false; |
- var range = document.createRange(); |
- range.setStart(selection.anchorNode, selection.anchorOffset); |
- range.setEnd(selection.focusNode, selection.focusOffset); |
- return range.collapsed; |
- } |
- |
- /** |
- * @param {number} itemIndex |
- * @param {!Node} node |
- * @param {number} offset |
- * @return {!{item: number, node: !Node, offset: number}} |
- */ |
- _createSelectionModel(itemIndex, node, offset) { |
- return {item: itemIndex, node: node, offset: offset}; |
- } |
- |
- /** |
- * @param {?Selection} selection |
- */ |
- _updateSelectionModel(selection) { |
- var range = selection && selection.rangeCount ? selection.getRangeAt(0) : null; |
- if (!range || selection.isCollapsed || !this.element.hasSelection()) { |
- this._headSelection = null; |
- this._anchorSelection = null; |
- return false; |
- } |
- |
- var firstSelected = Number.MAX_VALUE; |
- var lastSelected = -1; |
+ this._innerElement.style.height = height + 'px'; |
- var hasVisibleSelection = false; |
- for (var i = 0; i < this._renderedItems.length; ++i) { |
- if (range.intersectsNode(this._renderedItems[i].element())) { |
- var index = i + this._firstActiveIndex; |
- firstSelected = Math.min(firstSelected, index); |
- lastSelected = Math.max(lastSelected, index); |
- hasVisibleSelection = true; |
- } |
- } |
- if (hasVisibleSelection) { |
- firstSelected = |
- this._createSelectionModel(firstSelected, /** @type {!Node} */ (range.startContainer), range.startOffset); |
- lastSelected = |
- this._createSelectionModel(lastSelected, /** @type {!Node} */ (range.endContainer), range.endOffset); |
- } |
- var topOverlap = range.intersectsNode(this._topGapElement) && this._topGapElement._active; |
- var bottomOverlap = range.intersectsNode(this._bottomGapElement) && this._bottomGapElement._active; |
- if (!topOverlap && !bottomOverlap && !hasVisibleSelection) { |
- this._headSelection = null; |
- this._anchorSelection = null; |
- return false; |
- } |
- |
- if (!this._anchorSelection || !this._headSelection) { |
- this._anchorSelection = this._createSelectionModel(0, this.element, 0); |
- this._headSelection = this._createSelectionModel(this._itemCount - 1, this.element, this.element.children.length); |
- this._selectionIsBackward = false; |
- } |
- |
- var isBackward = this._isSelectionBackwards(selection); |
- var startSelection = this._selectionIsBackward ? this._headSelection : this._anchorSelection; |
- var endSelection = this._selectionIsBackward ? this._anchorSelection : this._headSelection; |
- if (topOverlap && bottomOverlap && hasVisibleSelection) { |
- firstSelected = firstSelected.item < startSelection.item ? firstSelected : startSelection; |
- lastSelected = lastSelected.item > endSelection.item ? lastSelected : endSelection; |
- } else if (!hasVisibleSelection) { |
- firstSelected = startSelection; |
- lastSelected = endSelection; |
- } else if (topOverlap) { |
- firstSelected = isBackward ? this._headSelection : this._anchorSelection; |
- } else if (bottomOverlap) { |
- lastSelected = isBackward ? this._anchorSelection : this._headSelection; |
- } |
- |
- if (isBackward) { |
- this._anchorSelection = lastSelected; |
- this._headSelection = firstSelected; |
- } else { |
- this._anchorSelection = firstSelected; |
- this._headSelection = lastSelected; |
- } |
- this._selectionIsBackward = isBackward; |
- return true; |
+ this._update(); |
} |
- /** |
- * @param {?Selection} selection |
- */ |
- _restoreSelection(selection) { |
- var anchorElement = null; |
- var anchorOffset; |
- if (this._firstActiveIndex <= this._anchorSelection.item && this._anchorSelection.item <= this._lastActiveIndex) { |
- anchorElement = this._anchorSelection.node; |
- anchorOffset = this._anchorSelection.offset; |
- } else { |
- if (this._anchorSelection.item < this._firstActiveIndex) |
- anchorElement = this._topGapElement; |
- else if (this._anchorSelection.item > this._lastActiveIndex) |
- anchorElement = this._bottomGapElement; |
- anchorOffset = this._selectionIsBackward ? 1 : 0; |
- } |
- |
- var headElement = null; |
- var headOffset; |
- if (this._firstActiveIndex <= this._headSelection.item && this._headSelection.item <= this._lastActiveIndex) { |
- headElement = this._headSelection.node; |
- headOffset = this._headSelection.offset; |
- } else { |
- if (this._headSelection.item < this._firstActiveIndex) |
- headElement = this._topGapElement; |
- else if (this._headSelection.item > this._lastActiveIndex) |
- headElement = this._bottomGapElement; |
- headOffset = this._selectionIsBackward ? 0 : 1; |
- } |
- |
- selection.setBaseAndExtent(anchorElement, anchorOffset, headElement, headOffset); |
- } |
- |
- refresh() { |
- this._observer.disconnect(); |
- this._innerRefresh(); |
- if (this._stickToBottom) |
- this._observer.observe(this._contentElement, this._observerConfig); |
- } |
- |
- _innerRefresh() { |
- if (!this._visibleHeight()) |
- return; // Do nothing for invisible controls. |
- |
- if (!this._itemCount) { |
- for (var i = 0; i < this._renderedItems.length; ++i) |
- this._renderedItems[i].willHide(); |
- this._renderedItems = []; |
- this._contentElement.removeChildren(); |
- this._topGapElement.style.height = '0px'; |
- this._bottomGapElement.style.height = '0px'; |
- this._firstActiveIndex = -1; |
- this._lastActiveIndex = -1; |
+ _update() { |
+ if (!this._cumulativeHeights) { |
+ this.refresh(); |
return; |
} |
- var selection = this.element.getComponentSelection(); |
- var shouldRestoreSelection = this._updateSelectionModel(selection); |
- |
- var visibleFrom = this.element.scrollTop; |
var visibleHeight = this._visibleHeight(); |
- var isInvalidating = !this._cumulativeHeights; |
- |
- for (var i = 0; i < this._renderedItems.length; ++i) { |
- // Tolerate 1-pixel error due to double-to-integer rounding errors. |
- if (this._cumulativeHeights && |
- Math.abs(this._cachedItemHeight(this._firstActiveIndex + i) - this._renderedItems[i].element().offsetHeight) > |
- 1) |
- delete this._cumulativeHeights; |
- } |
- this._rebuildCumulativeHeightsIfNeeded(); |
- var oldFirstActiveIndex = this._firstActiveIndex; |
- var oldLastActiveIndex = this._lastActiveIndex; |
+ var visibleFrom = this.element.scrollTop; |
var activeHeight = visibleHeight * 2; |
- // When the viewport is scrolled to the bottom, using the cumulative heights estimate is not |
- // precise enough to determine next visible indices. This stickToBottom check avoids extra |
- // calls to refresh in those cases. |
- if (this._stickToBottom) { |
- this._firstActiveIndex = |
- Math.max(this._itemCount - Math.ceil(activeHeight / this._provider.minimumRowHeight()), 0); |
- this._lastActiveIndex = this._itemCount - 1; |
- } else { |
- this._firstActiveIndex = Math.max( |
- Array.prototype.lowerBound.call( |
- this._cumulativeHeights, visibleFrom + 1 - (activeHeight - visibleHeight) / 2), |
- 0); |
- // Proactively render more rows in case some of them will be collapsed without triggering refresh. @see crbug.com/390169 |
- this._lastActiveIndex = this._firstActiveIndex + Math.ceil(activeHeight / this._provider.minimumRowHeight()) - 1; |
- this._lastActiveIndex = Math.min(this._lastActiveIndex, this._itemCount - 1); |
- } |
- |
- var topGapHeight = this._cumulativeHeights[this._firstActiveIndex - 1] || 0; |
- var bottomGapHeight = |
- this._cumulativeHeights[this._cumulativeHeights.length - 1] - this._cumulativeHeights[this._lastActiveIndex]; |
- |
- /** |
- * @this {UI.ViewportControl} |
- */ |
- function prepare() { |
- this._topGapElement.style.height = topGapHeight + 'px'; |
- this._bottomGapElement.style.height = bottomGapHeight + 'px'; |
- this._topGapElement._active = !!topGapHeight; |
- this._bottomGapElement._active = !!bottomGapHeight; |
- this._contentElement.style.setProperty('height', '10000000px'); |
- } |
- |
- if (isInvalidating) |
- this._fullViewportUpdate(prepare.bind(this)); |
- else |
- this._partialViewportUpdate(oldFirstActiveIndex, oldLastActiveIndex, prepare.bind(this)); |
- this._contentElement.style.removeProperty('height'); |
- // Should be the last call in the method as it might force layout. |
- if (shouldRestoreSelection) |
- this._restoreSelection(selection); |
- if (this._stickToBottom) |
- this.element.scrollTop = 10000000; |
- } |
+ var firstActiveIndex = Math.max( |
+ Array.prototype.lowerBound.call(this._cumulativeHeights, visibleFrom + 1 - (activeHeight - visibleHeight) / 2), |
+ 0); |
+ var lastActiveIndex = Math.min( |
+ Array.prototype.lowerBound.call( |
+ this._cumulativeHeights, visibleFrom + visibleHeight + (activeHeight - visibleHeight) / 2), |
+ this._itemCount - 1); |
- /** |
- * @param {function()} prepare |
- */ |
- _fullViewportUpdate(prepare) { |
- for (var i = 0; i < this._renderedItems.length; ++i) |
- this._renderedItems[i].willHide(); |
- prepare(); |
- this._renderedItems = []; |
- this._contentElement.removeChildren(); |
- for (var i = this._firstActiveIndex; i <= this._lastActiveIndex; ++i) { |
- var viewportElement = this._providerElement(i); |
- this._contentElement.appendChild(viewportElement.element()); |
- this._renderedItems.push(viewportElement); |
- } |
- for (var i = 0; i < this._renderedItems.length; ++i) |
- this._renderedItems[i].wasShown(); |
- } |
- |
- /** |
- * @param {number} oldFirstActiveIndex |
- * @param {number} oldLastActiveIndex |
- * @param {function()} prepare |
- */ |
- _partialViewportUpdate(oldFirstActiveIndex, oldLastActiveIndex, prepare) { |
- var willBeHidden = []; |
- for (var i = 0; i < this._renderedItems.length; ++i) { |
- var index = oldFirstActiveIndex + i; |
- if (index < this._firstActiveIndex || this._lastActiveIndex < index) |
- willBeHidden.push(this._renderedItems[i]); |
+ var children = this._innerElement.children; |
+ for (var i = children.length - 1; i >= 0; --i) { |
+ var element = children[i]; |
+ if (element[this._indexSymbol] < firstActiveIndex || element[this._indexSymbol] > lastActiveIndex) |
+ element.remove(); |
} |
- for (var i = 0; i < willBeHidden.length; ++i) |
- willBeHidden[i].willHide(); |
- prepare(); |
- for (var i = 0; i < willBeHidden.length; ++i) |
- willBeHidden[i].element().remove(); |
- this._renderedItems = []; |
- var anchor = this._contentElement.firstChild; |
- var wasShown = []; |
- for (var i = this._firstActiveIndex; i <= this._lastActiveIndex; ++i) { |
- var viewportElement = this._providerElement(i); |
- var element = viewportElement.element(); |
- if (element !== anchor) { |
- this._contentElement.insertBefore(element, anchor); |
- wasShown.push(viewportElement); |
- } else { |
- anchor = anchor.nextSibling; |
- } |
- this._renderedItems.push(viewportElement); |
- } |
- for (var i = 0; i < wasShown.length; ++i) |
- wasShown[i].wasShown(); |
+ for (var i = firstActiveIndex; i <= lastActiveIndex; ++i) |
+ this._insertElement(i); |
} |
/** |
- * @return {?string} |
- */ |
- _selectedText() { |
- this._updateSelectionModel(this.element.getComponentSelection()); |
- if (!this._headSelection || !this._anchorSelection) |
- return null; |
- |
- var startSelection = null; |
- var endSelection = null; |
- if (this._selectionIsBackward) { |
- startSelection = this._headSelection; |
- endSelection = this._anchorSelection; |
- } else { |
- startSelection = this._anchorSelection; |
- endSelection = this._headSelection; |
- } |
- |
- var textLines = []; |
- for (var i = startSelection.item; i <= endSelection.item; ++i) |
- textLines.push(this._providerElement(i).element().deepTextContent()); |
- |
- var endSelectionElement = this._providerElement(endSelection.item).element(); |
- if (endSelection.node && endSelection.node.isSelfOrDescendant(endSelectionElement)) { |
- var itemTextOffset = this._textOffsetInNode(endSelectionElement, endSelection.node, endSelection.offset); |
- textLines[textLines.length - 1] = textLines.peekLast().substring(0, itemTextOffset); |
- } |
- |
- var startSelectionElement = this._providerElement(startSelection.item).element(); |
- if (startSelection.node && startSelection.node.isSelfOrDescendant(startSelectionElement)) { |
- var itemTextOffset = this._textOffsetInNode(startSelectionElement, startSelection.node, startSelection.offset); |
- textLines[0] = textLines[0].substring(itemTextOffset); |
- } |
- |
- return textLines.join('\n'); |
- } |
- |
- /** |
- * @param {!Element} itemElement |
- * @param {!Node} container |
- * @param {number} offset |
- * @return {number} |
+ * @param {number} index |
*/ |
- _textOffsetInNode(itemElement, container, offset) { |
- var chars = 0; |
- var node = itemElement; |
- while ((node = node.traverseNextTextNode()) && !node.isSelfOrDescendant(container)) |
- chars += node.textContent.length; |
- return chars + offset; |
- } |
+ _insertElement(index) { |
+ var element = this._provider.itemElement(index); |
+ if (!element || element.parentElement === this._innerElement) |
+ return; |
- /** |
- * @param {!Event} event |
- */ |
- _onScroll(event) { |
- this.refresh(); |
+ element.style.position = 'absolute'; |
+ element.style.top = (this._cumulativeHeights[index - 1] || 0) + 'px'; |
+ element.style.left = '0'; |
+ element.style.right = '0'; |
+ element[this._indexSymbol] = index; |
+ this._innerElement.appendChild(element); |
} |
/** |
* @return {number} |
*/ |
firstVisibleIndex() { |
- var firstVisibleIndex = |
- Math.max(Array.prototype.lowerBound.call(this._cumulativeHeights, this.element.scrollTop + 1), 0); |
- return Math.max(firstVisibleIndex, this._firstActiveIndex); |
+ return Math.max(Array.prototype.lowerBound.call(this._cumulativeHeights, this.element.scrollTop + 1), 0); |
} |
/** |
* @return {number} |
*/ |
lastVisibleIndex() { |
- var lastVisibleIndex; |
- if (this._stickToBottom) { |
- lastVisibleIndex = this._itemCount - 1; |
- } else { |
- lastVisibleIndex = |
- this.firstVisibleIndex() + Math.ceil(this._visibleHeight() / this._provider.minimumRowHeight()) - 1; |
- } |
- return Math.min(lastVisibleIndex, this._lastActiveIndex); |
- } |
- |
- /** |
- * @return {?Element} |
- */ |
- renderedElementAt(index) { |
- if (index < this._firstActiveIndex) |
- return null; |
- if (index > this._lastActiveIndex) |
- return null; |
- return this._renderedItems[index - this._firstActiveIndex].element(); |
+ return Math.min( |
+ Array.prototype.lowerBound.call(this._cumulativeHeights, this.element.scrollTop + this._visibleHeight()), |
+ this._itemCount); |
} |
/** |
@@ -545,31 +118,22 @@ UI.ViewportControl = class { |
* @param {number} index |
*/ |
forceScrollItemToBeFirst(index) { |
- this.setStickToBottom(false); |
- this._rebuildCumulativeHeightsIfNeeded(); |
this.element.scrollTop = index > 0 ? this._cumulativeHeights[index - 1] : 0; |
- if (this.element.isScrolledToBottom()) |
- this.setStickToBottom(true); |
- this.refresh(); |
+ this._update(); |
} |
/** |
* @param {number} index |
*/ |
forceScrollItemToBeLast(index) { |
- this.setStickToBottom(false); |
- this._rebuildCumulativeHeightsIfNeeded(); |
this.element.scrollTop = this._cumulativeHeights[index] - this._visibleHeight(); |
- if (this.element.isScrolledToBottom()) |
- this.setStickToBottom(true); |
- this.refresh(); |
+ this._update(); |
} |
/** |
* @return {number} |
*/ |
_visibleHeight() { |
- // Use offsetHeight instead of clientHeight to avoid being affected by horizontal scroll. |
return this.element.offsetHeight; |
} |
}; |
@@ -584,7 +148,7 @@ UI.ViewportControl.Provider.prototype = { |
* @param {number} index |
* @return {number} |
*/ |
- fastHeight(index) { |
+ fastItemHeight(index) { |
return 0; |
}, |
@@ -596,65 +160,10 @@ UI.ViewportControl.Provider.prototype = { |
}, |
/** |
- * @return {number} |
- */ |
- minimumRowHeight() { |
- return 0; |
- }, |
- |
- /** |
* @param {number} index |
- * @return {?UI.ViewportElement} |
+ * @return {?Element} |
*/ |
itemElement(index) { |
return null; |
} |
}; |
- |
-/** |
- * @interface |
- */ |
-UI.ViewportElement = function() {}; |
-UI.ViewportElement.prototype = { |
- willHide() {}, |
- |
- wasShown() {}, |
- |
- /** |
- * @return {!Element} |
- */ |
- element() {}, |
-}; |
- |
-/** |
- * @implements {UI.ViewportElement} |
- * @unrestricted |
- */ |
-UI.StaticViewportElement = class { |
- /** |
- * @param {!Element} element |
- */ |
- constructor(element) { |
- this._element = element; |
- } |
- |
- /** |
- * @override |
- */ |
- willHide() { |
- } |
- |
- /** |
- * @override |
- */ |
- wasShown() { |
- } |
- |
- /** |
- * @override |
- * @return {!Element} |
- */ |
- element() { |
- return this._element; |
- } |
-}; |