diff --git a/equal-nodes-span b/equal-nodes-span new file mode 100644 index 0000000..1a6df44 --- /dev/null +++ b/equal-nodes-span @@ -0,0 +1,220 @@ +(function($) { + + $.fn.jOrgChart = function(options) { + var opts = $.extend({}, $.fn.jOrgChart.defaults, options); + var $appendTo = $(opts.chartElement); + + $this = $(this); + var $container = $("
"); + if($this.is("ul")) { + buildNode($this.find("li:first"), $container, 0, opts); + } + else if($this.is("li")) { + buildNode($this, $container, 0, opts); + } + $appendTo.append($container); + + // add drag and drop if enabled + if(opts.dragAndDrop){ + $('div.node').draggable({ + cursor : 'move', + distance : 40, + helper : 'clone', + opacity : 0.8, + revert : 'invalid', + revertDuration : 100, + snap : 'div.node.expanded', + snapMode : 'inner', + stack : 'div.node' + }); + + $('div.node').droppable({ + accept : '.node', + activeClass : 'drag-active', + hoverClass : 'drop-hover' + }); + + // Drag start event handler for nodes + $('div.node').bind("dragstart", function handleDragStart( event, ui ){ + + var sourceNode = $(this); + sourceNode.parentsUntil('.node-container') + .find('*') + .filter('.node') + .droppable('disable'); + }); + + // Drag stop event handler for nodes + $('div.node').bind("dragstop", function handleDragStop( event, ui ){ + + /* reload the plugin */ + $(opts.chartElement).children().remove(); + $this.jOrgChart(opts); + }); + + // Drop event handler for nodes + $('div.node').bind("drop", function handleDropEvent( event, ui ) { + + var targetID = $(this).data("tree-node"); + var targetLi = $this.find("li").filter(function() { return $(this).data("tree-node") === targetID; } ); + var targetUl = targetLi.children('ul'); + + var sourceID = ui.draggable.data("tree-node"); + var sourceLi = $this.find("li").filter(function() { return $(this).data("tree-node") === sourceID; } ); + var sourceUl = sourceLi.parent('ul'); + + if (targetUl.length > 0){ + targetUl.append(sourceLi); + } else { + targetLi.append(""); + targetLi.children('ul').append(sourceLi); + } + + //Removes any empty lists + if (sourceUl.children().length === 0){ + sourceUl.remove(); + } + + }); // handleDropEvent + + } // Drag and drop + }; + + // Option defaults + $.fn.jOrgChart.defaults = { + chartElement : 'body', + depth : -1, + chartClass : "jOrgChart", + dragAndDrop: false + }; + + var nodeCount = 0; + // Method that recursively builds the tree + function buildNode($node, $appendTo, level, opts) { + var $table = $(""); + var $tbody = $(""); + + // Construct the node container(s) + var $nodeRow = $("").addClass("node-cells"); + var $nodeCell = $(""); + var $downLineCell = $(""); + $childNodes.each(function() { + var $left = $("").addClass("line left top"); + var $right = $("").addClass("line right top"); + $linesRow.append($left).append($right); + }); + + // horizontal line shouldn't extend beyond the first and last child branches + $linesRow.find("td:first") + .removeClass("top") + .end() + .find("td:last") + .removeClass("top"); + + $tbody.append($linesRow); + var $childNodesRow = $(""); + $childNodes.each(function() { + var $td = $("
").addClass("node-cell").attr("colspan", 2); + var $childNodes = $node.children("ul:first").children("li"); + var $nodeDiv; + + if($childNodes.length > 1) { + $nodeCell.attr("colspan", $childNodes.length * 2); + } + // Draw the node + // Get the contents - any markup except li and ul allowed + var $nodeContent = $node.clone() + .children("ul,li") + .remove() + .end() + .html(); + + //Increaments the node count which is used to link the source list and the org chart + nodeCount++; + $node.data("tree-node", nodeCount); + $nodeDiv = $("
").addClass("node") + .data("tree-node", nodeCount) + .append($nodeContent); + + // Expand and contract nodes + if ($childNodes.length > 0) { + $nodeDiv.click(function() { + var $this = $(this); + var $tr = $this.closest("tr"); + + if($tr.hasClass('contracted')){ + $this.css('cursor','n-resize'); + $tr.removeClass('contracted').addClass('expanded'); + $tr.nextAll("tr").css('display', ''); + + // Update the
  • appropriately so that if the tree redraws collapsed/non-collapsed nodes + // maintain their appearance + $node.removeClass('collapsed'); + }else{ + $this.css('cursor','s-resize'); + $tr.removeClass('expanded').addClass('contracted'); + $tr.nextAll("tr").css('display', 'none'); + + $node.addClass('collapsed'); + } + }); + } + + $nodeCell.append($nodeDiv); + $nodeRow.append($nodeCell); + $tbody.append($nodeRow); + + if($childNodes.length > 0) { + // if it can be expanded then change the cursor + $nodeDiv.css('cursor','n-resize'); + + // recurse until leaves found (-1) or to the level specified + if(opts.depth == -1 || (level+1 < opts.depth)) { + var $downLineRow = $("
  • ").attr("colspan", $childNodes.length*2); + $downLineRow.append($downLineCell); + + // draw the connecting line from the parent node to the horizontal line + $downLine = $("
    ").addClass("line down"); + $downLineCell.append($downLine); + $tbody.append($downLineRow); + + // Draw the horizontal lines + var $linesRow = $("
      
    "); + $td.attr("colspan", 2); + // recurse through children lists and items + buildNode($(this), $td, level+1, opts); + $childNodesRow.append($td); + }); + + } + $tbody.append($childNodesRow); + } + + // any classes on the LI element get copied to the relevant node in the tree + // apart from the special 'collapsed' class, which collapses the sub-tree at this point + if ($node.attr('class') != undefined) { + var classList = $node.attr('class').split(/\s+/); + $.each(classList, function(index,item) { + if (item == 'collapsed') { + console.log($node); + $nodeRow.nextAll('tr').css('display', 'none'); + $nodeRow.removeClass('expanded'); + $nodeRow.addClass('contracted'); + $nodeDiv.css('cursor','s-resize'); + } else { + $nodeDiv.addClass(item); + } + }); + } + + $table.append($tbody); + $appendTo.append($table); + + /* Prevent trees collapsing if a link inside a node is clicked */ + $nodeDiv.children('a').click(function(e){ + console.log(e); + e.stopPropagation(); + }); + }; + +})(jQuery);