From 81865eb0630f978337a4ff47e34536a2a72504ca Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Tue, 25 Apr 2017 01:50:47 -0500 Subject: [PATCH] Treeview Examples: Treeview Fix Shift and Enter Key Handling (pull #377) For issue #364, fix bug preventing Enter, CTRL+Enter, and Shift+Enter from executing links in the navigation treeview examples. For issue #367, allow the Shift modifier to be used with printable characters for typeahead in the treeviews. --- examples/treeview/treeview-1/js/treeitem.js | 140 ++++++++-------- .../treeview/treeview-2/js/treeitemLinks.js | 152 ++++++++++-------- examples/treeview/treeview-2/treeview-2a.html | 2 +- examples/treeview/treeview-2/treeview-2b.html | 1 - 4 files changed, 158 insertions(+), 137 deletions(-) diff --git a/examples/treeview/treeview-1/js/treeitem.js b/examples/treeview/treeview-1/js/treeitem.js index b2de109256..6acb639f8d 100644 --- a/examples/treeview/treeview-1/js/treeitem.js +++ b/examples/treeview/treeview-1/js/treeitem.js @@ -114,87 +114,95 @@ Treeitem.prototype.handleKeydown = function (event) { return str.length === 1 && str.match(/\S/); } - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + function printableCharacter (item) { + if (char == '*') { + item.tree.expandAllSiblingItems(item); + flag = true; + } + else { + if (isPrintableCharacter(char)) { + item.tree.setFocusByFirstCharacter(item, char); + flag = true; + } + } + } + + if (event.altKey || event.ctrlKey || event.metaKey) { return; } - switch (event.keyCode) { - case this.keyCode.SPACE: - case this.keyCode.RETURN: - // Create simulated mouse event to mimic the behavior of ATs - // and let the event handler handleClick do the housekeeping. - try { - clickEvent = new MouseEvent('click', { - 'view': window, - 'bubbles': true, - 'cancelable': true - }); - } - catch (err) { - if (document.createEvent) { - // DOM Level 3 for IE 9+ - clickEvent = document.createEvent('MouseEvents'); - clickEvent.initEvent('click', true, true); + if (event.shift) { + printableCharacter(this); + } + else { + switch (event.keyCode) { + case this.keyCode.SPACE: + case this.keyCode.RETURN: + // Create simulated mouse event to mimic the behavior of ATs + // and let the event handler handleClick do the housekeeping. + try { + clickEvent = new MouseEvent('click', { + 'view': window, + 'bubbles': true, + 'cancelable': true + }); } - } - tgt.dispatchEvent(clickEvent); - flag = true; - break; - - case this.keyCode.UP: - this.tree.setFocusToPreviousItem(this); - flag = true; - break; - - case this.keyCode.DOWN: - this.tree.setFocusToNextItem(this); - flag = true; - break; + catch (err) { + if (document.createEvent) { + // DOM Level 3 for IE 9+ + clickEvent = document.createEvent('MouseEvents'); + clickEvent.initEvent('click', true, true); + } + } + tgt.dispatchEvent(clickEvent); + flag = true; + break; - case this.keyCode.RIGHT: - if (this.isExpandable) { - this.tree.expandTreeitem(this); + case this.keyCode.UP: + this.tree.setFocusToPreviousItem(this); flag = true; - } - break; + break; - case this.keyCode.LEFT: - if (this.isExpandable) { - this.tree.collapseTreeitem(this); + case this.keyCode.DOWN: + this.tree.setFocusToNextItem(this); flag = true; - } - else { - if (this.inGroup) { - this.tree.setFocusToParentItem(this); + break; + + case this.keyCode.RIGHT: + if (this.isExpandable) { + this.tree.expandTreeitem(this); flag = true; } - } - break; + break; - case this.keyCode.HOME: - this.tree.setFocusToFirstItem(); - flag = true; - break; - - case this.keyCode.END: - this.tree.setFocusToLastItem(); - flag = true; - break; + case this.keyCode.LEFT: + if (this.isExpandable) { + this.tree.collapseTreeitem(this); + flag = true; + } + else { + if (this.inGroup) { + this.tree.setFocusToParentItem(this); + flag = true; + } + } + break; - default: + case this.keyCode.HOME: + this.tree.setFocusToFirstItem(); + flag = true; + break; - if (char == '*') { - this.tree.expandAllSiblingItems(this); + case this.keyCode.END: + this.tree.setFocusToLastItem(); flag = true; - } - else { - if (isPrintableCharacter(char)) { - this.tree.setFocusByFirstCharacter(this, char); - flag = true; - } - } + break; + + default: + printableCharacter(this); + break; + } - break; } if (flag) { diff --git a/examples/treeview/treeview-2/js/treeitemLinks.js b/examples/treeview/treeview-2/js/treeitemLinks.js index a7838d76be..efecc311ee 100644 --- a/examples/treeview/treeview-2/js/treeitemLinks.js +++ b/examples/treeview/treeview-2/js/treeitemLinks.js @@ -33,6 +33,7 @@ var TreeitemLink = function (node, treeObj, group) { this.groupTreeitem = group; this.domNode = node; this.label = node.textContent.trim(); + this.stopDefaultClick = false; if (node.getAttribute('aria-label')) { this.label = node.getAttribute('aria-label').trim(); @@ -117,87 +118,97 @@ TreeitemLink.prototype.handleKeydown = function (event) { return str.length === 1 && str.match(/\S/); } - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return; + function printableCharacter (item) { + if (char == '*') { + item.tree.expandAllSiblingItems(item); + flag = true; + } + else { + if (isPrintableCharacter(char)) { + item.tree.setFocusByFirstCharacter(item, char); + flag = true; + } + } } - switch (event.keyCode) { - case this.keyCode.SPACE: - case this.keyCode.RETURN: - // Create simulated mouse event to mimic the behavior of ATs - // and let the event handler handleClick do the housekeeping. - try { - clickEvent = new MouseEvent('click', { - 'view': window, - 'bubbles': true, - 'cancelable': true - }); - } - catch (err) { - if (document.createEvent) { - // DOM Level 3 for IE 9+ - clickEvent = document.createEvent('MouseEvents'); - clickEvent.initEvent('click', true, true); - } - } - tgt.dispatchEvent(clickEvent); - flag = true; - break; + this.stopDefaultClick = false; - case this.keyCode.UP: - this.tree.setFocusToPreviousItem(this); - flag = true; - break; + if (event.altKey || event.ctrlKey || event.metaKey) { + return; + } - case this.keyCode.DOWN: - this.tree.setFocusToNextItem(this); - flag = true; - break; + if (event.shift) { + if (event.keyCode == this.keyCode.SPACE || event.keyCode == this.keyCode.RETURN) { + event.stopPropagation(); + this.stopDefaultClick = true; + } + else { + printableCharacter(this); + } + } + else { + switch (event.keyCode) { + case this.keyCode.SPACE: + case this.keyCode.RETURN: + if (this.isExpandable) { + if (this.domNode.getAttribute('aria-expanded') == 'true') { + this.tree.collapseTreeitem(this); + } + else { + this.tree.expandTreeitem(this); + } + flag = true; + } + else { + event.stopPropagation(); + this.stopDefaultClick = true; + } + break; - case this.keyCode.RIGHT: - if (this.isExpandable) { - this.tree.expandTreeitem(this); + case this.keyCode.UP: + this.tree.setFocusToPreviousItem(this); flag = true; - } - break; + break; - case this.keyCode.LEFT: - if (this.isExpandable) { - this.tree.collapseTreeitem(this); + case this.keyCode.DOWN: + this.tree.setFocusToNextItem(this); flag = true; - } - else { - if (this.inGroup) { - this.tree.setFocusToParentItem(this); + break; + + case this.keyCode.RIGHT: + if (this.isExpandable) { + this.tree.expandTreeitem(this); flag = true; } - } - break; + break; - case this.keyCode.HOME: - this.tree.setFocusToFirstItem(); - flag = true; - break; - - case this.keyCode.END: - this.tree.setFocusToLastItem(); - flag = true; - break; + case this.keyCode.LEFT: + if (this.isExpandable) { + this.tree.collapseTreeitem(this); + flag = true; + } + else { + if (this.inGroup) { + this.tree.setFocusToParentItem(this); + flag = true; + } + } + break; - default: + case this.keyCode.HOME: + this.tree.setFocusToFirstItem(); + flag = true; + break; - if (char == '*') { - this.tree.expandAllSiblingItems(this); + case this.keyCode.END: + this.tree.setFocusToLastItem(); flag = true; - } - else { - if (isPrintableCharacter(char)) { - this.tree.setFocusByFirstCharacter(this, char); - flag = true; - } - } + break; - break; + default: + printableCharacter(this); + break; + } } if (flag) { @@ -207,6 +218,12 @@ TreeitemLink.prototype.handleKeydown = function (event) { }; TreeitemLink.prototype.handleClick = function (event) { + + // only process click events that directly happened on this treeitem + if (event.target !== this.domNode && event.target !== this.domNode.firstElementChild) { + return; + } + if (this.isExpandable) { if (this.domNode.getAttribute('aria-expanded') == 'true') { this.tree.collapseTreeitem(this); @@ -216,9 +233,6 @@ TreeitemLink.prototype.handleClick = function (event) { } event.stopPropagation(); } - else { - this.tree.setFocusToItem(this); - } }; TreeitemLink.prototype.handleFocus = function (event) { diff --git a/examples/treeview/treeview-2/treeview-2a.html b/examples/treeview/treeview-2/treeview-2a.html index 06f9a39ed1..9d35daf3a2 100644 --- a/examples/treeview/treeview-2/treeview-2a.html +++ b/examples/treeview/treeview-2/treeview-2a.html @@ -14,7 +14,6 @@ -
@@ -50,6 +49,7 @@

Navigation Treeview Example Using Computed Properties

Example

+

Foods

    diff --git a/examples/treeview/treeview-2/treeview-2b.html b/examples/treeview/treeview-2/treeview-2b.html index 31482c7f92..f905865628 100644 --- a/examples/treeview/treeview-2/treeview-2b.html +++ b/examples/treeview/treeview-2/treeview-2b.html @@ -14,7 +14,6 @@ -