JSFiddle - React, Tailwind, and code Playground
by donabrams
HTML
<ul id="treeExample">
<li><a href="javascript:void(0);">item 1</a>
<ul>
<li><a href="javascript:void(0);">item 1.1</a></li>
<li><a href="javascript:void(0);">item 1.2</a></li>
<li><a href="javascript:void(0);">item 1.3</a></li>
</ul>
</li>
<li><a href="javascript:void(0);">item 2</a>
<ul>
<li><a id="TARGETTED" href="javascript:void(0);">item 2.1</a>
<ul>
<li><a href="javascript:void(0);">item 2.1.1</a></li>
<li><a href="javascript:void(0);">item 2.2.2</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="javascript:void(0);">item 3</a></li>
</ul>
<button id="focus_button">FOCUS</button>
CSS
body { font-size:62.5%; margin:20px; }
#treeExample { margin:2em 0 5em; width:400px; }
.tree { font-size:1.5em; }
.tree,.tree ul,.tree li { list-style:none; margin:0; padding:0; zoom: 1; }
.tree ul { margin-left:8px; }
.tree li a { color:#555; padding:.1em 7px .1em 27px; display:block; text-decoration:none; border:1px dashed #fff; background:url(../images/icon-file.gif) 5px 50% no-repeat; }
.tree li a.tree-parent { background:url(../images/icon-folder-open.gif) 5px 50% no-repeat; }
.tree li a.tree-parent-collapsed { background:url(../images/icon-folder.gif) 5px 50% no-repeat; }
.tree li a:hover,.tree li a.tree-parent:hover,.tree li a:focus,.tree li a.tree-parent:focus,.tree li a.tree-item-active { color:#000; border:1px solid#eee; background-color:#fafafa; -moz-border-radius:4px; -webkit-border-radius:4px; border-radius:4px; }
.tree li a:focus,.tree li a.tree-parent:focus,.tree li a.tree-item-active { border:1px solid #e2f3fb; background-color:#f2fafd; }
.tree ul.tree-group-collapsed { display:none; }
JavaScript
/**
* --------------------------------------------------------------------
* jQuery tree plugin
* Author: Scott Jehl, [email protected]
* Copyright (c) 2009 Filament Group
* licensed under MIT (filamentgroup.com/examples/mit-license.txt)
* --------------------------------------------------------------------
*/
$.fn.tree = function(settings){
var o = $.extend({
expanded: ''
},settings);
return $(this).each(function(){
if( !$(this).parents('.tree').length ){
//save reference to tree UL
var tree = $(this);
//add the role and default state attributes
if( !$('body').is('[role]') ){ $('body').attr('role','application'); }
//add role and class of tree
tree.attr({'role': 'tree'}).addClass('tree');
//set first node's tabindex to 0
tree.find('a:eq(0)').attr('tabindex','0');
//set all others to -1
tree.find('a:gt(0)').attr('tabindex','-1');
//add group role and tree-group-collapsed class to all ul children
tree.find('ul').attr('role','group').addClass('tree-group-collapsed');
//add treeitem role to all li children
tree.find('li').attr('role','treeitem');
//find tree group parents
tree.find('li:has(ul)')
.attr('aria-expanded', 'false')
.find('>a')
.addClass('tree-parent tree-parent-collapsed');
//expanded at load
tree
.find(o.expanded)
.attr('aria-expanded', 'true')
.find('>a')
.removeClass('tree-parent-collapsed')
.next()
.removeClass('tree-group-collapsed');
//bind the custom events
tree
//expand a tree node
.on('expand',function(event){
var target = $(event.target) || tree.find('a[tabindex=0]');
target.removeClass('tree-parent-collapsed');
...