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