我正在寻找一些用于构建组织树/图的算法解决方案,它允许缩进或抵消一个或多个级别。
我有一组json数据:
[{
"id": 1,
"level":1,
"parent_id": 0,
"name": "Board of Director"
}, {
"id": 2,
"level":2,
"parent_id": 1,
"name": "Finance Division"
}, {
"id": 3,
"level":3,
"parent_id": 2,
"name": "Finance Department"
}, {
"id": 4,
"level":3,
"parent_id": 2,
"name": "Sales Department"
}, {
"id": 5,
"level":3,
"parent_id": 1,
"name": "HR Division"
}]
简要说明: _parent_id_属性通过使用line连接分部与其父级,而级属性用于分类分区应位于或缩进的位置,例如:级别1(董事会),级别2(财务部门)和级别3(财务部,销售部,人力资源部)。由于人力资源部门的_parent_id_ = 1且级别 = 3,因此图表中的位置应与财务部门和销售部门保持一致。
下面是模型组织树以及显示为 HR Division 的缩进示例。
.tree li {
list-style-type: none;
margin: 0;
padding: 10px 5px 0 5px;
position: relative
}
.tree li::before,
.tree li::after {
content: '';
left: -20px;
position: absolute;
right: auto
}
.tree li::before {
border-left: 1px solid #999;
bottom: 50px;
height: 100%;
top: 0;
width: 1px
}
.tree li::after {
border-top: 1px solid #999;
top: 30px;
width: 25px
}
.tree li div {
border: 1px solid #999;
display: inline-block;
padding: 8px 24px;
text-decoration: none
}
.tree li.parent > div {
cursor: pointer
}
.tree > ul > li::before,
.tree > ul > li::after {
border: 0
}
.tree li:last-child::before {
height: 30px
}
.tree li.parent > div:hover,
.tree li.parent > div:hover + ul li div {
background: #f3f3f4;
border: 1px solid #94a0b4;
color: #000
}
li div.just-line {
display: none;
}
div.just-line + ul > li::before {
padding: 0;
border-left: 0;
}
div.just-line + ul > li::after {
left: -40px;
width: 45px;
}
.no-padding {
padding: 0 !important;
}

