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

Side by Side Diff: chrome/browser/resources/local_ntp/local_ntp.js

Issue 473583002: [Local NTP] Implementing Material Design styling (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixing comments. Created 6 years, 4 months 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 5
6 /** 6 /**
7 * @fileoverview The local InstantExtended NTP. 7 * @fileoverview The local InstantExtended NTP.
8 */ 8 */
9 9
10 10
(...skipping 10 matching lines...) Expand all
21 21
22 /** 22 /**
23 * Enum for classnames. 23 * Enum for classnames.
24 * @enum {string} 24 * @enum {string}
25 * @const 25 * @const
26 */ 26 */
27 var CLASSES = { 27 var CLASSES = {
28 ALTERNATE_LOGO: 'alternate-logo', // Shows white logo if required by theme 28 ALTERNATE_LOGO: 'alternate-logo', // Shows white logo if required by theme
29 BLACKLIST: 'mv-blacklist', // triggers tile blacklist animation 29 BLACKLIST: 'mv-blacklist', // triggers tile blacklist animation
30 BLACKLIST_BUTTON: 'mv-x', 30 BLACKLIST_BUTTON: 'mv-x',
31 DARK: 'dark',
32 DEFAULT_THEME: 'default-theme',
31 DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide', 33 DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide',
34 DOT: 'dot',
32 FAKEBOX_DISABLE: 'fakebox-disable', // Makes fakebox non-interactive 35 FAKEBOX_DISABLE: 'fakebox-disable', // Makes fakebox non-interactive
33 FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox 36 FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox
34 // Applies drag focus style to the fakebox 37 // Applies drag focus style to the fakebox
35 FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused', 38 FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused',
36 FAVICON: 'mv-favicon', 39 FAVICON: 'mv-favicon',
40 FAVICON_FALLBACK: 'mv-favicon-fallback',
37 HIDE_BLACKLIST_BUTTON: 'mv-x-hide', // hides blacklist button during animation 41 HIDE_BLACKLIST_BUTTON: 'mv-x-hide', // hides blacklist button during animation
38 HIDE_FAKEBOX_AND_LOGO: 'hide-fakebox-logo', 42 HIDE_FAKEBOX_AND_LOGO: 'hide-fakebox-logo',
39 HIDE_NOTIFICATION: 'mv-notice-hide', 43 HIDE_NOTIFICATION: 'mv-notice-hide',
40 // Vertically centers the most visited section for a non-Google provided page. 44 // Vertically centers the most visited section for a non-Google provided page.
41 NON_GOOGLE_PAGE: 'non-google-page', 45 NON_GOOGLE_PAGE: 'non-google-page',
42 PAGE: 'mv-page', // page tiles 46 PAGE: 'mv-page', // page tiles
43 PAGE_READY: 'mv-page-ready', // page tile when ready 47 PAGE_READY: 'mv-page-ready', // page tile when ready
44 RTL: 'rtl', // Right-to-left language text. 48 RTL: 'rtl', // Right-to-left language text.
45 THUMBNAIL: 'mv-thumb', 49 THUMBNAIL: 'mv-thumb',
50 THUMBNAIL_FALLBACK: 'mv-thumb-fallback',
46 THUMBNAIL_MASK: 'mv-mask', 51 THUMBNAIL_MASK: 'mv-mask',
47 TILE: 'mv-tile', 52 TILE: 'mv-tile',
53 TILE_INNER: 'mv-tile-inner',
48 TITLE: 'mv-title' 54 TITLE: 'mv-title'
49 }; 55 };
50 56
51 57
52 /** 58 /**
53 * Enum for HTML element ids. 59 * Enum for HTML element ids.
54 * @enum {string} 60 * @enum {string}
55 * @const 61 * @const
56 */ 62 */
57 var IDS = { 63 var IDS = {
58 ATTRIBUTION: 'attribution', 64 ATTRIBUTION: 'attribution',
59 ATTRIBUTION_TEXT: 'attribution-text', 65 ATTRIBUTION_TEXT: 'attribution-text',
60 CUSTOM_THEME_STYLE: 'ct-style', 66 CUSTOM_THEME_STYLE: 'ct-style',
61 FAKEBOX: 'fakebox', 67 FAKEBOX: 'fakebox',
62 FAKEBOX_INPUT: 'fakebox-input', 68 FAKEBOX_INPUT: 'fakebox-input',
69 FAKEBOX_TEXT: 'fakebox-text',
63 LOGO: 'logo', 70 LOGO: 'logo',
64 NOTIFICATION: 'mv-notice', 71 NOTIFICATION: 'mv-notice',
65 NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x', 72 NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x',
66 NOTIFICATION_MESSAGE: 'mv-msg', 73 NOTIFICATION_MESSAGE: 'mv-msg',
67 NTP_CONTENTS: 'ntp-contents', 74 NTP_CONTENTS: 'ntp-contents',
68 RESTORE_ALL_LINK: 'mv-restore', 75 RESTORE_ALL_LINK: 'mv-restore',
69 TILES: 'mv-tiles', 76 TILES: 'mv-tiles',
70 UNDO_LINK: 'mv-undo' 77 UNDO_LINK: 'mv-undo'
71 }; 78 };
72 79
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 /** 169 /**
163 * True if a page has been blacklisted and we're waiting on the 170 * True if a page has been blacklisted and we're waiting on the
164 * onmostvisitedchange callback. See onMostVisitedChange() for how this 171 * onmostvisitedchange callback. See onMostVisitedChange() for how this
165 * is used. 172 * is used.
166 * @type {boolean} 173 * @type {boolean}
167 */ 174 */
168 var isBlacklisting = false; 175 var isBlacklisting = false;
169 176
170 177
171 /** 178 /**
179 * Stores whether the current theme has a dark background.
180 * @type {boolean}
181 */
182 var isBackgroundDark = false;
183
184
185 /**
172 * Current number of tiles columns shown based on the window width, including 186 * Current number of tiles columns shown based on the window width, including
173 * those that just contain filler. 187 * those that just contain filler.
174 * @type {number} 188 * @type {number}
175 */ 189 */
176 var numColumnsShown = 0; 190 var numColumnsShown = 0;
177 191
178 192
179 /** 193 /**
180 * A flag to indicate Most Visited changed caused by user action. If true, then 194 * A flag to indicate Most Visited changed caused by user action. If true, then
181 * in onMostVisitedChange() tiles remain visible so no flickering occurs. 195 * in onMostVisitedChange() tiles remain visible so no flickering occurs.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 * @const 273 * @const
260 */ 274 */
261 var MOST_VISITED_PAINT_TIMEOUT_MSEC = 500; 275 var MOST_VISITED_PAINT_TIMEOUT_MSEC = 500;
262 276
263 277
264 /** 278 /**
265 * A Tile is either a rendering of a Most Visited page or "filler" used to 279 * A Tile is either a rendering of a Most Visited page or "filler" used to
266 * pad out the section when not enough pages exist. 280 * pad out the section when not enough pages exist.
267 * 281 *
268 * @param {Element} elem The element for rendering the tile. 282 * @param {Element} elem The element for rendering the tile.
283 * @param {Element=} opt_innerElem The element for contents of tile.
269 * @param {Element=} opt_titleElem The element for rendering the title. 284 * @param {Element=} opt_titleElem The element for rendering the title.
270 * @param {Element=} opt_thumbnailElem The element for rendering the thumbnail. 285 * @param {Element=} opt_thumbnailElem The element for rendering the thumbnail.
271 * @param {number=} opt_rid The RID for the corresponding Most Visited page. 286 * @param {number=} opt_rid The RID for the corresponding Most Visited page.
272 * Should only be left unspecified when creating a filler tile. 287 * Should only be left unspecified when creating a filler tile.
273 * @constructor 288 * @constructor
274 */ 289 */
275 function Tile(elem, opt_titleElem, opt_thumbnailElem, opt_rid) { 290 function Tile(elem, opt_innerElem, opt_titleElem, opt_thumbnailElem, opt_rid) {
276 /** @type {Element} */ 291 /** @type {Element} */
277 this.elem = elem; 292 this.elem = elem;
278 293
279 /** @type {Element|undefined} */ 294 /** @type {Element|undefined} */
295 this.innerElem = opt_innerElem;
296
297 /** @type {Element|undefined} */
280 this.titleElem = opt_titleElem; 298 this.titleElem = opt_titleElem;
281 299
282 /** @type {Element|undefined} */ 300 /** @type {Element|undefined} */
283 this.thumbnailElem = opt_thumbnailElem; 301 this.thumbnailElem = opt_thumbnailElem;
284 302
285 /** @type {number|undefined} */ 303 /** @type {number|undefined} */
286 this.rid = opt_rid; 304 this.rid = opt_rid;
287 } 305 }
288 306
289 307
290 /** 308 /**
309 * Determines whether a theme should be considered to have dark background.
310 * @param {ThemeBackgroundInfo} info Theme background information.
311 * @return {boolean} Whether the theme has dark background.
312 * @private
313 */
314 function getIsBackgroundDark(info) {
315 if (info.imageUrl)
316 return true;
317 var rgba = info.backgroundColorRgba;
318 var luminance = 0.3 * rgba[0] + 0.59 * rgba[1] + 0.11 * rgba[2];
319 return luminance < 128;
320 }
321
322
323 /**
291 * Updates the NTP based on the current theme. 324 * Updates the NTP based on the current theme.
292 * @private 325 * @private
293 */ 326 */
294 function onThemeChange() { 327 function renderTheme() {
295 var info = ntpApiHandle.themeBackgroundInfo; 328 var info = ntpApiHandle.themeBackgroundInfo;
296 if (!info) 329 if (!info) {
330 isBackgroundDark = false;
297 return; 331 return;
332 }
333
334 isBackgroundDark = getIsBackgroundDark(info);
335 ntpContents.classList.toggle(CLASSES.DARK, isBackgroundDark);
298 336
299 var background = [convertToRGBAColor(info.backgroundColorRgba), 337 var background = [convertToRGBAColor(info.backgroundColorRgba),
300 info.imageUrl, 338 info.imageUrl,
301 info.imageTiling, 339 info.imageTiling,
302 info.imageHorizontalAlignment, 340 info.imageHorizontalAlignment,
303 info.imageVerticalAlignment].join(' ').trim(); 341 info.imageVerticalAlignment].join(' ').trim();
304 document.body.style.background = background; 342 document.body.style.background = background;
305 document.body.classList.toggle(CLASSES.ALTERNATE_LOGO, info.alternateLogo); 343 document.body.classList.toggle(CLASSES.ALTERNATE_LOGO, info.alternateLogo);
306 updateThemeAttribution(info.attributionUrl); 344 updateThemeAttribution(info.attributionUrl);
307 setCustomThemeStyle(info); 345 setCustomThemeStyle(info);
346 }
308 347
348
349 /**
350 * Updates the NTP based on the current theme, then rerenders all tiles.
351 * @private
352 */
353 function onThemeChange() {
354 renderTheme();
309 tilesContainer.innerHTML = ''; 355 tilesContainer.innerHTML = '';
310 renderAndShowTiles(); 356 renderAndShowTiles();
311 } 357 }
312 358
313 359
314 /** 360 /**
315 * Updates the NTP style according to theme. 361 * Updates the NTP style according to theme.
316 * @param {Object=} opt_themeInfo The information about the theme. If it is 362 * @param {Object=} opt_themeInfo The information about the theme. If it is
317 * omitted the style will be reverted to the default. 363 * omitted the style will be reverted to the default.
318 * @private 364 * @private
319 */ 365 */
320 function setCustomThemeStyle(opt_themeInfo) { 366 function setCustomThemeStyle(opt_themeInfo) {
321 var customStyleElement = $(IDS.CUSTOM_THEME_STYLE); 367 var customStyleElement = $(IDS.CUSTOM_THEME_STYLE);
322 var head = document.head; 368 var head = document.head;
323 369
324 if (opt_themeInfo && !opt_themeInfo.usingDefaultTheme) { 370 if (opt_themeInfo && !opt_themeInfo.usingDefaultTheme) {
371 ntpContents.classList.remove(CLASSES.DEFAULT_THEME);
325 var themeStyle = 372 var themeStyle =
326 '#attribution {' + 373 '#attribution {' +
327 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorLightRgba) + ';' + 374 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorLightRgba) + ';' +
328 '}' + 375 '}' +
329 '#mv-msg {' + 376 '#mv-msg {' +
330 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorRgba) + ';' + 377 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorRgba) + ';' +
331 '}' + 378 '}' +
332 '#mv-notice-links span {' + 379 '#mv-notice-links span {' +
333 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorLightRgba) + ';' + 380 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorLightRgba) + ';' +
334 '}' + 381 '}' +
335 '#mv-notice-x {' + 382 '#mv-notice-x {' +
336 ' -webkit-filter: drop-shadow(0 0 0 ' + 383 ' -webkit-filter: drop-shadow(0 0 0 ' +
337 convertToRGBAColor(opt_themeInfo.textColorRgba) + ');' + 384 convertToRGBAColor(opt_themeInfo.textColorRgba) + ');' +
338 '}' + 385 '}' +
339 '.mv-page-ready {' + 386 '.mv-page-ready .mv-mask {' +
340 ' border: 1px solid ' + 387 ' border: 1px solid ' +
341 convertToRGBAColor(opt_themeInfo.sectionBorderColorRgba) + ';' + 388 convertToRGBAColor(opt_themeInfo.sectionBorderColorRgba) + ';' +
342 '}' + 389 '}' +
343 '.mv-page-ready:hover, .mv-page-ready:focus {' + 390 '.mv-page-ready:hover .mv-mask, .mv-page-ready:focus .mv-mask {' +
344 ' border-color: ' + 391 ' border-color: ' +
345 convertToRGBAColor(opt_themeInfo.headerColorRgba) + ';' + 392 convertToRGBAColor(opt_themeInfo.headerColorRgba) + ';' +
346 '}'; 393 '}';
347 394
348 if (customStyleElement) { 395 if (customStyleElement) {
349 customStyleElement.textContent = themeStyle; 396 customStyleElement.textContent = themeStyle;
350 } else { 397 } else {
351 customStyleElement = document.createElement('style'); 398 customStyleElement = document.createElement('style');
352 customStyleElement.type = 'text/css'; 399 customStyleElement.type = 'text/css';
353 customStyleElement.id = IDS.CUSTOM_THEME_STYLE; 400 customStyleElement.id = IDS.CUSTOM_THEME_STYLE;
354 customStyleElement.textContent = themeStyle; 401 customStyleElement.textContent = themeStyle;
355 head.appendChild(customStyleElement); 402 head.appendChild(customStyleElement);
356 } 403 }
357 404
358 } else if (customStyleElement) { 405 } else {
359 head.removeChild(customStyleElement); 406 ntpContents.classList.add(CLASSES.DEFAULT_THEME);
407 if (customStyleElement)
408 head.removeChild(customStyleElement);
360 } 409 }
361 } 410 }
362 411
363 412
364 /** 413 /**
365 * Renders the attribution if the URL is present, otherwise hides it. 414 * Renders the attribution if the URL is present, otherwise hides it.
366 * @param {string} url The URL of the attribution image, if any. 415 * @param {string} url The URL of the attribution image, if any.
367 * @private 416 * @private
368 */ 417 */
369 function updateThemeAttribution(url) { 418 function updateThemeAttribution(url) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 color[3] / 255 + ')'; 454 color[3] / 255 + ')';
406 } 455 }
407 456
408 457
409 /** 458 /**
410 * Handles a new set of Most Visited page data. 459 * Handles a new set of Most Visited page data.
411 */ 460 */
412 function onMostVisitedChange() { 461 function onMostVisitedChange() {
413 if (isBlacklisting) { 462 if (isBlacklisting) {
414 // Trigger the blacklist animation, which then triggers reloadAllTiles(). 463 // Trigger the blacklist animation, which then triggers reloadAllTiles().
415 var lastBlacklistedTileElement = lastBlacklistedTile.elem; 464 var lastBlacklistedTileElem = lastBlacklistedTile.elem;
416 lastBlacklistedTileElement.addEventListener( 465 lastBlacklistedTileElem.addEventListener(
417 'webkitTransitionEnd', blacklistAnimationDone); 466 'webkitTransitionEnd', blacklistAnimationDone);
418 lastBlacklistedTileElement.classList.add(CLASSES.BLACKLIST); 467 lastBlacklistedTileElem.classList.add(CLASSES.BLACKLIST);
419 } else { 468 } else {
420 reloadAllTiles(); 469 reloadAllTiles();
421 } 470 }
422 } 471 }
423 472
424 473
425 /** 474 /**
426 * Handles the end of the blacklist animation by showing the notification and 475 * Handles the end of the blacklist animation by showing the notification and
427 * re-rendering the new set of tiles. 476 * re-rendering the new set of tiles.
428 */ 477 */
(...skipping 21 matching lines...) Expand all
450 tiles.push(createTile(pages[i], i)); 499 tiles.push(createTile(pages[i], i));
451 500
452 tilesContainer.innerHTML = ''; 501 tilesContainer.innerHTML = '';
453 renderAndShowTiles(); 502 renderAndShowTiles();
454 } 503 }
455 504
456 505
457 /** 506 /**
458 * Binds onload events for a tile's internal <iframe> elements. 507 * Binds onload events for a tile's internal <iframe> elements.
459 * @param {Tile} tile The main tile to bind events to. 508 * @param {Tile} tile The main tile to bind events to.
460 * @param {Barrier} tileVisibilityBarrier A barrier to make tile visible the 509 * @param {Barrier} tileVisibilityBarrier A barrier to make all tiles visible
461 * moment all tiles are loaded. 510 * the moment all tiles are loaded.
462 */ 511 */
463 function bindTileOnloadEvents(tile, tileVisibilityBarrier) { 512 function bindTileOnloadEvents(tile, tileVisibilityBarrier) {
464 if (tile.titleElem) { 513 if (tile.titleElem) {
465 tileVisibilityBarrier.add(); 514 tileVisibilityBarrier.add();
466 tile.titleElem.onload = function() { 515 tile.titleElem.onload = function() {
467 tile.titleElem.hidden = false;
468 tileVisibilityBarrier.remove(); 516 tileVisibilityBarrier.remove();
469 }; 517 };
470 } 518 }
471
472 if (tile.thumbnailElem) { 519 if (tile.thumbnailElem) {
473 tileVisibilityBarrier.add(); 520 tileVisibilityBarrier.add();
474 tile.thumbnailElem.onload = function() { 521 tile.thumbnailElem.onload = function() {
475 tile.thumbnailElem.hidden = false;
476 tile.elem.classList.add(CLASSES.PAGE_READY); 522 tile.elem.classList.add(CLASSES.PAGE_READY);
477 tileVisibilityBarrier.remove(); 523 tileVisibilityBarrier.remove();
478 }; 524 };
479 } 525 }
480 } 526 }
481 527
482 528
483 /** 529 /**
484 * Renders the current list of visible tiles to DOM, and hides tiles that are 530 * Renders the current list of visible tiles to DOM, and hides tiles that are
485 * already in the DOM but should not be seen. 531 * already in the DOM but should not be seen.
486 */ 532 */
487 function renderAndShowTiles() { 533 function renderAndShowTiles() {
488 var numExisting = tilesContainer.querySelectorAll('.' + CLASSES.TILE).length; 534 var numExisting = tilesContainer.querySelectorAll('.' + CLASSES.TILE).length;
489 // Only add visible tiles to the DOM, to avoid creating invisible tiles that 535 // Only add visible tiles to the DOM, to avoid creating invisible tiles that
490 // produce meaningless impression metrics. However, if a tile becomes 536 // produce meaningless impression metrics. However, if a tile becomes
491 // invisible then we leave it in DOM to prevent reload if it's shown again. 537 // invisible then we leave it in DOM to prevent reload if it's shown again.
492 var numDesired = Math.min(tiles.length, numColumnsShown * NUM_ROWS); 538 var numDesired = Math.min(tiles.length, numColumnsShown * NUM_ROWS);
493 539
494 // If we need to render new tiles, manage the visibility to hide intermediate 540 // If we need to render new tiles, manage the visibility to hide intermediate
495 // load states of the <iframe>s. 541 // load states of the <iframe>s.
496 if (numExisting < numDesired) { 542 if (numExisting < numDesired) {
497 var tileVisibilityBarrier = new Barrier(function() { 543 var showAll = function() {
498 tilesContainer.style.visibility = 'visible'; 544 for (var i = 0; i < numDesired; ++i) {
499 }); 545 if (tiles[i].titleElem || tiles[i].thumbnailElem)
546 tiles[i].elem.classList.add(CLASSES.PAGE_READY);
547 }
548 };
549 var tileVisibilityBarrier = new Barrier(showAll);
500 550
501 if (!userInitiatedMostVisitedChange) { 551 if (!userInitiatedMostVisitedChange) {
502 // Make titleContainer invisible, but still taking up space. 552 // Make titleContainer invisible, but still taking up space.
503 // titleContainer becomes visible again (1) on timeout, or (2) when all 553 // titleContainer becomes visible again (1) on timeout, or (2) when all
504 // tiles finish loading (using tileVisibilityBarrier). 554 // tiles finish loading (using tileVisibilityBarrier).
505 tilesContainer.style.visibility = 'hidden';
506 window.setTimeout(function() { 555 window.setTimeout(function() {
507 tileVisibilityBarrier.cancel(); 556 tileVisibilityBarrier.cancel();
508 tilesContainer.style.visibility = 'visible'; 557 showAll();
509 }, MOST_VISITED_PAINT_TIMEOUT_MSEC); 558 }, MOST_VISITED_PAINT_TIMEOUT_MSEC);
510 } 559 }
511 userInitiatedMostVisitedChange = false; 560 userInitiatedMostVisitedChange = false;
512 561
513 for (var i = numExisting; i < numDesired; ++i) { 562 for (var i = numExisting; i < numDesired; ++i) {
514 bindTileOnloadEvents(tiles[i], tileVisibilityBarrier); 563 bindTileOnloadEvents(tiles[i], tileVisibilityBarrier);
515 tilesContainer.appendChild(tiles[i].elem); 564 tilesContainer.appendChild(tiles[i].elem);
516 } 565 }
517 } 566 }
518 567
519 // Show only the desired tiles. Not using .hidden because it does not work for 568 // Show only the desired tiles. Note that .hidden does not work for
520 // inline-block elements. 569 // inline-block elements like tiles[i].elem.
521 for (var i = 0; i < numDesired; ++i) 570 for (var i = 0; i < numDesired; ++i)
522 tiles[i].elem.style.display = 'inline-block'; 571 tiles[i].elem.style.display = 'inline-block';
523 // If |numDesired| < |numExisting| then hide extra tiles (e.g., this occurs 572 // If |numDesired| < |numExisting| then hide extra tiles (e.g., this occurs
524 // when window is downsized). 573 // when window is downsized).
525 for (; i < numExisting; ++i) 574 for (; i < numExisting; ++i)
526 tiles[i].elem.style.display = 'none'; 575 tiles[i].elem.style.display = 'none';
527 } 576 }
528 577
529 578
530 /** 579 /**
531 * Builds a URL to display a most visited tile title in an iframe. 580 * Builds a URL to display a most visited tile title in an iframe.
532 * @param {number} rid The restricted ID. 581 * @param {number} rid The restricted ID.
533 * @param {number} position The position of the iframe in the UI. 582 * @param {number} position The position of the iframe in the UI.
534 * @return {string} An URL to display the most visited title in an iframe. 583 * @return {string} An URL to display the most visited title in an iframe.
535 */ 584 */
536 function getMostVisitedTitleIframeUrl(rid, position) { 585 function getMostVisitedTitleIframeUrl(rid, position) {
537 var url = 'chrome-search://most-visited/' + 586 var url = 'chrome-search://most-visited/' +
538 encodeURIComponent(MOST_VISITED_TITLE_IFRAME); 587 encodeURIComponent(MOST_VISITED_TITLE_IFRAME);
588 var titleColor = isBackgroundDark ? NTP_DESIGN.titleColorAgainstDark :
589 NTP_DESIGN.titleColor;
539 var params = [ 590 var params = [
540 'rid=' + encodeURIComponent(rid), 591 'rid=' + encodeURIComponent(rid),
541 'f=' + encodeURIComponent(NTP_DESIGN.fontFamily), 592 'f=' + encodeURIComponent(NTP_DESIGN.fontFamily),
542 'fs=' + encodeURIComponent(NTP_DESIGN.fontSize), 593 'fs=' + encodeURIComponent(NTP_DESIGN.fontSize),
543 'c=' + encodeURIComponent(NTP_DESIGN.titleColor), 594 'c=' + encodeURIComponent(titleColor),
544 'pos=' + encodeURIComponent(position)]; 595 'pos=' + encodeURIComponent(position)];
545 if (NTP_DESIGN.titleTextAlign) 596 if (NTP_DESIGN.titleTextAlign)
546 params.push('ta=' + encodeURIComponent(NTP_DESIGN.titleTextAlign)); 597 params.push('ta=' + encodeURIComponent(NTP_DESIGN.titleTextAlign));
547 if (NTP_DESIGN.titleTextFade) 598 if (NTP_DESIGN.titleTextFade)
548 params.push('tf=' + encodeURIComponent(NTP_DESIGN.titleTextFade)); 599 params.push('tf=' + encodeURIComponent(NTP_DESIGN.titleTextFade));
549 return url + '?' + params.join('&'); 600 return url + '?' + params.join('&');
550 } 601 }
551 602
552 603
553 /** 604 /**
554 * Builds a URL to display a most visited tile thumbnail in an iframe. 605 * Builds a URL to display a most visited tile thumbnail in an iframe.
555 * @param {number} rid The restricted ID. 606 * @param {number} rid The restricted ID.
556 * @param {number} position The position of the iframe in the UI. 607 * @param {number} position The position of the iframe in the UI.
557 * @return {string} An URL to display the most visited thumbnail in an iframe. 608 * @return {string} An URL to display the most visited thumbnail in an iframe.
558 */ 609 */
559 function getMostVisitedThumbnailIframeUrl(rid, position) { 610 function getMostVisitedThumbnailIframeUrl(rid, position) {
560 var url = 'chrome-search://most-visited/' + 611 var url = 'chrome-search://most-visited/' +
561 encodeURIComponent(MOST_VISITED_THUMBNAIL_IFRAME); 612 encodeURIComponent(MOST_VISITED_THUMBNAIL_IFRAME);
562 var params = [ 613 var params = [
563 'rid=' + encodeURIComponent(rid), 614 'rid=' + encodeURIComponent(rid),
564 'f=' + encodeURIComponent(NTP_DESIGN.fontFamily), 615 'f=' + encodeURIComponent(NTP_DESIGN.fontFamily),
565 'fs=' + encodeURIComponent(NTP_DESIGN.fontSize), 616 'fs=' + encodeURIComponent(NTP_DESIGN.fontSize),
566 'c=' + encodeURIComponent(NTP_DESIGN.thumbnailTextColor), 617 'c=' + encodeURIComponent(NTP_DESIGN.thumbnailTextColor),
567 'pos=' + encodeURIComponent(position)]; 618 'pos=' + encodeURIComponent(position)];
619 if (NTP_DESIGN.thumbnailFallback)
620 params.push('etfb=1');
568 return url + '?' + params.join('&'); 621 return url + '?' + params.join('&');
569 } 622 }
570 623
571 624
572 /** 625 /**
573 * Creates a Tile with the specified page data. If no data is provided, a 626 * Creates a Tile with the specified page data. If no data is provided, a
574 * filler Tile is created. 627 * filler Tile is created.
575 * @param {Object} page The page data. 628 * @param {Object} page The page data.
576 * @param {number} position The position of the tile. 629 * @param {number} position The position of the tile.
577 * @return {Tile} The new Tile. 630 * @return {Tile} The new Tile.
578 */ 631 */
579 function createTile(page, position) { 632 function createTile(page, position) {
580 var tileElement = document.createElement('div'); 633 var tileElem = document.createElement('div');
581 tileElement.classList.add(CLASSES.TILE); 634 tileElem.classList.add(CLASSES.TILE);
635 var innerElem = createAndAppendElement(tileElem, 'div', CLASSES.TILE_INNER);
582 636
583 if (page) { 637 if (page) {
584 var rid = page.rid; 638 var rid = page.rid;
585 tileElement.classList.add(CLASSES.PAGE); 639 tileElem.classList.add(CLASSES.PAGE);
586 640
587 var navigateFunction = function(e) { 641 var navigateFunction = function(e) {
588 e.preventDefault(); 642 e.preventDefault();
589 ntpApiHandle.navigateContentWindow(rid, getDispositionFromEvent(e)); 643 ntpApiHandle.navigateContentWindow(rid, getDispositionFromEvent(e));
590 }; 644 };
591 645
592 // The click handler for navigating to the page identified by the RID. 646 // The click handler for navigating to the page identified by the RID.
593 tileElement.addEventListener('click', navigateFunction); 647 tileElem.addEventListener('click', navigateFunction);
594 648
595 // Make thumbnails tab-accessible. 649 // Make thumbnails tab-accessible.
596 tileElement.setAttribute('tabindex', '1'); 650 tileElem.setAttribute('tabindex', '1');
597 registerKeyHandler(tileElement, KEYCODE.ENTER, navigateFunction); 651 registerKeyHandler(tileElem, KEYCODE.ENTER, navigateFunction);
598 652
599 // The iframe which renders the page title. 653 // The iframe which renders the page title.
600 var titleElement = document.createElement('iframe'); 654 var titleElem = document.createElement('iframe');
601 titleElement.tabIndex = '-1'; 655 titleElem.tabIndex = '-1';
602 656
603 // Why iframes have IDs: 657 // Why iframes have IDs:
604 // 658 //
605 // On navigating back to the NTP we see several onmostvisitedchange() events 659 // On navigating back to the NTP we see several onmostvisitedchange() events
606 // in series with incrementing RIDs. After the first event, a set of iframes 660 // in series with incrementing RIDs. After the first event, a set of iframes
607 // begins loading RIDs n, n+1, ..., n+k-1; after the second event, these get 661 // begins loading RIDs n, n+1, ..., n+k-1; after the second event, these get
608 // destroyed and a new set begins loading RIDs n+k, n+k+1, ..., n+2k-1. 662 // destroyed and a new set begins loading RIDs n+k, n+k+1, ..., n+2k-1.
609 // Now due to crbug.com/68841, Chrome incorrectly loads the content for the 663 // Now due to crbug.com/68841, Chrome incorrectly loads the content for the
610 // first set of iframes into the most recent set of iframes. 664 // first set of iframes into the most recent set of iframes.
611 // 665 //
612 // Giving iframes distinct ids seems to cause some invalidation and prevent 666 // Giving iframes distinct ids seems to cause some invalidation and prevent
613 // associating the incorrect data. 667 // associating the incorrect data.
614 // 668 //
615 // TODO(jered): Find and fix the root (probably Blink) bug. 669 // TODO(jered): Find and fix the root (probably Blink) bug.
616 670
617 // Keep this ID here. See comment above. 671 // Keep this ID here. See comment above.
618 titleElement.id = 'title-' + rid; 672 titleElem.id = 'title-' + rid;
619 titleElement.className = CLASSES.TITLE; 673 titleElem.className = CLASSES.TITLE;
620 titleElement.hidden = true; 674 titleElem.src = getMostVisitedTitleIframeUrl(rid, position);
621 titleElement.src = getMostVisitedTitleIframeUrl(rid, position); 675 innerElem.appendChild(titleElem);
622 tileElement.appendChild(titleElement); 676
677 // A fallback element for missing thumbnails.
678 if (NTP_DESIGN.thumbnailFallback) {
679 var fallbackElem = createAndAppendElement(
680 innerElem, 'div', CLASSES.THUMBNAIL_FALLBACK);
681 if (NTP_DESIGN.thumbnailFallback === THUMBNAIL_FALLBACK.DOT)
682 createAndAppendElement(fallbackElem, 'div', CLASSES.DOT);
683 }
623 684
624 // The iframe which renders either a thumbnail or domain element. 685 // The iframe which renders either a thumbnail or domain element.
625 var thumbnailElement = document.createElement('iframe'); 686 var thumbnailElem = document.createElement('iframe');
626 thumbnailElement.tabIndex = '-1'; 687 thumbnailElem.tabIndex = '-1';
627 // Keep this ID here. See comment above. 688 // Keep this ID here. See comment above.
628 thumbnailElement.id = 'thumb-' + rid; 689 thumbnailElem.id = 'thumb-' + rid;
629 thumbnailElement.className = CLASSES.THUMBNAIL; 690 thumbnailElem.className = CLASSES.THUMBNAIL;
630 thumbnailElement.hidden = true; 691 thumbnailElem.src = getMostVisitedThumbnailIframeUrl(rid, position);
631 thumbnailElement.src = getMostVisitedThumbnailIframeUrl(rid, position); 692 innerElem.appendChild(thumbnailElem);
632 tileElement.appendChild(thumbnailElement);
633
634 // A mask to darken the thumbnail on focus.
635 var maskElement = createAndAppendElement(
636 tileElement, 'div', CLASSES.THUMBNAIL_MASK);
637 693
638 // The button used to blacklist this page. 694 // The button used to blacklist this page.
639 var blacklistButton = createAndAppendElement( 695 var blacklistButton = createAndAppendElement(
640 tileElement, 'div', CLASSES.BLACKLIST_BUTTON); 696 innerElem, 'div', CLASSES.BLACKLIST_BUTTON);
641 var blacklistFunction = generateBlacklistFunction(rid); 697 var blacklistFunction = generateBlacklistFunction(rid);
642 blacklistButton.addEventListener('click', blacklistFunction); 698 blacklistButton.addEventListener('click', blacklistFunction);
643 blacklistButton.title = configData.translatedStrings.removeThumbnailTooltip; 699 blacklistButton.title = configData.translatedStrings.removeThumbnailTooltip;
644 700
701 // A helper mask on top of the tile that is used to create hover border
702 // and/or to darken the thumbnail on focus.
703 var maskElement = createAndAppendElement(
704 innerElem, 'div', CLASSES.THUMBNAIL_MASK);
705
645 // When a tile is focused, have delete also blacklist the page. 706 // When a tile is focused, have delete also blacklist the page.
646 registerKeyHandler(tileElement, KEYCODE.DELETE, blacklistFunction); 707 registerKeyHandler(tileElem, KEYCODE.DELETE, blacklistFunction);
647 708
648 // The page favicon, if any. 709 // The page favicon, or a fallback.
649 var faviconUrl = page.faviconUrl; 710 var favicon = createAndAppendElement(innerElem, 'div', CLASSES.FAVICON);
650 if (faviconUrl) { 711 if (page.faviconUrl) {
651 var favicon = createAndAppendElement(tileElement, 'div', CLASSES.FAVICON); 712 favicon.style.backgroundImage = 'url(' + page.faviconUrl + ')';
652 favicon.style.backgroundImage = 'url(' + faviconUrl + ')'; 713 } else {
714 favicon.classList.add(CLASSES.FAVICON_FALLBACK);
653 } 715 }
654 return new Tile(tileElement, titleElement, thumbnailElement, rid); 716 return new Tile(tileElem, innerElem, titleElem, thumbnailElem, rid);
655 } else { 717 } else {
656 return new Tile(tileElement); 718 return new Tile(tileElem);
657 } 719 }
658 } 720 }
659 721
660 722
661 /** 723 /**
662 * Generates a function to be called when the page with the corresponding RID 724 * Generates a function to be called when the page with the corresponding RID
663 * is blacklisted. 725 * is blacklisted.
664 * @param {number} rid The RID of the page being blacklisted. 726 * @param {number} rid The RID of the page being blacklisted.
665 * @return {function(Event)} A function which handles the blacklisting of the 727 * @return {function(Event)} A function which handles the blacklisting of the
666 * page by updating state variables and notifying Chrome. 728 * page by updating state variables and notifying Chrome.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 if (newNumColumns < MIN_NUM_COLUMNS) 802 if (newNumColumns < MIN_NUM_COLUMNS)
741 newNumColumns = MIN_NUM_COLUMNS; 803 newNumColumns = MIN_NUM_COLUMNS;
742 else if (newNumColumns > MAX_NUM_COLUMNS) 804 else if (newNumColumns > MAX_NUM_COLUMNS)
743 newNumColumns = MAX_NUM_COLUMNS; 805 newNumColumns = MAX_NUM_COLUMNS;
744 806
745 if (numColumnsShown != newNumColumns) { 807 if (numColumnsShown != newNumColumns) {
746 numColumnsShown = newNumColumns; 808 numColumnsShown = newNumColumns;
747 var tilesContainerWidth = numColumnsShown * tileRequiredWidth; 809 var tilesContainerWidth = numColumnsShown * tileRequiredWidth;
748 tilesContainer.style.width = tilesContainerWidth + 'px'; 810 tilesContainer.style.width = tilesContainerWidth + 'px';
749 if (fakebox) { 811 if (fakebox) {
750 // -2 to account for border. 812 fakebox.style.width = // -2 to account for border.
751 fakebox.style.width =
752 (tilesContainerWidth - NTP_DESIGN.tileMargin - 2) + 'px'; 813 (tilesContainerWidth - NTP_DESIGN.tileMargin - 2) + 'px';
753 } 814 }
754 // Render without clearing tiles. 815 // Render without clearing tiles.
755 renderAndShowTiles(); 816 renderAndShowTiles();
756 } 817 }
757 } 818 }
758 819
759 820
760 /** 821 /**
761 * Returns the tile corresponding to the specified page RID. 822 * Returns the tile corresponding to the specified page RID.
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 notification = $(IDS.NOTIFICATION); 990 notification = $(IDS.NOTIFICATION);
930 attribution = $(IDS.ATTRIBUTION); 991 attribution = $(IDS.ATTRIBUTION);
931 ntpContents = $(IDS.NTP_CONTENTS); 992 ntpContents = $(IDS.NTP_CONTENTS);
932 993
933 if (configData.isGooglePage) { 994 if (configData.isGooglePage) {
934 var logo = document.createElement('div'); 995 var logo = document.createElement('div');
935 logo.id = IDS.LOGO; 996 logo.id = IDS.LOGO;
936 997
937 fakebox = document.createElement('div'); 998 fakebox = document.createElement('div');
938 fakebox.id = IDS.FAKEBOX; 999 fakebox.id = IDS.FAKEBOX;
939 fakebox.innerHTML = 1000 var fakeboxHtml = [];
940 '<input id="' + IDS.FAKEBOX_INPUT + 1001 fakeboxHtml.push('<input id="' + IDS.FAKEBOX_INPUT +
941 '" autocomplete="off" tabindex="-1" aria-hidden="true">' + 1002 '" autocomplete="off" tabindex="-1" aria-hidden="true">');
942 '<div id="cursor"></div>'; 1003 if (NTP_DESIGN.showFakeboxHint && configData.searchboxPlaceholder) {
1004 fakeboxHtml.push('<div id="' + IDS.FAKEBOX_TEXT + '">' +
1005 configData.searchboxPlaceholder + '</div>');
1006 }
1007 fakeboxHtml.push('<div id="cursor"></div>');
1008 fakebox.innerHTML = fakeboxHtml.join('');
943 1009
944 ntpContents.insertBefore(fakebox, ntpContents.firstChild); 1010 ntpContents.insertBefore(fakebox, ntpContents.firstChild);
945 ntpContents.insertBefore(logo, ntpContents.firstChild); 1011 ntpContents.insertBefore(logo, ntpContents.firstChild);
946 } else { 1012 } else {
947 document.body.classList.add(CLASSES.NON_GOOGLE_PAGE); 1013 document.body.classList.add(CLASSES.NON_GOOGLE_PAGE);
948 } 1014 }
949 1015
950 var notificationMessage = $(IDS.NOTIFICATION_MESSAGE); 1016 var notificationMessage = $(IDS.NOTIFICATION_MESSAGE);
951 notificationMessage.textContent = 1017 notificationMessage.textContent =
952 configData.translatedStrings.thumbnailRemovedNotification; 1018 configData.translatedStrings.thumbnailRemovedNotification;
(...skipping 23 matching lines...) Expand all
976 ntpApiHandle = topLevelHandle.newTabPage; 1042 ntpApiHandle = topLevelHandle.newTabPage;
977 ntpApiHandle.onthemechange = onThemeChange; 1043 ntpApiHandle.onthemechange = onThemeChange;
978 ntpApiHandle.onmostvisitedchange = onMostVisitedChange; 1044 ntpApiHandle.onmostvisitedchange = onMostVisitedChange;
979 1045
980 ntpApiHandle.oninputstart = onInputStart; 1046 ntpApiHandle.oninputstart = onInputStart;
981 ntpApiHandle.oninputcancel = restoreNtp; 1047 ntpApiHandle.oninputcancel = restoreNtp;
982 1048
983 if (ntpApiHandle.isInputInProgress) 1049 if (ntpApiHandle.isInputInProgress)
984 onInputStart(); 1050 onInputStart();
985 1051
986 onThemeChange(); 1052 renderTheme();
987 onMostVisitedChange(); 1053 onMostVisitedChange();
988 1054
989 searchboxApiHandle = topLevelHandle.searchBox; 1055 searchboxApiHandle = topLevelHandle.searchBox;
990 1056
991 if (fakebox) { 1057 if (fakebox) {
992 // Listener for updating the key capture state. 1058 // Listener for updating the key capture state.
993 document.body.onmousedown = function(event) { 1059 document.body.onmousedown = function(event) {
994 if (isFakeboxClick(event)) 1060 if (isFakeboxClick(event))
995 searchboxApiHandle.startCapturingKeyStrokes(); 1061 searchboxApiHandle.startCapturingKeyStrokes();
996 else if (isFakeboxFocused()) 1062 else if (isFakeboxFocused())
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 1109
1044 return { 1110 return {
1045 init: init, 1111 init: init,
1046 listen: listen 1112 listen: listen
1047 }; 1113 };
1048 } 1114 }
1049 1115
1050 if (!window.localNTPUnitTest) { 1116 if (!window.localNTPUnitTest) {
1051 LocalNTP().listen(); 1117 LocalNTP().listen();
1052 } 1118 }
OLDNEW
« no previous file with comments | « chrome/browser/resources/local_ntp/local_ntp.css ('k') | chrome/browser/resources/local_ntp/local_ntp_design.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698