Index: chrome/browser/resources/ntp_search/tile_page.js |
diff --git a/chrome/browser/resources/ntp_search/tile_page.js b/chrome/browser/resources/ntp_search/tile_page.js |
deleted file mode 100644 |
index c8862cc7be028e9d78cc0ba2b62c26e31b2d91eb..0000000000000000000000000000000000000000 |
--- a/chrome/browser/resources/ntp_search/tile_page.js |
+++ /dev/null |
@@ -1,1132 +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. |
- |
-cr.define('ntp', function() { |
- 'use strict'; |
- |
- /** |
- * The maximum gap from the edge of the scrolling area which will display |
- * the shadow with transparency. After this point the shadow will become |
- * 100% opaque. |
- * @type {number} |
- * @const |
- */ |
- var MAX_SCROLL_SHADOW_GAP = 16; |
- |
- /** |
- * @type {number} |
- * @const |
- */ |
- var SCROLL_BAR_WIDTH = 12; |
- |
- //---------------------------------------------------------------------------- |
- // Tile |
- //---------------------------------------------------------------------------- |
- |
- /** |
- * A virtual Tile class. Each TilePage subclass should have its own Tile |
- * subclass implemented too (e.g. MostVisitedPage contains MostVisited |
- * tiles, and MostVisited is a Tile subclass). |
- * @constructor |
- */ |
- function Tile() { |
- console.error('Tile is a virtual class and is not supposed to be ' + |
- 'instantiated'); |
- } |
- |
- /** |
- * Creates a Tile subclass. We need to use this function to create a Tile |
- * subclass because a Tile must also subclass a HTMLElement (which can be |
- * any HTMLElement), so we need to individually add methods and getters here. |
- * @param {Object} Subclass The prototype object of the class we want to be |
- * a Tile subclass. |
- * @param {Object} The extended Subclass object. |
- */ |
- Tile.subclass = function(Subclass) { |
- var Base = Tile.prototype; |
- for (var name in Base) { |
- if (!Subclass.hasOwnProperty(name)) |
- Subclass[name] = Base[name]; |
- } |
- for (var name in TileGetters) { |
- if (!Subclass.hasOwnProperty(name)) |
- Subclass.__defineGetter__(name, TileGetters[name]); |
- } |
- return Subclass; |
- }; |
- |
- Tile.prototype = { |
- // Tile data object. |
- data_: null, |
- |
- /** |
- * Initializes a Tile. |
- */ |
- initialize: function() { |
- this.classList.add('tile'); |
- this.reset(); |
- }, |
- |
- /** |
- * Resets the tile DOM. |
- */ |
- reset: function() { |
- }, |
- |
- /** |
- * The data for this Tile. |
- * @param {Object} data A dictionary of relevant data for the page. |
- */ |
- set data(data) { |
- // TODO(pedrosimonetti): Remove data.filler usage everywhere. |
- if (!data || data.filler) { |
- if (this.data_) |
- this.reset(); |
- return; |
- } |
- |
- this.data_ = data; |
- }, |
- }; |
- |
- var TileGetters = { |
- /** |
- * The TileCell associated to this Tile. |
- * @type {TileCell} |
- */ |
- 'tileCell': function() { |
- return findAncestorByClass(this, 'tile-cell'); |
- }, |
- |
- /** |
- * The index of the Tile. |
- * @type {number} |
- */ |
- 'index': function() { |
- assert(this.tileCell); |
- return this.tileCell.index; |
- }, |
- }; |
- |
- //---------------------------------------------------------------------------- |
- // TileCell |
- //---------------------------------------------------------------------------- |
- |
- /** |
- * Creates a new TileCell object. A TileCell represents a cell in the |
- * TilePage's grid. A TilePage uses TileCells to position Tiles in the proper |
- * place and to animate them individually. Each TileCell is associated to |
- * one Tile at a time (or none if it is a filler object), and that association |
- * might change when the grid is resized. When that happens, the grid is |
- * updated and the Tiles are moved to the proper TileCell. We cannot move the |
- * the TileCell itself during the resize because this transition is animated |
- * with CSS and there's no way to stop CSS animations, and we really want to |
- * animate with CSS to take advantage of hardware acceleration. |
- * @constructor |
- * @extends {HTMLDivElement} |
- * @param {HTMLElement} tile Tile element that will be associated to the cell. |
- */ |
- function TileCell(tile) { |
- var tileCell = cr.doc.createElement('div'); |
- tileCell.__proto__ = TileCell.prototype; |
- tileCell.initialize(tile); |
- |
- return tileCell; |
- } |
- |
- TileCell.prototype = { |
- __proto__: HTMLDivElement.prototype, |
- |
- /** |
- * Initializes a TileCell. |
- * @param {Tile} tile The Tile that will be assigned to this TileCell. |
- */ |
- initialize: function(tile) { |
- this.className = 'tile-cell'; |
- this.assign(tile); |
- }, |
- |
- /** |
- * The index of the TileCell. |
- * @type {number} |
- */ |
- get index() { |
- return Array.prototype.indexOf.call(this.tilePage.tiles_, |
- this.tile); |
- }, |
- |
- /** |
- * The Tile associated to this TileCell. |
- * @type {Tile} |
- */ |
- get tile() { |
- return this.firstElementChild; |
- }, |
- |
- /** |
- * The TilePage associated to this TileCell. |
- * @type {TilePage} |
- */ |
- get tilePage() { |
- return findAncestorByClass(this, 'tile-page'); |
- }, |
- |
- /** |
- * Assigns a Tile to the this TileCell. |
- * @type {TilePage} |
- */ |
- assign: function(tile) { |
- if (this.tile) |
- this.replaceChild(tile, this.tile); |
- else |
- this.appendChild(tile); |
- }, |
- |
- /** |
- * Called when an app is removed from Chrome. Animates its disappearance. |
- * @param {boolean=} opt_animate Whether the animation should be animated. |
- */ |
- doRemove: function(opt_animate) { |
- this.tilePage.removeTile(this.tile, false); |
- }, |
- }; |
- |
- //---------------------------------------------------------------------------- |
- // TilePage |
- //---------------------------------------------------------------------------- |
- |
- /** |
- * Creates a new TilePage object. This object contains tiles and controls |
- * their layout. |
- * @constructor |
- * @extends {HTMLDivElement} |
- */ |
- function TilePage() { |
- var el = cr.doc.createElement('div'); |
- el.__proto__ = TilePage.prototype; |
- |
- return el; |
- } |
- |
- TilePage.prototype = { |
- __proto__: HTMLDivElement.prototype, |
- |
- /** |
- * Reference to the Tile subclass that will be used to create the tiles. |
- * @constructor |
- * @extends {Tile} |
- */ |
- TileClass: Tile, |
- |
- // The config object should be defined by a TilePage subclass if it |
- // wants the non-default behavior. |
- config: { |
- // The width of a cell. |
- cellWidth: 110, |
- // The start margin of a cell (left or right according to text direction). |
- cellMarginStart: 12, |
- // The maximum number of Tiles to be displayed. |
- maxTileCount: 6, |
- // Whether the TilePage content will be scrollable. |
- scrollable: false, |
- }, |
- |
- /** |
- * Initializes a TilePage. |
- */ |
- initialize: function() { |
- this.className = 'tile-page'; |
- |
- // The div that wraps the scrollable element. |
- this.frame_ = this.ownerDocument.createElement('div'); |
- this.frame_.className = 'tile-page-frame'; |
- this.appendChild(this.frame_); |
- |
- // The content/scrollable element. |
- this.content_ = this.ownerDocument.createElement('div'); |
- this.content_.className = 'tile-page-content'; |
- this.frame_.appendChild(this.content_); |
- |
- if (this.config.scrollable) { |
- this.content_.classList.add('scrollable'); |
- |
- // The scrollable shadow top. |
- this.shadowTop_ = this.ownerDocument.createElement('div'); |
- this.shadowTop_.className = 'shadow-top'; |
- this.content_.appendChild(this.shadowTop_); |
- |
- // The scrollable shadow bottom. |
- this.shadowBottom_ = this.ownerDocument.createElement('div'); |
- this.shadowBottom_.className = 'shadow-bottom'; |
- this.content_.appendChild(this.shadowBottom_); |
- } |
- |
- // The div that defines the tile grid viewport. |
- this.tileGrid_ = this.ownerDocument.createElement('div'); |
- this.tileGrid_.className = 'tile-grid'; |
- this.content_.appendChild(this.tileGrid_); |
- |
- // The tile grid contents, which can be scrolled. |
- this.tileGridContent_ = this.ownerDocument.createElement('div'); |
- this.tileGridContent_.className = 'tile-grid-content'; |
- this.tileGrid_.appendChild(this.tileGridContent_); |
- |
- // The list of Tile elements which is used to fill the TileGrid cells. |
- this.tiles_ = []; |
- |
- // TODO(pedrosimonetti): Check duplication of these methods. |
- this.addEventListener('cardselected', this.handleCardSelection_); |
- this.addEventListener('carddeselected', this.handleCardDeselection_); |
- |
- this.tileGrid_.addEventListener('webkitTransitionEnd', |
- this.onTileGridTransitionEnd_.bind(this)); |
- |
- this.content_.addEventListener('scroll', this.onScroll.bind(this)); |
- }, |
- |
- /** |
- * The list of Tile elements. |
- * @type {Array<Tile>} |
- */ |
- get tiles() { |
- return this.tiles_; |
- }, |
- |
- /** |
- * The number of Tiles in this TilePage. |
- * @type {number} |
- */ |
- get tileCount() { |
- return this.tiles_.length; |
- }, |
- |
- /** |
- * Whether or not this TilePage is selected. |
- * @type {boolean} |
- */ |
- get selected() { |
- return Array.prototype.indexOf.call(this.parentNode.children, this) == |
- ntp.getCardSlider().currentCard; |
- }, |
- |
- /** |
- * Removes the tilePage from the DOM and cleans up event handlers. |
- */ |
- remove: function() { |
- // This checks arguments.length as most remove functions have a boolean |
- // |opt_animate| argument, but that's not necesarilly applicable to |
- // removing a tilePage. Selecting a different card in an animated way and |
- // deleting the card afterward is probably a better choice. |
- assert(typeof arguments[0] != 'boolean', |
- 'This function takes no |opt_animate| argument.'); |
- this.parentNode.removeChild(this); |
- }, |
- |
- /** |
- * Notify interested subscribers that a tile has been removed from this |
- * page. |
- * @param {Tile} tile The newly added tile. |
- * @param {number} index The index of the tile that was added. |
- * @param {boolean} wasAnimated Whether the removal was animated. |
- */ |
- fireAddedEvent: function(tile, index, wasAnimated) { |
- var e = document.createEvent('Event'); |
- e.initEvent('tilePage:tile_added', true, true); |
- e.addedIndex = index; |
- e.addedTile = tile; |
- e.wasAnimated = wasAnimated; |
- this.dispatchEvent(e); |
- }, |
- |
- /** |
- * Removes the given tile and animates the repositioning of the other tiles. |
- * @param {boolean=} opt_animate Whether the removal should be animated. |
- * @param {boolean=} opt_dontNotify Whether a page should be removed if the |
- * last tile is removed from it. |
- */ |
- removeTile: function(tile, opt_animate, opt_dontNotify) { |
- var tiles = this.tiles; |
- var index = tiles.indexOf(tile); |
- tile.parentNode.removeChild(tile); |
- tiles.splice(index, 1); |
- this.renderGrid(); |
- |
- if (!opt_dontNotify) |
- this.fireRemovedEvent(tile, index, !!opt_animate); |
- }, |
- |
- /** |
- * Notify interested subscribers that a tile has been removed from this |
- * page. |
- * @param {TileCell} tile The tile that was removed. |
- * @param {number} oldIndex Where the tile was positioned before removal. |
- * @param {boolean} wasAnimated Whether the removal was animated. |
- */ |
- fireRemovedEvent: function(tile, oldIndex, wasAnimated) { |
- var e = document.createEvent('Event'); |
- e.initEvent('tilePage:tile_removed', true, true); |
- e.removedIndex = oldIndex; |
- e.removedTile = tile; |
- e.wasAnimated = wasAnimated; |
- this.dispatchEvent(e); |
- }, |
- |
- /** |
- * Removes all tiles from the page. |
- */ |
- removeAllTiles: function() { |
- while (this.tiles.length > 0) { |
- this.removeTile(this.tiles[this.tiles.length - 1]); |
- } |
- }, |
- |
- /** |
- * Called when the page is selected (in the card selector). |
- * @param {Event} e A custom cardselected event. |
- * @private |
- */ |
- handleCardSelection_: function(e) { |
- ntp.layout(); |
- }, |
- |
- /** |
- * Called when the page loses selection (in the card selector). |
- * @param {Event} e A custom carddeselected event. |
- * @private |
- */ |
- handleCardDeselection_: function(e) { |
- }, |
- |
- // ######################################################################### |
- // Extended Chrome Instant |
- // ######################################################################### |
- |
- |
- // properties |
- // ------------------------------------------------------------------------- |
- |
- // The number of columns. |
- colCount_: 0, |
- // The number of rows. |
- rowCount_: 0, |
- // The number of visible rows. We initialize this value with zero so |
- // we can detect when the first time the page is rendered. |
- numOfVisibleRows_: 1, |
- // The number of the last column being animated. We initialize this value |
- // with zero so we can detect when the first time the page is rendered. |
- animatingColCount_: 0, |
- // The index of the topmost row visible. |
- pageOffset_: 0, |
- // Data object representing the tiles. |
- dataList_: null, |
- |
- /** |
- * Appends a tile to the end of the tile grid. |
- * @param {Tile} tile The tile to be added. |
- * @param {number} index The location in the tile grid to insert it at. |
- * @protected |
- */ |
- appendTile: function(tile) { |
- var index = this.tiles_.length; |
- this.addTileAt(tile, index); |
- }, |
- |
- /** |
- * Adds the given element to the tile grid. |
- * @param {Tile} tile The tile to be added. |
- * @param {number} index The location in the tile grid to insert it at. |
- * @protected |
- */ |
- addTileAt: function(tile, index) { |
- this.tiles_.splice(index, 0, tile); |
- this.fireAddedEvent(tile, index, false); |
- this.renderGrid(); |
- }, |
- |
- /** |
- * Create a blank tile. |
- * @protected |
- */ |
- createTile_: function() { |
- return new this.TileClass(); |
- }, |
- |
- /** |
- * Create blank tiles. |
- * @param {number} count The desired number of Tiles to be created. If this |
- * value the maximum value defined in |config.maxTileCount|, the maximum |
- * value will be used instead. |
- * @protected |
- */ |
- createTiles_: function(count) { |
- count = Math.min(count, this.config.maxTileCount); |
- for (var i = 0; i < count; i++) { |
- this.appendTile(this.createTile_()); |
- } |
- }, |
- |
- /** |
- * This method will create/remove necessary/unnecessary tiles, render the |
- * grid when the number of tiles has changed, and finally will call |
- * |updateTiles_| which will in turn render the individual tiles. |
- * @protected |
- */ |
- updateGrid: function() { |
- var dataListLength = this.dataList_.length; |
- var tileCount = this.tileCount; |
- // Create or remove tiles if necessary. |
- if (tileCount < dataListLength) { |
- this.createTiles_(dataListLength - tileCount); |
- } else if (tileCount > dataListLength) { |
- var tiles = this.tiles_; |
- while (tiles.length > dataListLength) { |
- var previousLength = tiles.length; |
- // It doesn't matter which tiles are being removed here because |
- // they're going to be reconstructed below when calling updateTiles_ |
- // method, so the first tiles are being removed here. |
- this.removeTile(tiles[0]); |
- assert(tiles.length < previousLength); |
- } |
- } |
- |
- this.updateTiles_(); |
- }, |
- |
- /** |
- * Update the tiles after a change to |dataList_|. |
- */ |
- updateTiles_: function() { |
- var maxTileCount = this.config.maxTileCount; |
- var dataList = this.dataList_; |
- var tiles = this.tiles; |
- for (var i = 0; i < maxTileCount; i++) { |
- var data = dataList[i]; |
- var tile = tiles[i]; |
- |
- // TODO(pedrosimonetti): What do we do when there's no tile here? |
- if (!tile) |
- return; |
- |
- if (i >= dataList.length) |
- tile.reset(); |
- else |
- tile.data = data; |
- } |
- }, |
- |
- /** |
- * Sets the dataList that will be used to create Tiles. |
- * TODO(pedrosimonetti): Use setters and getters instead. |
- */ |
- setDataList: function(dataList) { |
- this.dataList_ = dataList.slice(0, this.config.maxTileCount); |
- }, |
- |
- // internal helpers |
- // ------------------------------------------------------------------------- |
- |
- /** |
- * Gets the required width for a Tile. |
- * @private |
- */ |
- getTileRequiredWidth_: function() { |
- var config = this.config; |
- return config.cellWidth + config.cellMarginStart; |
- }, |
- |
- /** |
- * Gets the the maximum number of columns that can fit in a given width. |
- * @param {number} width The width in pixels. |
- * @private |
- */ |
- getColCountForWidth_: function(width) { |
- var scrollBarIsVisible = this.config.scrollable && |
- this.content_.scrollHeight > this.content_.clientHeight; |
- var scrollBarWidth = scrollBarIsVisible ? SCROLL_BAR_WIDTH : 0; |
- var availableWidth = width + this.config.cellMarginStart - scrollBarWidth; |
- |
- var requiredWidth = this.getTileRequiredWidth_(); |
- var colCount = Math.floor(availableWidth / requiredWidth); |
- return colCount; |
- }, |
- |
- /** |
- * Gets the width for a given number of columns. |
- * @param {number} colCount The number of columns. |
- * @private |
- */ |
- getWidthForColCount_: function(colCount) { |
- var requiredWidth = this.getTileRequiredWidth_(); |
- var width = colCount * requiredWidth - this.config.cellMarginStart; |
- return width; |
- }, |
- |
- /** |
- * Returns the position of the tile at |index|. |
- * @param {number} index Tile index. |
- * @private |
- * @return {!{top: number, left: number}} Position. |
- */ |
- getTilePosition_: function(index) { |
- var colCount = this.colCount_; |
- var row = Math.floor(index / colCount); |
- var col = index % colCount; |
- if (isRTL()) |
- col = colCount - col - 1; |
- var config = this.config; |
- var top = ntp.TILE_ROW_HEIGHT * row; |
- var left = col * (config.cellWidth + config.cellMarginStart); |
- return {top: top, left: left}; |
- }, |
- |
- // rendering |
- // ------------------------------------------------------------------------- |
- |
- /** |
- * Renders the tile grid, and the individual tiles. Rendering the grid |
- * consists of adding/removing tile rows and tile cells according to the |
- * specified size (defined by the number of columns in the grid). While |
- * rendering the grid, the tiles are rendered in order in their respective |
- * cells and tile fillers are rendered when needed. This method sets the |
- * private properties colCount_ and rowCount_. |
- * |
- * This method should be called every time the contents of the grid changes, |
- * that is, when the number, contents or order of the tiles has changed. |
- * @param {number=} opt_colCount The number of columns. |
- * @param {number=} opt_tileCount Forces a particular number of tiles to |
- * be drawn. This is useful for cases like the restoration/insertion |
- * of tiles when you need to place a tile in a place of the grid that |
- * is not rendered at the moment. |
- * @protected |
- */ |
- renderGrid: function(opt_colCount, opt_tileCount) { |
- var colCount = opt_colCount || this.colCount_; |
- |
- var tileGridContent = this.tileGridContent_; |
- var tiles = this.tiles_; |
- var tileCount = opt_tileCount || tiles.length; |
- |
- var rowCount = Math.ceil(tileCount / colCount); |
- var tileRows = tileGridContent.getElementsByClassName('tile-row'); |
- |
- for (var tile = 0, row = 0; row < rowCount; row++) { |
- var tileRow = tileRows[row]; |
- |
- // Create tile row if there's no one yet. |
- if (!tileRow) { |
- tileRow = cr.doc.createElement('div'); |
- tileRow.className = 'tile-row'; |
- tileGridContent.appendChild(tileRow); |
- } |
- |
- // The tiles inside the current row. |
- var tileRowTiles = tileRow.childNodes; |
- |
- // Remove excessive columns from a particular tile row. |
- var maxColCount = Math.min(colCount, tileCount - tile); |
- maxColCount = Math.max(0, maxColCount); |
- while (tileRowTiles.length > maxColCount) { |
- tileRow.removeChild(tileRow.lastElementChild); |
- } |
- |
- // For each column in the current row. |
- for (var col = 0; col < colCount; col++, tile++) { |
- var tileCell; |
- var tileElement; |
- if (tileRowTiles[col]) { |
- tileCell = tileRowTiles[col]; |
- } else { |
- var span = cr.doc.createElement('span'); |
- tileCell = new TileCell(span); |
- } |
- |
- // Render Tiles. |
- tileElement = tiles[tile]; |
- if (tile < tileCount && tileElement) { |
- tileCell.classList.remove('filler'); |
- if (!tileCell.tile) |
- tileCell.appendChild(tileElement); |
- else if (tileElement != tileCell.tile) |
- tileCell.replaceChild(tileElement, tileCell.tile); |
- } else if (!tileCell.classList.contains('filler')) { |
- tileCell.classList.add('filler'); |
- tileElement = cr.doc.createElement('span'); |
- tileElement.className = 'tile'; |
- if (tileCell.tile) |
- tileCell.replaceChild(tileElement, tileCell.tile); |
- else |
- tileCell.appendChild(tileElement); |
- } |
- |
- if (!tileRowTiles[col]) |
- tileRow.appendChild(tileCell); |
- } |
- } |
- |
- // Remove excessive tile rows from the tile grid. |
- while (tileRows.length > rowCount) { |
- tileGridContent.removeChild(tileGridContent.lastElementChild); |
- } |
- |
- this.colCount_ = colCount; |
- this.rowCount_ = rowCount; |
- |
- // If we are manually changing the tile count (which can happen during |
- // the restoration/insertion animation) we should not fire the scroll |
- // event once some cells might contain dummy tiles which will cause |
- // an error. |
- if (!opt_tileCount) |
- this.onScroll(); |
- }, |
- |
- // layout |
- // ------------------------------------------------------------------------- |
- |
- /** |
- * Calculates the layout of the tile page according to the current Bottom |
- * Panel's size. This method will resize the containers of the tile page, |
- * and re-render the grid when its dimension changes (number of columns or |
- * visible rows changes). This method also sets the private properties |
- * |numOfVisibleRows_| and |animatingColCount_|. |
- * |
- * This method should be called every time the dimension of the grid changes |
- * or when you need to reinforce its dimension. |
- * @param {boolean=} opt_animate Whether the layout be animated. |
- */ |
- layout: function(opt_animate) { |
- var contentHeight = ntp.getContentHeight(); |
- this.content_.style.height = contentHeight + 'px'; |
- |
- var contentWidth = ntp.getContentWidth(); |
- var colCount = this.getColCountForWidth_(contentWidth); |
- var lastColCount = this.colCount_; |
- var animatingColCount = this.animatingColCount_; |
- if (colCount != animatingColCount) { |
- if (opt_animate) |
- this.tileGrid_.classList.add('animate-grid-width'); |
- |
- if (colCount > animatingColCount) { |
- // If the grid is expanding, it needs to be rendered first so the |
- // revealing tiles are visible as soon as the animation starts. |
- if (colCount != lastColCount) |
- this.renderGrid(colCount); |
- |
- // Hides affected columns and forces the reflow. |
- this.showTileCols_(animatingColCount, false); |
- // Trigger reflow, making the tiles completely hidden. |
- this.tileGrid_.offsetTop; |
- // Fades in the affected columns. |
- this.showTileCols_(animatingColCount, true); |
- } else { |
- // Fades out the affected columns. |
- this.showTileCols_(colCount, false); |
- } |
- |
- var newWidth = this.getWidthForColCount_(colCount); |
- this.tileGrid_.style.width = newWidth + 'px'; |
- |
- // TODO(pedrosimonetti): move to handler below. |
- var self = this; |
- this.onTileGridTransitionEndHandler_ = function() { |
- if (colCount < lastColCount) |
- self.renderGrid(colCount); |
- else |
- self.showTileCols_(0, true); |
- }; |
- } |
- |
- this.animatingColCount_ = colCount; |
- |
- this.frame_.style.width = contentWidth + 'px'; |
- |
- this.onScroll(); |
- }, |
- |
- // tile repositioning animation |
- // ------------------------------------------------------------------------- |
- |
- /** |
- * Tile repositioning state. |
- * @type {{index: number, isRemoving: number}} |
- */ |
- tileRepositioningState_: null, |
- |
- /** |
- * Gets the repositioning state. |
- * @return {{index: number, isRemoving: number}} The repositioning data. |
- */ |
- getTileRepositioningState: function() { |
- return this.tileRepositioningState_; |
- }, |
- |
- /** |
- * Sets the repositioning state that will be used to animate the tiles. |
- * @param {number} index The tile's index. |
- * @param {boolean} isRemoving Whether the tile is being removed. |
- */ |
- setTileRepositioningState: function(index, isRemoving) { |
- this.tileRepositioningState_ = { |
- index: index, |
- isRemoving: isRemoving |
- }; |
- }, |
- |
- /** |
- * Resets the repositioning state. |
- */ |
- resetTileRepositioningState: function() { |
- this.tileRepositioningState_ = null; |
- }, |
- |
- /** |
- * Animates a tile removal. |
- * @param {number} index The index of the tile to be removed. |
- * @param {Object} newDataList The new data list. |
- */ |
- animateTileRemoval: function(index, newDataList) { |
- var tiles = this.tiles_; |
- var tileCount = tiles.length; |
- assert(tileCount > 0); |
- |
- var tileCells = this.querySelectorAll('.tile-cell'); |
- var extraTileIndex = tileCount - 1; |
- var extraCell = tileCells[extraTileIndex]; |
- var extraTileData = newDataList[extraTileIndex]; |
- |
- var repositioningStartIndex = index + 1; |
- var repositioningEndIndex = tileCount; |
- |
- this.initializeRepositioningAnimation_(index, repositioningEndIndex, |
- true); |
- |
- var tileBeingRemoved = tiles[index]; |
- tileBeingRemoved.scrollTop; |
- |
- // The extra tile is the new one that will appear. It can be a normal |
- // tile (when there's extra data for it), or a filler tile. |
- var extraTile = createTile(this, extraTileData); |
- if (!extraTileData) |
- extraCell.classList.add('filler'); |
- // The extra tile is being assigned in order to put it in the right spot. |
- extraCell.assign(extraTile); |
- |
- this.executeRepositioningAnimation_(tileBeingRemoved, extraTile, |
- repositioningStartIndex, repositioningEndIndex, true); |
- |
- // Cleans up the animation. |
- var onPositioningTransitionEnd = function(e) { |
- var propertyName = e.propertyName; |
- if (!(propertyName == '-webkit-transform' || |
- propertyName == 'opacity')) { |
- return; |
- } |
- |
- lastAnimatingTile.removeEventListener('webkitTransitionEnd', |
- onPositioningTransitionEnd); |
- |
- this.finalizeRepositioningAnimation_(tileBeingRemoved, |
- repositioningStartIndex, repositioningEndIndex, true); |
- |
- this.removeTile(tileBeingRemoved); |
- |
- // If the extra tile is a real one (not a filler), then it needs to be |
- // added to the tile list. The tile has been placed in the right spot |
- // but the tile page still doesn't know about this new tile. |
- if (extraTileData) |
- this.appendTile(extraTile); |
- |
- }.bind(this); |
- |
- // Listens to the animation end. |
- var lastAnimatingTile = extraTile; |
- lastAnimatingTile.addEventListener('webkitTransitionEnd', |
- onPositioningTransitionEnd); |
- }, |
- |
- /** |
- * Animates a tile restoration. |
- * @param {number} index The index of the tile to be restored. |
- * @param {Object} newDataList The new data list. |
- */ |
- animateTileRestoration: function(index, newDataList) { |
- var tiles = this.tiles_; |
- var tileCount = tiles.length; |
- |
- var tileCells = this.getElementsByClassName('tile-cell'); |
- |
- // If the desired position is outside the grid, then the grid must be |
- // expanded so there will be a cell in the desired position. |
- if (index >= tileCells.length) |
- this.renderGrid(null, index + 1); |
- |
- var extraTileIndex = Math.min(tileCount, this.config.maxTileCount - 1); |
- var extraCell = tileCells[extraTileIndex]; |
- var extraTileData = newDataList[extraTileIndex + 1]; |
- |
- var repositioningStartIndex = index; |
- var repositioningEndIndex = tileCount - (extraTileData ? 1 : 0); |
- |
- this.initializeRepositioningAnimation_(index, repositioningEndIndex); |
- |
- var restoredData = newDataList[index]; |
- var tileBeingRestored = createTile(this, restoredData); |
- |
- // Temporarily assume the |index| cell so the tile can be animated in |
- // the right spot. |
- tileCells[index].appendChild(tileBeingRestored); |
- |
- if (this.config.scrollable) |
- this.content_.scrollTop = tileCells[index].offsetTop; |
- |
- var extraTile; |
- if (extraCell) |
- extraTile = extraCell.tile; |
- |
- this.executeRepositioningAnimation_(tileBeingRestored, extraTile, |
- repositioningStartIndex, repositioningEndIndex, false); |
- |
- // Cleans up the animation. |
- var onPositioningTransitionEnd = function(e) { |
- var propertyName = e.propertyName; |
- if (!(propertyName == '-webkit-transform' || |
- propertyName == 'opacity')) { |
- return; |
- } |
- |
- lastAnimatingTile.removeEventListener('webkitTransitionEnd', |
- onPositioningTransitionEnd); |
- |
- // When there's an extra data, it means the tile is a real one (not a |
- // filler), and therefore it needs to be removed from the tile list. |
- if (extraTileData) |
- this.removeTile(extraTile); |
- |
- this.finalizeRepositioningAnimation_(tileBeingRestored, |
- repositioningStartIndex, repositioningEndIndex, false); |
- |
- this.addTileAt(tileBeingRestored, index); |
- |
- }.bind(this); |
- |
- // Listens to the animation end. |
- var lastAnimatingTile = tileBeingRestored; |
- lastAnimatingTile.addEventListener('webkitTransitionEnd', |
- onPositioningTransitionEnd); |
- }, |
- |
- // animation helpers |
- // ------------------------------------------------------------------------- |
- |
- /** |
- * Moves a tile to a new position. |
- * @param {Tile} tile A tile. |
- * @param {number} left Left coordinate. |
- * @param {number} top Top coordinate. |
- * @private |
- */ |
- moveTileTo_: function(tile, left, top) { |
- tile.style.left = left + 'px'; |
- tile.style.top = top + 'px'; |
- }, |
- |
- /** |
- * Resets a tile's position. |
- * @param {Tile} tile A tile. |
- * @private |
- */ |
- resetTilePosition_: function(tile) { |
- tile.style.left = ''; |
- tile.style.top = ''; |
- }, |
- |
- /** |
- * Initializes the repositioning animation. |
- * @param {number} startIndex Index of the first tile to be repositioned. |
- * @param {number} endIndex Index of the last tile to be repositioned. |
- * @param {boolean} isRemoving Whether the tile is being removed. |
- * @private |
- */ |
- initializeRepositioningAnimation_: function(startIndex, endIndex, |
- isRemoving) { |
- // Move tiles from relative to absolute position. |
- var tiles = this.tiles_; |
- var tileGridContent = this.tileGridContent_; |
- for (var i = startIndex; i < endIndex; i++) { |
- var tile = tiles[i]; |
- var position = this.getTilePosition_(i); |
- this.moveTileTo_(tile, position.left, position.top); |
- tile.style.zIndex = endIndex - i; |
- tileGridContent.appendChild(tile); |
- } |
- |
- tileGridContent.classList.add('animate-tile-repositioning'); |
- |
- if (!isRemoving) |
- tileGridContent.classList.add('undo-removal'); |
- }, |
- |
- /** |
- * Executes the repositioning animation. |
- * @param {Tile} targetTile The tile that is being removed/restored. |
- * @param {Tile} extraTile The extra tile that is going to appear/disappear. |
- * @param {number} startIndex Index of the first tile to be repositioned. |
- * @param {number} endIndex Index of the last tile to be repositioned. |
- * @param {boolean} isRemoving Whether the tile is being removed. |
- * @private |
- */ |
- executeRepositioningAnimation_: function(targetTile, extraTile, startIndex, |
- endIndex, isRemoving) { |
- targetTile.classList.add('target-tile'); |
- |
- // Alternate the visualization of the target and extra tiles. |
- fadeTile(targetTile, !isRemoving); |
- if (extraTile) |
- fadeTile(extraTile, isRemoving); |
- |
- // Move tiles to the new position. |
- var tiles = this.tiles_; |
- var positionDiff = isRemoving ? -1 : 1; |
- for (var i = startIndex; i < endIndex; i++) { |
- var position = this.getTilePosition_(i + positionDiff); |
- this.moveTileTo_(tiles[i], position.left, position.top); |
- } |
- }, |
- |
- /** |
- * Finalizes the repositioning animation. |
- * @param {Tile} targetTile The tile that is being removed/restored. |
- * @param {number} startIndex Index of the first tile to be repositioned. |
- * @param {number} endIndex Index of the last tile to be repositioned. |
- * @param {boolean} isRemoving Whether the tile is being removed. |
- * @private |
- */ |
- finalizeRepositioningAnimation_: function(targetTile, startIndex, endIndex, |
- isRemoving) { |
- // Remove temporary class names. |
- var tileGridContent = this.tileGridContent_; |
- tileGridContent.classList.remove('animate-tile-repositioning'); |
- tileGridContent.classList.remove('undo-removal'); |
- targetTile.classList.remove('target-tile'); |
- |
- // Move tiles back to relative position. |
- var tiles = this.tiles_; |
- var tileCells = this.querySelectorAll('.tile-cell'); |
- var positionDiff = isRemoving ? -1 : 1; |
- for (var i = startIndex; i < endIndex; i++) { |
- var tile = tiles[i]; |
- this.resetTilePosition_(tile); |
- tile.style.zIndex = ''; |
- var tileCell = tileCells[i + positionDiff]; |
- if (tileCell) |
- tileCell.assign(tile); |
- } |
- }, |
- |
- /** |
- * Animates the display of columns. |
- * @param {number} col The column number. |
- * @param {boolean} show Whether or not to show the row. |
- */ |
- showTileCols_: function(col, show) { |
- var prop = show ? 'remove' : 'add'; |
- var max = 10; // TODO(pedrosimonetti): Add const? |
- var tileGridContent = this.tileGridContent_; |
- for (var i = col; i < max; i++) { |
- tileGridContent.classList[prop]('hide-col-' + i); |
- } |
- }, |
- |
- // event handlers |
- // ------------------------------------------------------------------------- |
- |
- /** |
- * Handles the scroll event. |
- * @protected |
- */ |
- onScroll: function() { |
- // If the TilePage is scrollable, then the opacity of shadow top and |
- // bottom must adjusted, indicating when there's an overflow content. |
- if (this.config.scrollable) { |
- var content = this.content_; |
- var topGap = Math.min(MAX_SCROLL_SHADOW_GAP, content.scrollTop); |
- var bottomGap = Math.min(MAX_SCROLL_SHADOW_GAP, content.scrollHeight - |
- content.scrollTop - content.clientHeight); |
- |
- this.shadowTop_.style.opacity = topGap / MAX_SCROLL_SHADOW_GAP; |
- this.shadowBottom_.style.opacity = bottomGap / MAX_SCROLL_SHADOW_GAP; |
- } |
- }, |
- |
- /** |
- * Handles the end of the horizontal tile grid transition. |
- * @param {Event} e The tile grid webkitTransitionEnd event. |
- */ |
- onTileGridTransitionEnd_: function(e) { |
- if (!this.selected) |
- return; |
- |
- // We should remove the classes that control transitions when the |
- // transition ends so when the text is resized (Ctrl + '+'), no other |
- // transition should happen except those defined in the specification. |
- // For example, the tile has a transition for its 'width' property which |
- // is used when the tile is being hidden. But when you resize the text, |
- // and therefore the tile changes its 'width', this change should not be |
- // animated. |
- |
- // When the tile grid width transition ends, we need to remove the class |
- // 'animate-grid-width' which handles the tile grid width transition, and |
- // individual tile transitions. TODO(pedrosimonetti): Investigate if we |
- // can improve the performance here by using a more efficient selector. |
- var tileGrid = this.tileGrid_; |
- if (e.target == tileGrid && |
- tileGrid.classList.contains('animate-grid-width')) { |
- tileGrid.classList.remove('animate-grid-width'); |
- |
- if (this.onTileGridTransitionEndHandler_) |
- this.onTileGridTransitionEndHandler_(); |
- } |
- }, |
- }; |
- |
- /** |
- * Creates a new tile given a particular data. If there's no data, then |
- * a tile filler will be created. |
- * @param {TilePage} tilePage A TilePage. |
- * @param {Object=} opt_data The data that will be used to create the tile. |
- * @return {Tile} The new tile. |
- */ |
- function createTile(tilePage, opt_data) { |
- var tile; |
- if (opt_data) { |
- // If there's data, the new tile will be a real one (not a filler). |
- tile = new tilePage.TileClass(opt_data); |
- } else { |
- // Otherwise, it will be a fake filler tile. |
- tile = cr.doc.createElement('span'); |
- tile.className = 'tile'; |
- } |
- return tile; |
- } |
- |
- /** |
- * Fades a tile. |
- * @param {Tile} tile A Tile. |
- * @param {boolean} isFadeIn Whether to fade-in the tile. If |isFadeIn| is |
- * false, then the tile is going to fade-out. |
- */ |
- function fadeTile(tile, isFadeIn) { |
- var className = 'animate-hide-tile'; |
- tile.classList.add(className); |
- if (isFadeIn) { |
- // Forces a reflow to ensure that the fade-out animation will work. |
- tile.scrollTop; |
- tile.classList.remove(className); |
- } |
- } |
- |
- return { |
- Tile: Tile, |
- TilePage: TilePage, |
- }; |
-}); |