<div class="tree">
<ul>
<li data-id="1">
<div>Board of Director</div>
<ul>
<li>
<div>Finance Division</div>
<ul>
<li>
<div>Finance Department</div>
<li>
<div>Sales Department</div>
</li>
</ul>
</li>
<li class="no-padding">
<div class="just-line"></div>
<ul>
<li>
<div>HR Division</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
&#13;
非常感谢任何帮助或建议。感谢。
答案 0 :(得分:1)
为了让您入门,这是一个两步解决方案,首先生成一个树并呈现DOM。
var data = [{ "id": 1, "level": 1, "parent_id": 0, "name": "Board of Director" }, { "id": 2, "level": 2, "parent_id": 1, "name": "Finance Division" }, { "id": 3, "level": 3, "parent_id": 2, "name": "Finance Department" }, { "id": 4, "level": 3, "parent_id": 2, "name": "Sales Department" }, { "id": 5, "level": 3, "parent_id": 1, "name": "HR Division" }],
tree = function (data, root) {
var r, o = {};
data.forEach(function (a) {
a.children = o[a.id] && o[a.id].children;
o[a.id] = a;
if (a.parent_id === root) {
r = a;
} else {
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || [];
o[a.parent_id].children.push(a);
}
});
return r;
}(data, 0),
ul = document.createElement('ul');
[tree].forEach(function iter(level) {
return function (a) {
var li = document.createElement('li'),
div = document.createElement('div'),
ul,
l = level;
this.appendChild(li);
while (++l < a.level) {
div.className = 'just-line';
li.className = 'no-padding';
li.appendChild(div);
ul = document.createElement('ul');
li.appendChild(ul);
li = document.createElement('li');
ul.appendChild(li);
div = document.createElement('div');
}
div.appendChild(document.createTextNode(a.name));
li.appendChild(div);
if (a.children) {
ul = document.createElement('ul');
li.appendChild(ul);
a.children.forEach(iter(a.level), ul);
}
};
}(0), ul);
document.getElementById('tree').appendChild(ul);
&#13;
.tree li { list-style-type: none; margin: 0; padding: 10px 5px 0 5px; position: relative; }
.tree li::before, .tree li::after { content: ''; left: -20px; position: absolute; right: auto; }
.tree li::before { border-left: 1px solid #999; bottom: 50px; height: 100%; top: 0; width: 1px; }
.tree li::after { border-top: 1px solid #999; top: 30px; width: 25px; }
.tree li div { border: 1px solid #999; display: inline-block; padding: 8px 24px; text-decoration: none; }
.tree li.parent > div { cursor: pointer; }
.tree > ul > li::before, .tree > ul > li::after { border: 0; }
.tree li:last-child::before { height: 30px; }
.tree li.parent > div:hover, .tree li.parent > div:hover + ul li div { background: #f3f3f4; border: 1px solid #94a0b4; color: #000; }
li div.just-line { display: none; }
div.just-line + ul > li::before { padding: 0; border-left: 0; }
div.just-line + ul > li::after { left: -40px; width: 45px; }
.no-padding { padding: 0 !important; }
&#13;
<div id="tree" class="tree"></div>
&#13;
答案 1 :(得分:0)
对于编码,我会选择像AngularJS
这样的MVC框架示例:http://jsfiddle.net/brendanowen/uXbn6/8/
您唯一需要做的就是创建一个类似于结构的数据模型。你的是平的,我会选择像树一样的数据,它更容易适应MVC之类的框架;)
[{"id": 1,"level":1,"parent_id": 0, "name": "Board of Director", childs: [{"id": 2, ..., childs: [{}]}}];
答案 2 :(得分:0)
看到DOM已经是一棵树了,我们可以利用这个事实。
以下我认为你做了什么。
var data = [{
"id": 1,
"level":1,
"parent_id": 0,
"name": "Board of Director"
}, {
"id": 2,
"level":2,
"parent_id": 1,
"name": "Finance Division"
}, {
"id": 3,
"level":3,
"parent_id": 2,
"name": "Finance Department"
}, {
"id": 4,
"level":3,
"parent_id": 2,
"name": "Sales Department"
}, {
"id": 5,
"level":3,
"parent_id": 1,
"name": "HR Division"
}];
document.addEventListener("DOMContentLoaded", function(event) {
var
qsa = document.querySelectorAll.bind(document),
ce = document.createElement.bind(document);
var rootparent = qsa('.tree UL')[0];
rootparent.innerHTML = '';
data.forEach(function (e) {
var parent = qsa('[data-id=\'' + e.parent_id+'\'] UL')[0]
|| rootparent;
var li = ce("LI");
var div = ce('DIV');
var ul = ce('UL');
li.appendChild(div);
li.appendChild(ul);
li.setAttribute('data-id', e.id);
div.textContent = e.name;
parent.appendChild(li);
});
});
.tree li {
list-style-type: none;
margin: 0;
padding: 10px 5px 0 5px;
position: relative
}
.tree li::before,
.tree li::after {
content: '';
left: -20px;
position: absolute;
right: auto
}
.tree li::before {
border-left: 1px solid #999;
bottom: 50px;
height: 100%;
top: 0;
width: 1px
}
.tree li::after {
border-top: 1px solid #999;
top: 30px;
width: 25px
}
.tree li div {
border: 1px solid #999;
display: inline-block;
padding: 8px 24px;
text-decoration: none
}
.tree li.parent > div {
cursor: pointer
}
.tree > ul > li::before,
.tree > ul > li::after {
border: 0
}
.tree li:last-child::before {
height: 30px
}
.tree li.parent > div:hover,
.tree li.parent > div:hover + ul li div {
background: #f3f3f4;
border: 1px solid #94a0b4;
color: #000
}
li div.just-line {
display: none;
}
div.just-line + ul > li::before {
padding: 0;
border-left: 0;
}
div.just-line + ul > li::after {
left: -40px;
width: 45px;
}
.no-padding {
padding: 0 !important;
}
<div class="tree">
<ul>
</ul>
</div>