Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 21 matching lines...) Expand all Loading... | |
| 32 DARK: 'dark', | 32 DARK: 'dark', |
| 33 DEFAULT_THEME: 'default-theme', | 33 DEFAULT_THEME: 'default-theme', |
| 34 DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide', | 34 DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide', |
| 35 DOT: 'dot', | 35 DOT: 'dot', |
| 36 FAKEBOX_DISABLE: 'fakebox-disable', // Makes fakebox non-interactive | 36 FAKEBOX_DISABLE: 'fakebox-disable', // Makes fakebox non-interactive |
| 37 FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox | 37 FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox |
| 38 // Applies drag focus style to the fakebox | 38 // Applies drag focus style to the fakebox |
| 39 FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused', | 39 FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused', |
| 40 FAVICON: 'mv-favicon', | 40 FAVICON: 'mv-favicon', |
| 41 FAVICON_FALLBACK: 'mv-favicon-fallback', | 41 FAVICON_FALLBACK: 'mv-favicon-fallback', |
| 42 FOCUSED: 'mv-focused', | |
| 42 HIDE_BLACKLIST_BUTTON: 'mv-x-hide', // hides blacklist button during animation | 43 HIDE_BLACKLIST_BUTTON: 'mv-x-hide', // hides blacklist button during animation |
| 43 HIDE_FAKEBOX_AND_LOGO: 'hide-fakebox-logo', | 44 HIDE_FAKEBOX_AND_LOGO: 'hide-fakebox-logo', |
| 44 HIDE_NOTIFICATION: 'mv-notice-hide', | 45 HIDE_NOTIFICATION: 'mv-notice-hide', |
| 45 // Vertically centers the most visited section for a non-Google provided page. | 46 // Vertically centers the most visited section for a non-Google provided page. |
| 46 NON_GOOGLE_PAGE: 'non-google-page', | 47 NON_GOOGLE_PAGE: 'non-google-page', |
| 47 PAGE: 'mv-page', // page tiles | 48 PAGE: 'mv-page', // page tiles |
| 48 PAGE_READY: 'mv-page-ready', // page tile when ready | 49 PAGE_READY: 'mv-page-ready', // page tile when ready |
| 49 RTL: 'rtl', // Right-to-left language text. | 50 RTL: 'rtl', // Right-to-left language text. |
| 50 THUMBNAIL: 'mv-thumb', | 51 THUMBNAIL: 'mv-thumb', |
| 51 THUMBNAIL_FALLBACK: 'mv-thumb-fallback', | 52 THUMBNAIL_FALLBACK: 'mv-thumb-fallback', |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 78 UNDO_LINK: 'mv-undo' | 79 UNDO_LINK: 'mv-undo' |
| 79 }; | 80 }; |
| 80 | 81 |
| 81 | 82 |
| 82 /** | 83 /** |
| 83 * Enum for keycodes. | 84 * Enum for keycodes. |
| 84 * @enum {number} | 85 * @enum {number} |
| 85 * @const | 86 * @const |
| 86 */ | 87 */ |
| 87 var KEYCODE = { | 88 var KEYCODE = { |
| 88 DELETE: 46, | |
| 89 ENTER: 13 | 89 ENTER: 13 |
| 90 }; | 90 }; |
| 91 | 91 |
| 92 | 92 |
| 93 /** | 93 /** |
| 94 * Enum for the state of the NTP when it is disposed. | 94 * Enum for the state of the NTP when it is disposed. |
| 95 * @enum {number} | 95 * @enum {number} |
| 96 * @const | 96 * @const |
| 97 */ | 97 */ |
| 98 var NTP_DISPOSE_STATE = { | 98 var NTP_DISPOSE_STATE = { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 | 161 |
| 162 | 162 |
| 163 /** | 163 /** |
| 164 * The last blacklisted tile if any, which by definition should not be filler. | 164 * The last blacklisted tile if any, which by definition should not be filler. |
| 165 * @type {?Tile} | 165 * @type {?Tile} |
| 166 */ | 166 */ |
| 167 var lastBlacklistedTile = null; | 167 var lastBlacklistedTile = null; |
| 168 | 168 |
| 169 | 169 |
| 170 /** | 170 /** |
| 171 * The iframe element which is currently keyboard focused, or null. | |
| 172 * @type {?Element} | |
| 173 */ | |
| 174 var focusedIframe = null; | |
| 175 | |
| 176 | |
| 177 /** | |
| 171 * True if a page has been blacklisted and we're waiting on the | 178 * True if a page has been blacklisted and we're waiting on the |
| 172 * onmostvisitedchange callback. See onMostVisitedChange() for how this | 179 * onmostvisitedchange callback. See onMostVisitedChange() for how this |
| 173 * is used. | 180 * is used. |
| 174 * @type {boolean} | 181 * @type {boolean} |
| 175 */ | 182 */ |
| 176 var isBlacklisting = false; | 183 var isBlacklisting = false; |
| 177 | 184 |
| 178 | 185 |
| 179 /** | 186 /** |
| 180 * Current number of tiles columns shown based on the window width, including | 187 * Current number of tiles columns shown based on the window width, including |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorLightRgba) + ';' + | 406 ' color: ' + convertToRGBAColor(opt_themeInfo.textColorLightRgba) + ';' + |
| 400 '}' + | 407 '}' + |
| 401 '#mv-notice-x {' + | 408 '#mv-notice-x {' + |
| 402 ' -webkit-filter: drop-shadow(0 0 0 ' + | 409 ' -webkit-filter: drop-shadow(0 0 0 ' + |
| 403 convertToRGBAColor(opt_themeInfo.textColorRgba) + ');' + | 410 convertToRGBAColor(opt_themeInfo.textColorRgba) + ');' + |
| 404 '}' + | 411 '}' + |
| 405 '.mv-page-ready .mv-mask {' + | 412 '.mv-page-ready .mv-mask {' + |
| 406 ' border: 1px solid ' + | 413 ' border: 1px solid ' + |
| 407 convertToRGBAColor(opt_themeInfo.sectionBorderColorRgba) + ';' + | 414 convertToRGBAColor(opt_themeInfo.sectionBorderColorRgba) + ';' + |
| 408 '}' + | 415 '}' + |
| 409 '.mv-page-ready:hover .mv-mask, .mv-page-ready:focus .mv-mask {' + | 416 '.mv-page-ready:hover .mv-mask, .mv-focused ~ .mv-mask {' + |
| 410 ' border-color: ' + | 417 ' border-color: ' + |
| 411 convertToRGBAColor(opt_themeInfo.headerColorRgba) + ';' + | 418 convertToRGBAColor(opt_themeInfo.headerColorRgba) + ';' + |
| 412 '}'; | 419 '}'; |
| 413 | 420 |
| 414 if (customStyleElement) { | 421 if (customStyleElement) { |
| 415 customStyleElement.textContent = themeStyle; | 422 customStyleElement.textContent = themeStyle; |
| 416 } else { | 423 } else { |
| 417 customStyleElement = document.createElement('style'); | 424 customStyleElement = document.createElement('style'); |
| 418 customStyleElement.type = 'text/css'; | 425 customStyleElement.type = 'text/css'; |
| 419 customStyleElement.id = IDS.CUSTOM_THEME_STYLE; | 426 customStyleElement.id = IDS.CUSTOM_THEME_STYLE; |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 tileElem.classList.add(CLASSES.PAGE); | 681 tileElem.classList.add(CLASSES.PAGE); |
| 675 | 682 |
| 676 var navigateFunction = function(e) { | 683 var navigateFunction = function(e) { |
| 677 e.preventDefault(); | 684 e.preventDefault(); |
| 678 ntpApiHandle.navigateContentWindow(rid, getDispositionFromEvent(e)); | 685 ntpApiHandle.navigateContentWindow(rid, getDispositionFromEvent(e)); |
| 679 }; | 686 }; |
| 680 | 687 |
| 681 // The click handler for navigating to the page identified by the RID. | 688 // The click handler for navigating to the page identified by the RID. |
| 682 tileElem.addEventListener('click', navigateFunction); | 689 tileElem.addEventListener('click', navigateFunction); |
| 683 | 690 |
| 684 // Make thumbnails tab-accessible. | |
| 685 tileElem.setAttribute('tabindex', '1'); | |
| 686 registerKeyHandler(tileElem, KEYCODE.ENTER, navigateFunction); | |
| 687 | |
| 688 // The iframe which renders the page title. | 691 // The iframe which renders the page title. |
| 689 var titleElem = document.createElement('iframe'); | 692 var titleElem = document.createElement('iframe'); |
| 690 titleElem.tabIndex = '-1'; | 693 // Enable tab navigation on the iframe, which will move the selection to the |
| 694 // link element (which also has a tabindex). | |
| 695 titleElem.tabIndex = '0'; | |
| 691 | 696 |
| 692 // Why iframes have IDs: | 697 // Why iframes have IDs: |
| 693 // | 698 // |
| 694 // On navigating back to the NTP we see several onmostvisitedchange() events | 699 // On navigating back to the NTP we see several onmostvisitedchange() events |
| 695 // in series with incrementing RIDs. After the first event, a set of iframes | 700 // in series with incrementing RIDs. After the first event, a set of iframes |
| 696 // begins loading RIDs n, n+1, ..., n+k-1; after the second event, these get | 701 // begins loading RIDs n, n+1, ..., n+k-1; after the second event, these get |
| 697 // destroyed and a new set begins loading RIDs n+k, n+k+1, ..., n+2k-1. | 702 // destroyed and a new set begins loading RIDs n+k, n+k+1, ..., n+2k-1. |
| 698 // Now due to crbug.com/68841, Chrome incorrectly loads the content for the | 703 // Now due to crbug.com/68841, Chrome incorrectly loads the content for the |
| 699 // first set of iframes into the most recent set of iframes. | 704 // first set of iframes into the most recent set of iframes. |
| 700 // | 705 // |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 733 blacklistButton, 'div', CLASSES.BLACKLIST_BUTTON_INNER); | 738 blacklistButton, 'div', CLASSES.BLACKLIST_BUTTON_INNER); |
| 734 var blacklistFunction = generateBlacklistFunction(rid); | 739 var blacklistFunction = generateBlacklistFunction(rid); |
| 735 blacklistButton.addEventListener('click', blacklistFunction); | 740 blacklistButton.addEventListener('click', blacklistFunction); |
| 736 blacklistButton.title = configData.translatedStrings.removeThumbnailTooltip; | 741 blacklistButton.title = configData.translatedStrings.removeThumbnailTooltip; |
| 737 | 742 |
| 738 // A helper mask on top of the tile that is used to create hover border | 743 // A helper mask on top of the tile that is used to create hover border |
| 739 // and/or to darken the thumbnail on focus. | 744 // and/or to darken the thumbnail on focus. |
| 740 var maskElement = createAndAppendElement( | 745 var maskElement = createAndAppendElement( |
| 741 innerElem, 'div', CLASSES.THUMBNAIL_MASK); | 746 innerElem, 'div', CLASSES.THUMBNAIL_MASK); |
| 742 | 747 |
| 743 // When a tile is focused, have delete also blacklist the page. | |
| 744 registerKeyHandler(tileElem, KEYCODE.DELETE, blacklistFunction); | |
| 745 | |
| 746 // The page favicon, or a fallback. | 748 // The page favicon, or a fallback. |
| 747 var favicon = createAndAppendElement(innerElem, 'div', CLASSES.FAVICON); | 749 var favicon = createAndAppendElement(innerElem, 'div', CLASSES.FAVICON); |
| 748 if (page.faviconUrl) { | 750 if (page.faviconUrl) { |
| 749 favicon.style.backgroundImage = 'url(' + page.faviconUrl + ')'; | 751 favicon.style.backgroundImage = 'url(' + page.faviconUrl + ')'; |
| 750 } else { | 752 } else { |
| 751 favicon.classList.add(CLASSES.FAVICON_FALLBACK); | 753 favicon.classList.add(CLASSES.FAVICON_FALLBACK); |
| 752 } | 754 } |
| 753 return new Tile(tileElem, innerElem, titleElem, thumbnailElem, rid); | 755 return new Tile(tileElem, innerElem, titleElem, thumbnailElem, rid); |
| 754 } else { | 756 } else { |
| 755 return new Tile(tileElem); | 757 return new Tile(tileElem); |
| 756 } | 758 } |
| 757 } | 759 } |
| 758 | 760 |
| 759 | 761 |
| 760 /** | 762 /** |
| 761 * Generates a function to be called when the page with the corresponding RID | 763 * Generates a function to be called when the page with the corresponding RID |
| 762 * is blacklisted. | 764 * is blacklisted. |
| 763 * @param {number} rid The RID of the page being blacklisted. | 765 * @param {number} rid The RID of the page being blacklisted. |
| 764 * @return {function(Event)} A function which handles the blacklisting of the | 766 * @return {function(Event)} A function which handles the blacklisting of the |
| 765 * page by updating state variables and notifying Chrome. | 767 * page by updating state variables and notifying Chrome. |
| 766 */ | 768 */ |
| 767 function generateBlacklistFunction(rid) { | 769 function generateBlacklistFunction(rid) { |
| 768 return function(e) { | 770 return function(e) { |
| 769 // Prevent navigation when the page is being blacklisted. | 771 // Prevent navigation when the page is being blacklisted. |
| 770 e.stopPropagation(); | 772 if (e) |
| 773 e.stopPropagation(); | |
| 771 | 774 |
| 772 userInitiatedMostVisitedChange = true; | 775 userInitiatedMostVisitedChange = true; |
| 773 isBlacklisting = true; | 776 isBlacklisting = true; |
| 774 tilesContainer.classList.add(CLASSES.HIDE_BLACKLIST_BUTTON); | 777 tilesContainer.classList.add(CLASSES.HIDE_BLACKLIST_BUTTON); |
| 775 lastBlacklistedTile = getTileByRid(rid); | 778 lastBlacklistedTile = getTileByRid(rid); |
| 776 ntpApiHandle.deleteMostVisitedItem(rid); | 779 ntpApiHandle.deleteMostVisitedItem(rid); |
| 777 }; | 780 }; |
| 778 } | 781 } |
| 779 | 782 |
| 780 | 783 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1026 function getEmbeddedSearchApiHandle() { | 1029 function getEmbeddedSearchApiHandle() { |
| 1027 if (window.cideb) | 1030 if (window.cideb) |
| 1028 return window.cideb; | 1031 return window.cideb; |
| 1029 if (window.chrome && window.chrome.embeddedSearch) | 1032 if (window.chrome && window.chrome.embeddedSearch) |
| 1030 return window.chrome.embeddedSearch; | 1033 return window.chrome.embeddedSearch; |
| 1031 return null; | 1034 return null; |
| 1032 } | 1035 } |
| 1033 | 1036 |
| 1034 | 1037 |
| 1035 /** | 1038 /** |
| 1039 * Event handler for the focus changed and blacklist messages on link elements. | |
| 1040 * Used to toggle visual treatment on the tiles (depending on the message). | |
| 1041 * @param {Event} event received. | |
| 1042 */ | |
| 1043 function handlePostMessage(event) { | |
| 1044 if (event.data == 'linkFocused') { | |
|
huangs
2014/09/11 20:31:41
Should validate event.origin.
Mathieu
2014/09/11 20:54:10
Done.
| |
| 1045 var activeElement = document.activeElement; | |
| 1046 if (activeElement.classList.contains(CLASSES.TITLE)) { | |
| 1047 activeElement.classList.add(CLASSES.FOCUSED); | |
| 1048 focusedIframe = activeElement; | |
| 1049 } | |
| 1050 } else if (event.data == 'linkBlurred') { | |
| 1051 if (focusedIframe) | |
| 1052 focusedIframe.classList.remove(CLASSES.FOCUSED); | |
| 1053 focusedIframe = null; | |
| 1054 } else if (event.data.indexOf('tileBlacklisted') == 0) { | |
| 1055 var tilePosition = event.data.split(',')[1]; | |
| 1056 if (tilePosition) | |
| 1057 generateBlacklistFunction(tiles[tilePosition].rid)(); | |
| 1058 } | |
| 1059 } | |
| 1060 | |
| 1061 | |
| 1062 /** | |
| 1036 * Prepares the New Tab Page by adding listeners, rendering the current | 1063 * Prepares the New Tab Page by adding listeners, rendering the current |
| 1037 * theme, the most visited pages section, and Google-specific elements for a | 1064 * theme, the most visited pages section, and Google-specific elements for a |
| 1038 * Google-provided page. | 1065 * Google-provided page. |
| 1039 */ | 1066 */ |
| 1040 function init() { | 1067 function init() { |
| 1041 tilesContainer = $(IDS.TILES); | 1068 tilesContainer = $(IDS.TILES); |
| 1042 notification = $(IDS.NOTIFICATION); | 1069 notification = $(IDS.NOTIFICATION); |
| 1043 attribution = $(IDS.ATTRIBUTION); | 1070 attribution = $(IDS.ATTRIBUTION); |
| 1044 ntpContents = $(IDS.NTP_CONTENTS); | 1071 ntpContents = $(IDS.NTP_CONTENTS); |
| 1045 | 1072 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1144 setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled); | 1171 setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled); |
| 1145 } | 1172 } |
| 1146 | 1173 |
| 1147 if (searchboxApiHandle.rtl) { | 1174 if (searchboxApiHandle.rtl) { |
| 1148 $(IDS.NOTIFICATION).dir = 'rtl'; | 1175 $(IDS.NOTIFICATION).dir = 'rtl'; |
| 1149 document.body.setAttribute('dir', 'rtl'); | 1176 document.body.setAttribute('dir', 'rtl'); |
| 1150 // Add class for setting alignments based on language directionality. | 1177 // Add class for setting alignments based on language directionality. |
| 1151 document.body.classList.add(CLASSES.RTL); | 1178 document.body.classList.add(CLASSES.RTL); |
| 1152 $(IDS.TILES).dir = 'rtl'; | 1179 $(IDS.TILES).dir = 'rtl'; |
| 1153 } | 1180 } |
| 1181 | |
| 1182 window.addEventListener('message', handlePostMessage); | |
| 1154 } | 1183 } |
| 1155 | 1184 |
| 1156 | 1185 |
| 1157 /** | 1186 /** |
| 1158 * Binds event listeners. | 1187 * Binds event listeners. |
| 1159 */ | 1188 */ |
| 1160 function listen() { | 1189 function listen() { |
| 1161 document.addEventListener('DOMContentLoaded', init); | 1190 document.addEventListener('DOMContentLoaded', init); |
| 1162 } | 1191 } |
| 1163 | 1192 |
| 1164 return { | 1193 return { |
| 1165 init: init, | 1194 init: init, |
| 1166 listen: listen | 1195 listen: listen |
| 1167 }; | 1196 }; |
| 1168 } | 1197 } |
| 1169 | 1198 |
| 1170 if (!window.localNTPUnitTest) { | 1199 if (!window.localNTPUnitTest) { |
| 1171 LocalNTP().listen(); | 1200 LocalNTP().listen(); |
| 1172 } | 1201 } |
| OLD | NEW |