如何在客户端生成父/子窝?

时间:2012-03-12 20:52:45

标签: javascript recursion tree d3.js

我搜索了无数的父/子数组/对象/此处和其他地方的任何问题,但无法解决我的问题。我知道这有点长,但我想确保我为你们提供足够的信息。

这就是我想要做的事情:

  1. 我在页面上有一些<div> - 描述的项目,包含父/子关系,通过我的数据库中的php生成
  2. 我想将这些项目用作D3.js树形图的数据源(节点链接树图http://mbostock.github.com/d3/ex/cluster.html
  3. 我用左/右嵌套设置值存储它们,但也存储了parentID值,所以我可以为<div>元素添加ID,parentID,rgt,lft和depth属性,所以我应该有任何需要的东西在客户端生成父/子关系
  4. 由于各种原因,我不是在服务器端创建JSON文件以用作数据源,而是需要根据#3
  5. 中的属性在客户端创建它。
  6. 我很难让各种建议的javascript函数工作,我发现的所有D3示例都使用了预先存在的JSON文件或生成的基于数学的文件,而不是页面上已有元素的属性
  7. 这是一个使用D3树形图已经适用于我的示例,但它不是动态生成的:

    var tree3 = 
    {"sid": "1", "children": [
        {"sid": "2", "children": [
            {"sid": "5", "children": [
                {"sid": "75"},
                {"sid": "85", "children": [
                    {"sid": "87"}, ...
    

    为了让您了解这些属性在DOM中的位置,我最初尝试过以下内容,但当然它不会生成任何层次结构:

    function tree() {
        var tree=[];
        $("article").each(function(){
            tree.push({
                sid:$(this).attr("sid"), 
                l:$(this).attr("l"), 
                r:$(this).attr("r"),
                pid:$(this).attr("pid")
            });
        });
        return tree;
    }
    

    我一直在使用下面的变体未能成功地获取嵌套数组:

    function tree2() {
       $("article").(function(d) {
           return d.parent().attr("pid") === 0;
    }, function(parent, child) {
        return parent.attr("pid") === child.parent().attr("sid");
    }).toArray();
    }
    

    所以,我正在疯狂地试图创建正确嵌套的javascript数组,但我突然意识到我可能不需要并且D3的数据选择器和方法就足够了。能帮我解决一下代码:

    1. 拉出所需的属性以在D3函数中生成父/子关系(“sid”是标识符),或者,如果不可能,
    2. 在javascript中创建所需的数组或类似数组的对象供D3使用(仍以“sid”作为标识符)。
    3. 提前致谢。

1 个答案:

答案 0 :(得分:1)

你需要递归!基本上诀窍是随时传递当前父级,这会改变上下文并允许您沿着树走下去。

更新:Working fiddle

假设你的HTML结构是这样的:

<div sid="1" pid="">
    <div sid="1.1" pid="1">
        <div sid="1.1.1" pid="1.1">
        </div>
    </div>
</div>

你可以这样做:

var _json = {};

function addTreeNode(div, parentObj) {

    var childObj = {
        sid: $(div).attr("sid"),
        pid: $(div).attr("pid")
    }

    // add this to it's parent in the JSON hierarchy
    if (!parentObj.children) parentObj.children = [];
    parentObj.children.push(childObj);

    // keep adding for all children div's
    $(div).find("div").each(function() {
        addTreeNode(this, childObj);
    });
}

// start at the roots, it will magically work it's way out to the leaves
$("body > div").each(function(){
    addTreeNode(this, _json);
});

console.log(_json);

请注意,如果树足够大,导致堆栈溢出,尤其是在IE中。在这种情况下,您需要将其切换为from recursion to iteration。但是,这并不是那么漂亮。