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 11 matching lines...) Expand all Loading... |
22 | 22 |
23 //---------------------------------------------------------------------------- | 23 //---------------------------------------------------------------------------- |
24 // Tile | 24 // Tile |
25 //---------------------------------------------------------------------------- | 25 //---------------------------------------------------------------------------- |
26 | 26 |
27 /** | 27 /** |
28 * A virtual Tile class. Each TilePage subclass should have its own Tile | 28 * A virtual Tile class. Each TilePage subclass should have its own Tile |
29 * subclass implemented too (e.g. MostVisitedPage contains MostVisited | 29 * subclass implemented too (e.g. MostVisitedPage contains MostVisited |
30 * tiles, and MostVisited is a Tile subclass). | 30 * tiles, and MostVisited is a Tile subclass). |
31 * @constructor | 31 * @constructor |
32 * @param {Object} config TilePage configuration object. | |
33 */ | 32 */ |
34 function Tile(config) { | 33 function Tile() { |
35 console.error('Tile is a virtual class and is not supposed to be ' + | 34 console.error('Tile is a virtual class and is not supposed to be ' + |
36 'instantiated'); | 35 'instantiated'); |
37 } | 36 } |
38 | 37 |
39 /** | 38 /** |
40 * Creates a Tile subclass. We need to use this function to create a Tile | 39 * Creates a Tile subclass. We need to use this function to create a Tile |
41 * subclass because a Tile must also subclass a HTMLElement (which can be | 40 * subclass because a Tile must also subclass a HTMLElement (which can be |
42 * any HTMLElement), so we need to individually add methods and getters here. | 41 * any HTMLElement), so we need to individually add methods and getters here. |
43 * @param {Object} Subclass The prototype object of the class we want to be | 42 * @param {Object} Subclass The prototype object of the class we want to be |
44 * a Tile subclass. | 43 * a Tile subclass. |
(...skipping 11 matching lines...) Expand all Loading... |
56 } | 55 } |
57 return Subclass; | 56 return Subclass; |
58 }; | 57 }; |
59 | 58 |
60 Tile.prototype = { | 59 Tile.prototype = { |
61 // Tile data object. | 60 // Tile data object. |
62 data_: null, | 61 data_: null, |
63 | 62 |
64 /** | 63 /** |
65 * Initializes a Tile. | 64 * Initializes a Tile. |
66 * @param {Object} config TilePage configuration object. | |
67 */ | 65 */ |
68 initialize: function(config) { | 66 initialize: function() { |
69 this.classList.add('tile'); | 67 this.classList.add('tile'); |
70 this.reset(); | 68 this.reset(); |
71 }, | 69 }, |
72 | 70 |
73 /** | 71 /** |
74 * Resets the tile DOM. | 72 * Resets the tile DOM. |
75 */ | 73 */ |
76 reset: function() { | 74 reset: function() { |
77 }, | 75 }, |
78 | 76 |
79 /** | 77 /** |
80 * Update the appearance of this tile according to |data|. | 78 * The data for this Tile. |
81 * @param {Object} data A dictionary of relevant data for the page. | 79 * @param {Object} data A dictionary of relevant data for the page. |
82 */ | 80 */ |
83 setData: function(data) { | 81 set data(data) { |
84 // TODO(pedrosimonetti): Remove data.filler usage everywhere. | 82 // TODO(pedrosimonetti): Remove data.filler usage everywhere. |
85 if (!data || data.filler) { | 83 if (!data || data.filler) { |
86 if (this.data_) | 84 if (this.data_) |
87 this.reset(); | 85 this.reset(); |
88 return; | 86 return; |
89 } | 87 } |
90 | 88 |
91 this.data_ = data; | 89 this.data_ = data; |
92 } | 90 }, |
93 }; | 91 }; |
94 | 92 |
95 var TileGetters = { | 93 var TileGetters = { |
96 /** | 94 /** |
97 * The TileCell associated to this Tile. | 95 * The TileCell associated to this Tile. |
98 * @type {TileCell} | 96 * @type {TileCell} |
99 */ | 97 */ |
100 'tileCell': function() { | 98 'tileCell': function() { |
101 return findAncestorByClass(this, 'tile-cell'); | 99 return findAncestorByClass(this, 'tile-cell'); |
102 }, | 100 }, |
103 | 101 |
104 /** | 102 /** |
105 * The index of the Tile. | 103 * The index of the Tile. |
106 * @type {number} | 104 * @type {number} |
107 */ | 105 */ |
108 'index': function() { | 106 'index': function() { |
109 assert(this.tileCell); | 107 assert(this.tileCell); |
110 return this.tileCell.index; | 108 return this.tileCell.index; |
111 }, | 109 }, |
112 | |
113 /** | |
114 * Tile data object. | |
115 * @type {Object} | |
116 */ | |
117 'data': function() { | |
118 return this.data_; | |
119 } | |
120 }; | 110 }; |
121 | 111 |
122 //---------------------------------------------------------------------------- | 112 //---------------------------------------------------------------------------- |
123 // TileCell | 113 // TileCell |
124 //---------------------------------------------------------------------------- | 114 //---------------------------------------------------------------------------- |
125 | 115 |
126 /** | 116 /** |
127 * Creates a new TileCell object. A TileCell represents a cell in the | 117 * Creates a new TileCell object. A TileCell represents a cell in the |
128 * TilePage's grid. A TilePage uses TileCells to position Tiles in the proper | 118 * TilePage's grid. A TilePage uses TileCells to position Tiles in the proper |
129 * place and to animate them individually. Each TileCell is associated to | 119 * place and to animate them individually. Each TileCell is associated to |
(...skipping 28 matching lines...) Expand all Loading... |
158 this.className = 'tile-cell'; | 148 this.className = 'tile-cell'; |
159 this.assign(tile); | 149 this.assign(tile); |
160 }, | 150 }, |
161 | 151 |
162 /** | 152 /** |
163 * The index of the TileCell. | 153 * The index of the TileCell. |
164 * @type {number} | 154 * @type {number} |
165 */ | 155 */ |
166 get index() { | 156 get index() { |
167 return Array.prototype.indexOf.call(this.tilePage.tiles_, | 157 return Array.prototype.indexOf.call(this.tilePage.tiles_, |
168 this.firstChild); | 158 this.tile); |
169 }, | 159 }, |
170 | 160 |
171 /** | 161 /** |
| 162 * The Tile associated to this TileCell. |
| 163 * @type {Tile} |
| 164 */ |
| 165 get tile() { |
| 166 return this.firstElementChild; |
| 167 }, |
| 168 |
| 169 /** |
172 * The TilePage associated to this TileCell. | 170 * The TilePage associated to this TileCell. |
173 * @type {TilePage} | 171 * @type {TilePage} |
174 */ | 172 */ |
175 get tilePage() { | 173 get tilePage() { |
176 return findAncestorByClass(this, 'tile-page'); | 174 return findAncestorByClass(this, 'tile-page'); |
177 }, | 175 }, |
178 | 176 |
179 /** | 177 /** |
180 * Assigns a Tile to the this TileCell. | 178 * Assigns a Tile to the this TileCell. |
181 * @type {TilePage} | 179 * @type {TilePage} |
182 */ | 180 */ |
183 assign: function(tile) { | 181 assign: function(tile) { |
184 if (this.firstChild) | 182 if (this.tile) |
185 this.replaceChild(tile, this.firstChild); | 183 this.replaceChild(tile, this.tile); |
186 else | 184 else |
187 this.appendChild(tile); | 185 this.appendChild(tile); |
188 }, | 186 }, |
189 | 187 |
190 /** | 188 /** |
191 * Called when an app is removed from Chrome. Animates its disappearance. | 189 * Called when an app is removed from Chrome. Animates its disappearance. |
192 * @param {boolean=} opt_animate Whether the animation should be animated. | 190 * @param {boolean=} opt_animate Whether the animation should be animated. |
193 */ | 191 */ |
194 doRemove: function(opt_animate) { | 192 doRemove: function(opt_animate) { |
195 if (opt_animate) | 193 this.tilePage.removeTile(this.tile, false); |
196 this.firstChild.classList.add('removing-tile-contents'); | |
197 else | |
198 this.tilePage.removeTile(this, false); | |
199 }, | 194 }, |
200 }; | 195 }; |
201 | 196 |
202 //---------------------------------------------------------------------------- | 197 //---------------------------------------------------------------------------- |
203 // TilePage | 198 // TilePage |
204 //---------------------------------------------------------------------------- | 199 //---------------------------------------------------------------------------- |
205 | 200 |
206 /** | 201 /** |
207 * Creates a new TilePage object. This object contains tiles and controls | 202 * Creates a new TilePage object. This object contains tiles and controls |
208 * their layout. | 203 * their layout. |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 * @param {Tile} tile The tile to be added. | 439 * @param {Tile} tile The tile to be added. |
445 * @param {number} index The location in the tile grid to insert it at. | 440 * @param {number} index The location in the tile grid to insert it at. |
446 * @protected | 441 * @protected |
447 */ | 442 */ |
448 addTileAt: function(tile, index) { | 443 addTileAt: function(tile, index) { |
449 this.tiles_.splice(index, 0, tile); | 444 this.tiles_.splice(index, 0, tile); |
450 this.fireAddedEvent(tile, index); | 445 this.fireAddedEvent(tile, index); |
451 }, | 446 }, |
452 | 447 |
453 /** | 448 /** |
| 449 * Create a blank tile. |
| 450 * @protected |
| 451 */ |
| 452 createTile_: function() { |
| 453 return new this.TileClass(this.config); |
| 454 }, |
| 455 |
| 456 /** |
454 * Create blank tiles. | 457 * Create blank tiles. |
455 * @private | 458 * @param {number} count The desired number of Tiles to be created. If this |
456 * @param {number} count The number of Tiles to be created. | 459 * value the maximum value defined in |config.maxTileCount|, the maximum |
| 460 * value will be used instead. |
| 461 * @protected |
457 */ | 462 */ |
458 createTiles_: function(count) { | 463 createTiles_: function(count) { |
459 var Class = this.TileClass; | 464 count = Math.min(count, this.config.maxTileCount); |
460 var config = this.config; | |
461 count = Math.min(count, config.maxTileCount); | |
462 for (var i = 0; i < count; i++) { | 465 for (var i = 0; i < count; i++) { |
463 this.appendTile(new Class(config)); | 466 this.appendTile(this.createTile_()); |
464 } | 467 } |
465 }, | 468 }, |
466 | 469 |
467 /** | 470 /** |
468 * Update the tiles after a change to |dataList_|. | 471 * Update the tiles after a change to |dataList_|. |
469 */ | 472 */ |
470 updateTiles_: function() { | 473 updateTiles_: function() { |
471 var maxTileCount = this.config.maxTileCount; | 474 var maxTileCount = this.config.maxTileCount; |
472 var dataList = this.dataList_; | 475 var dataList = this.dataList_; |
473 var tiles = this.tiles; | 476 var tiles = this.tiles; |
474 for (var i = 0; i < maxTileCount; i++) { | 477 for (var i = 0; i < maxTileCount; i++) { |
475 var data = dataList[i]; | 478 var data = dataList[i]; |
476 var tile = tiles[i]; | 479 var tile = tiles[i]; |
477 | 480 |
478 // TODO(pedrosimonetti): What do we do when there's no tile here? | 481 // TODO(pedrosimonetti): What do we do when there's no tile here? |
479 if (!tile) | 482 if (!tile) |
480 return; | 483 return; |
481 | 484 |
482 if (i >= dataList.length) | 485 if (i >= dataList.length) |
483 tile.reset(); | 486 tile.reset(); |
484 else | 487 else |
485 tile.setData(data); | 488 tile.data = data; |
486 } | 489 } |
487 }, | 490 }, |
488 | 491 |
489 /** | 492 /** |
490 * Sets the dataList that will be used to create Tiles. This method will | 493 * Sets the dataList that will be used to create Tiles. This method will |
491 * create/remove necessary/unnecessary tiles, render the grid when the | 494 * create/remove necessary/unnecessary tiles, render the grid when the |
492 * number of tiles has changed, and finally will call |updateTiles_| which | 495 * number of tiles has changed, and finally will call |updateTiles_| which |
493 * will in turn render the individual tiles. | 496 * will in turn render the individual tiles. |
494 * @param {Array} dataList The array of data. | 497 * @param {Array} dataList The array of data. |
495 */ | 498 */ |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 * @param {number=} opt_colCount The number of columns. | 595 * @param {number=} opt_colCount The number of columns. |
593 * @private | 596 * @private |
594 */ | 597 */ |
595 renderGrid_: function(opt_colCount) { | 598 renderGrid_: function(opt_colCount) { |
596 var colCount = opt_colCount || this.colCount_; | 599 var colCount = opt_colCount || this.colCount_; |
597 | 600 |
598 var tileGridContent = this.tileGridContent_; | 601 var tileGridContent = this.tileGridContent_; |
599 var tiles = this.tiles_; | 602 var tiles = this.tiles_; |
600 var tileCount = tiles.length; | 603 var tileCount = tiles.length; |
601 | 604 |
602 var numOfVisibleRows = this.numOfVisibleRows_; | |
603 var rowCount = Math.ceil(tileCount / colCount); | 605 var rowCount = Math.ceil(tileCount / colCount); |
604 var tileRows = tileGridContent.getElementsByClassName('tile-row'); | 606 var tileRows = tileGridContent.getElementsByClassName('tile-row'); |
605 | 607 |
606 var pageOffset = this.pageOffset_; | |
607 | |
608 for (var tile = 0, row = 0; row < rowCount; row++) { | 608 for (var tile = 0, row = 0; row < rowCount; row++) { |
609 var tileRow = tileRows[row]; | 609 var tileRow = tileRows[row]; |
610 | 610 |
611 // Create tile row if there's no one yet. | 611 // Create tile row if there's no one yet. |
612 if (!tileRow) { | 612 if (!tileRow) { |
613 tileRow = cr.doc.createElement('div'); | 613 tileRow = cr.doc.createElement('div'); |
614 tileRow.className = 'tile-row'; | 614 tileRow.className = 'tile-row'; |
615 tileGridContent.appendChild(tileRow); | 615 tileGridContent.appendChild(tileRow); |
616 } | 616 } |
617 | 617 |
(...skipping 15 matching lines...) Expand all Loading... |
633 tileCell = tileRowTiles[col]; | 633 tileCell = tileRowTiles[col]; |
634 } else { | 634 } else { |
635 var span = cr.doc.createElement('span'); | 635 var span = cr.doc.createElement('span'); |
636 tileCell = new TileCell(span, this.config); | 636 tileCell = new TileCell(span, this.config); |
637 } | 637 } |
638 | 638 |
639 // Render Tiles. | 639 // Render Tiles. |
640 if (tile < tileCount) { | 640 if (tile < tileCount) { |
641 tileCell.classList.remove('filler'); | 641 tileCell.classList.remove('filler'); |
642 tileElement = tiles[tile]; | 642 tileElement = tiles[tile]; |
643 if (!tileCell.firstChild) | 643 if (!tileCell.tile) |
644 tileCell.appendChild(tileElement); | 644 tileCell.appendChild(tileElement); |
645 else if (tileElement != tileCell.firstChild) | 645 else if (tileElement != tileCell.tile) |
646 tileCell.replaceChild(tileElement, tileCell.firstChild); | 646 tileCell.replaceChild(tileElement, tileCell.tile); |
647 } else if (!tileCell.classList.contains('filler')) { | 647 } else if (!tileCell.classList.contains('filler')) { |
648 tileCell.classList.add('filler'); | 648 tileCell.classList.add('filler'); |
649 tileElement = cr.doc.createElement('span'); | 649 tileElement = cr.doc.createElement('span'); |
650 tileElement.className = 'tile'; | 650 tileElement.className = 'tile'; |
651 if (tileCell.firstChild) | 651 if (tileCell.tile) |
652 tileCell.replaceChild(tileElement, tileCell.firstChild); | 652 tileCell.replaceChild(tileElement, tileCell.tile); |
653 else | 653 else |
654 tileCell.appendChild(tileElement); | 654 tileCell.appendChild(tileElement); |
655 } | 655 } |
656 | 656 |
657 if (!tileRowTiles[col]) | 657 if (!tileRowTiles[col]) |
658 tileRow.appendChild(tileCell); | 658 tileRow.appendChild(tileCell); |
659 } | 659 } |
660 } | 660 } |
661 | 661 |
662 // Remove excessive tile rows from the tile grid. | 662 // Remove excessive tile rows from the tile grid. |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 | 851 |
852 var repositioningStartIndex = index; | 852 var repositioningStartIndex = index; |
853 var repositioningEndIndex = tileCount - (extraTileData ? 1 : 0); | 853 var repositioningEndIndex = tileCount - (extraTileData ? 1 : 0); |
854 | 854 |
855 this.initializeRepositioningAnimation_(index, repositioningEndIndex); | 855 this.initializeRepositioningAnimation_(index, repositioningEndIndex); |
856 | 856 |
857 var restoredData = newDataList[index]; | 857 var restoredData = newDataList[index]; |
858 var tileBeingRestored = createTile(this, restoredData); | 858 var tileBeingRestored = createTile(this, restoredData); |
859 tileCells[index].appendChild(tileBeingRestored); | 859 tileCells[index].appendChild(tileBeingRestored); |
860 | 860 |
861 var extraTile = extraCell.firstChild; | 861 var extraTile = extraCell.tile; |
862 | 862 |
863 this.executeRepositioningAnimation_(tileBeingRestored, extraTile, | 863 this.executeRepositioningAnimation_(tileBeingRestored, extraTile, |
864 repositioningStartIndex, repositioningEndIndex, false); | 864 repositioningStartIndex, repositioningEndIndex, false); |
865 | 865 |
866 // Cleans up the animation. | 866 // Cleans up the animation. |
867 var onPositioningTransitionEnd = function(e) { | 867 var onPositioningTransitionEnd = function(e) { |
868 var propertyName = e.propertyName; | 868 var propertyName = e.propertyName; |
869 if (!(propertyName == '-webkit-transform' || | 869 if (!(propertyName == '-webkit-transform' || |
870 propertyName == 'opacity')) { | 870 propertyName == 'opacity')) { |
871 return; | 871 return; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 * a tile filler will be created. | 1069 * a tile filler will be created. |
1070 * @param {TilePage} tilePage A TilePage. | 1070 * @param {TilePage} tilePage A TilePage. |
1071 * @param {Object=} opt_data The data that will be used to create the tile. | 1071 * @param {Object=} opt_data The data that will be used to create the tile. |
1072 * @return {Tile} The new tile. | 1072 * @return {Tile} The new tile. |
1073 */ | 1073 */ |
1074 function createTile(tilePage, opt_data) { | 1074 function createTile(tilePage, opt_data) { |
1075 var tile; | 1075 var tile; |
1076 if (opt_data) { | 1076 if (opt_data) { |
1077 // If there's data, the new tile will be a real one (not a filler). | 1077 // If there's data, the new tile will be a real one (not a filler). |
1078 tile = new tilePage.TileClass(tilePage.config); | 1078 tile = new tilePage.TileClass(tilePage.config); |
1079 tile.setData(opt_data); | 1079 tile.data = opt_data; |
1080 } else { | 1080 } else { |
1081 // Otherwise, it will be a fake filler tile. | 1081 // Otherwise, it will be a fake filler tile. |
1082 tile = cr.doc.createElement('span'); | 1082 tile = cr.doc.createElement('span'); |
1083 tile.className = 'tile'; | 1083 tile.className = 'tile'; |
1084 } | 1084 } |
1085 return tile; | 1085 return tile; |
1086 } | 1086 } |
1087 | 1087 |
1088 /** | 1088 /** |
1089 * Fades a tile. | 1089 * Fades a tile. |
1090 * @param {Tile} tile A Tile. | 1090 * @param {Tile} tile A Tile. |
1091 * @param {boolean} isFadeIn Whether to fade-in the tile. If |isFadeIn| is | 1091 * @param {boolean} isFadeIn Whether to fade-in the tile. If |isFadeIn| is |
1092 * false, then the tile is going to fade-out. | 1092 * false, then the tile is going to fade-out. |
1093 */ | 1093 */ |
1094 function fadeTile(tile, isFadeIn) { | 1094 function fadeTile(tile, isFadeIn) { |
1095 var className = 'animate-hide-tile'; | 1095 var className = 'animate-hide-tile'; |
1096 tile.classList.add(className); | 1096 tile.classList.add(className); |
1097 if (isFadeIn) { | 1097 if (isFadeIn) { |
1098 // Forces a reflow to ensure that the fade-out animation will work. | 1098 // Forces a reflow to ensure that the fade-out animation will work. |
1099 tile.scrollTop; | 1099 tile.scrollTop; |
1100 tile.classList.remove(className); | 1100 tile.classList.remove(className); |
1101 } | 1101 } |
1102 } | 1102 } |
1103 | 1103 |
1104 return { | 1104 return { |
1105 Tile: Tile, | 1105 Tile: Tile, |
1106 TilePage: TilePage, | 1106 TilePage: TilePage, |
1107 }; | 1107 }; |
1108 }); | 1108 }); |
OLD | NEW |