{"id":12329,"date":"2024-05-07T14:33:29","date_gmt":"2024-05-07T11:33:29","guid":{"rendered":"https:\/\/dhtmlx.com\/blog\/?p=12329"},"modified":"2024-06-21T17:06:09","modified_gmt":"2024-06-21T14:06:09","slug":"integrating-context-menu-javascript-gantt-chart-dhtmlx","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/integrating-context-menu-javascript-gantt-chart-dhtmlx\/","title":{"rendered":"Integrating a Context Menu into a JavaScript Gantt Chart with DHTMLX"},"content":{"rendered":"<p>It is time to remind you that DHTMLX Gantt is a highly customizable tool that can be complemented with additional functionalities required for your project management app. Today, you will learn how to complement a DHTMLX-based <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/\" target=\"_blank\" rel=\"noopener\">JavaScript Gantt chart<\/a> with a custom context menu for improving users\u2019 efficiency and productivity in task management. Taking into account the great intercompatibility of DHTMLX products, the Suite\u2019s Menu widget is a perfect addition to the Gantt component for achieving the goal of this tutorial.<\/p>\n<p>Let us review this demo in more detail and provide you with technical details that will help you integrate a similar feature into your project.<\/p>\n<h5>Initializing and Configuring a Context Menu<\/h5>\n<p>In our use case scenario, a context menu is a useful UI element that can display different options based on the context of the user&#8217;s interaction with the Gantt chart. <\/p>\n<p>If you right-click on any task in the Gantt chart in the sample below, you can play around with all available task operations.<br \/>\n<iframe class=\"snippet-container js-iframe\" width=\"100%\" height=\"560\" frameborder=\"0\" data-src=\"https:\/\/snippet.dhtmlx.com\/ateynir5?mode=mobile\"><\/iframe> <a href=\"https:\/\/snippet.dhtmlx.com\/ateynir5?tag=gantt&amp;mode=wide rel=\" target=\"_blank\">Check the sample &gt;<\/a><br \/>\nTo save time, we\u2019ll omit the initialization stage of our Gantt component that is clearly described in the <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__general_gantt_chart.html\" target=\"_blank\" rel=\"noopener\">documentation<\/a>, and go straight to implementing a context menu with <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxMenu\/\" target=\"_blank\" rel=\"noopener\">DHTMLX Menu<\/a>.<\/p>\n<p>The first step is to create a new instance of the context menu.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">let contextMenu <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dhx.<span class=\"me1\">ContextMenu<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">null<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> css<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;dhx_widget--bg_gray&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, use the <strong><a href=\"https:\/\/docs.dhtmlx.com\/gantt\/api__gantt_oncontextmenu_event.html\" target=\"_blank\" rel=\"noopener\">onContextMenu<\/a><\/strong> event handler, which fires after the rightclick on a task.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">gantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onContextMenu&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>taskId<span class=\"sy0\">,<\/span> linkId<span class=\"sy0\">,<\/span> event<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><\/div><\/div>\n<p>In the menu configuration, different menu items are shown depending on the click location. When calling a context menu for a regular task in the timeline, it will include the \u201cSplit Task\u201d item. However, this option is not available in the context menu for tasks with the project type and when calling the menu for tasks in the grid area since it is assumed that tasks should be split right at the click location.<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-12330\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image9.gif\" alt=\"DHTMLX Gantt with a custom context menu\" width=\"998\" height=\"483\" \/><br \/>\nAt the very beginning of the function in the event handler, it is necessary to collect the information where exactly the context menu is called.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">let itemsConfig <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>taskId<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"kw1\">const<\/span> task <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>taskId<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>For this purpose, you\u2019ll need several configs (variables):<\/p>\n<ul>\n<li><strong>isTaskBar<\/strong> &#8211; shows whether the taskbar in the timeline (the type of task is not taken into account here) is clicked.<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> isTaskBar <span class=\"sy0\">=<\/span> event.<span class=\"me1\">target<\/span>.<span class=\"me1\">closest<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;.gantt_task_line&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li><strong>isParentTask<\/strong> &#8211; shows if the task has child tasks.<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> isParentTask <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">hasChild<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li><strong>isSplitTask<\/strong> &#8211; shows if the task is rendered in split mode, when all of its child tasks (taskbars) are displayed on a single line in the timeline.<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> isSplitTask <span class=\"sy0\">=<\/span> task.<span class=\"me1\">render<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">&quot;split&quot;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li><strong>barHidden<\/strong> &#8211; shows if the task is displayed in the timeline.<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> barHidden <span class=\"sy0\">=<\/span> task.<span class=\"me1\">hide_bar<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>If a task has a parent, it is necessary to determine whether its parent is displayed in the split mode. It is done the following way:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">let hasSplitParent <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">parent<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> parent <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">parent<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; hasSplitParent <span class=\"sy0\">=<\/span> parent.<span class=\"me1\">render<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">&quot;split&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>After that, you need to add all parameters to the <strong>itemsConfig<\/strong> object.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">itemsConfig <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span> isTaskBar<span class=\"sy0\">,<\/span> isParentTask<span class=\"sy0\">,<\/span> isSplitTask<span class=\"sy0\">,<\/span> barHidden<span class=\"sy0\">,<\/span> hasSplitParent <span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>For the custom context menu, you need to remove all previous context menu items, and then add new ones returned by the <strong>generateMenuItems<\/strong> function.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">contextMenu.<span class=\"me1\">data<\/span>.<span class=\"me1\">removeAll<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\ncontextMenu.<span class=\"me1\">data<\/span>.<span class=\"me1\">parse<\/span><span class=\"br0\">&#40;<\/span>generateMenuItems<span class=\"br0\">&#40;<\/span>itemsConfig<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Now it is time to show the context menu in the click position.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">contextMenu.<span class=\"me1\">showAt<\/span><span class=\"br0\">&#40;<\/span>event<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Next, you need to calculate the position of the mouse click relative to the timeline. And from the resulting click position, you\u2019ll get the click date, which should be added to the <strong>clickDate<\/strong> parameter. It will be used in various context menu actions.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> clickPosition <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">getRelativeEventPosition<\/span><span class=\"br0\">&#40;<\/span>event<span class=\"sy0\">,<\/span> gantt.$task_data<span class=\"br0\">&#41;<\/span>.<span class=\"me1\">x<\/span><span class=\"sy0\">;<\/span><br \/>\nclickDate <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">dateFromPos<\/span><span class=\"br0\">&#40;<\/span>clickPosition<span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>The function of the <strong>onContextMenu<\/strong> event handler must return <em>false<\/em> to disable the default context menu function (i.e. the browser should not display the default context menu).<\/p>\n<p>Now let us get back to the <strong>generateMenuItems<\/strong> function. In this function, data for context menu items is generated. Each object for a context menu item contains an icon, item type, ID, and text.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; icon<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;dxi dxi-chevron-up&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;menuItem&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;add_sibling_above&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; value<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Add sibling above&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><\/div><\/div>\n<p>Next, you need to create objects for two menu items &#8211; &#8220;Cancel copy\/cut operation&#8221; and &#8220;Show all hidden tasks&#8221;.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> cancelCopyCut <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; icon<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;dxi dxi-close&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;menuItem&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;cancel_paste&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; value<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Cancel copy\/cut operation&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> showAllHidden <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; icon<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;dxi dxi-eye&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;menuItem&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;show_hidden&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; value<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Show all hidden tasks&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After a click on a taskbar in the grid or in the timeline, the function will be invoked with the config and various elements will be added to the context menu.<\/p>\n<p>When clicks occur in other areas of the Gantt chart, you need to check if there are tasks selected for copying and cutting. If so, you add this object to the array of menu items. If some tasks are hidden, then a second menu item is added. Under the mentioned conditions, these menu items will always be visible, regardless of click positions in the Gantt chart.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> menuItems <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>tasksToCopy.<span class=\"me1\">length<\/span> <span class=\"sy0\">+<\/span> tasksToCut.<span class=\"me1\">length<\/span> <span class=\"sy0\">&gt;<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; menuItems.<span class=\"me1\">push<\/span><span class=\"br0\">&#40;<\/span>cancelCopyCut<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw4\">Object<\/span>.<span class=\"me1\">keys<\/span><span class=\"br0\">&#40;<\/span>hiddenTasks<span class=\"br0\">&#41;<\/span>.<span class=\"me1\">length<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; menuItems.<span class=\"me1\">push<\/span><span class=\"br0\">&#40;<\/span>showAllHidden<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"kw1\">return<\/span> menuItems<span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Now get back to the context menu configuration. Before creating an instance of the context menu, it is reasonable to consider the <strong>generateMenuItems<\/strong> function in order not to return to this matter later.<\/p>\n<p>You have to add an event handler for clicks on context menu items. With each click, the <strong>click<\/strong> function will be invoked. This function will use the ID of the menu item.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">contextMenu.<span class=\"me1\">events<\/span>.<span class=\"me1\">on<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;click&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; applyCommand<span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; targetId <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Now we can focus on the configuration of each context menu option separately.<\/p>\n<h6>Create\/Update\/Delete<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-12332\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image4-1-1024x314.png\" alt=\"Context Menu - Create\/Update\/Delete\" width=\"1024\" height=\"314\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image4-1-1024x314.png 1024w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image4-1-300x92.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image4-1-768x236.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image4-1.png 1477w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><br \/>\nFirst, we describe the Create\/Update\/Delete section. This section includes the following nested menu items:<\/p>\n<ul>\n<li>Add sibling above<\/li>\n<\/ul>\n<p>This item adds a task at the same level, only on top of the task being clicked on:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;add_sibling_above&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">createTask<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> gantt.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;New task&quot;<\/span><span class=\"sy0\">,<\/span> start_date<span class=\"sy0\">:<\/span> task.<span class=\"me1\">start_date<\/span><span class=\"sy0\">,<\/span> duration<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> task.<span class=\"me1\">parent<\/span><span class=\"sy0\">,<\/span> gantt.<span class=\"me1\">getTaskIndex<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>To do this, you need to specify the parent of the task as the second parameter and the index of the task inside the branch as the third parameter.<\/p>\n<ul>\n<li>Add sibling below<\/li>\n<\/ul>\n<p>This item adds a task at the same level, only below the task being clicked on.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;add_sibling_below&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">createTask<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> gantt.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;New task&quot;<\/span><span class=\"sy0\">,<\/span> start_date<span class=\"sy0\">:<\/span> task.<span class=\"me1\">start_date<\/span><span class=\"sy0\">,<\/span> duration<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> task.<span class=\"me1\">parent<\/span><span class=\"sy0\">,<\/span> gantt.<span class=\"me1\">getTaskIndex<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>To do this, you need to specify the parent of the task as the second parameter and increase the index of the task inside the branch by 1 as the third parameter.<\/p>\n<ul>\n<li>Add subtask at the top<\/li>\n<\/ul>\n<p>This item adds a subtask at the top of the branch (above all other subtasks):<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;add_subtask_top&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">createTask<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> gantt.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;New subtask&quot;<\/span><span class=\"sy0\">,<\/span> start_date<span class=\"sy0\">:<\/span> task.<span class=\"me1\">start_date<\/span><span class=\"sy0\">,<\/span> duration<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> task.<span class=\"me1\">id<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>To do this, you specify the task ID as the second parameter and set zero index as the third parameter.<\/p>\n<ul>\n<li>Add subtask at the bottom<\/li>\n<\/ul>\n<p>This item adds a subtask at the bottom of the branch (below all other subtasks):<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;add_subtask_bottom&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">createTask<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> gantt.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;New subtask&quot;<\/span><span class=\"sy0\">,<\/span> start_date<span class=\"sy0\">:<\/span> task.<span class=\"me1\">start_date<\/span><span class=\"sy0\">,<\/span> duration<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>To do this, you should specify the task ID as the second parameter and omit the third parameter. In the same way, tasks are added using the built-in &#8220;+&#8221; button in the grid area of the Gantt chart.<\/p>\n<ul>\n<li>Edit task<\/li>\n<\/ul>\n<p>This item opens a task\u2019s lightbox (edit form).<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;edit&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">showLightbox<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Delete task<\/li>\n<\/ul>\n<p>This item opens a confirm message box on task deletion.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;delete&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">confirm<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Delete task?&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; ok<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Yes&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; cancel<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;No&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; callback<span class=\"sy0\">:<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>result<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>result <span class=\"sy0\">&amp;&amp;<\/span> gantt.<span class=\"me1\">isTaskExists<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">deleteTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>If a user is positive on the question in the message box, the task is deleted.<\/p>\n<h6>Copy\/Paste<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-12334\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image6-1-1024x317.png\" alt=\"Context menu - Copy\/Paste\" width=\"1024\" height=\"317\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image6-1-1024x317.png 1024w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image6-1-300x93.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image6-1-768x238.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image6-1.png 1478w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><br \/>\nUsing this section of the context menu, end-users can perform cut, copy, and paste operations with tasks.<\/p>\n<ul>\n<li>Cut<\/li>\n<\/ul>\n<p>Here the task is marked for cutting so that it can later be moved to some other position. Since an end-user may decide that the task should not be copied but cut, it is necessary to check if the ID with the task is present in the <strong>tasksToCopy<\/strong> array. If the ID with the task is in there, you should remove it from the array.<\/p>\n<p>Next, you check that the task ID is not in the <strong>tasksToCut<\/strong> array to exclude duplicate IDs. If the task with the ID is not in the array, add it there. After that, you refresh the task to highlight it using styles.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;cut&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> copyIndex <span class=\"sy0\">=<\/span> tasksToCopy.<span class=\"me1\">indexOf<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">&gt;<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>copyIndex<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; tasksToCopy.<span class=\"me1\">splice<\/span><span class=\"br0\">&#40;<\/span>copyIndex<span class=\"sy0\">,<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ exclude duplicates<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>tasksToCut.<span class=\"me1\">indexOf<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">===<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; tasksToCut.<span class=\"me1\">push<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">refreshTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Copy<\/li>\n<\/ul>\n<p>Here the task is marked for copying so that it can later be added to some other position. Since an end-user may decide that the task should not be cut but copied, you need to check if the task ID is in the <strong>tasksToCut<\/strong> array. If so, you remove it from the array. Next, check that the task ID lacks in the <strong>taskToCopy<\/strong> array to exclude duplicate IDs. If the task ID is not in the array, add it there. After that, you redraw the task to highlight it using styles.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;copy&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> cutIndex <span class=\"sy0\">=<\/span> tasksToCut.<span class=\"me1\">indexOf<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">&gt;<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>cutIndex<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; tasksToCut.<span class=\"me1\">splice<\/span><span class=\"br0\">&#40;<\/span>cutIndex<span class=\"sy0\">,<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ exclude duplicates<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>tasksToCopy.<span class=\"me1\">indexOf<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">===<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; tasksToCopy.<span class=\"me1\">push<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">refreshTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Paste sibling<\/li>\n<\/ul>\n<p>Here the <strong>pasteTasks<\/strong> function is executed. It copies and moves the marked tasks below the task on which the context menu is called.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;paste_sibling&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; pasteTasks<span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">parent<\/span><span class=\"sy0\">,<\/span> gantt.<span class=\"me1\">getTaskIndex<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Paste as child<\/li>\n<\/ul>\n<p>Like in the previous option, here the <strong>pasteTasks<\/strong> function is executed. It will copy and move marked tasks inside the task on which the context menu is called.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;paste_child&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; pasteTasks<span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Cancel copy\/cut operation<\/li>\n<\/ul>\n<p>Here copying and cutting marks are removed from tasks.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;cancel_paste&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; tasksToCopy <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; tasksToCut <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">render<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<h6>Change Tree Level<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-12335\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image7-1-1024x263.png\" alt=\"context menu - change tree level item\" width=\"1024\" height=\"263\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image7-1-1024x263.png 1024w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image7-1-300x77.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image7-1-768x197.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image7-1.png 1478w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><br \/>\nThis section helps organize the hierarchical structure within the project. You can add hierarchy to the project by:<\/p>\n<ul>\n<li>choosing a task and indenting it, thereby making it a subtask, and the task above turns into a project task:<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;indent&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> prevId <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getPrevSibling<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>prevId<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> newParent <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>prevId<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">moveTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"sy0\">,<\/span> gantt.<span class=\"me1\">getChildren<\/span><span class=\"br0\">&#40;<\/span>newParent.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">length<\/span><span class=\"sy0\">,<\/span> newParent.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; newParent.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">types<\/span>.<span class=\"me1\">project<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; newParent.$open <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>newParent.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> task.<span class=\"me1\">id<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>and vice versa \u2013 outdenting a task, making it not a subtask of the previous parent task:<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;outdent&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> oldParent <span class=\"sy0\">=<\/span> task.<span class=\"me1\">parent<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">isTaskExists<\/span><span class=\"br0\">&#40;<\/span>oldParent<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">&amp;&amp;<\/span> oldParent <span class=\"sy0\">!=<\/span> gantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">root_id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">var<\/span> index <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTaskIndex<\/span><span class=\"br0\">&#40;<\/span>oldParent<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">moveTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"sy0\">,<\/span> index<span class=\"sy0\">,<\/span> gantt.<span class=\"me1\">getParent<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">parent<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>gantt.<span class=\"me1\">hasChild<\/span><span class=\"br0\">&#40;<\/span>oldParent<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>oldParent<span class=\"br0\">&#41;<\/span>.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">types<\/span>.<span class=\"me1\">task<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>oldParent<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> task.<span class=\"me1\">id<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>You can play around with this useful feature in this <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/samples\/02_extensions\/09_multiselection.html\" target=\"_blank\" rel=\"noopener\">sample<\/a>.<\/p>\n<h6>Change Task Type<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-12336\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image3-1-1024x250.png\" alt=\"context menu - change task type\" width=\"1024\" height=\"250\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image3-1-1024x250.png 1024w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image3-1-300x73.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image3-1-768x187.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image3-1.png 1477w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><br \/>\nIn this part of the context menu, you can specify a task type for the selected task.<\/p>\n<ul>\n<li>Regular task<\/li>\n<\/ul>\n<p>Here you set the &#8220;task&#8221; type. As previously, it could be a milestone with a zero duration, you should set the task duration and update the <strong>end_date<\/strong> parameter. After that update the task.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;type_task&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;task&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">duration<\/span> <span class=\"sy0\">=<\/span> task.<span class=\"me1\">duration<\/span> <span class=\"sy0\">||<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">end_date<\/span> <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">calculateEndDate<\/span><span class=\"br0\">&#40;<\/span>task<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Project task<\/li>\n<\/ul>\n<p>You set the \u201cproject\u201d type for a task and update it.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;type_project&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;project&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Milestone task<\/li>\n<\/ul>\n<p>You set the &#8220;milestone&#8221; type for a task and update it.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;type_milestone&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;milestone&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<h6>Change Visibility<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-12337\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image2-1-1024x274.png\" alt=\"context menu - change visibility item\" width=\"1024\" height=\"274\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image2-1-1024x274.png 1024w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image2-1-300x80.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image2-1-768x205.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image2-1.png 1478w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><br \/>\nThis context menu item focuses on managing the visibility of tasks and related elements and includes the following options:<\/p>\n<ul>\n<li>Rollup<\/li>\n<\/ul>\n<p>We start with the <strong>rollup<\/strong> parameter of tasks. Rolled-up elements are displayed on the project bar and offer a quick overview of the project schedule. First, change the rollup parameter so that the task is displayed on the project bar. Update the task and its parent to render the changes.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;rollup&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">rollup<\/span> <span class=\"sy0\">=<\/span> <span class=\"sy0\">!<\/span>task.<span class=\"me1\">rollup<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">parent<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Hide task bar<\/li>\n<\/ul>\n<p>For this option, you need to change the task\u2019s <strong>hide_bar<\/strong> parameter to hide the task in the timeline. Update the task to render changes.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;hide_bar&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">hide_bar<\/span> <span class=\"sy0\">=<\/span> <span class=\"sy0\">!<\/span>task.<span class=\"me1\">hide_bar<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Hide task row<\/li>\n<\/ul>\n<p>Add a task to the <strong>hiddenTasks<\/strong> object to hide the entire task row. Then update the task to render the changes. The task won&#8217;t be shown in the grid and in the timeline.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;hide_row&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; hiddenTasks<span class=\"br0\">&#91;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#93;<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<ul>\n<li>Show all hidden tasks<\/li>\n<\/ul>\n<p>Empty the <strong>hiddenTasks<\/strong> object to display all previously hidden tasks. Then, execute the render command to render the changes.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;show_hidden&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; hiddenTasks <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">render<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<h6>Mark as Complete<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-12338\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image5.gif\" alt=\"context menu - mark as complete item\" width=\"998\" height=\"483\" \/><br \/>\nWith this context menu item, end-users can show that a given task is complete.<\/p>\n<p>In code, the value of the task progress parameter should be set to 1 (i.e. 100%).<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;complete&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">progress<\/span> <span class=\"sy0\">=<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<h6>Split Task<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-12339\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2024\/05\/image8.gif\" alt=\"context menu - split task\" width=\"998\" height=\"483\" \/><br \/>\nThis feature comes in handy when you need to divide large tasks into several more manageable pieces.<\/p>\n<p>When clicking on this option, it seems that the selected task is divided into 2 parts at the click location. In fact, there are two copies of an original task, where you change their IDs and <strong>start_date<\/strong> or <strong>end_date<\/strong> parameters. The original task becomes a project shown in split mode.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;split&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">batchUpdate<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">hasChild<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">message<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;The task already has children, so, it won't be split to new sub tasks&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> leftChild <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">copy<\/span><span class=\"br0\">&#40;<\/span>task<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; leftChild.<span class=\"me1\">id<\/span> <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; leftChild.<span class=\"me1\">end_date<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> <span class=\"kw4\">Date<\/span><span class=\"br0\">&#40;<\/span>clickDate<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; leftChild.<span class=\"me1\">parent<\/span> <span class=\"sy0\">=<\/span> task.<span class=\"me1\">id<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; leftChild.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;task&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> rightChild <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">copy<\/span><span class=\"br0\">&#40;<\/span>task<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; rightChild.<span class=\"me1\">id<\/span> <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; rightChild.<span class=\"me1\">start_date<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> <span class=\"kw4\">Date<\/span><span class=\"br0\">&#40;<\/span>clickDate<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; rightChild.<span class=\"me1\">parent<\/span> <span class=\"sy0\">=<\/span> task.<span class=\"me1\">id<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; rightChild.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;task&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; task.<span class=\"me1\">render<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">'split'<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; task.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;project&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">close<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">addTask<\/span><span class=\"br0\">&#40;<\/span>leftChild<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">addTask<\/span><span class=\"br0\">&#40;<\/span>rightChild<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>If one task has already been divided into 2, then each of the parts can also be divided into 2. Under the hood, changes take place in the tree structure.<\/p>\n<p>To bring it back, it is necessary to click &#8220;Unsplit parent&#8221;. Here you need to call the unsplit function. It is invoked only in tasks with the &#8220;project&#8221; type. This option is available in the grid only, but if the task is expanded, it will no longer be displayed in the split mode, and then the option will be available in the timeline.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;unsplit&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; unsplit<span class=\"br0\">&#40;<\/span>task<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>The <strong>unsplit<\/strong> function is also used for the same purpose in the parent task.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">case<\/span> <span class=\"st0\">&quot;unsplit_parent&quot;<\/span><span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> parent <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">parent<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; unsplit<span class=\"br0\">&#40;<\/span>parent<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>This function deletes all descendants of the task, and the task itself receives the task type. The start and end dates of the task do not change, and it no longer appears in the split mode.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> unsplit<span class=\"br0\">&#40;<\/span>task<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">batchUpdate<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">eachTask<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>child<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">isTaskExists<\/span><span class=\"br0\">&#40;<\/span>child.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">deleteTask<\/span><span class=\"br0\">&#40;<\/span>child.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">delete<\/span> task.<span class=\"me1\">render<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; task.<span class=\"me1\">type<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;task&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>That&#8217;s all we have to say about context menu operations. Now we want to show you how to implement some other things such as hide tasks or mark tasks for cutting and copying<\/p>\n<p>To hide tasks, you need to use the <strong>onBeforeTaskDisplay<\/strong> event handler. If it returns <em>false<\/em>, the task will not be displayed in the Gantt chart. Check if the task ID is in the <strong>hiddenTasks<\/strong> object. If the ID is there with the <em>true<\/em> value for the task, the task will be hidden.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">let hiddenTasks <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\ngantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onBeforeTaskDisplay&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> task<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"sy0\">!<\/span>hiddenTasks<span class=\"br0\">&#91;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Now, let us proceed to the <strong>pasteTasks<\/strong> function.<\/p>\n<p>First, you iterate through the <strong>tasksToCopy<\/strong> array. In this array, you get the task object by ID, perform a deep copy of the task, change its ID, and add the task to Gantt.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">tasksToCopy.<span class=\"me1\">forEach<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> task <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> clone <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">copy<\/span><span class=\"br0\">&#40;<\/span>task<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; clone.<span class=\"me1\">id<\/span> <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">addTask<\/span><span class=\"br0\">&#40;<\/span>clone<span class=\"sy0\">,<\/span> parentId<span class=\"sy0\">,<\/span> index<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, you iterate through the <strong>TasksToCut<\/strong> array. Here you should use the <strong>moveTask()<\/strong> method to move the task to a different parent and a new position.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">tasksToCut.<span class=\"me1\">forEach<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">moveTask<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> index<span class=\"sy0\">,<\/span> parentId<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>In case the task where you copy or move the task becomes a parent, open it. Then you need to empty the <strong>tasksToCopy<\/strong> and <strong>tasksToCut<\/strong> arrays.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">gantt.<span class=\"me1\">open<\/span><span class=\"br0\">&#40;<\/span>parentId<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\ntasksToCopy <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\ntasksToCut <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>In the <strong>grid_row_class<\/strong> and <strong>task_class<\/strong> templates, you return the class name <strong>task_to_copy<\/strong> when the task ID is in the <strong>tasksToCopy<\/strong> array and return <strong>task_to_cut<\/strong> in case the task ID is presented in the <strong>tasksToCut<\/strong> array.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">gantt.<span class=\"me1\">templates<\/span>.<span class=\"me1\">grid_row_class<\/span> <span class=\"sy0\">=<\/span><br \/>\ngantt.<span class=\"me1\">templates<\/span>.<span class=\"me1\">task_class<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>start<span class=\"sy0\">,<\/span> end<span class=\"sy0\">,<\/span> task<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>tasksToCopy.<span class=\"me1\">indexOf<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">&gt;<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"st0\">&quot;task_to_copy&quot;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>tasksToCut.<span class=\"me1\">indexOf<\/span><span class=\"br0\">&#40;<\/span>task.<span class=\"me1\">id<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">&gt;<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"st0\">&quot;task_to_cut&quot;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>There are two types of styles applied for these classes:<br \/>\n1. opacity<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">.<span class=\"me1\">task_to_cut<\/span>.<span class=\"me1\">gantt_row<\/span><span class=\"sy0\">,<\/span><br \/>\n.<span class=\"me1\">task_to_cut<\/span>.<span class=\"me1\">gantt_row<\/span>.<span class=\"me1\">odd<\/span><span class=\"sy0\">,<\/span><br \/>\n.<span class=\"me1\">task_to_cut<\/span>.<span class=\"me1\">gantt_task_line<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; opacity<span class=\"sy0\">:<\/span> <span class=\"nu0\">0.5<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>2. bordering<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">.<span class=\"me1\">task_to_copy<\/span>.<span class=\"me1\">gantt_row<\/span><span class=\"sy0\">,<\/span><br \/>\n.<span class=\"me1\">task_to_copy<\/span>.<span class=\"me1\">gantt_row<\/span>.<span class=\"me1\">odd<\/span><span class=\"sy0\">,<\/span><br \/>\n.<span class=\"me1\">task_to_copy<\/span>.<span class=\"me1\">gantt_task_line<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; border<span class=\"sy0\">:<\/span> 2px dotted LightSkyBlue<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Also, disable the <strong>round_dnd_dates<\/strong> config so that tasks can be moved to any position and Gantt won&#8217;t snap them to the timeline cells.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">gantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">round_dnd_dates<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After dividing the task, its duration may become more or less than 1 day. Once the task is moved to a new position, Gantt recalculates the task duration, which will be rounded to the nearest integer number. Then Gantt recalculates the end date depending on the task duration.<\/p>\n<p>If the task duration becomes 0, the task will shrink and it will be inconvenient to drag it. So it is necessary to modify the duration parameter to be greater than 0.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">gantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onTaskDrag&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> mode<span class=\"sy0\">,<\/span> task<span class=\"sy0\">,<\/span> original<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; task.<span class=\"me1\">duration<\/span> <span class=\"sy0\">=<\/span> task.<span class=\"me1\">duration<\/span> <span class=\"sy0\">||<\/span> <span class=\"nu0\">1<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>In fact, it is possible to calculate the task duration in other units and show this parameter differently (e.g. in fractional units). But we don\u2019t want to make things more complicated in this tutorial so we won\u2019t consider this scenario. But you can see how it works in this <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/samples\/?sample='09_worktime\/09_decimal_durations.html'&amp;filter='decimal\" target=\"_blank\" rel=\"noopener\">sample<\/a>.<\/p>\n<p>These are the main points that you should know to add a custom context menu to your Gantt project like in our <a href=\"https:\/\/snippet.dhtmlx.com\/ateynir5?mode=wide\" target=\"_blank\" rel=\"noopener\">sample<\/a>.<\/p>\n<h5>Conclusion<\/h5>\n<p>As you can see, the use of a context menu can significantly enhance the functionality and user experience of a Gantt app. If you decide to go with DHTMLX Gantt for your project management app, you don\u2019t need any third-party tools to implement a custom context menu. The Menu widget from the Suite library is an ideal tool for this purpose. You can test the functional capabilities of both products free of charge by downloading <a href=\"https:\/\/dhtmlx.com\/docs\/download\/\" target=\"_blank\" rel=\"noopener\">30-day trial versions<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It is time to remind you that DHTMLX Gantt is a highly customizable tool that can be complemented with additional functionalities required for your project management app. Today, you &#8230;<\/p>\n","protected":false},"author":101014,"featured_media":12342,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71],"tags":[33,20,10],"class_list":["post-12329","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-all-posts","tag-gantt","tag-dhtmlxsuite"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/12329","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/101014"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=12329"}],"version-history":[{"count":16,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/12329\/revisions"}],"predecessor-version":[{"id":12536,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/12329\/revisions\/12536"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/12342"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=12329"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=12329"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=12329"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}