Chromium Code Reviews| 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 |
| index 924600e3bf2a45a23914cfbc594aec9e53e85cb3..386180cf3d8ea9237b3ebd62fff19b876ba572f4 100644 |
| --- a/chrome/browser/resources/ntp_search/tile_page.js |
| +++ b/chrome/browser/resources/ntp_search/tile_page.js |
| @@ -5,8 +5,70 @@ |
| cr.define('ntp', function() { |
| 'use strict'; |
| + |
| + /** |
| + * 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 |
| + * @param {Object} gridValues Tile page configuration object. |
| + */ |
| + function Tile(gridValues) { |
| + throw 'Tile is a virtual class and is not supposed to be instantiated'; |
| + } |
| + |
| + /** |
| + * Creates a Tile subclass. |
| + */ |
| + 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)) { |
|
Evan Stade
2012/08/07 21:57:12
no curlies
pedrosimonetti2
2012/08/08 08:14:22
Done.
|
| + Subclass.__defineGetter__(name, TileGetters[name]); |
| + } |
| + } |
| + return Subclass; |
| + }; |
| + |
| + Tile.prototype = { |
| + initialize: function(gridValues) { |
| + // TODO: rename to tile |
| + this.baseClassName = 'tile ' + gridValues.tileClassName; |
| + this.className = this.baseClassName; |
| + |
| + // TODO set using CSS? |
| + if (gridValues.reinforceStyles) { |
| + var style = this.style; |
| + style.width = gridValues.tileWidth + 'px'; |
| + style.height = gridValues.tileHeight + 'px'; |
| + style.borderWidth = gridValues.tileBorderWidth + 'px'; |
| + } |
| + }, |
| + |
| + tearDown_: function() { |
| + }, |
| + }; |
| + |
| + var TileGetters = { |
| + 'tileCell': function() { |
| + return findAncestorByClass(this, 'tile-cell'); |
| + }, |
| + 'index': function() { |
| + assert(this.tileCell); |
| + return this.tileCell.index; |
| + } |
| + }; |
| + |
| + |
| + |
| // We can't pass the currently dragging tile via dataTransfer because of |
| // http://crbug.com/31037 |
| + // TODO(xci) drag |
| var currentlyDraggingTile = null; |
| function getCurrentlyDraggingTile() { |
| return currentlyDraggingTile; |
| @@ -26,6 +88,7 @@ cr.define('ntp', function() { |
| * @param {DataTransfer} dataTransfer A dataTransfer object from a drag event. |
| * @param {string} effect A drop effect to change to (i.e. copy, move, none). |
| */ |
| + // TODO(xci) drag |
| function setCurrentDropEffect(dataTransfer, effect) { |
| dataTransfer.dropEffect = effect; |
| if (currentlyDraggingTile) |
| @@ -33,68 +96,67 @@ cr.define('ntp', function() { |
| } |
| /** |
| - * Creates a new Tile object. Tiles wrap content on a TilePage, providing |
| - * some styling and drag functionality. |
| + * 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. |
| + * @param {Object} gridValues Tile page configuration object. |
| */ |
| - function Tile(contents) { |
| - var tile = cr.doc.createElement('div'); |
| - tile.__proto__ = Tile.prototype; |
| - tile.initialize(contents); |
| + function TileCell(tile, gridValues) { |
| + var tileCell = cr.doc.createElement('div'); |
| + tileCell.__proto__ = TileCell.prototype; |
| + tileCell.initialize(tile, gridValues); |
| - return tile; |
| + return tileCell; |
| } |
| - Tile.prototype = { |
| + TileCell.prototype = { |
| __proto__: HTMLDivElement.prototype, |
| - initialize: function(contents) { |
| + initialize: function(tile, gridValues) { |
| // 'real' as opposed to doppleganger. |
| - this.className = 'tile real'; |
| - this.appendChild(contents); |
| - contents.tile = this; |
| - |
| - this.addEventListener('dragstart', this.onDragStart_); |
| - this.addEventListener('drag', this.onDragMove_); |
| - this.addEventListener('dragend', this.onDragEnd_); |
| - |
| - this.firstChild.addEventListener( |
| - 'webkitAnimationEnd', this.onContentsAnimationEnd_.bind(this)); |
| + // TODO(xci) remove the real class. |
| + this.className = 'tile-cell real'; |
| + |
| + if (gridValues.reinforceStyles) { |
| + var style = this.style; |
| + var borderWidth = 2 * gridValues.tileBorderWidth; |
| + style.width = gridValues.tileWidth + borderWidth + 'px'; |
| + style.height = gridValues.tileHeight + borderWidth + 'px'; |
| + // TODO(xci): should we change to marginRight for RTL languages? |
| + style.marginLeft = gridValues.tileHorMargin + 'px'; |
| + style.marginBottom = gridValues.tileVerMargin + 'px'; |
| + } |
| - this.eventTracker = new EventTracker(); |
| + this.assign_(tile); |
| }, |
| get index() { |
| - return Array.prototype.indexOf.call(this.tilePage.tileElements_, this); |
| + return Array.prototype.indexOf.call(this.tilePage.tileElements_, |
| + this.firstChild); |
| }, |
| get tilePage() { |
| return findAncestorByClass(this, 'tile-page'); |
| }, |
| - /** |
| - * Position the tile at |x, y|, and store this as the grid location, i.e. |
| - * where the tile 'belongs' when it's not being dragged. |
| - * @param {number} x The x coordinate, in pixels. |
| - * @param {number} y The y coordinate, in pixels. |
| - */ |
| - setGridPosition: function(x, y) { |
| - this.gridX = x; |
| - this.gridY = y; |
| - this.moveTo(x, y); |
| + assign_: function(tile) { |
| + if (this.firstChild) { |
|
Evan Stade
2012/08/07 21:57:12
no curlies
pedrosimonetti2
2012/08/08 08:14:22
Done.
|
| + this.replaceChild(tile, this.firstChild); |
| + } else { |
| + this.appendChild(tile); |
| + } |
| }, |
| - /** |
| - * Position the tile at |x, y|. |
| - * @param {number} x The x coordinate, in pixels. |
| - * @param {number} y The y coordinate, in pixels. |
| - */ |
| - moveTo: function(x, y) { |
| - // left overrides right in LTR, and right takes precedence in RTL. |
| - this.style.left = toCssPx(x); |
| - this.style.right = toCssPx(x); |
| - this.style.top = toCssPx(y); |
| + tearDown_: function() { |
| }, |
| /** |
| @@ -102,6 +164,7 @@ cr.define('ntp', function() { |
| * @param {Event} e The event for the drag. |
| * @private |
| */ |
| + // TODO(xci) drag |
| onDragStart_: function(e) { |
| // The user may start dragging again during a previous drag's finishing |
| // animation. |
| @@ -141,6 +204,7 @@ cr.define('ntp', function() { |
| * @param {Event} e The event for the drag. |
| * @private |
| */ |
| + // TODO(xci) drag |
| onDragMove_: function(e) { |
| if (e.view != window || (e.x == 0 && e.y == 0)) { |
| this.dragClone.hidden = true; |
| @@ -157,6 +221,7 @@ cr.define('ntp', function() { |
| * @param {Event} e The event for the drag. |
| * @private |
| */ |
| + // TODO(xci) drag |
| onDragEnd_: function(e) { |
| this.dragClone.hidden = false; |
| this.dragClone.classList.add('placing'); |
| @@ -166,7 +231,7 @@ cr.define('ntp', function() { |
| // tilePage will be null if we've already been removed. |
| var tilePage = this.tilePage; |
| if (tilePage) |
| - tilePage.positionTile_(this.index); |
| + //tilePage.positionTile_(this.index); // TODO(xci) function was deleted! |
| // Take an appropriate action with the drag clone. |
| if (this.landedOnTrash) { |
| @@ -219,6 +284,7 @@ cr.define('ntp', function() { |
| * @param {number} x x-axis offset, in pixels. |
| * @param {number} y y-axis offset, in pixels. |
| */ |
| + // TODO(xci) drag |
| showDoppleganger: function(x, y) { |
| // We always have to clear the previous doppleganger to make sure we get |
| // style updates for the contents of this tile. |
| @@ -245,6 +311,7 @@ cr.define('ntp', function() { |
| /** |
| * Destroys the current doppleganger. |
| */ |
| + // TODO(xci) drag |
| clearDoppleganger: function() { |
| if (this.doppleganger_) { |
| this.removeChild(this.doppleganger_); |
| @@ -256,6 +323,7 @@ cr.define('ntp', function() { |
| * Returns status of doppleganger. |
| * @return {boolean} True if there is a doppleganger showing for |this|. |
| */ |
| + // TODO(xci) drag |
| hasDoppleganger: function() { |
| return !!this.doppleganger_; |
| }, |
| @@ -266,6 +334,7 @@ cr.define('ntp', function() { |
| * the next drag starts (if the user starts a 2nd drag very quickly). |
| * @private |
| */ |
| + // TODO(xci) drag |
| finalizeDrag_: function() { |
| assert(this.classList.contains('dragging')); |
| @@ -284,6 +353,7 @@ cr.define('ntp', function() { |
| * resting spot. |
| * @param {Event} e The transition end event. |
| */ |
| + // TODO(xci) drag |
| onDragCloneTransitionEnd_: function(e) { |
| if (this.classList.contains('dragging') && |
| (e.propertyName == 'left' || e.propertyName == 'top' || |
| @@ -316,151 +386,101 @@ cr.define('ntp', function() { |
| }; |
| /** |
| - * Gives the proportion of the row width that is devoted to a single icon. |
| - * @param {number} rowTileCount The number of tiles in a row. |
| - * @param {number} tileSpacingFraction The proportion of the tile width which |
| - * will be used as spacing between tiles. |
| - * @return {number} The ratio between icon width and row width. |
| - */ |
| - function tileWidthFraction(rowTileCount, tileSpacingFraction) { |
| - return rowTileCount + (rowTileCount - 1) * tileSpacingFraction; |
| - } |
| - |
| - /** |
| - * Calculates an assortment of tile-related values for a grid with the |
| - * given dimensions. |
| - * @param {number} width The pixel width of the grid. |
| - * @param {number} numRowTiles The number of tiles in a row. |
| - * @param {number} tileSpacingFraction The proportion of the tile width which |
| - * will be used as spacing between tiles. |
| - * @return {Object} A mapping of pixel values. |
| - */ |
| - function tileValuesForGrid(width, numRowTiles, tileSpacingFraction) { |
| - var tileWidth = width / tileWidthFraction(numRowTiles, tileSpacingFraction); |
| - var offsetX = tileWidth * (1 + tileSpacingFraction); |
| - var interTileSpacing = offsetX - tileWidth; |
| - |
| - return { |
| - tileWidth: tileWidth, |
| - offsetX: offsetX, |
| - interTileSpacing: interTileSpacing, |
| - }; |
| - } |
| - |
| - // The smallest amount of horizontal blank space to display on the sides when |
| - // displaying a wide arrangement. There is an additional 26px of margin from |
| - // the tile page padding. |
| - var MIN_WIDE_MARGIN = 18; |
| - |
| - /** |
| * Creates a new TilePage object. This object contains tiles and controls |
| * their layout. |
| - * @param {Object} gridValues Pixel values that define the size and layout |
| - * of the tile grid. |
| * @constructor |
| * @extends {HTMLDivElement} |
| */ |
| - function TilePage(gridValues) { |
| + function TilePage() { |
| var el = cr.doc.createElement('div'); |
| - el.gridValues_ = gridValues; |
| el.__proto__ = TilePage.prototype; |
| el.initialize(); |
| return el; |
| } |
| - /** |
| - * Takes a collection of grid layout pixel values and updates them with |
| - * additional tiling values that are calculated from TilePage constants. |
| - * @param {Object} grid The grid layout pixel values to update. |
| - */ |
| - TilePage.initGridValues = function(grid) { |
| - // The amount of space we need to display a narrow grid (all narrow grids |
| - // are this size). |
| - grid.narrowWidth = |
| - grid.minTileWidth * tileWidthFraction(grid.minColCount, |
| - grid.tileSpacingFraction); |
| - // The minimum amount of space we need to display a wide grid. |
| - grid.minWideWidth = |
| - grid.minTileWidth * tileWidthFraction(grid.maxColCount, |
| - grid.tileSpacingFraction); |
| - // The largest we will ever display a wide grid. |
| - grid.maxWideWidth = |
| - grid.maxTileWidth * tileWidthFraction(grid.maxColCount, |
| - grid.tileSpacingFraction); |
| - // Tile-related pixel values for the narrow display. |
| - grid.narrowTileValues = tileValuesForGrid(grid.narrowWidth, |
| - grid.minColCount, |
| - grid.tileSpacingFraction); |
| - // Tile-related pixel values for the minimum narrow display. |
| - grid.wideTileValues = tileValuesForGrid(grid.minWideWidth, |
| - grid.maxColCount, |
| - grid.tileSpacingFraction); |
| - }; |
| - |
| TilePage.prototype = { |
| __proto__: HTMLDivElement.prototype, |
| + // The grid values should be defined by each TilePage subclass. |
| + gridValues_: { |
| + tileWidth: 0, |
| + tileHeight: 0, |
| + tileHorMargin: 0, // TODO margin with CSS / there's no margin in first col |
| + tileVerMargin: 0, |
| + tileBorderWidth: 0, |
| + bottomPanelHorMargin: 0, // TODO it doesn't make sense having this here. |
| + |
| + tileCount: 0, // TODO remove this dependency. rename it to maxTileCount. |
| + tileClassName: '', |
| + // TODO(pedrosimonetti): document this property? Consider removing it? |
| + reinforceStyles: true, |
| + |
| + // debug |
| + slowFactor: 1, |
| + debug: false |
| + }, |
| + |
| + get tileElements() { |
| + return this.tileElements_; |
| + }, |
| + |
| initialize: function() { |
| this.className = 'tile-page'; |
| - // Div that acts as a custom scrollbar. The scrollbar has to live |
| - // outside the content div so it doesn't flicker when scrolling (due to |
| - // repainting after the scroll, then repainting again when moved in the |
| - // onScroll handler). |scrollbar_| is only aesthetic, and it only |
| - // represents the thumb. Actual events are still handled by the invisible |
| - // native scrollbars. This div gives us more flexibility with the visuals. |
| - this.scrollbar_ = this.ownerDocument.createElement('div'); |
| - this.scrollbar_.className = 'tile-page-scrollbar'; |
| - this.scrollbar_.hidden = true; |
| - this.appendChild(this.scrollbar_); |
| - |
| // This contains everything but the scrollbar. |
| this.content_ = this.ownerDocument.createElement('div'); |
| this.content_.className = 'tile-page-content'; |
| this.appendChild(this.content_); |
| - // Div that sets the vertical position of the tile grid. |
| - this.topMargin_ = this.ownerDocument.createElement('div'); |
| - this.topMargin_.className = 'top-margin'; |
| - this.content_.appendChild(this.topMargin_); |
| - |
| // Div that holds the tiles. |
| this.tileGrid_ = this.ownerDocument.createElement('div'); |
| this.tileGrid_.className = 'tile-grid'; |
| - this.tileGrid_.style.minWidth = this.gridValues_.narrowWidth + 'px'; |
| + // TODO(xci) |
| + //this.tileGrid_.style.minWidth = this.gridValues_.narrowWidth + 'px'; |
| this.content_.appendChild(this.tileGrid_); |
| + // TODO(xci) new! |
| + this.tileGridContent_ = this.ownerDocument.createElement('div'); |
|
Evan Stade
2012/08/07 21:57:12
the code in this file doesn't look ready for revie
pedrosimonetti2
2012/08/08 08:14:22
It looks much better now.
|
| + this.tileGridContent_.className = 'tile-grid-content'; |
| + this.tileGrid_.appendChild(this.tileGridContent_); |
| + |
| + // TODO(xci) new! |
| + this.tileGrid_.addEventListener('webkitTransitionEnd', |
| + this.onTileGridAnimationEnd_.bind(this)); |
| + |
| // Ordered list of our tiles. |
| - this.tileElements_ = this.tileGrid_.getElementsByClassName('tile real'); |
| + //this.tileElements_ = this.tileGrid_.getElementsByClassName('tile real'); |
| + this.tileElements_ = []; |
| + |
| // Ordered list of the elements which want to accept keyboard focus. These |
| // elements will not be a part of the normal tab order; the tile grid |
| // initially gets focused and then these elements can be focused via the |
| // arrow keys. |
| + // TODO(xci) |
| + /* |
| this.focusableElements_ = |
| this.tileGrid_.getElementsByClassName('focusable'); |
| - |
| - // These are properties used in updateTopMargin. |
| - this.animatedTopMarginPx_ = 0; |
| - this.topMarginPx_ = 0; |
| + */ |
| this.eventTracker = new EventTracker(); |
| this.eventTracker.add(window, 'resize', this.onResize_.bind(this)); |
| + // TODO(xci) new |
| + this.eventTracker.add(window, 'keyup', this.onKeyUp_.bind(this)); |
| - this.addEventListener('DOMNodeInsertedIntoDocument', |
| - this.onNodeInsertedIntoDocument_); |
| + // TODO(xci) |
| + //this.addEventListener('DOMNodeInsertedIntoDocument', |
| + // this.onNodeInsertedIntoDocument_); |
| - this.content_.addEventListener('scroll', this.onScroll_.bind(this)); |
| - |
| - this.dragWrapper_ = new cr.ui.DragWrapper(this.tileGrid_, this); |
| + //this.dragWrapper_ = new cr.ui.DragWrapper(this.tileGrid_, this); |
| this.addEventListener('cardselected', this.handleCardSelection_); |
| this.addEventListener('carddeselected', this.handleCardDeselection_); |
| - this.addEventListener('focus', this.handleFocus_); |
| - this.addEventListener('keydown', this.handleKeyDown_); |
| - this.addEventListener('mousedown', this.handleMouseDown_); |
| + //this.addEventListener('focus', this.handleFocus_); |
| + //this.addEventListener('keydown', this.handleKeyDown_); |
| + //this.addEventListener('mousedown', this.handleMouseDown_); |
| - this.focusElementIndex_ = -1; |
| + //this.focusElementIndex_ = -1; |
| }, |
| get tiles() { |
| @@ -477,39 +497,12 @@ cr.define('ntp', function() { |
| }, |
| /** |
| - * The size of the margin (unused space) on the sides of the tile grid, in |
| - * pixels. |
| - * @type {number} |
| - */ |
| - get sideMargin() { |
| - return this.layoutValues_.leftMargin; |
| - }, |
| - |
| - /** |
| - * Returns the width of the scrollbar, in pixels, if it is active, or 0 |
| - * otherwise. |
| - * @type {number} |
| - */ |
| - get scrollbarWidth() { |
| - return this.scrollbar_.hidden ? 0 : 13; |
| - }, |
| - |
| - /** |
| - * Returns any extra padding to insert to the bottom of a tile page. By |
| - * default there is none, but subclasses can override. |
| - * @type {number} |
| - */ |
| - get extraBottomPadding() { |
| - return 0; |
| - }, |
| - |
| - /** |
| * The notification content of this tile (if any, otherwise null). |
| * @type {!HTMLElement} |
| */ |
| get notification() { |
| - return this.topMargin_.nextElementSibling.id == 'notification-container' ? |
| - this.topMargin_.nextElementSibling : null; |
| + return this.content_.firstChild.id == 'notification-container' ? |
| + this.content_.firstChild : null; |
| }, |
| /** |
| * The notification content of this tile (if any, otherwise null). |
| @@ -518,23 +511,11 @@ cr.define('ntp', function() { |
| set notification(node) { |
| assert(node instanceof HTMLElement, '|node| isn\'t an HTMLElement!'); |
| // NOTE: Implicitly removes from DOM if |node| is inside it. |
| - this.content_.insertBefore(node, this.topMargin_.nextElementSibling); |
| + this.content_.insertBefore(node, this.content_.firstChild); |
| this.positionNotification_(); |
| }, |
| /** |
| - * Fetches the size, in pixels, of the padding-top of the tile contents. |
| - * @type {number} |
| - */ |
| - get contentPadding() { |
| - if (typeof this.contentPadding_ == 'undefined') { |
| - this.contentPadding_ = |
| - parseInt(getComputedStyle(this.content_).paddingTop, 10); |
| - } |
| - return this.contentPadding_; |
| - }, |
| - |
| - /** |
| * Removes the tilePage from the DOM and cleans up event handlers. |
| */ |
| remove: function() { |
| @@ -563,9 +544,12 @@ cr.define('ntp', function() { |
| * @param {boolean} animate If true, the append will be animated. |
| * @protected |
| */ |
| + // TODO(xci) |
| + /* |
| appendTile: function(tileElement, animate) { |
| this.addTileAt(tileElement, this.tileElements_.length, animate); |
| }, |
| + */ |
| /** |
| * Adds the given element to the tile grid. |
| @@ -575,30 +559,18 @@ cr.define('ntp', function() { |
| * animated (other tiles, if they must reposition, do not animate). |
| * @protected |
| */ |
| + // TODO(xci) |
| + /* |
| addTileAt: function(tileElement, index, animate) { |
| - this.classList.remove('animating-tile-page'); |
| - if (animate) |
| - tileElement.classList.add('new-tile-contents'); |
| - |
| - // Make sure the index is positive and either in the the bounds of |
| - // this.tileElements_ or at the end (meaning append). |
| - assert(index >= 0 && index <= this.tileElements_.length); |
| - |
| - var wrapperDiv = new Tile(tileElement); |
| - // If is out of the bounds of the tile element list, .insertBefore() will |
| - // act just like appendChild(). |
| - this.tileGrid_.insertBefore(wrapperDiv, this.tileElements_[index]); |
| this.calculateLayoutValues_(); |
| - this.heightChanged_(); |
| - |
| - this.repositionTiles_(); |
| this.fireAddedEvent(wrapperDiv, index, animate); |
| }, |
| + */ |
| /** |
| * Notify interested subscribers that a tile has been removed from this |
| * page. |
| - * @param {Tile} tile The newly added tile. |
| + * @param {TileCell} tile The newly added tile. |
| * @param {number} index The index of the tile that was added. |
| * @param {boolean} wasAnimated Whether the removal was animated. |
| */ |
| @@ -632,7 +604,7 @@ cr.define('ntp', function() { |
| /** |
| * Notify interested subscribers that a tile has been removed from this |
| * page. |
| - * @param {Tile} tile The tile that was removed. |
| + * @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. |
| */ |
| @@ -649,6 +621,7 @@ cr.define('ntp', function() { |
| * Removes all tiles from the page. |
| */ |
| removeAllTiles: function() { |
| + // TODO(xci) dispatch individual tearDown functions |
| this.tileGrid_.innerHTML = ''; |
| }, |
| @@ -797,40 +770,12 @@ cr.define('ntp', function() { |
| * @private |
| */ |
| calculateLayoutValues_: function() { |
| - var grid = this.gridValues_; |
| - var availableSpace = this.tileGrid_.clientWidth - 2 * MIN_WIDE_MARGIN; |
| - var wide = availableSpace >= grid.minWideWidth; |
| - var numRowTiles = wide ? grid.maxColCount : grid.minColCount; |
| - |
| - var effectiveGridWidth = wide ? |
| - Math.min(Math.max(availableSpace, grid.minWideWidth), |
| - grid.maxWideWidth) : |
| - grid.narrowWidth; |
| - var realTileValues = tileValuesForGrid(effectiveGridWidth, numRowTiles, |
| - grid.tileSpacingFraction); |
| - |
| - // leftMargin centers the grid within the avaiable space. |
| - var minMargin = wide ? MIN_WIDE_MARGIN : 0; |
| - var leftMargin = |
| - Math.max(minMargin, |
| - (this.tileGrid_.clientWidth - effectiveGridWidth) / 2); |
| - |
| - var rowHeight = this.heightForWidth(realTileValues.tileWidth) + |
| - realTileValues.interTileSpacing; |
| - |
| - this.layoutValues_ = { |
| - colWidth: realTileValues.offsetX, |
| - gridWidth: effectiveGridWidth, |
| - leftMargin: leftMargin, |
| - numRowTiles: numRowTiles, |
| - rowHeight: rowHeight, |
| - tileWidth: realTileValues.tileWidth, |
| - wide: wide, |
| - }; |
| + this.layout_(); |
| // We need to update the top margin as well. |
| this.updateTopMargin_(); |
| + // TODO(pedrosimonetti): when do we really need to send this message? |
| this.firePageLayoutEvent_(); |
| }, |
| @@ -842,72 +787,6 @@ cr.define('ntp', function() { |
| cr.dispatchSimpleEvent(this, 'pagelayout', true, true); |
| }, |
| - /** |
| - * @return {number} The amount of margin that should be animated (in pixels) |
| - * for the current grid layout. |
| - */ |
| - getAnimatedLeftMargin_: function() { |
| - if (this.layoutValues_.wide) |
| - return 0; |
| - |
| - var grid = this.gridValues_; |
| - return (grid.minWideWidth - MIN_WIDE_MARGIN - grid.narrowWidth) / 2; |
| - }, |
| - |
| - /** |
| - * Calculates the x/y coordinates for an element and moves it there. |
| - * @param {number} index The index of the element to be positioned. |
| - * @param {number} indexOffset If provided, this is added to |index| when |
| - * positioning the tile. The effect is that the tile will be positioned |
| - * in a non-default location. |
| - * @private |
| - */ |
| - positionTile_: function(index, indexOffset) { |
| - var grid = this.gridValues_; |
| - var layout = this.layoutValues_; |
| - |
| - indexOffset = typeof indexOffset != 'undefined' ? indexOffset : 0; |
| - // Add the offset _after_ the modulus division. We might want to show the |
| - // tile off the side of the grid. |
| - var col = index % layout.numRowTiles + indexOffset; |
| - var row = Math.floor(index / layout.numRowTiles); |
| - // Calculate the final on-screen position for the tile. |
| - var realX = col * layout.colWidth + layout.leftMargin; |
| - var realY = row * layout.rowHeight; |
| - |
| - // Calculate the portion of the tile's position that should be animated. |
| - var animatedTileValues = layout.wide ? |
| - grid.wideTileValues : grid.narrowTileValues; |
| - // Animate the difference between three-wide and six-wide. |
| - var animatedLeftMargin = this.getAnimatedLeftMargin_(); |
| - var animatedX = col * animatedTileValues.offsetX + animatedLeftMargin; |
| - var animatedY = row * (this.heightForWidth(animatedTileValues.tileWidth) + |
| - animatedTileValues.interTileSpacing); |
| - |
| - var tile = this.tileElements_[index]; |
| - tile.setGridPosition(animatedX, animatedY); |
| - tile.firstChild.setBounds(layout.tileWidth, |
| - realX - animatedX, |
| - realY - animatedY); |
| - |
| - // This code calculates whether the tile needs to show a clone of itself |
| - // wrapped around the other side of the tile grid. |
| - var offTheRight = col == layout.numRowTiles || |
| - (col == layout.numRowTiles - 1 && tile.hasDoppleganger()); |
| - var offTheLeft = col == -1 || (col == 0 && tile.hasDoppleganger()); |
| - if (this.isCurrentDragTarget && (offTheRight || offTheLeft)) { |
| - var sign = offTheRight ? 1 : -1; |
| - tile.showDoppleganger(-layout.numRowTiles * layout.colWidth * sign, |
| - layout.rowHeight * sign); |
| - } else { |
| - tile.clearDoppleganger(); |
| - } |
| - |
| - if (index == this.tileElements_.length - 1) { |
| - this.tileGrid_.style.height = (realY + layout.rowHeight) + 'px'; |
| - this.queueUpdateScrollbars_(); |
| - } |
| - }, |
| /** |
| * Gets the index of the tile that should occupy coordinate (x, y). Note |
| @@ -920,6 +799,7 @@ cr.define('ntp', function() { |
| * |this|. |
| * @private |
| */ |
| + // TODO(xci) drag |
| getWouldBeIndexForPoint_: function(x, y) { |
| var grid = this.gridValues_; |
| var layout = this.layoutValues_; |
| @@ -938,32 +818,12 @@ cr.define('ntp', function() { |
| }, |
| /** |
| - * Window resize event handler. Window resizes may trigger re-layouts. |
| - * @param {Object} e The resize event. |
| - */ |
| - onResize_: function(e) { |
| - if (this.lastWidth_ == this.clientWidth && |
| - this.lastHeight_ == this.clientHeight) { |
| - return; |
| - } |
| - |
| - this.calculateLayoutValues_(); |
| - |
| - this.lastWidth_ = this.clientWidth; |
| - this.lastHeight_ = this.clientHeight; |
| - this.classList.add('animating-tile-page'); |
| - this.heightChanged_(); |
| - |
| - this.positionNotification_(); |
| - this.repositionTiles_(); |
| - }, |
| - |
| - /** |
| * The tile grid has an image mask which fades at the edges. We only show |
| * the mask when there is an active drag; it obscures doppleganger tiles |
| * as they enter or exit the grid. |
| * @private |
| */ |
| + // TODO(xci) drag |
| updateMask_: function() { |
| if (!this.isCurrentDragTarget) { |
| this.tileGrid_.style.WebkitMaskBoxImage = ''; |
| @@ -991,71 +851,21 @@ cr.define('ntp', function() { |
| this.tileGrid_.style.WebkitMaskBoxImage = gradient; |
| }, |
| + // TODO(xci) delete (used by drag and drop) |
| updateTopMargin_: function() { |
| - var layout = this.layoutValues_; |
| - |
| - // The top margin is set so that the vertical midpoint of the grid will |
| - // be 1/3 down the page. |
| - var numTiles = this.tileCount + |
| - (this.isCurrentDragTarget && !this.withinPageDrag_ ? 1 : 0); |
| - var numRows = Math.max(1, Math.ceil(numTiles / layout.numRowTiles)); |
| - var usedHeight = layout.rowHeight * numRows; |
| - var newMargin = document.documentElement.clientHeight / 3 - |
| - usedHeight / 3 - this.contentPadding; |
| - // The 'height' style attribute of topMargin is non-zero to work around |
| - // webkit's collapsing margin behavior, so we have to factor that into |
| - // our calculations here. |
| - newMargin = Math.max(newMargin, 0) - this.topMargin_.offsetHeight; |
| - |
| - // |newMargin| is the final margin we actually want to show. However, |
| - // part of that should be animated and part should not (for the same |
| - // reason as with leftMargin). The approach is to consider differences |
| - // when the layout changes from wide to narrow or vice versa as |
| - // 'animatable'. These differences accumulate in animatedTopMarginPx_, |
| - // while topMarginPx_ caches the real (total) margin. Either of these |
| - // calculations may come out to be negative, so we use margins as the |
| - // css property. |
| - |
| - if (typeof this.topMarginIsForWide_ == 'undefined') |
| - this.topMarginIsForWide_ = layout.wide; |
| - if (this.topMarginIsForWide_ != layout.wide) { |
| - this.animatedTopMarginPx_ += newMargin - this.topMarginPx_; |
| - this.topMargin_.style.marginBottom = toCssPx(this.animatedTopMarginPx_); |
| - } |
| - |
| - this.topMarginIsForWide_ = layout.wide; |
| - this.topMarginPx_ = newMargin; |
| - this.topMargin_.style.marginTop = |
| - toCssPx(this.topMarginPx_ - this.animatedTopMarginPx_); |
| + return; |
| }, |
| /** |
| * Position the notification if there's one showing. |
| */ |
| positionNotification_: function() { |
| - var notification = this.notification; |
| - if (!notification || notification.hidden) |
| + if (this.notification && !this.notification.hidden) { |
| return; |
| - |
| - // Update the horizontal position. |
| - var animatedLeftMargin = this.getAnimatedLeftMargin_(); |
| - notification.style.WebkitMarginStart = animatedLeftMargin + 'px'; |
| - var leftOffset = (this.layoutValues_.leftMargin - animatedLeftMargin) * |
| - (isRTL() ? -1 : 1); |
| - notification.style.WebkitTransform = 'translateX(' + leftOffset + 'px)'; |
| - |
| - // Update the allowable widths of the text. |
| - var buttonWidth = notification.querySelector('button').offsetWidth + 8; |
| - notification.querySelector('span').style.maxWidth = |
| - this.layoutValues_.gridWidth - buttonWidth + 'px'; |
| - |
| - // This makes sure the text doesn't condense smaller than the narrow size |
| - // of the grid (e.g. when a user makes the window really small). |
| - notification.style.minWidth = |
| - this.gridValues_.narrowWidth - buttonWidth + 'px'; |
| - |
| - // Update the top position. |
| - notification.style.marginTop = -notification.offsetHeight + 'px'; |
| + this.notification.style.margin = |
| + -this.notification.offsetHeight + 'px ' + |
| + this.layoutValues_.leftMargin + 'px 0'; |
| + } |
| }, |
| /** |
| @@ -1065,23 +875,6 @@ cr.define('ntp', function() { |
| */ |
| onNodeInsertedIntoDocument_: function(e) { |
| this.calculateLayoutValues_(); |
| - this.heightChanged_(); |
| - }, |
| - |
| - /** |
| - * Called when the height of |this| has changed: update the size of |
| - * tileGrid. |
| - * @private |
| - */ |
| - heightChanged_: function() { |
| - // The tile grid will expand to the bottom footer, or enough to hold all |
| - // the tiles, whichever is greater. It would be nicer if tilePage were |
| - // a flex box, and the tile grid could be box-flex: 1, but this exposes a |
| - // bug where repositioning tiles will cause the scroll position to reset. |
| - this.tileGrid_.style.minHeight = (this.clientHeight - |
| - this.tileGrid_.offsetTop - this.content_.offsetTop - |
| - this.extraBottomPadding - |
| - (this.footerNode_ ? this.footerNode_.clientHeight : 0)) + 'px'; |
| }, |
| /** |
| @@ -1112,78 +905,9 @@ cr.define('ntp', function() { |
| return true; |
| }, |
| - /** |
| - * Handler for the 'scroll' event on |content_|. |
| - * @param {Event} e The scroll event. |
| - * @private |
| - */ |
| - onScroll_: function(e) { |
| - this.queueUpdateScrollbars_(); |
| - }, |
| - |
| - /** |
| - * ID of scrollbar update timer. If 0, there's no scrollbar re-calc queued. |
| - * @private |
| - */ |
| - scrollbarUpdate_: 0, |
| - |
| - /** |
| - * Queues an update on the custom scrollbar. Used for two reasons: first, |
| - * coalescing of multiple updates, and second, because action like |
| - * repositioning a tile can require a delay before they affect values |
| - * like clientHeight. |
| - * @private |
| - */ |
| - queueUpdateScrollbars_: function() { |
| - if (this.scrollbarUpdate_) |
| - return; |
| - |
| - this.scrollbarUpdate_ = window.setTimeout( |
| - this.doUpdateScrollbars_.bind(this), 0); |
| - }, |
| - |
| - /** |
| - * Does the work of calculating the visibility, height and position of the |
| - * scrollbar thumb (there is no track or buttons). |
| - * @private |
| - */ |
| - doUpdateScrollbars_: function() { |
| - this.scrollbarUpdate_ = 0; |
| - |
| - var content = this.content_; |
| - |
| - // Adjust scroll-height to account for possible header-bar. |
| - var adjustedScrollHeight = content.scrollHeight - content.offsetTop; |
| - |
| - if (adjustedScrollHeight <= content.clientHeight) { |
| - this.scrollbar_.hidden = true; |
| - return; |
| - } else { |
| - this.scrollbar_.hidden = false; |
| - } |
| - |
| - var thumbTop = content.offsetTop + |
| - content.scrollTop / adjustedScrollHeight * content.clientHeight; |
| - var thumbHeight = content.clientHeight / adjustedScrollHeight * |
| - this.clientHeight; |
| - |
| - this.scrollbar_.style.top = thumbTop + 'px'; |
| - this.scrollbar_.style.height = thumbHeight + 'px'; |
| - this.firePageLayoutEvent_(); |
| - }, |
| - |
| - /** |
| - * Get the height for a tile of a certain width. Override this function to |
| - * get non-square tiles. |
| - * @param {number} width The pixel width of a tile. |
| - * @return {number} The height for |width|. |
| - */ |
| - heightForWidth: function(width) { |
| - return width; |
| - }, |
| - |
| /** Dragging **/ |
| + // TODO(xci) drag |
| get isCurrentDragTarget() { |
| return this.dragWrapper_.isCurrentDragTarget; |
| }, |
| @@ -1192,6 +916,7 @@ cr.define('ntp', function() { |
| * Thunk for dragleave events fired on |tileGrid_|. |
| * @param {Event} e A MouseEvent for the drag. |
| */ |
| + // TODO(xci) drag |
| doDragLeave: function(e) { |
| this.cleanupDrag(); |
| }, |
| @@ -1200,6 +925,7 @@ cr.define('ntp', function() { |
| * Performs all actions necessary when a drag enters the tile page. |
| * @param {Event} e A mouseover event for the drag enter. |
| */ |
| + // TODO(xci) drag |
| doDragEnter: function(e) { |
| // Applies the mask so doppleganger tiles disappear into the fog. |
| this.updateMask_(); |
| @@ -1213,6 +939,7 @@ cr.define('ntp', function() { |
| // The new tile may change the number of rows, hence the top margin |
| // will change. |
| if (!this.withinPageDrag_) |
| + // TODO(xci) this function does nothing now! |
| this.updateTopMargin_(); |
| this.doDragOver(e); |
| @@ -1223,6 +950,7 @@ cr.define('ntp', function() { |
| * a drag over the tile page. |
| * @param {Event} e A mouseover event for the drag over. |
| */ |
| + // TODO(xci) drag |
| doDragOver: function(e) { |
| e.preventDefault(); |
| @@ -1237,6 +965,7 @@ cr.define('ntp', function() { |
| * Performs all actions necessary when the user completes a drop. |
| * @param {Event} e A mouseover event for the drag drop. |
| */ |
| + // TODO(xci) drag |
| doDrop: function(e) { |
| e.stopPropagation(); |
| e.preventDefault(); |
| @@ -1273,6 +1002,7 @@ cr.define('ntp', function() { |
| * Appends the currently dragged tile to the end of the page. Called |
| * from outside the page, e.g. when dropping on a nav dot. |
| */ |
| + // TODO(xci) drag |
| appendDraggingTile: function() { |
| var originalPage = currentlyDraggingTile.tilePage; |
| if (originalPage == this) |
| @@ -1286,6 +1016,7 @@ cr.define('ntp', function() { |
| /** |
| * Makes sure all the tiles are in the right place after a drag is over. |
| */ |
| + // TODO(xci) drag |
| cleanupDrag: function() { |
| this.repositionTiles_(currentlyDraggingTile); |
| // Remove the drag mask. |
| @@ -1297,11 +1028,14 @@ cr.define('ntp', function() { |
| * @param {?Node} ignoreNode An optional node to ignore. |
| * @private |
| */ |
| + // TODO(xci) drag |
| repositionTiles_: function(ignoreNode) { |
| + /* |
| for (var i = 0; i < this.tileElements_.length; i++) { |
| if (!ignoreNode || ignoreNode !== this.tileElements_[i]) |
| - this.positionTile_(i); |
| + ;//this.positionTile_(i); TODO(xci) this function was deleted! |
| } |
| + */ |
| }, |
| /** |
| @@ -1309,6 +1043,7 @@ cr.define('ntp', function() { |
| * @param {Event} e A MouseEvent for the drag. |
| * @private |
| */ |
| + // TODO(xci) drag |
| updateDropIndicator_: function(newDragIndex) { |
| var oldDragIndex = this.currentDropIndex_; |
| if (newDragIndex == oldDragIndex) |
| @@ -1325,7 +1060,7 @@ cr.define('ntp', function() { |
| else |
| var adjustment = i >= newDragIndex ? 1 : 0; |
| - this.positionTile_(i, adjustment); |
| + //this.positionTile_(i, adjustment); TODO(xci) function was deleted! |
| } |
| this.currentDropIndex_ = newDragIndex; |
| }, |
| @@ -1336,6 +1071,7 @@ cr.define('ntp', function() { |
| * likely want to check |e.dataTransfer|. |
| * @return {boolean} True if this page can handle the drag. |
| */ |
| + // TODO(xci) drag |
| shouldAcceptDrag: function(e) { |
| return false; |
| }, |
| @@ -1346,6 +1082,7 @@ cr.define('ntp', function() { |
| * data. This should only be used if currentlyDraggingTile is null. |
| * @param {number} index The tile index at which the drop occurred. |
| */ |
| + // TODO(xci) drag |
| addDragData: function(dataTransfer, index) { |
| assert(false); |
| }, |
| @@ -1364,14 +1101,409 @@ cr.define('ntp', function() { |
| * 'copy'). |
| * @param {Object} dataTransfer The drag event dataTransfer object. |
| */ |
| + // TODO(xci) drag |
| setDropEffect: function(dataTransfer) { |
| assert(false); |
| }, |
| + |
| + |
| + // ######################################################################### |
| + // XCI - Extended Chrome Instant |
| + // ######################################################################### |
| + |
| + |
| + // properties |
| + // ------------------------------------------------------------------------- |
| + colCount: 5, |
| + rowCount: 2, |
| + |
| + numOfVisibleRows: 0, |
| + animatingColCount: 5, // TODO how to handle initialization of this value? |
| + |
| + // TODO move to layout? |
| + pageOffset: 0, |
| + |
| + appendTile: function(tile) { |
| + this.tileElements_.push(tile); |
| + this.renderGrid_(); |
| + }, |
| + |
| + // TODO(cxi): if this is not being used, delete. |
| + addTileAt: function(tile, index) { |
| + this.tileElements_.splice(index, 0, tile); |
| + this.appendTile(tile); |
| + }, |
| + |
| + // internal helpers |
| + // ------------------------------------------------------------------------- |
| + |
| + // TODO move to layout? |
| + getNumOfVisibleRows_: function() { |
| + return this.numOfVisibleRows; |
| + }, |
| + |
| + getTileRequiredWidth_: function() { |
| + var grid = this.gridValues_; |
| + return grid.tileWidth + 2 * grid.tileBorderWidth + grid.tileHorMargin; |
| + }, |
| + |
| + getColCountForWidth_: function(width) { |
| + var availableWidth = width + this.gridValues_.tileHorMargin; |
| + var requiredWidth = this.getTileRequiredWidth_(); |
| + var colCount = Math.floor(availableWidth / requiredWidth); |
| + return colCount; |
| + }, |
| + |
| + getWidthForColCount_: function(colCount) { |
| + var requiredWidth = this.getTileRequiredWidth_(); |
| + var width = colCount * requiredWidth - this.gridValues_.tileHorMargin; |
| + return width; |
| + }, |
| + |
| + getBottomPanelWidth_: function() { |
| + var windowWidth = cr.doc.documentElement.clientWidth; |
| + var width; |
| + // TODO(xci): add contants? |
| + if (windowWidth >= 948) { |
| + width = 748; |
| + } else if (windowWidth >= 500) { |
| + width = windowWidth - 2 * this.gridValues_.bottomPanelHorMargin; |
| + } else if (windowWidth >= 300) { |
| + // TODO(pedrosimonetti): check math and document |
| + width = Math.floor(((windowWidth - 300) / 200) * 100 + 200); |
| + } else { |
| + width = 200; |
| + } |
| + return width; |
| + }, |
| + |
| + getAvailableColCount_: function() { |
| + return this.getColCountForWidth_(this.getBottomPanelWidth_()); |
| + }, |
| + |
| + // rendering |
| + // ------------------------------------------------------------------------- |
| + |
| + // TODO(pedrosimonetti): document |
| + renderGrid_: function(colCount) { |
| + colCount = colCount || this.colCount; |
| + |
| + var tileGridContent = this.tileGridContent_; |
| + |
| + var tileElements = this.tileElements_; |
| + |
| + var tileCount = tileElements.length; |
| + var rowCount = Math.ceil(tileCount / colCount); |
| + |
| + var tileRows = tileGridContent.getElementsByClassName('tile-row'); |
| + var tileRow; |
| + var tileRowTiles; |
| + var tileCell; |
| + var tileElement; |
| + var maxColCount; |
| + |
| + var numOfVisibleRows = this.getNumOfVisibleRows_(); |
| + var pageOffset = this.pageOffset; |
| + |
| + for (var tile = 0, row = 0; row < rowCount; row++) { |
| + tileRow = tileRows[row]; |
| + |
| + // Create tile row if there's no one yet. |
| + if (!tileRow) { |
| + tileRow = cr.doc.createElement('div'); |
| + tileRow.className = 'tile-row tile-row-' + row;// TODO do we need id? |
| + tileGridContent.appendChild(tileRow); |
| + } |
| + |
| + // Adjust row visibility. |
| + var rowVisible = (row >= pageOffset && |
| + row <= (pageOffset + numOfVisibleRows - 1)); |
| + this.showTileRow_(tileRow, rowVisible); |
| + |
| + // The tiles inside the current row. |
| + tileRowTiles = tileRow.childNodes; |
| + |
| + // Remove excessive columns from a particular tile row. |
| + maxColCount = Math.min(colCount, tileCount - tile); |
| + while (tileRowTiles.length > maxColCount) { |
| + tileRow.removeChild(tileRow.lastElementChild); |
| + } |
| + |
| + // For each column in the current row. |
| + for (var col = 0; col < colCount; col++, tile++) { |
| + if (tileRowTiles[col]) { |
| + tileCell = tileRowTiles[col]; |
| + } else { |
| + var span = cr.doc.createElement('span'); |
| + tileCell = new TileCell(span, this.gridValues_); |
| + } |
| + |
| + // Reset column class. |
| + this.resetTileCol_(tileCell, col); |
| + |
| + // Render Tiles. |
| + if (tile < tileCount) { |
| + tileCell.classList.remove('filler'); |
| + tileElement = tileElements[tile]; |
| + if (tileCell.firstChild) { |
| + if (tileElement != tileCell.firstChild) { |
| + tileCell.replaceChild(tileElement, tileCell.firstChild); |
| + } |
| + } else { |
| + tileCell.appendChild(tileElement); |
| + } |
| + } else { |
| + // TODO(xci): check how to solve the problem with filler + animation |
| + if (!tileCell.classList.contains('filler')) { |
| + tileCell.classList.add('filler'); |
| + tileElement = cr.doc.createElement('span'); |
| + if (tileCell.firstChild) |
| + tileCell.replaceChild(tileElement, tileCell.firstChild); |
| + 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; |
| + }, |
| + |
| + layout_: function() { |
| + var pageList = $('page-list'); |
| + var panel = this.content_; |
| + var menu = $('page-list-menu'); |
| + var tileGrid = this.tileGrid_; |
| + var tileGridContent = this.tileGridContent_; |
| + var tileRows = tileGridContent.getElementsByClassName('tile-row'); |
| + |
| + tileGridContent.classList.add('animate-tile'); |
| + |
| + var bottomPanelWidth = this.getBottomPanelWidth_(); |
| + var colCount = this.getColCountForWidth_(bottomPanelWidth); |
| + var lastColCount = this.colCount; |
| + var animatingColCount = this.animatingColCount; |
| + |
| + var windowHeight = cr.doc.documentElement.clientHeight; |
| + |
| + // TODO better handling of height state |
| + // changeVisibleRows |
| + // TODO need to call paginate when height changes |
| + var numOfVisibleRows = this.numOfVisibleRows; |
| + // TODO(xci) constants? |
| + if (windowHeight > 500 && this.tileElements_.length > 5) { |
| + numOfVisibleRows = 2; |
| + } else { |
| + numOfVisibleRows = 1; |
| + } |
| + |
| + if (numOfVisibleRows != this.numOfVisibleRows) { |
| + this.numOfVisibleRows = numOfVisibleRows; |
| + this.paginate_(null, true); |
| + pageList.style.height = (107 * numOfVisibleRows) + 'px'; |
| + //tileGrid.style.height = (107 * numOfVisibleRows) + 'px'; |
| + } |
| + |
| + // changeVisibleCols |
| + if (colCount != animatingColCount) { |
| + |
| + var newWidth = this.getWidthForColCount_(colCount); |
| + if (colCount > animatingColCount) { |
| + |
| + // TODO actual size check |
| + if (colCount != lastColCount) { |
| + this.renderGrid_(colCount); |
| + } |
| + |
| + this.showTileCols_(animatingColCount, false); |
| + |
| + // TODO(xci) fix the slowdown debug function and test if we really |
| + // need this closure and if we really need to pass animatingCount. |
| + var self = this; |
| + setTimeout((function(animatingColCount) { |
| + return function() { |
| + self.showTileCols_(animatingColCount, true); |
| + } |
| + })(animatingColCount), 0); |
| + |
| + } else { |
| + this.showTileCols_(colCount, false); |
| + } |
| + |
| + tileGrid.style.width = newWidth + 'px'; |
| + menu.style.width = newWidth + 'px'; |
| + |
| + // TODO: listen animateEnd |
| + var self = this; |
| + this.onTileGridAnimationEndHandler_ = function() { |
| + if (colCount < lastColCount) { |
| + self.renderGrid_(colCount); |
| + } else { |
| + self.showTileCols_(0, true); |
| + } |
| + }; |
| + |
| + this.paginate_(); |
| + } |
| + |
| + panel.style.width = bottomPanelWidth + 'px'; |
| + |
| + this.animatingColCount = colCount; |
| + }, |
| + |
| + // animation helpers |
| + // ------------------------------------------------------------------------- |
| + |
| + // TODO make it local? |
| + showTileRow_: function(row, show) { |
| + row.classList[show ? 'remove' : 'add']('hide-row'); |
| + }, |
| + |
| + // TODO make it local? |
| + showTileCols_: function(col, show) { |
| + var prop = show ? 'remove' : 'add'; |
| + var max = 10; // TODO(pedrosimonetti) const? |
| + var tileGridContent = this.tileGridContent_; |
| + for (var i = col; i < max; i++) { |
| + tileGridContent.classList[prop]('hide-col-' + i); |
| + } |
| + }, |
| + |
| + // TODO make it local? |
| + resetTileCol_: function(tileCell, col) { |
| + var max = 10; |
| + for (var i = 0; i < max; i++) { |
| + if (i != col) { |
| + tileCell.classList.remove('tile-col-' + i); |
| + } |
| + } |
| + tileCell.classList.add('tile-col-' + col); |
| + }, |
| + |
| + // pagination |
| + // ------------------------------------------------------------------------- |
| + |
| + paginate_: function(pageOffset, force) { |
| + var numOfVisibleRows = this.getNumOfVisibleRows_(); |
| + var pageOffset = typeof pageOffset == 'number' ? |
| + pageOffset : this.pageOffset; |
| + |
| + pageOffset = Math.max(0, pageOffset); |
| + pageOffset = Math.min(this.rowCount - numOfVisibleRows, pageOffset); |
| + |
| + if (pageOffset != this.pageOffset || force) { |
| + var rows = this.tileGridContent_.getElementsByClassName('tile-row'); |
| + for (var i = 0, l = rows.length; i < l; i++) { |
| + var row = rows[i]; |
| + if (i >= pageOffset && i <= (pageOffset + numOfVisibleRows - 1)) { |
| + this.showTileRow_(row, true); |
| + } else { |
| + this.showTileRow_(row, false); |
| + } |
| + } |
| + |
| + this.pageOffset = pageOffset; |
| + this.tileGridContent_.style.webkitTransform = 'translate3d(0, ' + |
| + (-pageOffset * 106) + 'px, 0)'; |
| + } |
| + }, |
| + |
| + // event handlers |
| + // ------------------------------------------------------------------------- |
| + |
| + onResize_: function() { |
| + this.layout_(); |
| + }, |
| + |
| + onTileGridAnimationEnd_: function() { |
| + // TODO(xci): figure out how to cleanup each kind animation properly |
| + if (event.target == this.tileGrid_ && |
| + this.onTileGridAnimationEndHandler_) { |
| + if (this.tileGridContent_.classList.contains('animate-tile')) { |
| + this.onTileGridAnimationEndHandler_(); |
| + //this.tileGridContent_.classList.remove('animate-tile') |
| + } |
| + } |
| + }, |
| + |
| + onKeyUp_: function(e) { |
| + var pageOffset = this.pageOffset; |
| + |
| + var keyCode = e.keyCode; |
| + if (keyCode == 40 /* down */) { |
| + pageOffset++; |
| + } else if (keyCode == 38 /* up */) { |
| + pageOffset--; |
| + } |
| + |
| + if (pageOffset != this.pageOffset) { |
| + this.paginate_(pageOffset); |
| + } |
| + } |
| }; |
| + |
| + var duration = 200; |
| + var defaultDuration = 200; |
| + var animatedProperties = [ |
| + '#card-slider-frame .tile-grid', |
| + '#card-slider-frame .tile-grid-content', |
| + '#card-slider-frame .tile-row', |
| + '.animate-tile .tile-cell', |
| + '.debug .animate-tile .tile-cell' |
| + ]; |
| + |
| + function adjustAnimationTiming(slownessFactor, selectors) { |
| + slownessFactor = slownessFactor || 1; |
| + selectors = selectors || animatedProperties; |
| + duration = defaultDuration * slownessFactor; |
| + for (var i = 0, l = selectors.length; i < l; i++) { |
| + var selector = selectors[i]; |
| + var rule = findCSSRule(selector); |
| + if (rule) { |
| + rule.style.webkitTransitionDuration = duration + 'ms'; |
| + } else { |
| + throw 'Could not find the CSS rule "' + selector + '"'; |
| + } |
| + } |
| + } |
| + |
| + function findCSSRule(selectorText) { |
| + var rules = document.styleSheets[0].rules; |
| + for (var i = 0, l = rules.length; i < l; i++) { |
| + var rule = rules[i]; |
| + if (rule.selectorText == selectorText) |
| + { |
| + return rule; |
| + } |
| + } |
| + } |
| + |
| + function changeSlowFactor(el) { |
| + if (el.value) |
| + adjustAnimationTiming(el.value - 0, animatedProperties); |
| + } |
| + |
| + function changeDebugMode(el) { |
| + var prop = el.checked ? 'add' : 'remove'; |
| + document.body.classList[prop]('debug'); |
| + } |
| + |
| return { |
| - getCurrentlyDraggingTile: getCurrentlyDraggingTile, |
| - setCurrentDropEffect: setCurrentDropEffect, |
| - TilePage: TilePage, |
| + // TODO(xci) drag |
| + //getCurrentlyDraggingTile2: getCurrentlyDraggingTile, |
| + //setCurrentDropEffect2: setCurrentDropEffect, |
| + Tile2: Tile, |
| + TilePage2: TilePage, |
| }; |
| }); |