diff --git a/demo/cn/index.html b/demo/cn/index.html
index 98f39ece4bc3dab2c027b3a81c14cb33318d1d22..9764e0b9372c06d9a9dec75aea2d61ef560da6cf 100644
--- a/demo/cn/index.html
+++ b/demo/cn/index.html
@@ -123,6 +123,7 @@
{id: 508, pId: 5, name: "右键菜单 的 实现", file: "super/rightClickMenu"},
{id: 511, pId: 5, name: "与其他 DOM 拖拽互动", file: "super/dragWithOther"},
{id: 512, pId: 5, name: "异步加载模式下全部展开", file: "super/asyncForAll"},
+ {id: 517, pId: 5, name: "设置快捷键", file: "super/keyboard_navigation"},
{id: 6, pId: 0, name: "其他扩展功能 演示", open: false},
{id: 601, pId: 6, name: "隐藏普通节点", file: "exhide/common"},
diff --git a/demo/cn/super/fuzzySearch.html b/demo/cn/super/fuzzySearch.html
index aac48cb9d7681d510c22828fe505ebc4bcf61077..afd6eb22f7df6e1ddb9bf355cb319cceb12c6d60 100644
--- a/demo/cn/super/fuzzySearch.html
+++ b/demo/cn/super/fuzzySearch.html
@@ -51,7 +51,7 @@
diff --git a/demo/cn/super/keyboard_navigation.html b/demo/cn/super/keyboard_navigation.html
new file mode 100644
index 0000000000000000000000000000000000000000..d65a22eba708337788073bbad3b87b1d0ea02b12
--- /dev/null
+++ b/demo/cn/super/keyboard_navigation.html
@@ -0,0 +1,102 @@
+
+
+
+
ZTREE DEMO - Keyboard navigation
+
+
+
+
+
+
+
+
+
+
+
+
+
设置快捷键
+
[ 文件路径: super/keyboard_navigation.html ]
+
+
+
+
+ 1、设置说明
+
+ - 键盘导航不需要特殊配置。
+ - 只需要加载 keyboard_navigation.js 文件并初始化。
+
+
+ 2、快捷键说明
+
+ - Home (keycode 36):定位到第一个根节点
+ - End (keycode 35):定位到树上最后一个节点
+ - 下 (keycode 39):定位到下一个同级节点
+ - 右 (keycode 40):定位到下一个可视节点(包括子节点/同级节点 以及后面的父级节点)
+ - 上 (keycode 37):定位到前一个同级节点
+ - 左 (keycode 38):定位到前一个可视节点(包括子节点/同级节点 以及后面的父级节点)
+ - 空格 (keycode 32):切换当前父节点 折叠、展开状态
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/en/index.html b/demo/en/index.html
index b25a9ea101bedb7771108f9be2f481e31e652b03..4e75c23b9a355c83d765c2e2f9bdc3dfe840ec94 100644
--- a/demo/en/index.html
+++ b/demo/en/index.html
@@ -123,6 +123,7 @@
{id: 508, pId: 5, name: "Right-click Menu", file: "super/rightClickMenu"},
{id: 511, pId: 5, name: "Drag With Other DOMs", file: "super/dragWithOther"},
{id: 512, pId: 5, name: "Expand All Nodes with Async", file: "super/asyncForAll"},
+ {id: 517, pId: 5, name: "Keyboard Navigation", file: "super/keyboard_navigation"},
{id: 6, pId: 0, name: "Other Extension Package", open: false},
{id: 601, pId: 6, name: "hide ordinary node", file: "exhide/common"},
diff --git a/demo/en/super/fuzzySearch.html b/demo/en/super/fuzzySearch.html
index 14b3a623b59d37d08d549f64ba6c3509e51cc169..34d5e1030f859ddf481fb8594a2f805065ebbd55 100644
--- a/demo/en/super/fuzzySearch.html
+++ b/demo/en/super/fuzzySearch.html
@@ -51,7 +51,7 @@
Fuzzy Search
-
[ File Path: fuzzySearch/fuzzySearch.html ]
+
[ File Path: super/fuzzySearch.html ]
diff --git a/demo/en/super/keyboard_navigation.html b/demo/en/super/keyboard_navigation.html
new file mode 100644
index 0000000000000000000000000000000000000000..8d11b125cd46a660ab905194269deddf38ec8fb0
--- /dev/null
+++ b/demo/en/super/keyboard_navigation.html
@@ -0,0 +1,102 @@
+
+
+
+
ZTREE DEMO - Keyboard navigation
+
+
+
+
+
+
+
+
+
+
+
+
+
Keyboard navigation
+
[ File Path: super/keyboard_navigation.html ]
+
+
+
+
+ 1. Explanation of setting
+
+ - Keyboard navigation does not require special configuration setting.
+ - It does require that the keyboard_navigation.js file is loaded and the function initialized.
+
+
+ 2. Explanation of navigation
+
+ - Home: home key (keycode 36) Goes to the first root element is visible
+ - End: end key (keycode 35) Goes to the last leaf node and will expand nodes and scroll the element into view
+ - Down: right cursor key (keycode 39) Goes to the next visible node in the tree following the hierarchy
+ - Next: down cursor key (keycode 40) Goes to the next visible node at the same level
+ - Up: up cursor key (keycode 37) Goes to the prior visible node at the same level
+ - Previous: left cursor key (keycode 38) Goes to the prior visible node following the hierarchy
+ - Toggle: space key (keycode 32) Toggles the expand/collapse state of a parent node
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/js/keyboard_navigation.js b/demo/js/keyboard_navigation.js
new file mode 100644
index 0000000000000000000000000000000000000000..11f5e05c249366bfb2c66fcdec3cbe5ec810c8b1
--- /dev/null
+++ b/demo/js/keyboard_navigation.js
@@ -0,0 +1,255 @@
+/*
+ * JQuery zTree keyboard navigation extension
+ * zTree v3.5.42 or later
+ * http://www.xbrlquery.com/
+ *
+ * Copyright (c) 2019 Bill Seddon
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Date: 2020-02-18
+ */
+
+( function ($)
+{
+ /**
+ * Creates a function that adds keyboard navigation:
+ * Home: home key (keycode 36) Goes to the first root element is visible
+ * End: end key (keycode 35) Goes to the last leaf node and will expand nodes and scroll the element into view
+ * Down: right cursor key (keycode 39) Goes to the next visible node in the tree following the hierarchy
+ * Next: down cursor key (keycode 40) Goes to the next visible node at the same level
+ * Up: up cursor key (keycode 37) Goes to the prior visible node at the same level
+ * Previous: left cursor key (keycode 38) Goes to the prior visible node following the hierarchy
+ * Toggle: space key (keycode 32) Toggles the expand/collapse state of a parent node
+ */
+ $.fn.zTreeKeyboardNavigation = function(zTree, element)
+ {
+ if (typeof element === 'string' || element instanceof String)
+ {
+ element = $(element);
+ }
+
+ var rootNodes = zTree.getNodes();
+ if ( ! rootNodes ) return;
+
+ var focusSelectedNode = function()
+ {
+ if( ( selectedNodes = zTree.getSelectedNodes() ) && selectedNodes.length )
+ {
+ $("#" + selectedNodes[0].tId ).focus();
+ }
+ }
+
+ $(element).bind( 'keydown', function( e )
+ {
+ var selectedNodes = zTree.getSelectedNodes();
+ var selectedNode = selectedNodes.length ? selectedNodes[0] : null;
+
+ var processSpace = function()
+ {
+ // If there are no nodes or the selected node is not a parent, get out
+ if ( selectedNode && selectedNode.isParent )
+ {
+ // Toggle the node
+ zTree.expandNode( selectedNode, null, null, null, false );
+ }
+ }
+
+ var processHome = function()
+ {
+ zTree.selectNode( rootNodes[0], false, true );
+ }
+
+ var processEnd = function()
+ {
+ var nodes = zTree.transformToArray(rootNodes);
+ // Select the last node
+ zTree.selectNode( nodes[ nodes.length - 1 ] );
+ }
+
+ var processUp = function()
+ {
+ var priorNode;
+ if ( selectedNode )
+ {
+ priorNode = selectedNode.getPreNode();
+ if ( ! priorNode ) return;
+ }
+ else
+ {
+ processEnd();
+ }
+
+ if ( ! priorNode ) return;
+
+ zTree.selectNode( priorNode );
+ }
+
+ var processDown = function()
+ {
+ var nextNode;
+ if ( selectedNode )
+ {
+ nextNode = selectedNode.getNextNode();
+ if ( ! nextNode ) return;
+ }
+ else
+ {
+ processHome();
+ }
+
+ if ( ! nextNode ) return;
+
+ zTree.selectNode( nextNode );
+ }
+
+ var processOut = function()
+ {
+ if ( ! selectedNode ) return;
+
+ var parentNode = selectedNode.getParentNode();
+ var priorNode = selectedNode.getPreNode();
+ if ( ! parentNode && ! priorNode ) return; // Must have been the root node
+
+ if ( priorNode )
+ {
+ if ( priorNode.isParent )
+ {
+ // There is a prior node, now the the question is where is the last open node?
+ while ( priorNode )
+ {
+ if ( ! priorNode.isParent || ! priorNode.open || ! priorNode.children ) break;
+
+ priorNode = priorNode.children[ priorNode.children.length -1 ];
+ }
+
+ zTree.selectNode( priorNode );
+ return;
+ }
+ else
+ {
+ zTree.selectNode( priorNode );
+ return;
+ }
+ }
+
+ // Find the parent node with a valid prior sibling
+ if ( parentNode )
+ {
+ // This call should be silent otherwise (in my view a bug in)
+ // selectNode causes the root node to blur
+ zTree.selectNode( parentNode, false, true );
+ }
+ }
+
+ var processIn = function()
+ {
+ if ( ! selectedNode ) return;
+
+ if ( selectedNode.isParent && selectedNode.open && selectedNode.children )
+ {
+ zTree.selectNode( selectedNode.children[0] );
+ return;
+ }
+
+ var nextNode = selectedNode.getNextNode();
+ if ( nextNode )
+ {
+ zTree.selectNode( nextNode );
+ }
+ else
+ {
+ // Cannot be root if there is a selected node that is not a parent
+ var node = selectedNode;
+ // Find the parent node with a valid next sibling
+ while( node = node.getParentNode() )
+ {
+ var nextNode = node.getNextNode();
+ if ( nextNode )
+ {
+ zTree.selectNode( nextNode );
+ break;
+ }
+ }
+ }
+ }
+
+ var processLetter = function( keyCode )
+ {
+ if ( ! Array.from( {length: 26}, (v, i) => i + 65 ).includes( keyCode & 95 ) ) return false;
+
+ var nodes = zTree.transformToArray(rootNodes);
+ nodes = nodes.filter( node =>
+ {
+ return 'accesskey' in node && node.accesskey.length && ( node.accesskey.charCodeAt(0) & 95 ) == keyCode;
+ } );
+
+ if ( ! nodes.length ) return false;
+
+ var selectedNodes = zTree.getSelectedNodes();
+ if ( ! selectedNodes.length ) return false;
+
+ if ( selectedNodes[0] == nodes[0] ) return false;
+
+ zTree.selectNode( nodes[0] );
+
+ return true;
+ }
+
+ // console.log('before');
+ // console.log(document.activeElement);
+
+ switch ( e.keyCode )
+ {
+ case 32: /* Toggle parent nodes */
+ processSpace();
+ return;
+
+ case 36: /* Home - go to the root node */
+ processHome();
+ break;
+
+ case 35: /* End - go to the last node */
+ processEnd();
+ break;
+
+ case 33: /* PageUp */
+ // Do nothing
+ break;
+
+ case 34: /* PageDown */
+ // Do nothing
+ break;
+
+ case 37: /* Left */
+ processOut();
+ break;
+
+ case 38: /* Up */
+ processUp();
+ break;
+
+ case 39: /* Right */
+ processIn();
+ break;
+
+ case 40: /* Down */
+ processDown();
+ break;
+
+ default:
+ if ( ! processLetter( e.keyCode & 95 ) ) return;
+ break;
+ }
+
+ // console.log('after');
+ // console.log(document.activeElement);
+ focusSelectedNode();
+ } );
+
+ $(element).trigger({ type : 'keydown', which : 36, keyCode: 36 });
+ focusSelectedNode();
+ }
+
+} )(jQuery);
\ No newline at end of file
diff --git a/log v3.x.txt b/log v3.x.txt
index adf1fd8078b801febc278c864430d0bbafc9a80e..fddd02940be68cb54451338a83bece0be70ce0e5 100644
--- a/log v3.x.txt
+++ b/log v3.x.txt
@@ -14,6 +14,9 @@
+*2020.03.02* v3.5.42
+ * add demo 'Keyboard Navigation' Thanks @bseddon
+
*2020.01.19* v3.5.42
* merge PullRequest(fixed 'HTMLElement undefined' error) Thanks @ChangJin0520
* merge PullRequest(Add TypeScript type definition) Thanks @Itroads