Chromium Code Reviews| 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')) { |