diff --git a/docs/guides/dnd.md b/docs/guides/dnd.md index c06bec7e..9b15666a 100644 --- a/docs/guides/dnd.md +++ b/docs/guides/dnd.md @@ -5,20 +5,17 @@ sidebar_label: "Dragging Tasks within the Timeline" # Dragging Tasks within the Timeline -Dragging allows users to quickly change the start (end) dates of the tasks, their duration. - - +Dragging allows users to quickly change the start (end) dates of the tasks, their duration. By default, the drag-and-drop is enabled and the user can drag a task along its row in the timeline. To customize the drag-and-drop behavior, use the following events: - [onBeforeTaskDrag](api/event/onbeforetaskdrag.md) - to deny dragging of specific tasks -- [onTaskDrag](api/event/ontaskdrag.md) - to limit the area for dragging or to provide some other logic when the user drags a task +- [onTaskDrag](api/event/ontaskdrag.md) - to limit the area for dragging or to provide some other logic when the user drags a task - [onAfterTaskDrag](api/event/onaftertaskdrag.md) - to postprocess tasks after they have been dragged to a new place Let's consider typical cases when the default drag behavior needs customization: - 1. [Denying dragging specific tasks](#denying-dragging-of-specific-tasks). 2. [Denying dragging tasks out of specific dates](#denying-dragging-tasks-out-of-specific-dates). 3. [Dragging children together with the parent](#dragging-children-together-with-the-parent). @@ -26,30 +23,28 @@ Let's consider typical cases when the default drag behavior needs customization: 5. [Setting minimal task duration](#setting-minimal-task-duration). 6. [Autoscroll during tasks' dragging](#autoscrollduringtasksdragging). - ## Denying dragging of specific tasks To deny dragging of specific tasks, use the [onBeforeTaskDrag](api/event/onbeforetaskdrag.md) event: ~~~js -gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){ - if(gantt.getGlobalTaskIndex(id)%2==0){ - return false; //denies dragging if the global task index is odd +gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => { + if (gantt.getGlobalTaskIndex(taskId) % 2 === 0) { + return false; // denies dragging if the global task index is even } - return true; //allows dragging if the global task index is even + return true; // allows dragging if the global task index is odd }); ~~~ - ## Denying dragging tasks out of specific dates -To deny dragging tasks out of specific dates, use the [onTaskDrag](api/event/ontaskdrag.md) event. +To deny dragging tasks out of specific dates, use the [onTaskDrag](api/event/ontaskdrag.md) event.

The onTaskDrag event:

