Chromium Code Reviews| Index: chrome/browser/resources/local_ntp/local_ntp.js |
| diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js |
| index 26bf34eb8fa71b58fc06c858fd5b352fb07585bd..2e1bb608a3556560ba2a3c42ecffc2f471a1f366 100644 |
| --- a/chrome/browser/resources/local_ntp/local_ntp.js |
| +++ b/chrome/browser/resources/local_ntp/local_ntp.js |
| @@ -28,6 +28,7 @@ var CLASSES = { |
| ALTERNATE_LOGO: 'alternate-logo', // Shows white logo if required by theme |
| BLACKLIST: 'mv-blacklist', // triggers tile blacklist animation |
| BLACKLIST_BUTTON: 'mv-x', |
| + BLACKLIST_BUTTON_INNER: 'mv-x-inner', |
| DARK: 'dark', |
| DEFAULT_THEME: 'default-theme', |
| DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide', |
| @@ -176,13 +177,6 @@ var isBlacklisting = false; |
| /** |
| - * Stores whether the current theme has a dark background. |
| - * @type {boolean} |
| - */ |
| -var isBackgroundDark = false; |
| - |
| - |
| -/** |
| * Current number of tiles columns shown based on the window width, including |
| * those that just contain filler. |
| * @type {number} |
| @@ -268,6 +262,13 @@ var MOST_VISITED_THUMBNAIL_IFRAME = 'thumbnail.html'; |
| /** |
| + * The color of the title in RRGGBBAA format. |
| + * @type {string} |
|
Mathieu
2014/08/27 14:54:53
string|null ?
huangs
2014/08/27 18:13:52
Done.
|
| + */ |
| +var titleColor = null; |
| + |
| + |
| +/** |
| * Hide most visited tiles for at most this many milliseconds while painting. |
| * @type {number} |
| * @const |
| @@ -307,16 +308,16 @@ function Tile(elem, opt_innerElem, opt_titleElem, opt_thumbnailElem, opt_rid) { |
| /** |
| * Determines whether a theme should be considered to have dark background. |
|
Mathieu
2014/08/27 14:54:53
Mention that you are now looking at the text color
huangs
2014/08/27 18:13:52
Updated comment. The text color portion is implem
|
| - * @param {ThemeBackgroundInfo} info Theme background information. |
| + * @param {ThemeBackgroundInfo|undefined} info Theme background information. |
| * @return {boolean} Whether the theme has dark background. |
| * @private |
| */ |
| function getIsBackgroundDark(info) { |
| - if (info.imageUrl) |
| - return true; |
| - var rgba = info.backgroundColorRgba; |
| + if (!info) |
| + return false; |
| + var rgba = info.textColorRgba; |
| var luminance = 0.3 * rgba[0] + 0.59 * rgba[1] + 0.11 * rgba[2]; |
| - return luminance < 128; |
| + return luminance >= 128; |
| } |
| @@ -325,20 +326,34 @@ function getIsBackgroundDark(info) { |
| * @private |
| */ |
| function renderTheme() { |
| + var fakeboxText = $(IDS.FAKEBOX_TEXT); |
| + fakeboxText.innerHTML = ''; |
| + if (NTP_DESIGN.showFakeboxHint && |
| + configData.translatedStrings.searchboxPlaceholder) { |
| + fakeboxText.textContent = configData.translatedStrings.searchboxPlaceholder; |
| + } |
| + |
| var info = ntpApiHandle.themeBackgroundInfo; |
| + var isBackgroundDark = getIsBackgroundDark(info); |
| + ntpContents.classList.toggle(CLASSES.DARK, isBackgroundDark); |
| if (!info) { |
| - isBackgroundDark = false; |
| + titleColor = NTP_DESIGN.titleColor; |
| return; |
| } |
| - isBackgroundDark = getIsBackgroundDark(info); |
| - ntpContents.classList.toggle(CLASSES.DARK, isBackgroundDark); |
| + if (!info.usingDefaultTheme && info.textColorRgba) { |
| + titleColor = convertToRRGGBBAAColor(info.textColorRgba); |
| + } else { |
| + titleColor = isBackgroundDark ? |
| + NTP_DESIGN.titleColorAgainstDark : NTP_DESIGN.titleColor; |
| + } |
| var background = [convertToRGBAColor(info.backgroundColorRgba), |
| info.imageUrl, |
| info.imageTiling, |
| info.imageHorizontalAlignment, |
| info.imageVerticalAlignment].join(' ').trim(); |
| + |
| document.body.style.background = background; |
| document.body.classList.toggle(CLASSES.ALTERNATE_LOGO, info.alternateLogo); |
| updateThemeAttribution(info.attributionUrl); |
| @@ -366,7 +381,6 @@ function onThemeChange() { |
| function setCustomThemeStyle(opt_themeInfo) { |
| var customStyleElement = $(IDS.CUSTOM_THEME_STYLE); |
| var head = document.head; |
| - |
| if (opt_themeInfo && !opt_themeInfo.usingDefaultTheme) { |
| ntpContents.classList.remove(CLASSES.DEFAULT_THEME); |
| var themeStyle = |
| @@ -444,6 +458,19 @@ function setAttributionVisibility_(show) { |
| /** |
| + * Converts an Array of color components into RRGGBBAA format. |
| + * @param {Array.<number>} color Array of rgba color components. |
| + * @return {string} Color string in RRGGBBAA format. |
| + * @private |
| + */ |
| +function convertToRRGGBBAAColor(color) { |
| + return color.map(function(t) { |
| + return ('0' + t.toString(16)).slice(-2); // To 2-digit, 0-padded hex. |
| + }).join(''); |
| +} |
| + |
| + |
| + /** |
| * Converts an Array of color components into RGBA format "rgba(R,G,B,A)". |
| * @param {Array.<number>} color Array of rgba color components. |
| * @return {string} CSS color in RGBA format. |
| @@ -585,8 +612,6 @@ function renderAndShowTiles() { |
| function getMostVisitedTitleIframeUrl(rid, position) { |
| var url = 'chrome-search://most-visited/' + |
| encodeURIComponent(MOST_VISITED_TITLE_IFRAME); |
| - var titleColor = isBackgroundDark ? NTP_DESIGN.titleColorAgainstDark : |
| - NTP_DESIGN.titleColor; |
| var params = [ |
| 'rid=' + encodeURIComponent(rid), |
| 'f=' + encodeURIComponent(NTP_DESIGN.fontFamily), |
| @@ -632,6 +657,10 @@ function getMostVisitedThumbnailIframeUrl(rid, position) { |
| function createTile(page, position) { |
| var tileElem = document.createElement('div'); |
| tileElem.classList.add(CLASSES.TILE); |
| + // Prevent tile from being selected (and highlighted) when 'X' is clicked. |
| + tileElem.addEventListener('mousedown', function(e) { |
|
Mathieu
2014/08/27 14:54:53
Seems to me like it's going to prevent more than w
huangs
2014/08/27 18:13:52
It's not just "X", but also any area outside of <i
|
| + e.preventDefault(); |
| + }); |
| var innerElem = createAndAppendElement(tileElem, 'div', CLASSES.TILE_INNER); |
| if (page) { |
| @@ -694,6 +723,8 @@ function createTile(page, position) { |
| // The button used to blacklist this page. |
| var blacklistButton = createAndAppendElement( |
| innerElem, 'div', CLASSES.BLACKLIST_BUTTON); |
| + createAndAppendElement( |
| + blacklistButton, 'div', CLASSES.BLACKLIST_BUTTON_INNER); |
| var blacklistFunction = generateBlacklistFunction(rid); |
| blacklistButton.addEventListener('click', blacklistFunction); |
| blacklistButton.title = configData.translatedStrings.removeThumbnailTooltip; |
| @@ -757,6 +788,7 @@ function showNotification() { |
| */ |
| function hideNotification() { |
| notification.classList.add(CLASSES.HIDE_NOTIFICATION); |
| + notification.classList.remove(CLASSES.DELAYED_HIDE_NOTIFICATION); |
| } |
| @@ -785,11 +817,11 @@ function onRestoreAll() { |
| /** |
| - * Resizes elements because the number of tile columns may need to change in |
| - * response to resizing. Also shows or hides extra tiles tiles according to the |
| - * new width of the page. |
| + * Recomputes the number of tile columns, and width of various contents based |
| + * on the width of the window. |
| + * @return {boolean} Whether the number of tile columns has changed. |
| */ |
| -function onResize() { |
| +function updateContentWidth() { |
| var tileRequiredWidth = NTP_DESIGN.tileWidth + NTP_DESIGN.tileMargin; |
| // If innerWidth is zero, then use the maximum snap size. |
| var maxSnapSize = MAX_NUM_COLUMNS * tileRequiredWidth - |
| @@ -804,14 +836,28 @@ function onResize() { |
| else if (newNumColumns > MAX_NUM_COLUMNS) |
| newNumColumns = MAX_NUM_COLUMNS; |
| - if (numColumnsShown != newNumColumns) { |
| - numColumnsShown = newNumColumns; |
| - var tilesContainerWidth = numColumnsShown * tileRequiredWidth; |
| - tilesContainer.style.width = tilesContainerWidth + 'px'; |
| - if (fakebox) { |
| - fakebox.style.width = // -2 to account for border. |
| - (tilesContainerWidth - NTP_DESIGN.tileMargin - 2) + 'px'; |
| - } |
| + if (numColumnsShown === newNumColumns) |
| + return false; |
| + |
| + numColumnsShown = newNumColumns; |
| + var tilesContainerWidth = numColumnsShown * tileRequiredWidth; |
| + tilesContainer.style.width = tilesContainerWidth + 'px'; |
| + if (fakebox) { |
| + // -2 to account for border. |
| + var fakeboxWidth = (tilesContainerWidth - NTP_DESIGN.tileMargin - 2); |
| + fakebox.style.width = fakeboxWidth + 'px'; |
| + } |
| + return true; |
| +} |
| + |
| + |
| +/** |
| + * Resizes elements because the number of tile columns may need to change in |
| + * response to resizing. Also shows or hides extra tiles tiles according to the |
| + * new width of the page. |
| + */ |
| +function onResize() { |
| + if (updateContentWidth()) { |
| // Render without clearing tiles. |
| renderAndShowTiles(); |
| } |
| @@ -1000,11 +1046,7 @@ function init() { |
| var fakeboxHtml = []; |
| fakeboxHtml.push('<input id="' + IDS.FAKEBOX_INPUT + |
| '" autocomplete="off" tabindex="-1" aria-hidden="true">'); |
| - if (NTP_DESIGN.showFakeboxHint && |
| - configData.translatedStrings.searchboxPlaceholder) { |
| - fakeboxHtml.push('<div id="' + IDS.FAKEBOX_TEXT + '">' + |
| - configData.translatedStrings.searchboxPlaceholder + '</div>'); |
| - } |
| + fakeboxHtml.push('<div id="' + IDS.FAKEBOX_TEXT + '"></div>'); |
| fakeboxHtml.push('<div id="cursor"></div>'); |
| fakebox.innerHTML = fakeboxHtml.join(''); |
| @@ -1014,6 +1056,9 @@ function init() { |
| document.body.classList.add(CLASSES.NON_GOOGLE_PAGE); |
| } |
| + // Hide notifications after fade out, so we can't focus on links via keyboard. |
| + notification.addEventListener('webkitTransitionEnd', hideNotification); |
| + |
| var notificationMessage = $(IDS.NOTIFICATION_MESSAGE); |
| notificationMessage.textContent = |
| configData.translatedStrings.thumbnailRemovedNotification; |
| @@ -1033,10 +1078,12 @@ function init() { |
| configData.translatedStrings.attributionIntro; |
| var notificationCloseButton = $(IDS.NOTIFICATION_CLOSE_BUTTON); |
| + createAndAppendElement( |
| + notificationCloseButton, 'div', CLASSES.BLACKLIST_BUTTON_INNER); |
| notificationCloseButton.addEventListener('click', hideNotification); |
| window.addEventListener('resize', onResize); |
| - onResize(); |
| + updateContentWidth(); |
| var topLevelHandle = getEmbeddedSearchApiHandle(); |