')
.addClass('node ' + (nodeData.bg_color || '') + (level >= opts.depth ? ' slide-up' : ''))
.append('
' + nodeData[opts.nodeTitle] + '
')
// .append(typeof opts.nodeContent !== 'undefined' ? '
' + (nodeData[opts.nodeContent] || '') + '
' : '');
// append 4 direction arrows
var flags = nodeData.relationship || '';
// if (Number(flags.substr(0,1))) {
// $nodeDiv.append('
');
// }
// if(Number(flags.substr(1,1))) {
// $nodeDiv.append('
' +
// '
');
// }
// if(Number(flags.substr(2,1))) {
// $nodeDiv.append('
')
// .children('.title').prepend('
');
// }
$nodeDiv.on('mouseenter mouseleave', function(event) {
var $node = $(this), flag = false;
var $topEdge = $node.children('.topEdge');
var $rightEdge = $node.children('.rightEdge');
var $bottomEdge = $node.children('.bottomEdge');
var $leftEdge = $node.children('.leftEdge');
if (event.type === 'mouseenter') {
if ($topEdge.length) {
flag = getNodeState($node, 'parent').visible;
$topEdge.toggleClass('fa-chevron-up', !flag).toggleClass('fa-chevron-down', flag);
}
if ($bottomEdge.length) {
flag = getNodeState($node, 'children').visible;
$bottomEdge.toggleClass('fa-chevron-down', !flag).toggleClass('fa-chevron-up', flag);
}
if ($leftEdge.length) {
switchHorizontalArrow($node);
}
} else {
$node.children('.edge').removeClass('fa-chevron-up fa-chevron-down fa-chevron-right fa-chevron-left');
}
});
// define click event handler
// $nodeDiv.on('click', function(event) {
// $(this).closest('.orgchart').find('.focused').removeClass('focused');
// $(this).addClass('focused');
// });
// define click event handler for the top edge
// $nodeDiv.on('click', '.topEdge', function(event) {
// var $that = $(this);
// var $node = $that.parent();
// var parentState = getNodeState($node, 'parent');
// if (parentState.exist) {
// var $parent = $node.closest('table').closest('tr').siblings(':first').find('.node');
// if ($parent.is('.slide')) { return; }
// // hide the ancestor nodes and sibling nodes of the specified node
// if (parentState.visible) {
// hideAncestorsSiblings($node);
// $parent.one('transitionend', function() {
// if (isInAction($node)) {
// switchVerticalArrow($that);
// switchHorizontalArrow($node);
// }
// });
// } else { // show the ancestors and siblings
// showParent($node);
// }
// } else {
// // load the new parent node of the specified node by ajax request
// var nodeId = $that.parent()[0].id;
// // start up loading status
// if (startLoading($that, $node, opts)) {
// // load new nodes
// $.ajax({ 'url': opts.ajaxURL.parent + nodeId + '/', 'dataType': 'json' })
// .done(function(data) {
// if ($node.closest('.orgchart').data('inAjax')) {
// if (!$.isEmptyObject(data)) {
// addParent.call($node.closest('.orgchart').parent(), $node, data, opts);
// }
// }
// })
// .fail(function() { console.log('Failed to get parent node data'); })
// .always(function() { endLoading($that, $node, opts); });
// }
// }
// });
// bind click event handler for the bottom edge
// $nodeDiv.on('click', '.bottomEdge', function(event) {
// var $that = $(this);
// var $node = $that.parent();
// var childrenState = getNodeState($node, 'children');
// if (childrenState.exist) {
// var $children = $node.closest('tr').siblings(':last');
// if ($children.find('.node:visible').is('.slide')) { return; }
// // hide the descendant nodes of the specified node
// if (childrenState.visible) {
// hideDescendants($node);
// } else { // show the descendants
// showDescendants($node);
// }
// } else { // load the new children nodes of the specified node by ajax request
// var nodeId = $that.parent()[0].id;
// if (startLoading($that, $node, opts)) {
// $.ajax({ 'url': opts.ajaxURL.children + nodeId + '/', 'dataType': 'json' })
// .done(function(data, textStatus, jqXHR) {
// if ($node.closest('.orgchart').data('inAjax')) {
// if (data.children.length) {
// addChildren($node, data, $.extend({}, opts, { depth: 0 }));
// }
// }
// })
// .fail(function(jqXHR, textStatus, errorThrown) {
// console.log('Failed to get children nodes data');
// })
// .always(function() {
// endLoading($that, $node, opts);
// });
// }
// }
// });
// bind click event handler for the left and right edges
// $nodeDiv.on('click', '.leftEdge, .rightEdge', function(event) {
// var $that = $(this);
// var $node = $that.parent();
// var siblingsState = getNodeState($node, 'siblings');
// if (siblingsState.exist) {
// var $siblings = $node.closest('table').parent().siblings();
// if ($siblings.find('.node:visible').is('.slide')) { return; }
// if (opts.toggleSiblingsResp) {
// var $prevSib = $node.closest('table').parent().prev();
// var $nextSib = $node.closest('table').parent().next();
// if ($that.is('.leftEdge')) {
// if ($prevSib.is('.hidden')) {
// showSiblings($node, 'left');
// } else {
// hideSiblings($node, 'left');
// }
// } else {
// if ($nextSib.is('.hidden')) {
// showSiblings($node, 'right');
// } else {
// hideSiblings($node, 'right');
// }
// }
// } else {
// if (siblingsState.visible) {
// hideSiblings($node);
// } else {
// showSiblings($node);
// }
// }
// } else {
// // load the new sibling nodes of the specified node by ajax request
// var nodeId = $that.parent()[0].id;
// var url = (getNodeState($node, 'parent').exist) ? opts.ajaxURL.siblings : opts.ajaxURL.families;
// if (startLoading($that, $node, opts)) {
// $.ajax({ 'url': url + nodeId + '/', 'dataType': 'json' })
// .done(function(data, textStatus, jqXHR) {
// if ($node.closest('.orgchart').data('inAjax')) {
// if (data.siblings || data.children) {
// addSiblings($node, data, opts);
// }
// }
// })
// .fail(function(jqXHR, textStatus, errorThrown) {
// console.log('Failed to get sibling nodes data');
// })
// .always(function() {
// endLoading($that, $node, opts);
// });
// }
// }
// });
if (opts.draggable) {
$nodeDiv.on('dragstart', function(event) {
event.originalEvent.dataTransfer.setData('text/html', 'hack for firefox');
var $dragged = $(this);
var $dragZone = $dragged.closest('.nodes').siblings().eq(0).find('.node:first');
var $dragHier = $dragged.closest('table').find('.node');
$dragged.closest('.orgchart')
.data('dragged', $dragged)
.find('.node').each(function(index, node) {
if ($dragHier.index(node) === -1) {
if (opts.dropCriteria) {
if (opts.dropCriteria($dragged, $dragZone, $(node))) {
$(node).addClass('allowedDrop');
}
} else {
$(node).addClass('allowedDrop');
}
}
});
})
.on('dragover', function(event) {
event.preventDefault();
var $dropZone = $(this);
var $dragged = $dropZone.closest('.orgchart').data('dragged');
var $dragZone = $dragged.closest('.nodes').siblings().eq(0).find('.node:first');
if ($dragged.closest('table').find('.node').index($dropZone) > -1 ||
(opts.dropCriteria && !opts.dropCriteria($dragged, $dragZone, $dropZone))) {
event.originalEvent.dataTransfer.dropEffect = 'none';
}
})
.on('dragend', function(event) {
$(this).closest('.orgchart').find('.allowedDrop').removeClass('allowedDrop');
})
.on('drop', function(event) {
var $dropZone = $(this);
var $orgchart = $dropZone.closest('.orgchart');
var $dragged = $orgchart.data('dragged');
$orgchart.find('.allowedDrop').removeClass('allowedDrop');
var $dragZone = $dragged.closest('.nodes').siblings().eq(0).children();
// firstly, deal with the hierarchy of drop zone
if (!$dropZone.closest('tr').siblings().length) { // if the drop zone is a leaf node
$dropZone.append('
')
.parent().attr('colspan', 2)
.parent().after('
|
'
+ '
| | |
'
+ '
|
')
.siblings(':last').append($dragged.find('.horizontalEdge').remove().end().closest('table').parent());
} else {
var dropColspan = parseInt($dropZone.parent().attr('colspan')) + 2;
var horizontalEdges = '
';
$dropZone.closest('tr').next().addBack().children().attr('colspan', dropColspan);
if (!$dragged.find('.horizontalEdge').length) {
$dragged.append(horizontalEdges);
}
$dropZone.closest('tr').siblings().eq(1).children(':last').before('
| | ')
.end().next().append($dragged.closest('table').parent());
var $dropSibs = $dragged.closest('table').parent().siblings().find('.node:first');
if ($dropSibs.length === 1) {
$dropSibs.append(horizontalEdges);
}
}
// secondly, deal with the hierarchy of dragged node
var dragColspan = parseInt($dragZone.attr('colspan'));
if (dragColspan > 2) {
$dragZone.attr('colspan', dragColspan - 2)
.parent().next().children().attr('colspan', dragColspan - 2)
.end().next().children().slice(1, 3).remove();
var $dragSibs = $dragZone.parent().siblings('.nodes').children().find('.node:first');
if ($dragSibs.length ===1) {
$dragSibs.find('.horizontalEdge').remove();
}
} else {
$dragZone.removeAttr('colspan')
.find('.bottomEdge').remove()
.end().end().siblings().remove();
}
$orgchart.triggerHandler({ 'type': 'nodedropped.orgchart', 'draggedNode': $dragged, 'dragZone': $dragZone.children(), 'dropZone': $dropZone });
});
}
// allow user to append dom modification after finishing node create of orgchart
if (opts.createNode) {
opts.createNode($nodeDiv, nodeData);
}
dtd.resolve($nodeDiv);
return dtd.promise();
}
// recursively build the tree
function buildHierarchy ($appendTo, nodeData, level, opts, callback) {
var $table;
// Construct the node
var $childNodes = nodeData[opts.nodeChildren];
var hasChildren = $childNodes ? $childNodes.length : false;
if (Object.keys(nodeData).length > 1) { // if nodeData has nested structure
$table = $('
');
$appendTo.append($table);
$.when(createNode(nodeData, level, opts))
.done(function($nodeDiv) {
$table.append($nodeDiv.wrap(' |
').closest('tr'));
if (callback) {
callback();
}
})
.fail(function() {
console.log('Failed to creat node')
});
}
// Construct the inferior nodes and connectiong lines
if (hasChildren) {
if (Object.keys(nodeData).length === 1) { // if nodeData is just an array
$table = $appendTo;
}
var isHidden = level + 1 >= opts.depth ? ' hidden' : '';
// draw the line close to parent node
$table.append(' |
');
// draw the lines close to children nodes
var linesRow = '| | ';
for (var i=1; i<$childNodes.length; i++) {
linesRow += ' | | ';
}
linesRow += ' |
';
$table.append(linesRow);
// recurse through children nodes
var $childNodesRow = $('');
$table.append($childNodesRow);
$.each($childNodes, function() {
var $td = $('');
$childNodesRow.append($td);
buildHierarchy($td, this, level + 1, opts, callback);
});
}
}
// build the child nodes of specific node
function buildChildNode ($appendTo, nodeData, opts, callback) {
var opts = opts || $appendTo.closest('.orgchart').data('options');
var data = nodeData.children || nodeData.siblings;
$appendTo.find('td:first').attr('colspan', data.length * 2);
buildHierarchy($appendTo, { 'children': data }, 0, opts, callback);
}
// exposed method
function addChildren($node, data, opts) {
var count = 0;
buildChildNode.call($node.closest('.orgchart').parent(), $node.closest('table'), data, opts, function() {
if (++count === data.children.length) {
if (!$node.children('.bottomEdge').length) {
$node.append('');
}
if (!$node.find('.symbol').length) {
$node.children('.title').prepend('');
}
showDescendants($node);
}
});
}
// build the parent node of specific node
function buildParentNode($currentRoot, nodeData, opts, callback) {
var that = this;
var $table = $('');
nodeData.relationship = '001';
$.when(createNode(nodeData, 0, opts || $currentRoot.closest('.orgchart').data('options')))
.done(function($nodeDiv) {
$table.append($nodeDiv.removeClass('slide-up').addClass('slide-down').wrap(' | ').closest('tr'));
$table.append(' | ');
var linesRow = ' | | ';
$table.append('' + linesRow + ' ');
var oc = that.children('.orgchart');
oc.prepend($table)
.children('table:first').append(' | ')
.children().children('tr:last').children().append(oc.children('table').last());
callback();
})
.fail(function() {
console.log('Failed to create parent node');
});
}
// exposed method
//function addParent($currentRoot, data, opts) {
// buildParentNode.call(this, $currentRoot, data, opts, function() {
// if (!$currentRoot.children('.topEdge').length) {
// $currentRoot.children('.title').after('');
// }
// showParent($currentRoot);
// });
//}
// subsequent processing of build sibling nodes
function complementLine($oneSibling, siblingCount, existingSibligCount) {
var lines = '';
for (var i = 0; i < existingSibligCount; i++) {
lines += ' | | ';
}
$oneSibling.parent().prevAll('tr:gt(0)').children().attr('colspan', siblingCount * 2)
.end().next().children(':first').after(lines);
}
// build the sibling nodes of specific node
function buildSiblingNode($nodeChart, nodeData, opts, callback) {
var opts = opts || $nodeChart.closest('.orgchart').data('options');
var newSiblingCount = nodeData.siblings ? nodeData.siblings.length : nodeData.children.length;
var existingSibligCount = $nodeChart.parent().is('td') ? $nodeChart.closest('tr').children().length : 1;
var siblingCount = existingSibligCount + newSiblingCount;
var insertPostion = (siblingCount > 1) ? Math.floor(siblingCount/2 - 1) : 0;
// just build the sibling nodes for the specific node
if ($nodeChart.parent().is('td')) {
var $parent = $nodeChart.closest('tr').prevAll('tr:last');
$nodeChart.closest('tr').prevAll('tr:lt(2)').remove();
var childCount = 0;
buildChildNode.call($nodeChart.closest('.orgchart').parent(),$nodeChart.parent().closest('table'), nodeData, opts, function() {
if (++childCount === newSiblingCount) {
var $siblingTds = $nodeChart.parent().closest('table').children().children('tr:last').children('td');
if (existingSibligCount > 1) {
complementLine($siblingTds.eq(0).before($nodeChart.closest('td').siblings().andSelf().unwrap()), siblingCount, existingSibligCount);
$siblingTds.addClass('hidden').find('.node').addClass('slide-left');
} else {
complementLine($siblingTds.eq(insertPostion).after($nodeChart.closest('td').unwrap()), siblingCount, 1);
$siblingTds.not(':eq(' + insertPostion + 1 + ')').addClass('hidden')
.slice(0, insertPostion).find('.node').addClass('slide-right')
.end().end().slice(insertPostion).find('.node').addClass('slide-left');
}
callback();
}
});
} else { // build the sibling nodes and parent node for the specific ndoe
var nodeCount = 0;
buildHierarchy($nodeChart.closest('.orgchart'), nodeData, 0, opts, function() {
if (++nodeCount === siblingCount) {
complementLine($nodeChart.next().children().children('tr:last')
.children().eq(insertPostion).after($('')
.append($nodeChart)), siblingCount, 1);
$nodeChart.closest('tr').siblings().eq(0).addClass('hidden').find('.node').addClass('slide-down');
$nodeChart.parent().siblings().addClass('hidden')
.slice(0, insertPostion).find('.node').addClass('slide-right')
.end().end().slice(insertPostion).find('.node').addClass('slide-left');
callback();
}
});
}
}
function addSiblings($node, data, opts) {
buildSiblingNode.call($node.closest('.orgchart').parent(), $node.closest('table'), data, opts, function() {
$node.closest('.nodes').data('siblingsLoaded', true);
if (!$node.children('.leftEdge').length) {
$node.children('.topEdge').after('');
}
showSiblings($node);
});
}
function removeNodes($node) {
var $parent = $node.closest('table').parent();
var $sibs = $parent.parent().siblings();
if ($parent.is('td')) {
if (getNodeState($node, 'siblings').exist) {
$sibs.eq(2).children('.top:lt(2)').remove();
$sibs.eq(':lt(2)').children().attr('colspan', $sibs.eq(2).children().length);
$parent.remove();
} else {
$sibs.eq(0).children().removeAttr('colspan')
.find('.bottomEdge').remove()
.end().end().siblings().remove();
}
} else {
$parent.add($parent.siblings()).remove();
}
}
}));
| |