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

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

Issue 544293002: [New Tab Page] Change which elements get focused during tab ordering (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comment Created 6 years, 3 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
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 21 matching lines...) Expand all
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698