Перетаскивание задач в временной шкале

Перетаскивание задач в временной шкале упрощает корректировку их начальных и конечных дат, а также продолжительности. По умолчанию перетаскивание включено, что позволяет перемещать задачи вдоль их строк.

Для настройки работы перетаскивания вы можете использовать следующие события:

  • onBeforeTaskDrag: Ограничение перетаскивания для определенных задач.
  • onTaskDrag: Управление границами перетаскивания или добавление пользовательской логики при перетаскивании.
  • onAfterTaskDrag: Применение изменений после перемещения задачи.

Вот несколько распространенных сценариев, когда поведение перетаскивания по умолчанию может потребовать корректировки:

  1. Ограничение перетаскивания для определенных задач.
  2. Предотвращение перетаскивания задач за пределы определенных дат.
  3. Перетаскивание дочерних задач вместе с родительской.
  4. Перетаскивание проектов вместе с подзадачами.
  5. Установка минимальной продолжительности задачи.
  6. Включение автопрокрутки при перетаскивании задач.

Ограничение перетаскивания для определенных задач

Чтобы остановить перетаскивание определенных задач, можно использовать событие onBeforeTaskDrag:

gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){
    if(gantt.getGlobalTaskIndex(id) % 2 == 0){
        return false;      // Запретить перетаскивание, если индекс задачи четный
    }
    return true;           // Разрешить перетаскивание, если индекс задачи нечетный
});

Предотвращение перетаскивания задач за пределы определенных дат

Вы можете использовать событие onTaskDrag, чтобы убедиться, что задачи остаются в пределах заданного диапазона дат.

Событие onTaskDrag:

  • Срабатывает всякий раз, когда задача перемещается, изменяется ее размер или прогресс во временной шкале.
  • Второй аргумент, mode, указывает тип действия перетаскивания.
  • Доступные режимы перетаскивания перечислены в свойстве **drag_mode**.

Кратко, как это работает:

  1. Пользователь перетаскивает задачу.
  2. dhtmlxGantt пересчитывает новую дату задачи на основе ее позиции.
  3. Событие **onTaskDrag** срабатывает.
  4. Задача перерисовывается в диаграмме Ганта.

    Поскольку это событие срабатывает после пересчетов, вы можете указать в обработчике события пользовательские значения для задачи, не опасаясь, что они будут перезаписаны. Задача будет отображаться в скорректированной позиции.


Например, чтобы ограничить перетаскивание задач за пределы диапазона дат "31 марта, 2020 - 11 апреля, 2020", вы можете использовать следующий код:

Запрет перетаскивания задач за пределы интервала - [31.03.2020, 11.04.2020]

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){
            task.end_date = new Date(rightLimit);
            if(mode == modes.move)
                task.start_date = new Date(task.end_date - diff);
            }
        if(+task.start_date < +leftLimit){
            task.start_date = new Date(leftLimit);
            if(mode == modes.move)
                task.end_date = new Date(+task.start_date + diff);
        }
    }
});

Related sample:  Drag parent task with its children


Перетаскивание дочерних задач вместе с родительской

Чтобы перемещать дочерние задачи при перетаскивании родительской, используйте событие onTaskDrag (подробности выше):

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.refreshTask(child.id, true);
        }, id);
    }
});
 
// Выравнивание дочерних задач по шкале после перетаскивания
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){          
            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);
    }
});

Перетаскивание проектов вместе с подзадачами

Эта функция доступна только в Gantt PRO edition.

По умолчанию задачи типа проект не могут быть перетащены. Чтобы включить это, установите опцию drag_project в true:

gantt.config.drag_project = true;

Related sample:  Draggable projects


Перетаскивание зависимых задач вместе с независимыми задачами

Для получения подробной информации о перемещении задач вместе с их зависимостями обратитесь к специальной статье: Перетаскивание задач вместе с их зависимыми задачами.


Установка минимальной продолжительности задачи

Вы можете определить минимальную продолжительность задачи при изменении ее размера, используя настройку min_duration. Это помогает избежать задач с нулевой продолжительностью.

Укажите значение в миллисекундах:

// Минимальная продолжительность установлена на 1 день
gantt.config.min_duration = 24 * 60 * 60 * 1000;
 
// ИЛИ
 
// Минимальная продолжительность установлена на 1 час
gantt.config.min_duration = 60 * 60 * 1000;

Автопрокрутка при перетаскивании задач

При работе с большими наборами данных перетаскивание задач на дальние позиции или связывание задач, находящихся далеко друг от друга, может быть сложным. Функция автопрокрутки упрощает этот процесс. Она включена по умолчанию, но вы можете управлять ею с помощью настройки autoscroll:

gantt.config.autoscroll = false;
gantt.init("gantt_here");

Вы также можете настроить скорость прокрутки в миллисекундах с помощью свойства autoscroll_speed:

gantt.config.autoscroll = true;
gantt.config.autoscroll_speed = 50;
 
gantt.init("gantt_here");

Отключение изменения размера для определенных задач

Чтобы предотвратить изменение размера определенных задач, у вас есть два варианта:

  1. Скрыть ручки изменения размера через CSS. Используйте шаблон task_class, чтобы присвоить CSS класс задачам, которые вы хотите изменить:
gantt.templates.task_class = function(start, end, task){
    if(task.no_resize) { // 'no_resize' - это пользовательское свойство
        return "no_resize";
    }
    return "";
};

Затем скройте ручки изменения размера с помощью CSS:

.no_resize .gantt_task_drag {
   display: none !important;
}
  1. Программно предотвратить изменение размера с использованием события onBeforeTaskDrag. Верните false, чтобы заблокировать изменение размера:
gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){
    if(mode === "resize" && gantt.getTask(id).no_resize){
        return false;
    }
    return true;
});

Определение, какая сторона задачи изменяется

Режим "resize" перетаскивания позволяет изменять либо начальную, либо конечную дату задачи. Чтобы определить, какая сторона изменяется, используйте флаг gantt.getState().drag_from_start:

gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){
    if(mode === "resize"){
        if(gantt.getState().drag_from_start === true) {
            // Изменяется начальная дата
        } else {
            // Изменяется конечная дата
        }
    }
    return true;
});

Отключение изменения размера для начальных или конечных дат

Чтобы отключить изменение размера для определенных дат, найдите ручки изменения размера, используя следующие селекторы:

  • .gantt_task_drag[data-bind-property="start_date"]
  • .gantt_task_drag[data-bind-property="end_date"]

Например, чтобы отключить изменение размера начальных дат:

.gantt_task_drag[data-bind-property="start_date"] {
   display: none !important;
}

Чтобы отключить изменение размера конечных дат:

.gantt_task_drag[data-bind-property="end_date"] {
   display: none !important;
}

Кроме того, используйте событие onBeforeTaskDrag, чтобы программно заблокировать изменение размера:

gantt.attachEvent("onBeforeTaskDrag", function(id, mode, e){
    if(mode === "resize"){
        if(gantt.getState().drag_from_start === true) {
             return false; // Заблокировать изменение начальной даты
        } else {
             // Разрешить изменение конечной даты
        }
    }
    return true;
});
К началу