{"id":1868,"date":"2017-08-21T11:47:14","date_gmt":"2017-08-21T11:47:14","guid":{"rendered":"http:\/\/mindfusion.eu\/blog\/?p=1868"},"modified":"2021-01-21T14:22:21","modified_gmt":"2021-01-21T14:22:21","slug":"org-chart-in-javascript-with-the-diagram-library","status":"publish","type":"post","link":"https:\/\/mindfusion.dev\/blog\/org-chart-in-javascript-with-the-diagram-library\/","title":{"rendered":"Org Chart in JavaScript with the Diagram Library"},"content":{"rendered":"<p>In this blog post we will use the <a href=\"https:\/\/mindfusion.dev\/javascript-diagram.html\">Js Diagram library<\/a> to create a beautiful organizational chart, where people from the company are represented with the hierarchy links between them. Each employee has a photo, name, position, boss and section for comments. The links between them demonstrate the hierarchy.<\/p>\n<p><img decoding=\"async\" title=\"Organizational Chart in JavaScript\" src=\"https:\/\/mindfusion.dev\/samples\/javascript\/diagram\/org-chart.png\" \/><\/p>\n<p>Run the sample from <a href=\"https:\/\/mindfusion.dev\/samples\/javascript\/diagram\/OrgChart\/OrgChartEditor.html\">https:\/\/mindfusion.dev\/samples\/javascript\/diagram\/OrgChart\/OrgChartEditor.html<\/a><\/p>\n<p><strong>I. Application Setup<\/strong><\/p>\n<p>We create a new folder for the project and there we copy the scripts that the sample uses. They are predominantly jQuery scripts, which you can also link from the <a href=\"https:\/\/code.jquery.com\/\">jQuery CDN website.<\/a><\/p>\n<div id=\"attachment_1874\" style=\"width: 598px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2017\/08\/dir-structure.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1874\" class=\"size-full wp-image-1874\" src=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2017\/08\/dir-structure.png\" alt=\"Org Chart in JavaScript: Directory Structure\" width=\"588\" height=\"310\" srcset=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2017\/08\/dir-structure.png 588w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2017\/08\/dir-structure-300x158.png 300w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2017\/08\/dir-structure-500x264.png 500w\" sizes=\"auto, (max-width: 588px) 100vw, 588px\" \/><\/a><p id=\"caption-attachment-1874\" class=\"wp-caption-text\">Org Chart in JavaScript: Directory Structure<\/p><\/div>\n<p>The samples.css and samples.js scripts are used by all MindFusion JavaScript samples and are not relevant to your application. They layout and style the HTML content.<\/p>\n<p>We need to create two files for this application \u2013 an HTML page and a JavaScript file that will be used by it. We create OrgChartEditor.html and link the following scripts and a CSS file in the section:<\/p>\n<pre id=\"line1\">&lt;<span class=\"start-tag\">a<\/span> <span class=\"attribute-name\">href<\/span>=\"<a class=\"attribute-value\" href=\"view-source:http:\/\/common\/jquery.min.js\">http:\/\/common\/jquery.min.js<\/a>\"&gt;http:\/\/common\/jquery.min.js&lt;\/<span class=\"end-tag\">a<\/span>&gt;\n<span id=\"line255\"><\/span>&lt;<span class=\"start-tag\">a<\/span> <span class=\"attribute-name\">href<\/span>=\"<a class=\"attribute-value\" href=\"view-source:http:\/\/common\/jquery-ui.min.js\">http:\/\/common\/jquery-ui.min.js<\/a>\"&gt;http:\/\/common\/jquery-ui.min.js&lt;\/<span class=\"end-tag\">a<\/span>&gt;<\/pre>\n<p>Then we create an empty (for now) js file that will hold the code-behind for the web page. It is called OrgChartEditor.js. We must reference it, from the HTML but we will do that at the end, before the closing tag. That is done because some browsers might not load correctly the scripts if they are initialize before the HTML code for the canvas.<\/p>\n<pre id=\"line1\">&lt;<span class=\"start-tag\">a<\/span> <span class=\"attribute-name\">href<\/span>=\"<a class=\"attribute-value\" href=\"view-source:http:\/\/mindfusion.common.js\/\">http:\/\/MindFusion.Common.js<\/a>\"&gt;http:\/\/MindFusion.Common.js&lt;\/<span class=\"end-tag\">a<\/span>&gt;\n<span id=\"line259\"><\/span>&lt;<span class=\"start-tag\">a<\/span> <span class=\"attribute-name\">href<\/span>=\"<a class=\"attribute-value\" href=\"view-source:http:\/\/mindfusion.diagramming.js\/\">http:\/\/MindFusion.Diagramming.js<\/a>\"&gt;http:\/\/MindFusion.Diagramming.js&lt;\/<span class=\"end-tag\">a<\/span>&gt;\n<span id=\"line260\"><\/span>&lt;<span class=\"start-tag\">a<\/span> <span class=\"attribute-name\">href<\/span>=\"<a class=\"attribute-value\" href=\"view-source:http:\/\/orgcharteditor.js\/\">http:\/\/OrgChartEditor.js<\/a>\"&gt;http:\/\/OrgChartEditor.js&lt;\/<span class=\"end-tag\">a<\/span>&gt;<\/pre>\n<p>As you see, we have copied MindFusion.Common.js and MindFusion.Diagramming.js in the directory of the web page. There we have also saved OrgChartEditor.js.<\/p>\n<p>The diagram uses an HTML Canvas to render itself. We create one on the web page:<\/p>\n<pre id=\"line1\"><span id=\"line41\"><\/span><span class=\"comment\">&lt;!-- The Diagram component is bound to the canvas element below --&gt;<\/span>\n<span id=\"line42\"><\/span>&lt;<span class=\"start-tag\">div<\/span> <span class=\"attribute-name\">style<\/span>=\"<a class=\"attribute-value\">width: 100%; height: 100%; overflow: auto;<\/a>\"&gt;\n<span id=\"line43\"><\/span>\t&lt;<span class=\"start-tag\">canvas<\/span> <span class=\"attribute-name\">id<\/span>=\"<a class=\"attribute-value\">diagram<\/a>\" <span class=\"attribute-name\">width<\/span>=\"<a class=\"attribute-value\">2100<\/a>\" <span class=\"attribute-name\">height<\/span>=\"<a class=\"attribute-value\">2100<\/a>\"&gt;\n<span id=\"line44\"><\/span>\t\tThis page requires a browser that supports HTML 5 Canvas element.\n<span id=\"line45\"><\/span>\t&lt;\/<span class=\"end-tag\">canvas<\/span>&gt;\n<span id=\"line46\"><\/span>&lt;\/<span class=\"end-tag\">div<\/span>&gt;<\/pre>\n<p>Note that the element has an id. That\u2019s important because we will reference it in the code behind file.<\/p>\n<p><strong>II. The OrgChartNode.<\/strong><\/p>\n<p>Each employee on the diagram is represented by a special node \u2013 the OrgChartNode. This node is a customized <a href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/jsdiagram\/index.htm?CC_T_MindFusion_Diagramming_TableNode_Members_0.htm\">TableNode.<\/a><\/p>\n<pre>\/\/ creates a table node with the default settings\nvar OrgChartNode = function (parent, boss)\n{\n       AbstractionLayer.initializeBase(OrgChartNode, this, [parent]);\n\n       this.childNodes = [];\n\n\t\/\/ set up table cells\n\tthis.redimTable(3, 4);\n\tthis.getCell(1, 3).setColumnSpan(2);\n\tthis.getCell(0, 0).setRowSpan(4);\n\tthis.getCell(1, 1).setText(\"Title:\");\n\tthis.getCell(1, 1).setFont(\n            new Font(\"Verdana\", 3.5, true \/*bold*\/, false \/*italic*\/));\n\tthis.getCell(1, 2).setFont(\n            new Font(\"Verdana\", 3.5, true \/*bold*\/, false \/*italic*\/));\n\tthis.getCell(1, 0).setFont(\n            new Font(\"Verdana\", 3.5, true \/*bold*\/, false \/*italic*\/));\n\tthis.getCell(1, 3).setFont(\n            new Font(\"Verdana\", 3, false \/*bold*\/, false \/*italic*\/));\n\tthis.configureCells();\n<\/pre>\n<p>Each OrgChartNode has a parent and a boss. The CEO, which is the topmost node in the hierarchy has no boss. The OrgChartNode is a TableNode with 3 columns and four rows. Cell(0,0) is reserved for the image of the employee. It spans 4 rows.<\/p>\n<p>The cells in the second column with index 1 are for labels: title, name, id and comments. We style them with bold font.<\/p>\n<p>The prototype of the OrgChartNode gets or sets the properties which deal with the data we need for each employee. We set the fields for each new node and update the existing canvas elements. We define an updateCanvasElements method that calls the <a href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/jsdiagram\/index.htm?M_MindFusion_Diagramming_DiagramItem_updateCanvasElements_0.htm\">updateCanvasElements<\/a> of the parent class to mark the changes. We also declare setter\/getter methods for each OrgChartNode field:<\/p>\n<pre>OrgChartNode.prototype =\n{\n\t\/\/ updates the existing elements\n\tupdateCanvasElements: function (node)\n\t{\n\t\tthis.setFields();\n\t\tAbstractionLayer.callBaseMethod(OrgChartNode, this, 'updateCanvasElements');\n\t},\n\n        \/\/ gets the title of the employee\n\tgetTitle: function ()\n\t{\n\t\treturn this.title;\n\t},\n        \/\/ sets the title of the employee\n\tsetTitle: function (value)\n\t{\n\t\tif (this.title !== value)\n\t\t{\n\t\t\tthis.title = value;\n\t\t\tthis.invalidate();\n\t\t}\n\t},\n<\/pre>\n<p>When we set a new value we invalidate the canvas so that the changes can be rendered correctly on the screen.<\/p>\n<pre>\/\/ assigns the employee data to the table cells\nsetFields: function()\n{\n    \/\/ hide the caption and place the employee names on row 0 \n    this.setCaptionHeight(0);\n    this.getCell(1,0).setText(\"Name:\")\n    this.getCell(2,0).setText(this.fullName);\n    \u2026.\n    \u2026.\n    \u2026..\n    \/\/ rearrange the org hierarchy\n    this.setHierarchy();\n    this.setColor();\n},\n<\/pre>\n<p>The setFields method takes the data from the OrgChartNode fields and assigns it to the correct cells of the table. It also assigns the correct boss of the employee. In our samples bosses are assigned automatically and cannot be edited by the user. This is done by the setHierarchy method:<\/p>\n<pre>\/\/ rebuilds the hierarchy\nsetHierarchy: function ()\n{\n    \/\/ the ceo has no boss\n    if (this.boss == undefined)\n\t{\n\t   this.hierarchy = 0;\n\t}\n\telse\n\t {\n             \/\/ first level of executives under the boss\n\t     if (this.boss.hierarchy == undefined)\n\t     {\n\t\t  this.hierarchy = 1;\n\t     }\n\t     else\n\t     {\n\t         \/\/ increase the depth of the hierarchy\n\t\t this.hierarchy = this.boss.hierarchy + 1;\n\t\t this.boss.addChild(this);\n\t\t}\n\t  }\n         \n         \/\/ rearrange the hierarchy\n\t for (var i = 0; i &lt; this.childNodes; i++)\n\t\tthis.childNodes[i].setHierarchy();\n\t\tthis.setColor();\n},\n<\/pre>\n<p>The setColor method assigns the right color for the background of the table. Different levels in the hierarchy are distinguished by different colors. The top level \u2013 the CEO \u2013 is read.<\/p>\n<p><strong>III. Interaction<\/strong><\/p>\n<p>The org chart allows the users to do a lot of things: edit certain table cells, delete and create nodes, create and delete links, move and drag the nodes. This is done by handling a lot of events that the diagram library exposes.<\/p>\n<p>First, we set the <a href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/jsdiagram\/index.htm?M_MindFusion_Diagramming_Diagram_setBehavior_1_Behavior.htm\">Behavior<\/a> property of the diagram to <a href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/jsdiagram\/index.htm?CC_T_MindFusion_Diagramming_Behavior_0.htm\">\u201cCustom\u201d.<\/a> This means we will define how the library responds to user actions. This is done because none of the predefined Behavior modes answer the specific needs of our application:<\/p>\n<pre>diagram.setBehavior(Behavior.Custom);\n<\/pre>\n<p>Then we start handling events. First, we handle the <a href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/jsdiagram\/index.htm?F_MindFusion_Diagramming_Events_clicked.htm\">Clicked<\/a> event:<\/p>\n<pre>diagram.addEventListener(Event.clicked, function (diagram, eventArgs)\n{\n     \/\/ check which mouse button was clicked\n     var button = eventArgs.getMouseButton();\n     var position = eventArgs.getMousePosition();\n\n     \u2026.\n});\n<\/pre>\n<p>We handle differently clicks with the right and left mouse buttons. If it is the right mouse button we should create a new OrgChartNode:<\/p>\n<pre>\/\/ click with the right mouse button creates a node\nif (button === 2)\n{\n\tvar node = new OrgChartNode(diagram, undefined);\n\tnode.setBounds(new Rect(position.x, position.y, 20, 20));\n\tnode.resize();\n\n\t\/\/ adds the node to the diagram items\n\tdiagram.addItem(node);\n\n\t\/\/ rearrange the diagram\n\tdiagram.arrangeAnimated(tree);\n}\n<\/pre>\n<p>Initially, the node has no boss, it will be determined once we link it to the rest of the org chart.<\/p>\n<p>Let\u2019s see what happens when the users clicks on a node:<\/p>\n<pre>diagram.addEventListener(Event.nodeClicked, onNodeClicked);\n<\/pre>\n<p>We handle the nodeClicked event with the onNodeClicked method:<\/p>\n<pre>\/\/ raised when the user clicks on a node\nfunction onNodeClicked(diagram, eventArgs)\n{\n\t\/\/ checks if the user has clicked with the left mouse button (0)\n\tvar button = eventArgs.getMouseButton();\n\tif (button === 0)\n\t\teditNode(diagram, eventArgs);\n\n        \/\/click with the right mouse button creates a node\n        else if (button === 2)\n        createNode(diagram, eventArgs);\n}\n<\/pre>\n<p>When the node is clicked with the left mouse button \u2013 we edit it. When it is clicked with the right one \u2013 we create a new node, linked to it, one level deeper into the hierarchy.<\/p>\n<pre>\/\/ called when the user edits a table\nfunction editNode(diagram, eventArgs)\n{\n     var cellEditor = eventArgs.getNode().cellFromPoint(eventArgs.getMousePosition());\n\n     \/\/ the table node to edit\n     var tableNode = eventArgs.getNode();\n     ...\n     ...\n}\n<\/pre>\n<p>We use the <a href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/jsdiagram\/index.htm?M_MindFusion_Diagramming_TableNode_cellFromPoint_1_Point.htm\">cellFromPoint<\/a> method to identify the cell that was clicked. The cells that cannot be edited \u2013 the ones that render the labels \u2013 have no cellEditor.<\/p>\n<pre>\/\/ cells that cannot be edited have no cellEditor assigned\nif (cellEditor.cell != undefined)\n       if(cellEditor.cell.editable == true)\n\t   edit = true;\n<\/pre>\n<p>If the cell can be edited we check which is the cell and what type of content it renders:<\/p>\n<pre>\/\/ if the cell can be edited\nif (edit)\n{\n\tdiagram.beginEdit(eventArgs.getNode(),eventArgs.getMousePosition());\n\t$(\"diagram_inplaceInput\").attr(\"placeholder\", \"url\");\n\n\tcellEditor.cell.onEdited = function (diagram, tableCell)\n\t{\n\t\tif (edit)\n\t\t{\n\t\t\tif (cellEditor.cell.image)\n\t\t\t{\n\t\t\t\t\/\/ read and assign the URL of the new image\n\t\t\t\tif (tableCell.getNewText() != undefined &amp;&amp;\n\t\t\t\t\ttableCell.getNewText() != \"\" &amp;&amp;\n\t\t\t\t\ttableCell.getNewText != \"undefined\")\n\t\t\t\t{\n\t\t\t\ttableNode.setImageLocation(tableCell.getNewText());\n\t\t\t\tcellEditor.cell.text.height = 0;\n\t\t\t\tcellEditor.cell.text.text = \"\";\n\t\t\t\t}\n\t\t\t}\n              .....\n}\n<\/pre>\n<p>In the code above we check to see if the image location is correctly set and if so \u2013 we read the new image from the url and render it in the cell.<\/p>\n<p>Handling the other events is easier, let\u2019s look at the event fired when cell text is edited:<\/p>\n<pre>\/\/add an eventListener for the cellTextEdited event\ndiagram.addEventListener(Event.cellTextEdited, function (diagram, cellArgs)\n{\n   cellArgs.getCell().onEdited(diagram, cellArgs);\n});\n<\/pre>\n<p>Here we just call the onEdited method of the cell that is edited, which we explained above. The samples handles this way a lot of events: nodeDeleted, linkCreated, nodeModified and many more. You can check them in the source code provided with the sample.<\/p>\n<p><strong>IV. Diagram Layout<\/strong><\/p>\n<p>The org chart uses the predefined <a href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/jsdiagram\/index.htm?T_MindFusion_Graphs_TreeLayout_Members.htm\">TreeLayout<\/a> to arrange the diagram. It is ideal for hierarchical types of charts because it neatly arranges all nodes from a given level in a row\/column based on the direction set.<\/p>\n<pre>\/\/ we apply the tree layout to arrange the diagram\ntree = new MindFusion.Graphs.TreeLayout();\n\n\/\/ customize the tree layout\ntree.direction = MindFusion.Graphs.LayoutDirection.TopToBottom;\ntree.linkType = MindFusion.Graphs.TreeLayoutLinkType.Cascading;\n<\/pre>\n<p>The TreeLayout is animated:<\/p>\n<pre>\/\/ rearrange the diagram\ndiagram.arrangeAnimated(tree); \n<\/pre>\n<p>It is called not only at the beginning but also each time a new node is created or deleted, link is created and\/or deleted as well when link or node is edited.<\/p>\n<p><strong>V. New Nodes<\/strong><\/p>\n<p>Finally, let\u2019s see how nodes are created in code:<\/p>\n<pre>var ctoNode = new OrgChartNode(diagram, ceoNode);\nctoNode.setBounds(new Rect(25, 55, 60, 25));\nctoNode.setBoss(ceoNode);\nctoNode.setTitle(\"CTO\");\nctoNode.setFullName(\"Bob Smith\");\nctoNode.setImageLocation(\"cto.png\");\nctoNode.setComment(\"A great person!\");\nctoNode.resize();\ndiagram.addItem(ctoNode);\n<\/pre>\n<p>New nodes, as you already know are created by the user with a right mouse button click on any node. If a link is deleted, the node is detached from the hierarchy and the user should drop it over an existing node to indicate its place in the hierarchy.<\/p>\n<p>With this we finish our sample. We have presented you with the most important information on how this org chart in JavaScript is created. You can download the complete source code of the sample from this link:<\/p>\n<p align=\"center\"><a href=\"https:\/\/mindfusion.dev\/samples\/javascript\/diagram\/OrgChart.zip\">Download MindFusion JavaScript Organizational Chart Sample<\/a><\/p>\n<p>The sample is also available on GitHub at <a href=\"https:\/\/github.com\/MindFusionComponents\/JavaScript-Diagram-Samples\/tree\/master\/OrgChart\">https:\/\/github.com\/MindFusionComponents\/JavaScript-Diagram-Samples\/tree\/master\/OrgChart<\/a><\/p>\n<p>The sample is available online at <a href=\"https:\/\/mindfusion.dev\/samples\/javascript\/diagram\/OrgChart\/OrgChartEditor.html\">https:\/\/mindfusion.dev\/samples\/javascript\/diagram\/OrgChart\/OrgChartEditor.html<\/a><\/p>\n<p>Find out more about MindFusion JavaScript Diagram Library at <a href=\"https:\/\/mindfusion.dev\/javascript-diagram.html\">https:\/\/mindfusion.dev\/javascript-diagram.html<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post we will use the Js Diagram library to create a beautiful organizational chart, where people from the company are represented with the hierarchy links between them. Each employee has a photo, name, position, boss and section &hellip; <a href=\"https:\/\/mindfusion.dev\/blog\/org-chart-in-javascript-with-the-diagram-library\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[95,74],"tags":[482,80,441,480,481],"class_list":["post-1868","post","type-post","status-publish","format-standard","hentry","category-diagramming-2","category-sample-code","tag-dynamic-flowchart-in-javascript","tag-javascript","tag-javascript-flowchart","tag-javascript-org-chart","tag-organizational-javascript-chart"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3RlKs-u8","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/1868","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/comments?post=1868"}],"version-history":[{"count":9,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/1868\/revisions"}],"predecessor-version":[{"id":2625,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/1868\/revisions\/2625"}],"wp:attachment":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/media?parent=1868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/categories?post=1868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/tags?post=1868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}