Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(384)

Side by Side Diff: chrome/browser/resources/ntp_search/tile_page.js

Issue 11412214: NTP5: Fine tuning of Apps implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressing Dan's comments Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
9 /**
10 * The maximum gap from the edge of the scrolling area which will display
11 * the shadow with transparency. After this point the shadow will become
12 * 100% opaque.
13 * @type {number}
14 * @const
15 */
16 var MAX_SCROLL_SHADOW_GAP = 16;
17
18 /**
19 * @type {number}
20 * @const
21 */
22 var TILE_ROW_HEIGHT = 92;
23
24 /**
25 * @type {number}
26 * @const
27 */
28 var SCROLL_BAR_WIDTH = 12;
29
8 //---------------------------------------------------------------------------- 30 //----------------------------------------------------------------------------
9 // Tile 31 // Tile
10 //---------------------------------------------------------------------------- 32 //----------------------------------------------------------------------------
11 33
12 /** 34 /**
13 * A virtual Tile class. Each TilePage subclass should have its own Tile 35 * A virtual Tile class. Each TilePage subclass should have its own Tile
14 * subclass implemented too (e.g. MostVisitedPage contains MostVisited 36 * subclass implemented too (e.g. MostVisitedPage contains MostVisited
15 * tiles, and MostVisited is a Tile subclass). 37 * tiles, and MostVisited is a Tile subclass).
16 * @constructor 38 * @constructor
17 * @param {Object} config TilePage configuration object. 39 * @param {Object} config TilePage configuration object.
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 212
191 /** 213 /**
192 * Creates a new TilePage object. This object contains tiles and controls 214 * Creates a new TilePage object. This object contains tiles and controls
193 * their layout. 215 * their layout.
194 * @constructor 216 * @constructor
195 * @extends {HTMLDivElement} 217 * @extends {HTMLDivElement}
196 */ 218 */
197 function TilePage() { 219 function TilePage() {
198 var el = cr.doc.createElement('div'); 220 var el = cr.doc.createElement('div');
199 el.__proto__ = TilePage.prototype; 221 el.__proto__ = TilePage.prototype;
200 el.initialize();
201 222
202 return el; 223 return el;
203 } 224 }
204 225
205 TilePage.prototype = { 226 TilePage.prototype = {
206 __proto__: HTMLDivElement.prototype, 227 __proto__: HTMLDivElement.prototype,
207 228
208 /** 229 /**
209 * Reference to the Tile subclass that will be used to create the tiles. 230 * Reference to the Tile subclass that will be used to create the tiles.
210 * @constructor 231 * @constructor
211 * @extends {Tile} 232 * @extends {Tile}
212 */ 233 */
213 TileClass: Tile, 234 TileClass: Tile,
214 235
215 // The config object should be defined by a TilePage subclass if it 236 // The config object should be defined by a TilePage subclass if it
216 // wants the non-default behavior. 237 // wants the non-default behavior.
217 config: { 238 config: {
218 // The width of a cell. 239 // The width of a cell.
219 cellWidth: 110, 240 cellWidth: 110,
220 // The start margin of a cell (left or right according to text direction). 241 // The start margin of a cell (left or right according to text direction).
221 cellMarginStart: 12, 242 cellMarginStart: 12,
222 // The maximum number of Tiles to be displayed. 243 // The maximum number of Tiles to be displayed.
223 maxTileCount: 6 244 maxTileCount: 6,
245 // Whether the TilePage content will be scrollable.
246 scrollable: false,
224 }, 247 },
225 248
226 /** 249 /**
227 * Initializes a TilePage. 250 * Initializes a TilePage.
228 */ 251 */
229 initialize: function() { 252 initialize: function() {
230 this.className = 'tile-page'; 253 this.className = 'tile-page';
231 254
232 // The content defines the actual space a page has to display tiles. 255 // The div that wraps the scrollable element.
256 this.frame_ = this.ownerDocument.createElement('div');
257 this.frame_.className = 'tile-page-frame';
258 this.appendChild(this.frame_);
259
260 // The content/scrollable element.
233 this.content_ = this.ownerDocument.createElement('div'); 261 this.content_ = this.ownerDocument.createElement('div');
234 this.content_.className = 'tile-page-content'; 262 this.content_.className = 'tile-page-content';
235 this.appendChild(this.content_); 263 this.frame_.appendChild(this.content_);
264
265 if (this.config.scrollable) {
266 this.content_.classList.add('scrollable');
267
268 // The scrollable shadow top.
269 this.shadowTop_ = this.ownerDocument.createElement('div');
270 this.shadowTop_.className = 'shadow-top';
271 this.content_.appendChild(this.shadowTop_);
272
273 // The scrollable shadow bottom.
274 this.shadowBottom_ = this.ownerDocument.createElement('div');
275 this.shadowBottom_.className = 'shadow-bottom';
276 this.content_.appendChild(this.shadowBottom_);
277 }
236 278
237 // The div that defines the tile grid viewport. 279 // The div that defines the tile grid viewport.
238 this.tileGrid_ = this.ownerDocument.createElement('div'); 280 this.tileGrid_ = this.ownerDocument.createElement('div');
239 this.tileGrid_.className = 'tile-grid'; 281 this.tileGrid_.className = 'tile-grid';
240 this.content_.appendChild(this.tileGrid_); 282 this.content_.appendChild(this.tileGrid_);
241 283
242 // The tile grid contents, which can be scrolled. 284 // The tile grid contents, which can be scrolled.
243 this.tileGridContent_ = this.ownerDocument.createElement('div'); 285 this.tileGridContent_ = this.ownerDocument.createElement('div');
244 this.tileGridContent_.className = 'tile-grid-content'; 286 this.tileGridContent_.className = 'tile-grid-content';
245 this.tileGrid_.appendChild(this.tileGridContent_); 287 this.tileGrid_.appendChild(this.tileGridContent_);
246 288
247 // The list of Tile elements which is used to fill the TileGrid cells. 289 // The list of Tile elements which is used to fill the TileGrid cells.
248 this.tiles_ = []; 290 this.tiles_ = [];
249 291
250 // TODO(pedrosimonetti): Check duplication of these methods. 292 // TODO(pedrosimonetti): Check duplication of these methods.
251 this.addEventListener('cardselected', this.handleCardSelection_); 293 this.addEventListener('cardselected', this.handleCardSelection_);
252 this.addEventListener('carddeselected', this.handleCardDeselection_); 294 this.addEventListener('carddeselected', this.handleCardDeselection_);
253 295
254 this.tileGrid_.addEventListener('webkitTransitionEnd', 296 this.tileGrid_.addEventListener('webkitTransitionEnd',
255 this.onTileGridTransitionEnd_.bind(this)); 297 this.onTileGridTransitionEnd_.bind(this));
298
299 this.content_.addEventListener('scroll', this.onScroll.bind(this));
256 }, 300 },
257 301
258 /** 302 /**
259 * The list of Tile elements. 303 * The list of Tile elements.
260 * @type {Array<Tile>} 304 * @type {Array<Tile>}
261 */ 305 */
262 get tiles() { 306 get tiles() {
263 return this.tiles_; 307 return this.tiles_;
264 }, 308 },
265 309
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 var config = this.config; 535 var config = this.config;
492 return config.cellWidth + config.cellMarginStart; 536 return config.cellWidth + config.cellMarginStart;
493 }, 537 },
494 538
495 /** 539 /**
496 * Gets the the maximum number of columns that can fit in a given width. 540 * Gets the the maximum number of columns that can fit in a given width.
497 * @param {number} width The width in pixels. 541 * @param {number} width The width in pixels.
498 * @private 542 * @private
499 */ 543 */
500 getColCountForWidth_: function(width) { 544 getColCountForWidth_: function(width) {
501 var availableWidth = width + this.config.cellMarginStart; 545 var scrollBarIsVisible = this.config.scrollable &&
546 this.content_.scrollHeight > this.content_.clientHeight;
547 var scrollBarWidth = scrollBarIsVisible ? SCROLL_BAR_WIDTH : 0;
548 var availableWidth = width + this.config.cellMarginStart - scrollBarWidth;
549
502 var requiredWidth = this.getTileRequiredWidth_(); 550 var requiredWidth = this.getTileRequiredWidth_();
503 var colCount = Math.floor(availableWidth / requiredWidth); 551 var colCount = Math.floor(availableWidth / requiredWidth);
504 return colCount; 552 return colCount;
505 }, 553 },
506 554
507 /** 555 /**
508 * Gets the width for a given number of columns. 556 * Gets the width for a given number of columns.
509 * @param {number} colCount The number of columns. 557 * @param {number} colCount The number of columns.
510 * @private 558 * @private
511 */ 559 */
512 getWidthForColCount_: function(colCount) { 560 getWidthForColCount_: function(colCount) {
513 var requiredWidth = this.getTileRequiredWidth_(); 561 var requiredWidth = this.getTileRequiredWidth_();
514 var width = colCount * requiredWidth - this.config.cellMarginStart; 562 var width = colCount * requiredWidth - this.config.cellMarginStart;
515 return width; 563 return width;
516 }, 564 },
517 565
518 /** 566 /**
519 * Returns the position of the tile at |index|. 567 * Returns the position of the tile at |index|.
520 * @param {number} index Tile index. 568 * @param {number} index Tile index.
521 * @private 569 * @private
522 * @return {!{top: number, left: number}} Position. 570 * @return {!{top: number, left: number}} Position.
523 */ 571 */
524 getTilePosition_: function(index) { 572 getTilePosition_: function(index) {
525 var colCount = this.colCount_; 573 var colCount = this.colCount_;
574 var row = Math.floor(index / colCount);
526 var col = index % colCount; 575 var col = index % colCount;
527 if (isRTL()) 576 if (isRTL())
528 col = colCount - col - 1; 577 col = colCount - col - 1;
529 var config = this.config; 578 var config = this.config;
579 var top = TILE_ROW_HEIGHT * row;
530 var left = col * (config.cellWidth + config.cellMarginStart); 580 var left = col * (config.cellWidth + config.cellMarginStart);
531 return {top: 0, left: left}; 581 return {top: top, left: left};
532 }, 582 },
533 583
534 // rendering 584 // rendering
535 // ------------------------------------------------------------------------- 585 // -------------------------------------------------------------------------
536 586
537 /** 587 /**
538 * Renders the tile grid, and the individual tiles. Rendering the grid 588 * Renders the tile grid, and the individual tiles. Rendering the grid
539 * consists of adding/removing tile rows and tile cells according to the 589 * consists of adding/removing tile rows and tile cells according to the
540 * specified size (defined by the number of columns in the grid). While 590 * specified size (defined by the number of columns in the grid). While
541 * rendering the grid, the tiles are rendered in order in their respective 591 * rendering the grid, the tiles are rendered in order in their respective
(...skipping 21 matching lines...) Expand all
563 for (var tile = 0, row = 0; row < rowCount; row++) { 613 for (var tile = 0, row = 0; row < rowCount; row++) {
564 var tileRow = tileRows[row]; 614 var tileRow = tileRows[row];
565 615
566 // Create tile row if there's no one yet. 616 // Create tile row if there's no one yet.
567 if (!tileRow) { 617 if (!tileRow) {
568 tileRow = cr.doc.createElement('div'); 618 tileRow = cr.doc.createElement('div');
569 tileRow.className = 'tile-row'; 619 tileRow.className = 'tile-row';
570 tileGridContent.appendChild(tileRow); 620 tileGridContent.appendChild(tileRow);
571 } 621 }
572 622
573 // Adjust row visibility.
574 var rowVisible = row >= pageOffset &&
575 row <= (pageOffset + numOfVisibleRows - 1);
576 this.showTileRow_(tileRow, rowVisible);
577
578 // The tiles inside the current row. 623 // The tiles inside the current row.
579 var tileRowTiles = tileRow.childNodes; 624 var tileRowTiles = tileRow.childNodes;
580 625
581 // Remove excessive columns from a particular tile row. 626 // Remove excessive columns from a particular tile row.
582 var maxColCount = Math.min(colCount, tileCount - tile); 627 var maxColCount = Math.min(colCount, tileCount - tile);
583 maxColCount = Math.max(0, maxColCount); 628 maxColCount = Math.max(0, maxColCount);
584 while (tileRowTiles.length > maxColCount) { 629 while (tileRowTiles.length > maxColCount) {
585 tileRow.removeChild(tileRow.lastElementChild); 630 tileRow.removeChild(tileRow.lastElementChild);
586 } 631 }
587 632
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 } 664 }
620 } 665 }
621 666
622 // Remove excessive tile rows from the tile grid. 667 // Remove excessive tile rows from the tile grid.
623 while (tileRows.length > rowCount) { 668 while (tileRows.length > rowCount) {
624 tileGridContent.removeChild(tileGridContent.lastElementChild); 669 tileGridContent.removeChild(tileGridContent.lastElementChild);
625 } 670 }
626 671
627 this.colCount_ = colCount; 672 this.colCount_ = colCount;
628 this.rowCount_ = rowCount; 673 this.rowCount_ = rowCount;
674
675 if (this.onScroll)
Dan Beam 2012/11/30 23:41:45 nit: same nit re: if (this.onScroll)
pedro (no code reviews) 2012/12/01 00:02:29 Done.
676 this.onScroll();
629 }, 677 },
630 678
631 // layout 679 // layout
632 // ------------------------------------------------------------------------- 680 // -------------------------------------------------------------------------
633 681
634 /** 682 /**
635 * Calculates the layout of the tile page according to the current Bottom 683 * Calculates the layout of the tile page according to the current Bottom
636 * Panel's size. This method will resize the containers of the tile page, 684 * Panel's size. This method will resize the containers of the tile page,
637 * and re-render the grid when its dimension changes (number of columns or 685 * and re-render the grid when its dimension changes (number of columns or
638 * visible rows changes). This method also sets the private properties 686 * visible rows changes). This method also sets the private properties
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 // TODO(pedrosimonetti): move to handler below. 722 // TODO(pedrosimonetti): move to handler below.
675 var self = this; 723 var self = this;
676 this.onTileGridTransitionEndHandler_ = function() { 724 this.onTileGridTransitionEndHandler_ = function() {
677 if (colCount < lastColCount) 725 if (colCount < lastColCount)
678 self.renderGrid_(colCount); 726 self.renderGrid_(colCount);
679 else 727 else
680 self.showTileCols_(0, true); 728 self.showTileCols_(0, true);
681 }; 729 };
682 } 730 }
683 731
684 this.content_.style.width = contentWidth + 'px'; 732 this.animatingColCount_ = colCount;
685 733
686 this.animatingColCount_ = colCount; 734 this.frame_.style.width = contentWidth + 'px';
735
736 this.onScroll();
687 }, 737 },
688 738
689 // tile repositioning animation 739 // tile repositioning animation
690 // ------------------------------------------------------------------------- 740 // -------------------------------------------------------------------------
691 741
692 /** 742 /**
693 * Tile repositioning state. 743 * Tile repositioning state.
694 * @type {{index: number, isRemoving: number}} 744 * @type {{index: number, isRemoving: number}}
695 */ 745 */
696 tileRepositioningState_: null, 746 tileRepositioningState_: null,
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 var positionDiff = isRemoving ? -1 : 1; 995 var positionDiff = isRemoving ? -1 : 1;
946 for (var i = startIndex; i < endIndex; i++) { 996 for (var i = startIndex; i < endIndex; i++) {
947 var tile = tiles[i]; 997 var tile = tiles[i];
948 this.resetTilePosition_(tile); 998 this.resetTilePosition_(tile);
949 tile.style.zIndex = ''; 999 tile.style.zIndex = '';
950 tileCells[i + positionDiff].assign(tile); 1000 tileCells[i + positionDiff].assign(tile);
951 } 1001 }
952 }, 1002 },
953 1003
954 /** 1004 /**
955 * Animates the display of a row. TODO(pedrosimonetti): Make it local? 1005 * Animates the display of columns.
956 * @param {HTMLElement} row The row element.
957 * @param {boolean} show Whether or not to show the row.
958 */
959 showTileRow_: function(row, show) {
960 row.classList[show ? 'remove' : 'add']('hide-row');
961 },
962
963 /**
964 * Animates the display of columns. TODO(pedrosimonetti): Make it local?
965 * @param {number} col The column number. 1006 * @param {number} col The column number.
966 * @param {boolean} show Whether or not to show the row. 1007 * @param {boolean} show Whether or not to show the row.
967 */ 1008 */
968 showTileCols_: function(col, show) { 1009 showTileCols_: function(col, show) {
969 var prop = show ? 'remove' : 'add'; 1010 var prop = show ? 'remove' : 'add';
970 var max = 10; // TODO(pedrosimonetti): Add const? 1011 var max = 10; // TODO(pedrosimonetti): Add const?
971 var tileGridContent = this.tileGridContent_; 1012 var tileGridContent = this.tileGridContent_;
972 for (var i = col; i < max; i++) { 1013 for (var i = col; i < max; i++) {
973 tileGridContent.classList[prop]('hide-col-' + i); 1014 tileGridContent.classList[prop]('hide-col-' + i);
974 } 1015 }
975 }, 1016 },
976 1017
977 // event handlers 1018 // event handlers
978 // ------------------------------------------------------------------------- 1019 // -------------------------------------------------------------------------
979 1020
980 /** 1021 /**
1022 * Handles the scroll event.
1023 * @protected
1024 */
1025 onScroll: function() {
1026 // If the TilePage is scrollable, then the opacity of shadow top and
1027 // bottom must adjusted, indicating when there's an overflow content.
1028 if (this.config.scrollable) {
1029 var content = this.content_;
1030 var topGap = Math.min(MAX_SCROLL_SHADOW_GAP, content.scrollTop);
1031 var bottomGap = Math.min(MAX_SCROLL_SHADOW_GAP, content.scrollHeight -
1032 content.scrollTop - content.clientHeight);
1033
1034 this.shadowTop_.style.opacity = topGap / MAX_SCROLL_SHADOW_GAP;
1035 this.shadowBottom_.style.opacity = bottomGap / MAX_SCROLL_SHADOW_GAP;
1036 }
1037 },
1038
1039 /**
981 * Handles the end of the horizontal tile grid transition. 1040 * Handles the end of the horizontal tile grid transition.
982 * @param {Event} e The tile grid webkitTransitionEnd event. 1041 * @param {Event} e The tile grid webkitTransitionEnd event.
983 */ 1042 */
984 onTileGridTransitionEnd_: function(e) { 1043 onTileGridTransitionEnd_: function(e) {
985 if (!this.selected) 1044 if (!this.selected)
986 return; 1045 return;
987 1046
988 // We should remove the classes that control transitions when the 1047 // We should remove the classes that control transitions when the
989 // transition ends so when the text is resized (Ctrl + '+'), no other 1048 // transition ends so when the text is resized (Ctrl + '+'), no other
990 // transition should happen except those defined in the specification. 1049 // transition should happen except those defined in the specification.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 tile.scrollTop; 1102 tile.scrollTop;
1044 tile.classList.remove(className); 1103 tile.classList.remove(className);
1045 } 1104 }
1046 } 1105 }
1047 1106
1048 return { 1107 return {
1049 Tile: Tile, 1108 Tile: Tile,
1050 TilePage: TilePage, 1109 TilePage: TilePage,
1051 }; 1110 };
1052 }); 1111 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698