orgchart
Version:
Simple and direct organization chart(tree-like hierarchy) plugin based on pure DOM and jQuery.
218 lines (205 loc) • 8.51 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>Organization Chart Plugin</title>
<link rel="icon" href="img/logo.png">
<link rel="stylesheet" href="css/jquery.orgchart.css">
<link rel="stylesheet" href="css/style.css">
<style type="text/css">
#chart-container { height: 500px; }
.orgchart { padding-bottom: 20px; }
.orgchart.edit-state .edge, .orgchart.edit-state .toggleBtn { display: none; }
.orgchart .node .title { height: 30px; line-height: 30px; }
#edit-panel { margin: 0.5rem; padding: 0.5rem; border: 1px solid #aaa; }
#edit-panel .btn-inputs { width: 2rem; padding: 0; font-size: 1.5rem; }
#edit-panel .btn-inputs { vertical-align: sub; }
#edit-panel.edit-parent-node .btn-inputs { display: none; }
#edit-panel.edit-state>:not(#chart-state-panel) { display: none; }
#edit-panel label { font-weight: bold; }
#edit-panel.edit-parent-node .selected-node-group { display: none; }
#chart-state-panel, #selected-node, #btn-remove-input { margin-right: 1rem; }
#edit-panel button, #edit-panel input { padding: 0.5rem 1rem; font-size: 1rem; }
#edit-panel.edit-parent-node button:not(#btn-add-nodes) { display: none; }
#new-nodelist {
display: inline-block;
list-style:none;
margin-top: -0.5rem;
padding: 0;
vertical-align: text-top;
}
#new-nodelist>* { padding-bottom: 4px; }
.radio-panel input[type='radio'] { height: 1.25rem; width: 1.25rem; vertical-align: text-bottom; }
#btn-add-nodes { margin-left: 20px; }
</style>
</head>
<body>
<div id="chart-container"></div>
<div id="edit-panel">
<span id="chart-state-panel" class="radio-panel">
<input type="radio" name="chart-state" id="rd-view" value="view"><label for="rd-view">View</label>
<input type="radio" name="chart-state" id="rd-edit" value="edit" checked="true"><label for="rd-edit">Edit</label>
</span>
<label class="selected-node-group">selected node:</label>
<input type="text" id="selected-node" class="selected-node-group">
<label>new node:</label>
<ul id="new-nodelist">
<li><input type="text" class="new-node"></li>
</ul>
<button class="btn-inputs" id="btn-add-input">+</button>
<button class="btn-inputs" id="btn-remove-input">-</button>
<span id="node-type-panel" class="radio-panel">
<input type="radio" name="node-type" id="rd-parent" value="parent"><label for="rd-parent">Parent(root)</label>
<input type="radio" name="node-type" id="rd-child" value="children"><label for="rd-child">Child</label>
<input type="radio" name="node-type" id="rd-sibling" value="siblings"><label for="rd-sibling">Sibling</label>
</span>
<button type="button" id="btn-add-nodes">Add</button>
<button type="button" id="btn-delete-nodes">Delete</button>
<button type="button" id="btn-reset">Reset</button>
</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/html2canvas.min.js"></script>
<script type="text/javascript" src="js/jquery.orgchart.js"></script>
<script type="text/javascript">
$(function() {
var datascource = {
'name': 'Ball game',
'children': [
{ 'name': 'Football' },
{ 'name': 'Basketball' },
{ 'name': 'Volleyball' }
]
};
var getId = function() {
return (new Date().getTime()) * 1000 + Math.floor(Math.random() * 1001);
};
var oc = $('#chart-container').orgchart({
'data' : datascource,
'verticalLevel': 3,
'createNode': function($node, data) {
$node[0].id = getId();
}
});
oc.$chartContainer.on('click', '.node', function() {
var $this = $(this);
$('#selected-node').val($this.find('.title').text()).data('node', $this);
});
oc.$chartContainer.on('click', '.orgchart', function(event) {
if (!$(event.target).closest('.node').length) {
$('#selected-node').val('');
}
});
$('input[name="chart-state"]').on('click', function() {
$('.orgchart').toggleClass('edit-state', this.value !== 'view');
$('#edit-panel').toggleClass('edit-state', this.value === 'view');
if ($(this).val() === 'edit') {
$('.orgchart').find('.hidden').removeClass('hidden')
.end().find('.hierarchy').removeClass('isCollapsedDescendant isChildrenCollapsed isSiblingsCollapsed isCollapsedSibling')
.find('.node').removeClass('slide-up slide-down slide-right slide-left');
} else {
$('#btn-reset').trigger('click');
}
});
$('input[name="node-type"]').on('click', function() {
var $this = $(this);
if ($this.val() === 'parent') {
$('#edit-panel').addClass('edit-parent-node');
$('#new-nodelist').children(':gt(0)').remove();
} else {
$('#edit-panel').removeClass('edit-parent-node');
}
});
$('#btn-add-input').on('click', function() {
$('#new-nodelist').append('<li><input type="text" class="new-node"></li>');
});
$('#btn-remove-input').on('click', function() {
var inputs = $('#new-nodelist').children('li');
if (inputs.length > 1) {
inputs.last().remove();
}
});
$('#btn-add-nodes').on('click', function() {
var $chartContainer = $('#chart-container');
var nodeVals = [];
$('#new-nodelist').find('.new-node').each(function(index, item) {
var validVal = item.value.trim();
if (validVal.length) {
nodeVals.push(validVal);
}
});
var $node = $('#selected-node').data('node');
if (!nodeVals.length) {
alert('Please input value for new node');
return;
}
var nodeType = $('input[name="node-type"]:checked');
if (!nodeType.length) {
alert('Please select a node type');
return;
}
if (nodeType.val() !== 'parent' && !$('.orgchart').length) {
alert('Please creat the root node firstly when you want to build up the orgchart from the scratch');
return;
}
if (nodeType.val() !== 'parent' && !$node) {
alert('Please select one node in orgchart');
return;
}
if (nodeType.val() === 'parent') {
if (!$chartContainer.children('.orgchart').length) {// if the original chart has been deleted
oc = $chartContainer.orgchart({
'data' : { 'name': nodeVals[0] },
'chartClass': 'edit-state',
'exportButton': true,
'exportFilename': 'SportsChart',
'createNode': function($node, data) {
$node[0].id = getId();
}
});
} else {
oc.addParent($chartContainer.find('.node:first'), { 'name': nodeVals[0], 'id': getId() });
}
} else if (nodeType.val() === 'siblings') {
if ($node[0].id === oc.$chart.find('.node:first')[0].id) {
alert('You are not allowed to directly add sibling nodes to root node');
return;
}
oc.addSiblings($node, nodeVals.map(function (item) {
return { 'name': item, 'relationship': '110', 'id': getId() };
}));
} else {
if (!$node.siblings('.nodes').length) {
var rel = nodeVals.length > 1 ? '110' : '100';
oc.addChildren($node, nodeVals.map(function (item) {
return { 'name': item, 'relationship': rel, 'id': getId() };
}));
} else {
oc.addSiblings($node.siblings('.nodes').find('.node:first'), nodeVals.map(function (item) {
return { 'name': item, 'relationship': '110', 'id': getId() };
}));
}
}
});
$('#btn-delete-nodes').on('click', function() {
var $node = $('#selected-node').data('node');
if (!$node) {
alert('Please select one node in orgchart');
return;
} else if ($node[0] === $('.orgchart').find('.node:first')[0]) {
if (!window.confirm('Are you sure you want to delete the whole chart?')) {
return;
}
}
oc.removeNodes($node);
$('#selected-node').val('').data('node', null);
});
$('#btn-reset').on('click', function() {
$('.orgchart').find('.focused').removeClass('focused');
$('#selected-node').val('');
$('#new-nodelist').find('input:first').val('').parent().siblings().remove();
$('#node-type-panel').find('input').prop('checked', false);
});
});
</script>
</body>
</html>