Skip to content

Commit

Permalink
Adds keyboard navigation extension and example page
Browse files Browse the repository at this point in the history
  • Loading branch information
bseddon committed Feb 19, 2020
1 parent 03bcba6 commit 8f16821
Show file tree
Hide file tree
Showing 2 changed files with 337 additions and 0 deletions.
107 changes: 107 additions & 0 deletions demo/en/navigation/keyboard_navigation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<!DOCTYPE html>
<HTML>
<HEAD>
<TITLE> ZTREE DEMO - Keyboard navigation </TITLE>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../../css/demo.css" type="text/css">
<link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript" src="../../../js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="../../js/keyboard_navigation.js"></script>
<script type="text/javascript" src="../../../js/jquery.ztree.core.js"></script>
<script type="text/javascript" src="../../../js/jquery.ztree.exedit.js"></script>
<SCRIPT type="text/javascript">

var setting = {
data: {
simpleData: {
enable: true
}
}
};

var zNodes =[
{ id:1, pId:0, name:"Custom Icon 01", open:true, iconSkin:"pIcon01"},
{ id:11, pId:1, name:"leaf node 01", iconSkin:"icon01"},
{ id:12, pId:1, name:"leaf node 02", iconSkin:"icon02"},
{ id:13, pId:1, name:"parent node 03", iconSkin:"pIcon01"},
{ id:131, pId:13, name:"leaf node 01", iconSkin:"icon01"},
{ id:132, pId:13, name:"leaf node 02", iconSkin:"icon02"},
{ id:133, pId:13, name:"leaf node 03", iconSkin:"icon03"},
{ id:2, pId:0, name:"Custom Icon 02", open:true, iconSkin:"pIcon02"},
{ id:21, pId:2, name:"leaf node 01", iconSkin:"icon04"},
{ id:22, pId:2, name:"leaf node 02", iconSkin:"icon05"},
{ id:23, pId:2, name:"leaf node 03", iconSkin:"icon06"},
{ id:3, pId:0, name:"no Custom Icon", open:true },
{ id:31, pId:3, name:"leaf node 01"},
{ id:32, pId:3, name:"leaf node 02"},
{ id:33, pId:3, name:"leaf node 03"}
];

var $ = jQuery;
$(document).ready(function()
{
var element = "#treeDemo";
var zTree = $.fn.zTree.init($(element), setting, zNodes);
// Initialize keyboard navigation
$.fn.zTreeKeyboardNavigation(zTree, element);
});

</SCRIPT>
<style type="text/css">
.ztree li > a
{
border-left: 1px solid white;
}

.ztree li > a.curSelectedNode {
border-radius: 3px;
}

.ztree li span.button.pIcon01_ico_open{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/1_open.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.pIcon01_ico_close{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/1_close.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.pIcon02_ico_open, .ztree li span.button.pIcon02_ico_close{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/2.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.icon01_ico_docu{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/3.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.icon02_ico_docu{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/4.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.icon03_ico_docu{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/5.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.icon04_ico_docu{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/6.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.icon05_ico_docu{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/7.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.icon06_ico_docu{margin-right:2px; background: url(../../../css/zTreeStyle/img/diy/8.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
</style>
</HEAD>

<BODY>
<h1>Keyboard navigation</h1>
<h6>[ File Path: core/custom_keyboard_navigation.html ]</h6>
<div class="content_wrap">
<div class="zTreeDemoBackground left">
<ul id="treeDemo" class="ztree"></ul>
</div>
<div class="right">
<ul class="info">
<li class="title"><h2>1. Explanation of setting</h2>
<ul class="list">
<li>Keyboard navigation does not require special configuration setting.</li>
<li>It does require that the keyboard_navigation.js file is loaded and the function initialized.</li>
</ul>
</li>
<li class="title"><h2>2. Explanation of navigation</h2>
<ul class="list">
<li>Home: home key (keycode 36) Goes to the first root element is visible</li>
<li>End: end key (keycode 35) Goes to the last leaf node and will expand nodes and scroll the element into view</li>
<li>Down: right cursor key (keycode 39) Goes to the next visible node in the tree following the hierarchy</li>
<li>Next: down cursor key (keycode 40) Goes to the next visible node at the same level</li>
<li>Up: up cursor key (keycode 37) Goes to the prior visible node at the same level</li>
<li>Previous: left cursor key (keycode 38) Goes to the prior visible node following the hierarchy</li>
<li>Toggle: space key (keycode 32) Toggles the expand/collapse state of a parent node</li>
</ul>
</li>
<li class="title"><h2>3.Other explanation</h2>
<ul class="list">
<li>No other explanation.</li>
</ul>
</li>
</ul>
</div>
</div>
</BODY>
</HTML>
230 changes: 230 additions & 0 deletions demo/js/keyboard_navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*
* 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)
{
var rootNodes = zTree.getNodes();
if ( ! rootNodes ) return;

var focusSelectedNode = function()
{
if( ( selectedNodes = zTree.getSelectedNodes() ) && selectedNodes )
{
$("#" + selectedNodes[0].tId ).focus();
}
}

$(element).bind( 'keydown', function( e )
{
var selectedNodes = zTree.getSelectedNodes();
var selectedNode = selectedNodes ? 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;
}
}
}
}

if ( [32,33,34,35,36,37,38,39,40].includes(e.keyCode) )
{
// 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:
return;
}
}

// console.log('after');
// console.log(document.activeElement);
focusSelectedNode();
} );

$(element).trigger({ type : 'keydown', which : 36, keyCode: 36 });
focusSelectedNode();
}

} )(jQuery);

0 comments on commit 8f16821

Please sign in to comment.