JSFiddle - React, Tailwind, and code Playground

by tonyleeper

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<div class="container">
    <ul class="treeview" data-bind="treeview: { rootNode: rootNode }" tabindex="0"></ul>
</div>
<div class="test" data-bind="text: selectedNodeId"></div>

CSS

.test {
    position: absolute;
    top: 0;
    left: 300px;
    border: 1px solid black;
    width : 100px;
    height: 100px;
}

html, body {
    height: 100%;
}

* {
            padding: 0;
            margin: 0;
            -webkit-user-select: none;
            box-sizing: border-box;
    font-family: arial;
    font-size: 12px;
    line-height: 25px;
        }

.container {
    width : 300px;
    height: 100%;
    overflow: auto;
}

        .treeview {
            cursor: default;
            outline: 0;
            position: relative;
    padding: 3px 5px;
        }

        li {
            position: relative;   
            text-indent: 20px;
    margin: 2px 0;
        }

        .treeview label {
            display: block;
            height: 25px;
            border: 1px solid transparent;
            border-radius: 2px;
        }

        .treeview label:hover {
            border: 1px solid #bed2f0;
            background-color: #e9f0fa;
        }

        .treeview label span {
            position: relative;
            top: -2px;
            text-shadow: 0 1px white;
        }

        li.selected > label {
            border: 1px solid #cfcfcf;
            background-color: #ddd;
        }

        .treeview:focus li.selected > label {
            border: 1px solid #94b5e5;
            background-color: #bed2f0;
        }

        ul:not(.treeview) {
            display: none;
        }

        ul {
            list-style: none;
        }

        .children {
            display: none;
        }

        i {
            display: inline-block;
            background-repeat: no-repeat;
            position: absolute;
        }

        i.folder {
            background-image: url(http://s10.postimg.org/vr6k6n7r9/folder_closed_16.png);
            width: 16px;
            height: 16px;
            top: 0px;
            left: -20px;
        }

        

        i.open-closed-state {
            background-image:...

JavaScript

/**
                Treeview Mark-II
            */
	        ko.bindingHandlers.treeview = {
	            createTreeDOMNode: function(appendTo, treeNode, depth) {
	                depth = depth || 0;

	                var node = document.createElement("li");
	                node.setAttribute("data-id", treeNode.id);
	                node.setAttribute("data-type", treeNode.type);
	                node.setAttribute("style", "text-indent: " + ((depth + 2) * 19) + "px");

	                var label = document.createElement("label");
	                var span = document.createElement("span");
	                span.textContent = treeNode.displayName;

	                if (treeNode.children && treeNode.children.length > 0) {
	                    var expandIcon = document.createElement("i");
	                    expandIcon.setAttribute("class", "open-closed-state");
	                    span.appendChild(expandIcon);
	                }

	                var folderIcon = document.createElement("i");
	                folderIcon.setAttribute("class", "folder");
	                span.appendChild(folderIcon);
	                label.appendChild(span);

	                node.appendChild(label);

	                if (treeNode.children && treeNode.children.length > 0) {
	                    var children = document.createElement("ul");

	                    for (var i = 0; i < treeNode.children.length; i++) {
	                        ko.bindingHandlers.treeview.createTreeDOMNode(children, treeNode.children[i], depth + 1);
	                    }

	                    node.appendChild(children);
	                }

	                appendTo.appendChild(node);
	            },

	            scrollIntoView: function(node) {
	                // find the first scrollable element in the DOM heirarchy
	                var scrollableElement = node.parentNode;
	                while (scrollableElement.nodeName !== "BODY") {
	                    if (scrollableElement.scrollHeight >...