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')) { |