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

Unified Diff: chrome/browser/resources/md_bookmarks/folder_node.js

Issue 2820153003: [MD Bookmarks] Add keyboard navigation to sidebar. (Closed)
Patch Set: select_on_move Created 3 years, 8 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
Index: chrome/browser/resources/md_bookmarks/folder_node.js
diff --git a/chrome/browser/resources/md_bookmarks/folder_node.js b/chrome/browser/resources/md_bookmarks/folder_node.js
index cdca80866605f6c672c20a96a3b318ed0449ee5d..75890da0efe0efc98f1f45f7c737b6cacdfd6825 100644
--- a/chrome/browser/resources/md_bookmarks/folder_node.js
+++ b/chrome/browser/resources/md_bookmarks/folder_node.js
@@ -41,6 +41,10 @@ Polymer({
},
},
+ listeners: {
+ 'keydown': 'onKeydown_',
+ },
+
/** @override */
attached: function() {
this.watch('item_', function(state) {
@@ -60,6 +64,11 @@ Polymer({
},
/** @return {HTMLElement} */
+ getFocusTarget: function() {
+ return this.$.container;
+ },
+
+ /** @return {HTMLElement} */
getDropTarget: function() {
return this.$.container;
},
@@ -71,6 +80,115 @@ Polymer({
/**
* @private
+ * @param {!Event} e
+ */
+ onKeydown_: function(e) {
+ var direction = 0;
+ var handled = true;
+ // TODO(calamity): Handle left/right arrow keys.
+ if (e.key == 'ArrowUp') {
+ direction = -1;
+ } else if (e.key == 'ArrowDown') {
+ direction = 1;
+ } else {
+ handled = false;
+ }
+
+ if (direction) {
+ handled =
+ this.changeKeyboardSelection_(direction, this.root.activeElement);
+ }
+
+ if (!handled)
+ return;
+
+ e.preventDefault();
+ e.stopPropagation();
+ },
+
+ /**
+ * @private
+ * @param {number} direction
+ * @param {HTMLElement} currentFocus
+ * @return {boolean} Whether the event should be treated as handled.
+ */
+ changeKeyboardSelection_: function(direction, currentFocus) {
+ var isChildFolderNodeFocused =
+ currentFocus.tagName == 'BOOKMARKS-FOLDER-NODE';
+
+ // Get the next folder node. If there is no next element, the event will
+ // bubble to the parent node which will handle it.
+ var newFocusFolderNode = this.getNextVisibleFolderNode_(
+ direction == -1,
+ isChildFolderNodeFocused ?
+ /** @type {BookmarksFolderNodeElement} */ (currentFocus) :
+ this);
+
+ // If there is no newly focused node, allow the event to bubble.
+ if (!newFocusFolderNode)
+ return false;
+
+ if (newFocusFolderNode.itemId != ROOT_NODE_ID) {
+ newFocusFolderNode.selectFolder_();
+ newFocusFolderNode.getFocusTarget().focus();
+ }
+
+ return true;
+ },
+
+ /**
+ * Returns the next or previous visible bookmark node relative to |current|.
+ * @private
+ * @param {boolean} reverse
+ * @param {BookmarksFolderNodeElement} current Either this node, or an
+ * immediate child.
+ * @return {HTMLElement|null} Returns null if the next node is not within this
+ * folder node.
+ */
+ getNextVisibleFolderNode_: function(reverse, current) {
+ var newFocus = null;
+ var children =
+ Array.from(this.root.querySelectorAll('bookmarks-folder-node'));
tsergeant 2017/04/19 07:32:18 Pull this out into a helper getter, since it's use
calamity 2017/04/28 06:15:47 Done.
+
+ // The current node's successor can only be its first child.
+ if (this == current) {
tsergeant 2017/04/19 07:32:18 I find it confusing that this is packaged into thi
calamity 2017/04/28 06:15:47 Hmm, ok. I've changed things here a little bit. WD
tsergeant 2017/05/01 01:35:57 Yeah, I think this is a bit better. It's still a c
+ if (!reverse && children.length && !this.isClosed_)
+ newFocus = children[0];
+
+ return newFocus;
+ }
+
+ var index = children.indexOf(current);
+ assert(index != -1);
+ if (reverse) {
+ // A child node's predecessor is either the previous child's last visible
+ // descendant, or this node, which is its immediate parent.
+ newFocus =
+ index == 0 ? this : children[index - 1].getLastVisibleDescendant_();
+ } else if (index < children.length - 1) {
+ // A successor to a child is the next child.
+ newFocus = children[index + 1];
+ }
+
+ return newFocus;
+ },
+
+ /**
+ * @private
+ * @return {BookmarksFolderNodeElement}
+ */
+ getLastVisibleDescendant_: function() {
+ var children =
+ Array.from(this.root.querySelectorAll('bookmarks-folder-node'));
+
+ if (this.isClosed_ || children.length == 0)
+ return this;
+
+ return children.pop().getLastVisibleDescendant_();
+ },
+
+ /**
+ * @private
* @return {string}
*/
getFolderIcon_: function() {
@@ -140,4 +258,12 @@ Polymer({
isRootFolder_: function() {
return this.depth == 0;
},
+
+ /**
+ * @private
+ * @return {string}
+ */
+ getTabIndex_: function() {
+ return this.isSelectedFolder_ ? '0' : '';
+ },
});

Powered by Google App Engine
This is Rietveld 408576698