| Index: chrome/browser/resources/shared/js/cr/ui/grid.js
|
| ===================================================================
|
| --- chrome/browser/resources/shared/js/cr/ui/grid.js (revision 177292)
|
| +++ chrome/browser/resources/shared/js/cr/ui/grid.js (working copy)
|
| @@ -1,425 +0,0 @@
|
| -// Copyright (c) 2012 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.
|
| -
|
| -// require: list_selection_model.js
|
| -// require: list_selection_controller.js
|
| -// require: list.js
|
| -
|
| -/**
|
| - * @fileoverview This implements a grid control. Grid contains a bunch of
|
| - * similar elements placed in multiple columns. It's pretty similar to the list,
|
| - * except the multiple columns layout.
|
| - */
|
| -
|
| -cr.define('cr.ui', function() {
|
| - /** @const */ var ListSelectionController = cr.ui.ListSelectionController;
|
| - /** @const */ var List = cr.ui.List;
|
| - /** @const */ var ListItem = cr.ui.ListItem;
|
| -
|
| - /**
|
| - * Creates a new grid item element.
|
| - * @param {*} dataItem The data item.
|
| - * @constructor
|
| - * @extends {cr.ui.ListItem}
|
| - */
|
| - function GridItem(dataItem) {
|
| - var el = cr.doc.createElement('li');
|
| - el.dataItem = dataItem;
|
| - el.__proto__ = GridItem.prototype;
|
| - return el;
|
| - }
|
| -
|
| - GridItem.prototype = {
|
| - __proto__: ListItem.prototype,
|
| -
|
| - /**
|
| - * Called when an element is decorated as a grid item.
|
| - */
|
| - decorate: function() {
|
| - ListItem.prototype.decorate.call(this, arguments);
|
| - this.textContent = this.dataItem;
|
| - }
|
| - };
|
| -
|
| - /**
|
| - * Creates a new grid element.
|
| - * @param {Object=} opt_propertyBag Optional properties.
|
| - * @constructor
|
| - * @extends {cr.ui.List}
|
| - */
|
| - var Grid = cr.ui.define('grid');
|
| -
|
| - Grid.prototype = {
|
| - __proto__: List.prototype,
|
| -
|
| - /**
|
| - * The number of columns in the grid. Either set by the user, or lazy
|
| - * calculated as the maximum number of items fitting in the grid width.
|
| - * @type {number}
|
| - * @private
|
| - */
|
| - columns_: 0,
|
| -
|
| - /**
|
| - * Function used to create grid items.
|
| - * @type {function(): !GridItem}
|
| - * @override
|
| - */
|
| - itemConstructor_: GridItem,
|
| -
|
| - /**
|
| - * Whether or not the rows on list have various heights.
|
| - * Shows a warning at the setter because cr.ui.Grid does not support this.
|
| - * @type {boolean}
|
| - */
|
| - get fixedHeight() {
|
| - return true;
|
| - },
|
| - set fixedHeight(fixedHeight) {
|
| - if (!fixedHeight)
|
| - console.warn('cr.ui.Grid does not support fixedHeight = false');
|
| - },
|
| -
|
| - /**
|
| - * @return {number} The number of columns determined by width of the grid
|
| - * and width of the items.
|
| - * @private
|
| - */
|
| - getColumnCount_: function() {
|
| - // Size comes here with margin already collapsed.
|
| - var size = this.getDefaultItemSize_();
|
| -
|
| - // We should uncollapse margin, since margin isn't collapsed for
|
| - // inline-block elements according to css spec which are thumbnail items.
|
| -
|
| - var width = size.width + Math.min(size.marginLeft, size.marginRight);
|
| - var height = size.height + Math.min(size.marginTop, size.marginBottom);
|
| -
|
| - if (!width || !height)
|
| - return 0;
|
| -
|
| - var itemCount = this.dataModel ? this.dataModel.length : 0;
|
| - if (!itemCount)
|
| - return 0;
|
| -
|
| - var columns = Math.floor(this.clientWidthWithoutScrollbar_ / width);
|
| - if (!columns)
|
| - return 0;
|
| -
|
| - var rows = Math.ceil(itemCount / columns);
|
| - if (rows * height <= this.clientHeight_)
|
| - return columns;
|
| -
|
| - return Math.floor(this.clientWidthWithScrollbar_ / width);
|
| - },
|
| -
|
| - /**
|
| - * Measure and cache client width and height with and without scrollbar.
|
| - * Must be updated when offsetWidth and/or offsetHeight changed.
|
| - */
|
| - updateMetrics_: function() {
|
| - // Check changings that may affect number of columns.
|
| - var offsetWidth = this.offsetWidth;
|
| - var offsetHeight = this.offsetHeight;
|
| - var overflowY = getComputedStyle(this).overflowY;
|
| -
|
| - if (this.lastOffsetWidth_ == offsetWidth &&
|
| - this.lastOverflowY == overflowY) {
|
| - this.lastOffsetHeight_ = offsetHeight;
|
| - return;
|
| - }
|
| -
|
| - this.lastOffsetWidth_ = offsetWidth;
|
| - this.lastOffsetHeight_ = offsetHeight;
|
| - this.lastOverflowY = overflowY;
|
| - this.columns_ = 0;
|
| -
|
| - if (overflowY == 'auto' && offsetWidth > 0) {
|
| - // Column number may depend on whether scrollbar is present or not.
|
| - var originalClientWidth = this.clientWidth;
|
| - // At first make sure there is no scrollbar and calculate clientWidth
|
| - // (triggers reflow).
|
| - this.style.overflowY = 'hidden';
|
| - this.clientWidthWithoutScrollbar_ = this.clientWidth;
|
| - this.clientHeight_ = this.clientHeight;
|
| - if (this.clientWidth != originalClientWidth) {
|
| - // If clientWidth changed then previously scrollbar was shown.
|
| - this.clientWidthWithScrollbar_ = originalClientWidth;
|
| - } else {
|
| - // Show scrollbar and recalculate clientWidth (triggers reflow).
|
| - this.style.overflowY = 'scroll';
|
| - this.clientWidthWithScrollbar_ = this.clientWidth;
|
| - }
|
| - this.style.overflowY = '';
|
| - } else {
|
| - this.clientWidthWithoutScrollbar_ = this.clientWidthWithScrollbar_ =
|
| - this.clientWidth;
|
| - this.clientHeight_ = this.clientHeight;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * The number of columns in the grid. If not set, determined automatically
|
| - * as the maximum number of items fitting in the grid width.
|
| - * @type {number}
|
| - */
|
| - get columns() {
|
| - if (!this.columns_) {
|
| - this.columns_ = this.getColumnCount_();
|
| - }
|
| - return this.columns_ || 1;
|
| - },
|
| - set columns(value) {
|
| - if (value >= 0 && value != this.columns_) {
|
| - this.columns_ = value;
|
| - this.redraw();
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * @param {number} index The index of the item.
|
| - * @return {number} The top position of the item inside the list, not taking
|
| - * into account lead item. May vary in the case of multiple columns.
|
| - * @override
|
| - */
|
| - getItemTop: function(index) {
|
| - return Math.floor(index / this.columns) * this.getDefaultItemHeight_();
|
| - },
|
| -
|
| - /**
|
| - * @param {number} index The index of the item.
|
| - * @return {number} The row of the item. May vary in the case
|
| - * of multiple columns.
|
| - * @override
|
| - */
|
| - getItemRow: function(index) {
|
| - return Math.floor(index / this.columns);
|
| - },
|
| -
|
| - /**
|
| - * @param {number} row The row.
|
| - * @return {number} The index of the first item in the row.
|
| - * @override
|
| - */
|
| - getFirstItemInRow: function(row) {
|
| - return row * this.columns;
|
| - },
|
| -
|
| - /**
|
| - * Creates the selection controller to use internally.
|
| - * @param {cr.ui.ListSelectionModel} sm The underlying selection model.
|
| - * @return {!cr.ui.ListSelectionController} The newly created selection
|
| - * controller.
|
| - * @override
|
| - */
|
| - createSelectionController: function(sm) {
|
| - return new GridSelectionController(sm, this);
|
| - },
|
| -
|
| - /**
|
| - * Calculates the number of items fitting in the given viewport.
|
| - * @param {number} scrollTop The scroll top position.
|
| - * @param {number} clientHeight The height of viewport.
|
| - * @return {{first: number, length: number, last: number}} The index of
|
| - * first item in view port, The number of items, The item past the last.
|
| - * @override
|
| - */
|
| - getItemsInViewPort: function(scrollTop, clientHeight) {
|
| - var itemHeight = this.getDefaultItemHeight_();
|
| - var firstIndex =
|
| - this.autoExpands ? 0 : this.getIndexForListOffset_(scrollTop);
|
| - var columns = this.columns;
|
| - var count = this.autoExpands_ ? this.dataModel.length : Math.max(
|
| - columns * (Math.ceil(clientHeight / itemHeight) + 1),
|
| - this.countItemsInRange_(firstIndex, scrollTop + clientHeight));
|
| - count = columns * Math.ceil(count / columns);
|
| - count = Math.min(count, this.dataModel.length - firstIndex);
|
| - return {
|
| - first: firstIndex,
|
| - length: count,
|
| - last: firstIndex + count - 1
|
| - };
|
| - },
|
| -
|
| - /**
|
| - * Merges list items. Calls the base class implementation and then
|
| - * puts spacers on the right places.
|
| - * @param {number} firstIndex The index of first item, inclusively.
|
| - * @param {number} lastIndex The index of last item, exclusively.
|
| - * @param {Object.<string, ListItem>} cachedItems Old items cache.
|
| - * @param {Object.<string, ListItem>} newCachedItems New items cache.
|
| - * @override
|
| - */
|
| - mergeItems: function(firstIndex, lastIndex, cachedItems, newCachedItems) {
|
| - List.prototype.mergeItems.call(this,
|
| - firstIndex, lastIndex, cachedItems, newCachedItems);
|
| -
|
| - var afterFiller = this.afterFiller_;
|
| - var columns = this.columns;
|
| -
|
| - for (var item = this.beforeFiller_.nextSibling; item != afterFiller;) {
|
| - var next = item.nextSibling;
|
| - if (isSpacer(item)) {
|
| - // Spacer found on a place it mustn't be.
|
| - this.removeChild(item);
|
| - item = next;
|
| - continue;
|
| - }
|
| - var index = item.listIndex;
|
| - var nextIndex = index + 1;
|
| -
|
| - // Invisible pinned item could be outside of the
|
| - // [firstIndex, lastIndex). Ignore it.
|
| - if (index >= firstIndex && nextIndex < lastIndex &&
|
| - nextIndex % columns == 0) {
|
| - if (isSpacer(next)) {
|
| - // Leave the spacer on its place.
|
| - item = next.nextSibling;
|
| - } else {
|
| - // Insert spacer.
|
| - var spacer = this.ownerDocument.createElement('div');
|
| - spacer.className = 'spacer';
|
| - this.insertBefore(spacer, next);
|
| - item = next;
|
| - }
|
| - } else
|
| - item = next;
|
| - }
|
| -
|
| - function isSpacer(child) {
|
| - return child.classList.contains('spacer') &&
|
| - child != afterFiller; // Must not be removed.
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Returns the height of after filler in the list.
|
| - * @param {number} lastIndex The index of item past the last in viewport.
|
| - * @return {number} The height of after filler.
|
| - * @override
|
| - */
|
| - getAfterFillerHeight: function(lastIndex) {
|
| - var columns = this.columns;
|
| - var itemHeight = this.getDefaultItemHeight_();
|
| - // We calculate the row of last item, and the row of last shown item.
|
| - // The difference is the number of rows not shown.
|
| - var afterRows = Math.floor((this.dataModel.length - 1) / columns) -
|
| - Math.floor((lastIndex - 1) / columns);
|
| - return afterRows * itemHeight;
|
| - },
|
| -
|
| - /**
|
| - * Returns true if the child is a list item.
|
| - * @param {Node} child Child of the list.
|
| - * @return {boolean} True if a list item.
|
| - */
|
| - isItem: function(child) {
|
| - // Non-items are before-, afterFiller and spacers added in mergeItems.
|
| - return child.nodeType == Node.ELEMENT_NODE &&
|
| - !child.classList.contains('spacer');
|
| - },
|
| -
|
| - redraw: function() {
|
| - this.updateMetrics_();
|
| - var itemCount = this.dataModel ? this.dataModel.length : 0;
|
| - if (this.lastItemCount_ != itemCount) {
|
| - this.lastItemCount_ = itemCount;
|
| - // Force recalculation.
|
| - this.columns_ = 0;
|
| - }
|
| -
|
| - List.prototype.redraw.call(this);
|
| - }
|
| - };
|
| -
|
| - /**
|
| - * Creates a selection controller that is to be used with grids.
|
| - * @param {cr.ui.ListSelectionModel} selectionModel The selection model to
|
| - * interact with.
|
| - * @param {cr.ui.Grid} grid The grid to interact with.
|
| - * @constructor
|
| - * @extends {!cr.ui.ListSelectionController}
|
| - */
|
| - function GridSelectionController(selectionModel, grid) {
|
| - this.selectionModel_ = selectionModel;
|
| - this.grid_ = grid;
|
| - }
|
| -
|
| - GridSelectionController.prototype = {
|
| - __proto__: ListSelectionController.prototype,
|
| -
|
| - /**
|
| - * Check if accessibility is enabled: if ChromeVox is running
|
| - * (which provides spoken feedback for accessibility), make up/down
|
| - * behave the same as left/right. That's because the 2-dimensional
|
| - * structure of the grid isn't exposed, so it makes more sense to a
|
| - * user who is relying on spoken feedback to flatten it.
|
| - * @return {boolean} True if accessibility is enabled.
|
| - */
|
| - isAccessibilityEnabled: function() {
|
| - return window.cvox && cvox.Api &&
|
| - cvox.Api.isChromeVoxActive && cvox.Api.isChromeVoxActive();
|
| - },
|
| -
|
| - /**
|
| - * Returns the index below (y axis) the given element.
|
| - * @param {number} index The index to get the index below.
|
| - * @return {number} The index below or -1 if not found.
|
| - * @override
|
| - */
|
| - getIndexBelow: function(index) {
|
| - if (this.isAccessibilityEnabled())
|
| - return this.getIndexAfter(index);
|
| - var last = this.getLastIndex();
|
| - if (index == last)
|
| - return -1;
|
| - index += this.grid_.columns;
|
| - return Math.min(index, last);
|
| - },
|
| -
|
| - /**
|
| - * Returns the index above (y axis) the given element.
|
| - * @param {number} index The index to get the index above.
|
| - * @return {number} The index below or -1 if not found.
|
| - * @override
|
| - */
|
| - getIndexAbove: function(index) {
|
| - if (this.isAccessibilityEnabled())
|
| - return this.getIndexBefore(index);
|
| - if (index == 0)
|
| - return -1;
|
| - index -= this.grid_.columns;
|
| - return Math.max(index, 0);
|
| - },
|
| -
|
| - /**
|
| - * Returns the index before (x axis) the given element.
|
| - * @param {number} index The index to get the index before.
|
| - * @return {number} The index before or -1 if not found.
|
| - * @override
|
| - */
|
| - getIndexBefore: function(index) {
|
| - return index - 1;
|
| - },
|
| -
|
| - /**
|
| - * Returns the index after (x axis) the given element.
|
| - * @param {number} index The index to get the index after.
|
| - * @return {number} The index after or -1 if not found.
|
| - * @override
|
| - */
|
| - getIndexAfter: function(index) {
|
| - if (index == this.getLastIndex()) {
|
| - return -1;
|
| - }
|
| - return index + 1;
|
| - }
|
| - };
|
| -
|
| - return {
|
| - Grid: Grid,
|
| - GridItem: GridItem,
|
| - GridSelectionController: GridSelectionController
|
| - };
|
| -});
|
|
|