fancytree binding for Knockout

An experimental (incomplete) bindinghandler that integrates fancytree with knockout.

by waxwing

HTML

<script src="http://wwwendt.de/tech/fancytree/src/jquery.fancytree.js"></script>
<link rel="stylesheet" href="http://wwwendt.de/tech/fancytree/src/skin-win8/ui.fancytree.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-debug.js"></script>
<div data-bind="fancytree: tree"></div>

JavaScript

ko.bindingHandlers.fancytree = {
    init: function (element, valueAccessor) {
        var source = valueAccessor(),
            tree;

        $(element).fancytree({
            source: []
        });
        tree = $(element).fancytree("getTree");

        function processChildren(childArray, targetForNew) {

            function nodeAdded(koNode) {
                var node = unwrapNode(koNode),
                    targetNode;
                if (!targetForNew) {
                    targetNode = tree.rootNode;
                } else {
                    targetNode = tree.getNodeByKey(targetForNew);
                }
                targetNode.addChildren(node);
                return node;
            }

            var sub = childArray.subscribe(function (changes) {
                ko.utils.arrayForEach(changes, function (change) {
                    if (targetForNew && !tree.getNodeByKey(targetForNew)) {
                        console.log('disposing children ' + targetForNew);
                        sub.dispose();
                        return;
                    }

                    if (change.status === 'added') {
                        // TODO: Use index to add at correct position.
                        nodeAdded(change.value);
                    }

                    if (change.status === 'deleted') {
                        var id = change.value.key;
                        tree.getNodeByKey(id).remove();
                    }
                });
            }, null, 'arrayChange');

            var result = [];
            ko.utils.arrayForEach(childArray(), function (item) {
                result.push(unwrapNode(item));
            });

            return result;
        }

        function unwrapNode(koNode) {
            var node = {},
            initial = true;

            if (ko.isObservable(koNode.children)) {
                node.children = processChildren(koNode.children, koNode.key);
            } else {
               ...