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

Unified Diff: chrome/browser/resources/new_new_tab.js

Issue 147071: Make the options menu keyboard navigatable. Hide the menu when the... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/resources/new_new_tab.html ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/new_new_tab.js
===================================================================
--- chrome/browser/resources/new_new_tab.js (revision 19093)
+++ chrome/browser/resources/new_new_tab.js (working copy)
@@ -670,44 +670,171 @@
}, 10000);
}
-// Options menu
-// TODO(arv): Keyboard navigation of the menu items.
+var optionMenu = {
Glen Murphy 2009/06/24 17:04:03 Can you add a brief description?
+ button: $('option-button'),
+ menu: $('option-menu'),
+ handleMouseDown: function(e) {
+ if (this.isMenuShown()) {
+ this.hideMenu();
+ } else {
+ this.showMenu();
+ }
+ },
-function showMenu(button, menu) {
- function hide() {
- menu.style.display = '';
- menu.removeEventListener('blur', hide);
- window.removeEventListener('blur', hide);
- };
- menu.addEventListener('blur', hide);
- window.addEventListener('blur', hide);
- menu.style.display = 'block';
- menu.focus();
-}
+ showMenu: function() {
+ this.menu.style.display = 'block';
+ this.button.focus();
-$('option-button').addEventListener('click', function(e) {
- showMenu(this, $('option-menu'));
-});
+ if (!this.boundHideMenu_) {
+ this.boundHideMenu_ = bind(this.hideMenu, this);
+ this.boundHandleFocus_ = bind(this.handleFocus_, this);
+ }
+ document.addEventListener('focus', this.boundHandleFocus_, true);
+ document.addEventListener('mousedown', this.boundHandleFocus_, true);
+ window.addEventListener('blur', this.boundHideMenu_);
-$('option-menu').addEventListener('click', function(e) {
- var section = Section[e.target.getAttribute('section')];
- var show = e.target.getAttribute('show') == 'true';
- if (show) {
- showSection(section);
- } else {
- hideSection(section);
- }
+ this.menu.onmouseover = bind(this.handleMouseOver, this);
+ this.menu.onmouseout = bind(this.handleMouseOut, this);
+ this.menu.onmouseup = bind(this.handleMouseUp, this);
+ this.button.onkeydown = bind(this.handleKeyDown, this);
+ },
- // Hide menu now.
- this.style.display = 'none';
+ hideMenu: function() {
+ this.menu.style.display = 'none';
+ this.setSelectedIndex(-1);
- layoutLowerSections();
- mostVisited.updateDisplayMode();
- layoutMostVisited();
+ document.removeEventListener('focus', this.boundHandleFocus_, true);
+ document.removeEventListener('mousedown', this.boundhandleFocus_, true);
+ window.removeEventListener('blur', this.boundHide_);
+ },
- saveShownSections();
-});
+ handleFocus_: function(e) {
+ if (!this.menu.contains(e.target) && !this.button.contains(e.target)) {
+ this.hideMenu();
+ }
+ },
+ isMenuShown: function() {
+ return this.menu.style.display == 'block';
+ },
+
+ handleMouseOver: function(e) {
+ var el = e.target;
+ var index = Array.prototype.indexOf.call(this.menu.children, el);
+ console.log(el, index);
+ this.setSelectedIndex(index);
+ },
+
+ handleMouseOut: function(e) {
+ this.setSelectedIndex(-1);
+ },
+
+ handleMouseUp: function(e) {
+ var item = this.getSelectedItem();
+ if (item) {
+ this.executeItem(item);
+ }
+ },
+
+ handleKeyDown: function(e) {
+ var item = this.getSelectedItem();
+
+ var self = this;
+ function selectNextVisible(m) {
+ var children = self.menu.children;
+ var len = children.length;
+ var i = self.selectedIndex_;
+ if (i == -1 && m == -1) {
+ // Edge case when we need to go the last item fisrt.
+ i = 0;
+ }
+ while (true) {
+ i = (i + m + len) % len;
+ item = children[i];
+ if (item && item.style.display != 'none') {
+ break;
+ }
+ }
+ if (item) {
+ self.setSelectedIndex(i);
+ }
+ }
+
+ switch (e.keyIdentifier) {
+ case 'Down':
+ if (!this.isMenuShown()) {
+ this.showMenu();
+ }
+ selectNextVisible(1);
+ break;
+ case 'Up':
+ if (!this.isMenuShown()) {
+ this.showMenu();
+ }
+ selectNextVisible(-1);
+ break;
+ case 'Esc':
+ case 'U+001B': // Maybe this is remote desktop playing a prank?
+ this.hideMenu();
+ break;
+ case 'Enter':
+ if (this.isMenuShown()) {
+ if (item) {
+ this.executeItem(item);
+ }
+ } else {
+ this.showMenu();
+ }
+ break;
+ }
+ },
+
+ selectedIndex_: -1,
+ setSelectedIndex: function(i) {
+ if (i != this.selectedIndex_) {
+ var items = this.menu.children;
+ var oldItem = items[this.selectedIndex_];
+ if (oldItem) {
+ oldItem.removeAttribute('selected');
+ }
+ var newItem = items[i];
+ if (newItem) {
+ newItem.setAttribute('selected', 'selected');
+ }
+ this.selectedIndex_ = i;
+ }
+ },
+
+ getSelectedItem: function() {
+ return this.menu.children[this.selectedIndex_] || null;
+ },
+
+ executeItem: function(item) {
+ var section = Section[item.getAttribute('section')];
+ var show = item.getAttribute('show') == 'true';
+ if (show) {
+ showSection(section);
+ } else {
+ hideSection(section);
+ }
+
+ this.hideMenu();
+
+ layoutLowerSections();
+ mostVisited.updateDisplayMode();
+ layoutMostVisited();
+
+ saveShownSections();
+ },
+
+ init: function() {
+ this.button.onmousedown = bind(this.handleMouseDown, this);
+ this.button.onkeydown = bind(this.handleKeyDown, this);
+ }
+};
+
+optionMenu.init();
+
$('most-visited').addEventListener('click', function(e) {
var target = e.target;
if (hasClass(target, 'pin')) {
« no previous file with comments | « chrome/browser/resources/new_new_tab.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698