| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 cr.define('ntp', function() { | 5 cr.define('ntp', function() { |
| 6 'use strict'; | 6 'use strict'; |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * The maximum gap from the edge of the scrolling area which will display | 9 * The maximum gap from the edge of the scrolling area which will display |
| 10 * the shadow with transparency. After this point the shadow will become | 10 * the shadow with transparency. After this point the shadow will become |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 * place and to animate them individually. Each TileCell is associated to | 119 * place and to animate them individually. Each TileCell is associated to |
| 120 * one Tile at a time (or none if it is a filler object), and that association | 120 * one Tile at a time (or none if it is a filler object), and that association |
| 121 * might change when the grid is resized. When that happens, the grid is | 121 * might change when the grid is resized. When that happens, the grid is |
| 122 * updated and the Tiles are moved to the proper TileCell. We cannot move the | 122 * updated and the Tiles are moved to the proper TileCell. We cannot move the |
| 123 * the TileCell itself during the resize because this transition is animated | 123 * the TileCell itself during the resize because this transition is animated |
| 124 * with CSS and there's no way to stop CSS animations, and we really want to | 124 * with CSS and there's no way to stop CSS animations, and we really want to |
| 125 * animate with CSS to take advantage of hardware acceleration. | 125 * animate with CSS to take advantage of hardware acceleration. |
| 126 * @constructor | 126 * @constructor |
| 127 * @extends {HTMLDivElement} | 127 * @extends {HTMLDivElement} |
| 128 * @param {HTMLElement} tile Tile element that will be associated to the cell. | 128 * @param {HTMLElement} tile Tile element that will be associated to the cell. |
| 129 * @param {Object} config TilePage configuration object. | |
| 130 */ | 129 */ |
| 131 function TileCell(tile, config) { | 130 function TileCell(tile) { |
| 132 var tileCell = cr.doc.createElement('div'); | 131 var tileCell = cr.doc.createElement('div'); |
| 133 tileCell.__proto__ = TileCell.prototype; | 132 tileCell.__proto__ = TileCell.prototype; |
| 134 tileCell.initialize(tile, config); | 133 tileCell.initialize(tile); |
| 135 | 134 |
| 136 return tileCell; | 135 return tileCell; |
| 137 } | 136 } |
| 138 | 137 |
| 139 TileCell.prototype = { | 138 TileCell.prototype = { |
| 140 __proto__: HTMLDivElement.prototype, | 139 __proto__: HTMLDivElement.prototype, |
| 141 | 140 |
| 142 /** | 141 /** |
| 143 * Initializes a TileCell. | 142 * Initializes a TileCell. |
| 144 * @param {Tile} tile The Tile that will be assigned to this TileCell. | 143 * @param {Tile} tile The Tile that will be assigned to this TileCell. |
| 145 * @param {Object} config TilePage configuration object. | |
| 146 */ | 144 */ |
| 147 initialize: function(tile, config) { | 145 initialize: function(tile) { |
| 148 this.className = 'tile-cell'; | 146 this.className = 'tile-cell'; |
| 149 this.assign(tile); | 147 this.assign(tile); |
| 150 }, | 148 }, |
| 151 | 149 |
| 152 /** | 150 /** |
| 153 * The index of the TileCell. | 151 * The index of the TileCell. |
| 154 * @type {number} | 152 * @type {number} |
| 155 */ | 153 */ |
| 156 get index() { | 154 get index() { |
| 157 return Array.prototype.indexOf.call(this.tilePage.tiles_, | 155 return Array.prototype.indexOf.call(this.tilePage.tiles_, |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 this.tiles_.splice(index, 0, tile); | 442 this.tiles_.splice(index, 0, tile); |
| 445 this.fireAddedEvent(tile, index, false); | 443 this.fireAddedEvent(tile, index, false); |
| 446 this.renderGrid(); | 444 this.renderGrid(); |
| 447 }, | 445 }, |
| 448 | 446 |
| 449 /** | 447 /** |
| 450 * Create a blank tile. | 448 * Create a blank tile. |
| 451 * @protected | 449 * @protected |
| 452 */ | 450 */ |
| 453 createTile_: function() { | 451 createTile_: function() { |
| 454 return new this.TileClass(this.config); | 452 return new this.TileClass(); |
| 455 }, | 453 }, |
| 456 | 454 |
| 457 /** | 455 /** |
| 458 * Create blank tiles. | 456 * Create blank tiles. |
| 459 * @param {number} count The desired number of Tiles to be created. If this | 457 * @param {number} count The desired number of Tiles to be created. If this |
| 460 * value the maximum value defined in |config.maxTileCount|, the maximum | 458 * value the maximum value defined in |config.maxTileCount|, the maximum |
| 461 * value will be used instead. | 459 * value will be used instead. |
| 462 * @protected | 460 * @protected |
| 463 */ | 461 */ |
| 464 createTiles_: function(count) { | 462 createTiles_: function(count) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 * Renders the tile grid, and the individual tiles. Rendering the grid | 587 * Renders the tile grid, and the individual tiles. Rendering the grid |
| 590 * consists of adding/removing tile rows and tile cells according to the | 588 * consists of adding/removing tile rows and tile cells according to the |
| 591 * specified size (defined by the number of columns in the grid). While | 589 * specified size (defined by the number of columns in the grid). While |
| 592 * rendering the grid, the tiles are rendered in order in their respective | 590 * rendering the grid, the tiles are rendered in order in their respective |
| 593 * cells and tile fillers are rendered when needed. This method sets the | 591 * cells and tile fillers are rendered when needed. This method sets the |
| 594 * private properties colCount_ and rowCount_. | 592 * private properties colCount_ and rowCount_. |
| 595 * | 593 * |
| 596 * This method should be called every time the contents of the grid changes, | 594 * This method should be called every time the contents of the grid changes, |
| 597 * that is, when the number, contents or order of the tiles has changed. | 595 * that is, when the number, contents or order of the tiles has changed. |
| 598 * @param {number=} opt_colCount The number of columns. | 596 * @param {number=} opt_colCount The number of columns. |
| 597 * @param {number=} opt_tileCount Forces a particular number of tiles to |
| 598 * be drawn. This is useful for cases like the restoration/insertion |
| 599 * of tiles when you need to place a tile in a place of the grid that |
| 600 * is not rendered at the moment. |
| 599 * @protected | 601 * @protected |
| 600 */ | 602 */ |
| 601 renderGrid: function(opt_colCount) { | 603 renderGrid: function(opt_colCount, opt_tileCount) { |
| 602 var colCount = opt_colCount || this.colCount_; | 604 var colCount = opt_colCount || this.colCount_; |
| 603 | 605 |
| 604 var tileGridContent = this.tileGridContent_; | 606 var tileGridContent = this.tileGridContent_; |
| 605 var tiles = this.tiles_; | 607 var tiles = this.tiles_; |
| 606 var tileCount = tiles.length; | 608 var tileCount = opt_tileCount || tiles.length; |
| 607 | 609 |
| 608 var rowCount = Math.ceil(tileCount / colCount); | 610 var rowCount = Math.ceil(tileCount / colCount); |
| 609 var tileRows = tileGridContent.getElementsByClassName('tile-row'); | 611 var tileRows = tileGridContent.getElementsByClassName('tile-row'); |
| 610 | 612 |
| 611 for (var tile = 0, row = 0; row < rowCount; row++) { | 613 for (var tile = 0, row = 0; row < rowCount; row++) { |
| 612 var tileRow = tileRows[row]; | 614 var tileRow = tileRows[row]; |
| 613 | 615 |
| 614 // Create tile row if there's no one yet. | 616 // Create tile row if there's no one yet. |
| 615 if (!tileRow) { | 617 if (!tileRow) { |
| 616 tileRow = cr.doc.createElement('div'); | 618 tileRow = cr.doc.createElement('div'); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 629 } | 631 } |
| 630 | 632 |
| 631 // For each column in the current row. | 633 // For each column in the current row. |
| 632 for (var col = 0; col < colCount; col++, tile++) { | 634 for (var col = 0; col < colCount; col++, tile++) { |
| 633 var tileCell; | 635 var tileCell; |
| 634 var tileElement; | 636 var tileElement; |
| 635 if (tileRowTiles[col]) { | 637 if (tileRowTiles[col]) { |
| 636 tileCell = tileRowTiles[col]; | 638 tileCell = tileRowTiles[col]; |
| 637 } else { | 639 } else { |
| 638 var span = cr.doc.createElement('span'); | 640 var span = cr.doc.createElement('span'); |
| 639 tileCell = new TileCell(span, this.config); | 641 tileCell = new TileCell(span); |
| 640 } | 642 } |
| 641 | 643 |
| 642 // Render Tiles. | 644 // Render Tiles. |
| 643 if (tile < tileCount) { | 645 tileElement = tiles[tile]; |
| 646 if (tile < tileCount && tileElement) { |
| 644 tileCell.classList.remove('filler'); | 647 tileCell.classList.remove('filler'); |
| 645 tileElement = tiles[tile]; | |
| 646 if (!tileCell.tile) | 648 if (!tileCell.tile) |
| 647 tileCell.appendChild(tileElement); | 649 tileCell.appendChild(tileElement); |
| 648 else if (tileElement != tileCell.tile) | 650 else if (tileElement != tileCell.tile) |
| 649 tileCell.replaceChild(tileElement, tileCell.tile); | 651 tileCell.replaceChild(tileElement, tileCell.tile); |
| 650 } else if (!tileCell.classList.contains('filler')) { | 652 } else if (!tileCell.classList.contains('filler')) { |
| 651 tileCell.classList.add('filler'); | 653 tileCell.classList.add('filler'); |
| 652 tileElement = cr.doc.createElement('span'); | 654 tileElement = cr.doc.createElement('span'); |
| 653 tileElement.className = 'tile'; | 655 tileElement.className = 'tile'; |
| 654 if (tileCell.tile) | 656 if (tileCell.tile) |
| 655 tileCell.replaceChild(tileElement, tileCell.tile); | 657 tileCell.replaceChild(tileElement, tileCell.tile); |
| 656 else | 658 else |
| 657 tileCell.appendChild(tileElement); | 659 tileCell.appendChild(tileElement); |
| 658 } | 660 } |
| 659 | 661 |
| 660 if (!tileRowTiles[col]) | 662 if (!tileRowTiles[col]) |
| 661 tileRow.appendChild(tileCell); | 663 tileRow.appendChild(tileCell); |
| 662 } | 664 } |
| 663 } | 665 } |
| 664 | 666 |
| 665 // Remove excessive tile rows from the tile grid. | 667 // Remove excessive tile rows from the tile grid. |
| 666 while (tileRows.length > rowCount) { | 668 while (tileRows.length > rowCount) { |
| 667 tileGridContent.removeChild(tileGridContent.lastElementChild); | 669 tileGridContent.removeChild(tileGridContent.lastElementChild); |
| 668 } | 670 } |
| 669 | 671 |
| 670 this.colCount_ = colCount; | 672 this.colCount_ = colCount; |
| 671 this.rowCount_ = rowCount; | 673 this.rowCount_ = rowCount; |
| 672 | 674 |
| 673 this.onScroll(); | 675 // If we are manually changing the tile count (which can happen during |
| 676 // the restoration/insertion animation) we should not fire the scroll |
| 677 // event once some cells might contain dummy tiles which will cause |
| 678 // an error. |
| 679 if (!opt_tileCount) |
| 680 this.onScroll(); |
| 674 }, | 681 }, |
| 675 | 682 |
| 676 // layout | 683 // layout |
| 677 // ------------------------------------------------------------------------- | 684 // ------------------------------------------------------------------------- |
| 678 | 685 |
| 679 /** | 686 /** |
| 680 * Calculates the layout of the tile page according to the current Bottom | 687 * Calculates the layout of the tile page according to the current Bottom |
| 681 * Panel's size. This method will resize the containers of the tile page, | 688 * Panel's size. This method will resize the containers of the tile page, |
| 682 * and re-render the grid when its dimension changes (number of columns or | 689 * and re-render the grid when its dimension changes (number of columns or |
| 683 * visible rows changes). This method also sets the private properties | 690 * visible rows changes). This method also sets the private properties |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 | 846 |
| 840 /** | 847 /** |
| 841 * Animates a tile restoration. | 848 * Animates a tile restoration. |
| 842 * @param {number} index The index of the tile to be restored. | 849 * @param {number} index The index of the tile to be restored. |
| 843 * @param {Object} newDataList The new data list. | 850 * @param {Object} newDataList The new data list. |
| 844 */ | 851 */ |
| 845 animateTileRestoration: function(index, newDataList) { | 852 animateTileRestoration: function(index, newDataList) { |
| 846 var tiles = this.tiles_; | 853 var tiles = this.tiles_; |
| 847 var tileCount = tiles.length; | 854 var tileCount = tiles.length; |
| 848 | 855 |
| 849 var tileCells = this.querySelectorAll('.tile-cell'); | 856 var tileCells = this.getElementsByClassName('tile-cell'); |
| 857 |
| 858 // If the desired position is outside the grid, then the grid must be |
| 859 // expanded so there will be a cell in the desired position. |
| 860 if (index >= tileCells.length) |
| 861 this.renderGrid(null, index + 1); |
| 862 |
| 850 var extraTileIndex = Math.min(tileCount, this.config.maxTileCount - 1); | 863 var extraTileIndex = Math.min(tileCount, this.config.maxTileCount - 1); |
| 851 var extraCell = tileCells[extraTileIndex]; | 864 var extraCell = tileCells[extraTileIndex]; |
| 852 var extraTileData = newDataList[extraTileIndex + 1]; | 865 var extraTileData = newDataList[extraTileIndex + 1]; |
| 853 | 866 |
| 854 var repositioningStartIndex = index; | 867 var repositioningStartIndex = index; |
| 855 var repositioningEndIndex = tileCount - (extraTileData ? 1 : 0); | 868 var repositioningEndIndex = tileCount - (extraTileData ? 1 : 0); |
| 856 | 869 |
| 857 this.initializeRepositioningAnimation_(index, repositioningEndIndex); | 870 this.initializeRepositioningAnimation_(index, repositioningEndIndex); |
| 858 | 871 |
| 859 var restoredData = newDataList[index]; | 872 var restoredData = newDataList[index]; |
| 860 var tileBeingRestored = createTile(this, restoredData); | 873 var tileBeingRestored = createTile(this, restoredData); |
| 874 |
| 875 // Temporarily assume the |index| cell so the tile can be animated in |
| 876 // the right spot. |
| 861 tileCells[index].appendChild(tileBeingRestored); | 877 tileCells[index].appendChild(tileBeingRestored); |
| 862 | 878 |
| 863 if (this.config.scrollable) | 879 if (this.config.scrollable) |
| 864 this.content_.scrollTop = tileCells[index].offsetTop; | 880 this.content_.scrollTop = tileCells[index].offsetTop; |
| 865 | 881 |
| 866 var extraTile; | 882 var extraTile; |
| 867 if (extraCell) | 883 if (extraCell) |
| 868 extraTile = extraCell.tile; | 884 extraTile = extraCell.tile; |
| 869 | 885 |
| 870 this.executeRepositioningAnimation_(tileBeingRestored, extraTile, | 886 this.executeRepositioningAnimation_(tileBeingRestored, extraTile, |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 * Creates a new tile given a particular data. If there's no data, then | 1093 * Creates a new tile given a particular data. If there's no data, then |
| 1078 * a tile filler will be created. | 1094 * a tile filler will be created. |
| 1079 * @param {TilePage} tilePage A TilePage. | 1095 * @param {TilePage} tilePage A TilePage. |
| 1080 * @param {Object=} opt_data The data that will be used to create the tile. | 1096 * @param {Object=} opt_data The data that will be used to create the tile. |
| 1081 * @return {Tile} The new tile. | 1097 * @return {Tile} The new tile. |
| 1082 */ | 1098 */ |
| 1083 function createTile(tilePage, opt_data) { | 1099 function createTile(tilePage, opt_data) { |
| 1084 var tile; | 1100 var tile; |
| 1085 if (opt_data) { | 1101 if (opt_data) { |
| 1086 // If there's data, the new tile will be a real one (not a filler). | 1102 // If there's data, the new tile will be a real one (not a filler). |
| 1087 tile = new tilePage.TileClass(tilePage.config); | 1103 tile = new tilePage.TileClass(opt_data); |
| 1088 tile.data = opt_data; | |
| 1089 } else { | 1104 } else { |
| 1090 // Otherwise, it will be a fake filler tile. | 1105 // Otherwise, it will be a fake filler tile. |
| 1091 tile = cr.doc.createElement('span'); | 1106 tile = cr.doc.createElement('span'); |
| 1092 tile.className = 'tile'; | 1107 tile.className = 'tile'; |
| 1093 } | 1108 } |
| 1094 return tile; | 1109 return tile; |
| 1095 } | 1110 } |
| 1096 | 1111 |
| 1097 /** | 1112 /** |
| 1098 * Fades a tile. | 1113 * Fades a tile. |
| 1099 * @param {Tile} tile A Tile. | 1114 * @param {Tile} tile A Tile. |
| 1100 * @param {boolean} isFadeIn Whether to fade-in the tile. If |isFadeIn| is | 1115 * @param {boolean} isFadeIn Whether to fade-in the tile. If |isFadeIn| is |
| 1101 * false, then the tile is going to fade-out. | 1116 * false, then the tile is going to fade-out. |
| 1102 */ | 1117 */ |
| 1103 function fadeTile(tile, isFadeIn) { | 1118 function fadeTile(tile, isFadeIn) { |
| 1104 var className = 'animate-hide-tile'; | 1119 var className = 'animate-hide-tile'; |
| 1105 tile.classList.add(className); | 1120 tile.classList.add(className); |
| 1106 if (isFadeIn) { | 1121 if (isFadeIn) { |
| 1107 // Forces a reflow to ensure that the fade-out animation will work. | 1122 // Forces a reflow to ensure that the fade-out animation will work. |
| 1108 tile.scrollTop; | 1123 tile.scrollTop; |
| 1109 tile.classList.remove(className); | 1124 tile.classList.remove(className); |
| 1110 } | 1125 } |
| 1111 } | 1126 } |
| 1112 | 1127 |
| 1113 return { | 1128 return { |
| 1114 Tile: Tile, | 1129 Tile: Tile, |
| 1115 TilePage: TilePage, | 1130 TilePage: TilePage, |
| 1116 }; | 1131 }; |
| 1117 }); | 1132 }); |
| OLD | NEW |