orgchart
Version:
Simple and direct organization chart(tree-like hierarchy) library based on pure DOM.
148 lines (140 loc) • 5.52 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>OrgChart On-Demand Loading Demo</title>
<link rel="icon" href="img/logo.png">
<link rel="stylesheet" href="css/orgchart.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<section class="demo-notes">
<h1>On-Demand Loading Demo</h1>
<p>This demo loads ancestors and descendants only when users expand the corresponding branches.</p>
</section>
<div id="chart-container"></div>
<script type="text/javascript" src="js/orgchart.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
const responseMap = {
'/orgchart/ancestors/n1': {
'id': 'n0',
'name': 'Lao Lao',
'title': 'general manager', 'relationship': '001',
'children': [
{ 'id': 'n10','name': 'Bo Miao', 'title': 'department engineer', 'relationship': '110' },
{ 'id': 'n11', 'name': 'Yu Jie', 'title': 'department engineer', 'relationship': '110' },
{ 'id': 'n12', 'name': 'Yu Li', 'title': 'department engineer', 'relationship': '110' },
{ 'id': 'n13', 'name': 'Hong Miao', 'title': 'department engineer', 'relationship': '110' },
{ 'id': 'n14', 'name': 'Yu Wei', 'title': 'department engineer', 'relationship': '110' },
{ 'id': 'n15', 'name': 'Chun Miao', 'title': 'department engineer', 'relationship': '110' },
{ 'id': 'n16', 'name': 'Yu Tie', 'title': 'department engineer', 'relationship': '110' }
]
},
'/orgchart/descendants/n2': [
{ 'id': 'n4', 'name': 'Xiang Xiang', 'title': 'engineer', 'relationship': '110' }
],
'/orgchart/descendants/n3': [
{ 'id': 'n5', 'name': 'Pang Pang', 'title': 'engineer', 'relationship': '111',
'children': [
{ 'id': 'n6', 'name': 'Er Dan', 'title': 'UE engineer', 'relationship': '110'}
]
},
{ 'id': 'n7', 'name': 'Dan Dan', 'title': 'engineer', 'relationship': '110' }
]
};
const requestJson = (url) => new Promise((resolve) => {
window.setTimeout(() => resolve(responseMap[url]), 1000);
});
const datasource = {
'id': 'n1',
'name': 'Su Miao',
'title': 'department manager',
'relationship': '111',
'children': [
{ 'id': 'n2','name': 'Tie Hua', 'title': 'senior engineer', 'relationship': '111' },
{ 'id': 'n3','name': 'Hei Hei', 'title': 'senior engineer', 'relationship': '111' }
]
};
const oc = new OrgChart({
chartContainer: '#chart-container',
'data' : datasource,
'nodeContent': 'title',
'nodeId': 'id'
});
const chartElement = document.getElementById('chart-container');
const getAjaxFlag = () => oc.chart.dataset.inAjax === 'true';
const setAjaxFlag = (value) => {
oc.chart.dataset.inAjax = value ? 'true' : 'false';
};
const toggleLoading = (edgeElement, isLoading) => {
const nodeElement = edgeElement.parentElement;
const spinner = nodeElement.querySelector('.spinner');
edgeElement.classList.toggle('hidden', isLoading);
if (isLoading && !spinner) {
nodeElement.insertAdjacentHTML('beforeend', '<i class="oci oci-spinner spinner"></i>');
Array.from(nodeElement.children)
.filter((child) => !child.classList.contains('spinner'))
.forEach((child) => {
child.style.opacity = '0.2';
});
setAjaxFlag(true);
return;
}
if (!isLoading) {
const currentSpinner = nodeElement.querySelector('.spinner');
if (currentSpinner) {
currentSpinner.remove();
}
Array.from(nodeElement.children).forEach((child) => {
child.removeAttribute('style');
});
setAjaxFlag(false);
}
};
chartElement.addEventListener('click', async (event) => {
const clickableAncestor = event.target.closest('.topEdge, .horizontalEdge');
if (!clickableAncestor || !chartElement.contains(clickableAncestor)) {
return;
}
const nodeElement = clickableAncestor.parentElement;
const parentState = oc.getNodeState(nodeElement, 'parent');
if (!parentState.exist) {
if (getAjaxFlag()) {
return;
}
toggleLoading(clickableAncestor, true);
try {
const nodeData = nodeElement ? nodeElement.__ocNodeData || nodeElement.dataset : {};
const data = await requestJson('/orgchart/ancestors/' + nodeData.id);
oc.addAncestors(data, 'n0');
} finally {
toggleLoading(clickableAncestor, false);
}
}
});
chartElement.addEventListener('click', async (event) => {
const bottomEdge = event.target.closest('.bottomEdge');
if (!bottomEdge || !chartElement.contains(bottomEdge)) {
return;
}
const nodeElement = bottomEdge.parentElement;
const childrenState = oc.getNodeState(nodeElement, 'children');
if (!childrenState.exist) {
if (getAjaxFlag()) {
return;
}
toggleLoading(bottomEdge, true);
try {
const nodeData = nodeElement ? nodeElement.__ocNodeData || nodeElement.dataset : {};
const data = await requestJson('/orgchart/descendants/' + nodeData.id);
oc.addDescendants(data, nodeElement);
} finally {
toggleLoading(bottomEdge, false);
}
}
});
});
</script>
</body>
</html>