packages feed

profiteur-0.2.0.0: data/js/tree-browser.js

function mk(el) {
    return $(document.createElement(el));
}

function TreeBrowser(container, zoom) {
    this.zoom      = zoom;
    this.elements  = {};
    this.container = container;

    zoom.addChangeListener(this);
    this.onChange(zoom);
}

TreeBrowser.prototype.mkElement = function(node) {
    var div = mk('div').addClass('tree-browser node');

    if (node.isExpandable()) {
        var chevron = mk('span').addClass('tree-browser chevron');
        chevron.click(function() { node.toggleExpanded(); });
        div.append(chevron);
    }

    var code = mk('code').text(node.getCanonicalName());
    code.addClass('tree-browser name');
    code.attr('style', 'background-color: ' + node.getColor());
    code.click(function() { node.select(); });
    div.append(code);

    var children = mk('div').addClass('tree-browser children');
    div.append(children);

    return div;
};

TreeBrowser.prototype.renderNode = function(element, node) {
    if (node.isExpandable()) {
        element.children('.chevron').text(
                node.expanded ? Unicode.DOWN_TRIANGLE : Unicode.RIGHT_TRIANGLE);
    }

    element.children('.name').toggleClass('selected', node.isSelected());

    var children = element.children('.children');
    if (node.children.length > 0) {
        if (children.is(':empty')) {
            for (var i = 0; i < node.children.length; i++) {
                var div = this.mkElement(node.children[i]);
                this.elements[node.children[i].id] = div;
                this.renderNode(div, node.children[i]);
                children.append(div);
            }
        } else {
            children.children().detach();
            for (var i = 0; i < node.children.length; i++) {
                var div = this.elements[node.children[i].id];
                children.append(div);
            }
        }
    }

    if (node.children.length <= 0 && !children.is(':empty')) {
        children.empty();
    }
};

TreeBrowser.prototype.scrollToNode = function(node) {
    var element  = this.elements[node.id];
    var position = element.position();
    var top      = this.container.scrollTop();
    var left     = this.container.scrollLeft();
    var height   = this.container.height();
    var width    = this.container.width();

    if (position.top < 0 || position.top >= height ||
            position.left < 0 || position.left >= width) {
        this.container.scrollTop(top + position.top - height / 2);
        this.container.scrollLeft(left + position.left);
    }
};

TreeBrowser.prototype.onChange = function(source) {
    var _this   = this;
    if (source instanceof Zoom) {
        var node = _this.zoom.getZoom();
        _this.container.empty();
        _this.elements = [];
        _this.elements[node.id] = _this.mkElement(node);
        _this.container.append(_this.elements[node.id]);
        _this.renderNode(_this.elements[node.id], node);
        node.addChangeListener(_this);
    } else if ((source instanceof CostCentreNode) ||
            (source instanceof IndividualNode)) {
        var element = _this.elements[source.id];

        if (!element) return;  // Invisible source changed what?

        _this.renderNode(element, source);
        for (var i = 0; i < source.children.length; i++) {
            source.children[i].addChangeListener(_this);
        }

        if (source.isSelected()) _this.scrollToNode(source);
    }
}