@@ -59,79 +54,87 @@ To deny dragging tasks out of specific dates, use the [onTaskDrag](api/event/ont
  • The user makes a move.
  • dhtmlxGantt recalculates the task's date according to the new position.
  • dhtmlxGantt fires the [onTaskDrag](api/event/ontaskdrag.md) event.
  • -
  • dhtmlxGantt re-renders the task in the Gantt chart.
    As the [](api/event/ontaskdrag.md) event fires after dhtmlxGantt makes recalculation, +
  • dhtmlxGantt re-renders the task in the Gantt chart.
    As the [onTaskDrag](api/event/ontaskdrag.md) event fires after dhtmlxGantt makes recalculation, you can specify any custom values for the dragged task in the event's handler, without being afraid that these values will be overwritten. As a result, the task will be rendered in the desired position.
  • -Let's assume that you want to forbid users to drag tasks out of the **"31 March, 2020 - 11 April, 2020"** interval. +Let's assume that you want to forbid users to drag tasks out of the **"31 March, 2028 - 11 April, 2028"** interval. ![custom_dnd](/img/custom_dnd.png) Then, you can use the code as in: -[Denying dragging tasks out of interval - [31.03.2020, 11.04.2020]](Denying dragging tasks out of interval - [31.03.2020, 11.04.2020]) ~~~js -var leftLimit = new Date(2020, 2 ,31), rightLimit = new Date(2020, 3 ,12); - -gantt.attachEvent("onTaskDrag", function(id, mode, task, original){ - var modes = gantt.config.drag_mode; - if(mode == modes.move || mode == modes.resize){ - - var diff = original.duration*(1000*60*60*24); - - if(+task.end_date > +rightLimit){ +const leftLimit = new Date(2028, 2, 31); +const rightLimit = new Date(2028, 3, 12); +const millisecondsInDay = 24 * 60 * 60 * 1000; + +gantt.attachEvent("onTaskDrag", (taskId, dragMode, task, originalTask) => { + const dragModes = gantt.config.drag_mode; + + if (dragMode === dragModes.move || dragMode === dragModes.resize) { + const taskDuration = originalTask.duration * millisecondsInDay; + + if (+task.end_date > +rightLimit) { task.end_date = new Date(rightLimit); - if(mode == modes.move) - task.start_date = new Date(task.end_date - diff); + if (dragMode === dragModes.move) { + task.start_date = new Date(task.end_date - taskDuration); } - if(+task.start_date < +leftLimit){ + } + + if (+task.start_date < +leftLimit) { task.start_date = new Date(leftLimit); - if(mode == modes.move) - task.end_date = new Date(+task.start_date + diff); + if (dragMode === dragModes.move) { + task.end_date = new Date(+task.start_date + taskDuration); + } } } }); ~~~ - -[Drag parent task with its children](https://docs.dhtmlx.com/gantt/samples/08_api/05_limit_drag_dates.html) - - ## Dragging children together with the parent To allow dragging children when the user is dragging their parent's task, use the [onTaskDrag](api/event/ontaskdrag.md) event (see more on the event [above](guides/dnd.md#denying-dragging-tasks-out-of-specific-dates)): ~~~js -gantt.attachEvent("onTaskDrag", function(id, mode, task, original){ - var modes = gantt.config.drag_mode; - if(mode == modes.move){ - var diff = task.start_date - original.start_date; - gantt.eachTask(function(child){ - child.start_date = new Date(+child.start_date + diff); - child.end_date = new Date(+child.end_date + diff); +gantt.attachEvent("onTaskDrag", (taskId, dragMode, task, originalTask) => { + const dragModes = gantt.config.drag_mode; + + if (dragMode === dragModes.move) { + const dateShift = task.start_date - originalTask.start_date; + gantt.eachTask((child) => { + child.start_date = new Date(+child.start_date + dateShift); + child.end_date = new Date(+child.end_date + dateShift); gantt.refreshTask(child.id, true); - },id ); + }, taskId); } }); -//rounds positions of the child items to scale -gantt.attachEvent("onAfterTaskDrag", function(id, mode, e){ - var modes = gantt.config.drag_mode; - if(mode == modes.move ){ - var state = gantt.getState(); - gantt.eachTask(function(child){ + +// rounds positions of the child items to scale +gantt.attachEvent("onAfterTaskDrag", (taskId, dragMode, event) => { + const dragModes = gantt.config.drag_mode; + + if (dragMode === dragModes.move) { + const ganttState = gantt.getState(); + gantt.eachTask((child) => { child.start_date = gantt.roundDate({ - date:child.start_date, - unit:state.scale_unit, - step:state.scale_step - }); - child.end_date = gantt.calculateEndDate(child.start_date, - child.duration, gantt.config.duration_unit); - gantt.updateTask(child.id); - },id ); + date: child.start_date, + unit: ganttState.scale_unit, + step: ganttState.scale_step + }); + child.end_date = gantt.calculateEndDate( + child.start_date, + child.duration, + gantt.config.duration_unit + ); + gantt.updateTask(child.id); + }, taskId); } }); ~~~ +**Related sample**: [Drag parent task with its children](https://docs.dhtmlx.com/gantt/samples/08_api/05_limit_drag_dates.html) + ## Dragging projects with subtasks {#draggingprojectswithsubtasks} :::info @@ -145,16 +148,13 @@ You can enable drag and drop of projects using the [drag_project](api/config/dra gantt.config.drag_project = true; ~~~ - -[Draggable projects](https://docs.dhtmlx.com/gantt/samples/08_api/19_draggable_projects.html) - +**Related sample**: [Draggable projects](https://docs.dhtmlx.com/gantt/samples/08_api/19_draggable_projects.html) ## Dragging dependent tasks together with independent tasks There are several ways of implementing tasks moving with their dependent tasks. You can read about all of them in a separate article [Dragging Tasks Together with Their Dependent Tasks](guides/dragging-dependent-tasks.md). - ## Setting minimal task duration Minimal task duration can be specified via the [min_duration](api/config/min_duration.md) setting. @@ -164,19 +164,19 @@ The option defines the minimum size of the task that can be set during resizing The value is set in milliseconds: ~~~js // 1 day -gantt.config.min_duration = 24*60*60*1000; +gantt.config.min_duration = 24 * 60 * 60 * 1000; -//OR +// OR // 1 hour -gantt.config.min_duration = 60*60*1000; +gantt.config.min_duration = 60 * 60 * 1000; ~~~ ## Autoscroll during tasks' dragging {#autoscrollduringtasksdragging} If you have a large dataset in the Gantt chart, you often need to drag a task to a new distant position or set links between tasks located at a significant distance. -In this case the **autoscroll** functionality is of great help. It is enabled by default, but you can manage this behavior via +In this case the **autoscroll** functionality is of great help. It is enabled by default, but you can manage this behavior via the [autoscroll](api/config/autoscroll.md) configuration option. ~~~js @@ -189,7 +189,7 @@ Besides, you can adjust the speed of autoscrolling in milliseconds with the help ~~~js gantt.config.autoscroll = true; gantt.config.autoscroll_speed = 50; - + gantt.init("gantt_here"); ~~~ @@ -201,18 +201,19 @@ If you want to prevent certain tasks from being resized, there are two things yo In order to do this, you need to use the **task_class** template to add an extra CSS class to the required items so that you could locate them via the selector: ~~~js -gantt.templates.task_class = function(start, end, task){ - if(task.no_resize) { // no_resize is a custom property used for the demonstration +gantt.templates.task_class = (startDate, endDate, task) => { + if (task.no_resize) { // no_resize is a custom property used for the demonstration return "no_resize"; } return ""; +}; ~~~ Then, you can hide the resize handles using the following CSS: ~~~css -.no_resize .gantt_task_drag{ - display: none !important; +.no_resize .gantt_task_drag { + display: none !important; } ~~~ @@ -220,8 +221,8 @@ Then, you can hide the resize handles using the following CSS: Returning *false* from the handler will prevent resizing: ~~~js -gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){ - if(mode === "resize" && gantt.getTask(id).no_resize){ +gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => { + if (dragMode === "resize" && gantt.getTask(taskId).no_resize) { return false; } return true; @@ -235,9 +236,9 @@ The ["resize"](api/event/onbeforetaskdrag.md) mode of drag and drop means that t If you need to find out which date the user is modifying by the resize, you can use the **gantt.getState().drag_from_start** flag: ~~~js -gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){ - if(mode === "resize"){ - if(gantt.getState().drag_from_start === true) { +gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => { + if (dragMode === "resize") { + if (gantt.getState().drag_from_start === true) { // changing the start date of a task } else { // changing the end date of a task @@ -251,22 +252,22 @@ gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){ You can locate resize handles using the following selectors: -- .gantt_task_drag[data-bind-property="start_date"] -- .gantt_task_drag[data-bind-property="end_date"] +- `.gantt_task_drag[data-bind-property="start_date"]` +- `.gantt_task_drag[data-bind-property="end_date"]` The following CSS can be used for disabling resizing of start dates of tasks: ~~~css -.gantt_task_drag[data-bind-property="start_date"]{ - display: none !important; +.gantt_task_drag[data-bind-property="start_date"] { + display: none !important; } ~~~ Similarly, preventing resizing of the end dates looks like this: ~~~css -.gantt_task_drag[data-bind-property="end_date"]{ - display: none !important; +.gantt_task_drag[data-bind-property="end_date"] { + display: none !important; } ~~~ @@ -274,16 +275,14 @@ Another way to do this is use the [onBeforeTaskDrag](api/event/onbeforetaskdrag. Returning *false* from the handler will prevent resizing: ~~~js -gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){ - if(mode === "resize"){ - if(gantt.getState().drag_from_start === true) { - return false; +gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => { + if (dragMode === "resize") { + if (gantt.getState().drag_from_start === true) { + return false; } else { - // changing the end date of a task + // changing the end date of a task } } return true; }); ~~~ - - diff --git a/static/img/custom_dnd.png b/static/img/custom_dnd.png index 5c0c3b21..ed72db9f 100644 Binary files a/static/img/custom_dnd.png and b/static/img/custom_dnd.png differ