Hier ist ein Überblick über verschiedene Möglichkeiten, Aufgaben zusammen mit ihren abhängigen Aufgaben zu verschieben.
Eine Option ist die Verwendung der Erweiterung Automatische Planung. Diese Funktion plant Aufgaben automatisch basierend auf ihren Beziehungen.
Um die automatische Planung zu aktivieren, aktivieren Sie sie mit der Methode gantt.plugins:
gantt.plugins({
auto_scheduling: true
});
Setzen Sie dann die auto_scheduling Eigenschaft auf true
:
gantt.config.auto_scheduling = true;
Beim manuellen Ziehen von abhängigen Aufgaben ist der allgemeine Ansatz:
Sie können zwischen zwei Methoden wählen:
In jedem Fall besteht der erste Schritt darin, alle verknüpften Aufgaben abzurufen.
Um Aufgaben zu identifizieren, die verknüpft sind, verwenden Sie die Eigenschaften $source und $target in einem Aufgabenobjekt. Diese Eigenschaften werden automatisch generiert und enthalten die IDs der zugehörigen Verknüpfungen:
$source
- Verknüpfungen, die von der Aufgabe ausgehen.$target
- Verknüpfungen, die in die Aufgabe hineinkommen.var taskObj = gantt.getTask("t1");
var sourceLinks = taskObj.$source; //-> ["l1","l4"] - IDs der ausgehenden Verknüpfungen
var targetLinks = taskObj.$target; //-> ["l5","l8"] - IDs der eingehenden Verknüpfungen
Sobald Sie die Verknüpfungen haben, können Sie die abhängigen Aufgaben identifizieren.
Um durch die verknüpften Aufgaben zu iterieren, können Sie den folgenden Iterator verwenden:
gantt.eachSuccessor = function(callback, root){
if(!this.isTaskExists(root))
return;
// Unendliche Schleifen vermeiden, indem besuchte Aufgaben nachverfolgt werden
var traversedTasks = arguments[2] || {};
if(traversedTasks[root])
return;
traversedTasks[root] = true;
var rootTask = this.getTask(root);
var links = rootTask.$source;
if(links){
for(var i=0; i < links.length; i++){
var link = this.getLink(links[i]);
if(this.isTaskExists(link.target) && !traversedTasks[link.target]){
callback.call(this, this.getTask(link.target));
// Den gesamten Zweig durchlaufen, nicht nur erststufige Abhängigkeiten
this.eachSuccessor(callback, link.target, traversedTasks);
}
}
}
};
Abhängige Aufgaben können gleichzeitig mit der Hauptaufgabe verschoben werden, während sie gezogen wird. Dies erzeugt einen flüssigen visuellen Effekt, kann jedoch die Leistung beeinträchtigen, wenn viele Aufgaben gleichzeitig verschoben werden.
Beginnen Sie mit der Einrichtung des Iterators, wie oben gezeigt above.
Befestigen Sie als Nächstes einen Handler an das Ereignis onTaskDrag. Dieser Handler wird während jedes Drag-and-Drop-Frames ausgeführt und passt die Positionen der verknüpften Aufgaben an.
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.eachSuccessor(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 );
}
return true;
});
Schließlich, wenn das Drag-and-Drop abgeschlossen ist, runden Sie die Positionen der abhängigen Aufgaben auf die Skala. Dies kann mit dem Ereignis onAfterTaskDrag erfolgen:
gantt.attachEvent("onAfterTaskDrag", function(id, mode, e){
var modes = gantt.config.drag_mode;
if(mode == modes.move ){
gantt.eachSuccessor(function(child){
child.start_date = gantt.roundDate(child.start_date);
child.end_date = gantt.calculateEndDate(child.start_date, child.duration);
gantt.updateTask(child.id);
},id );
}
});
Diese Methode funktioniert gut, es sei denn, es gibt zu viele verknüpfte Aufgaben.
Eine andere Möglichkeit besteht darin, abhängige Aufgaben erst nach der Verschiebung der Hauptaufgabe anzupassen. Dieser Ansatz vereinfacht den Prozess und verbessert die Leistung.
So kann es gemacht werden:
Beginnen Sie mit der Einrichtung des Iterators, wie oben gezeigt above.
Sobald die Drag-and-Drop-Aktion abgeschlossen ist, verwenden Sie das Ereignis onBeforeTaskChanged, um den Unterschied in den Daten zwischen den ursprünglichen und geänderten Aufgabeninstanzen zu erfassen.
Beachten Sie, dass Drag-and-Drop zu diesem Zeitpunkt noch abgebrochen werden kann, da onBeforeTaskChanged
eine Stornierung ermöglicht. Vermeiden Sie es, zu diesem Zeitpunkt abhängige Aufgaben zu ändern.
Speichern Sie stattdessen den berechneten Unterschied in einer Variablen zur späteren Verwendung.
var diff = 0;
gantt.attachEvent("onBeforeTaskChanged", function(id, mode, originalTask){
var modes = gantt.config.drag_mode;
if(mode == modes.move ){
var modifiedTask = gantt.getTask(id);
diff = modifiedTask.start_date - originalTask.start_date;
}
return true;
});
Verwenden Sie schließlich das Ereignis onAfterTaskDrag, um den berechneten Unterschied auf alle abhängigen Aufgaben anzuwenden, sobald das Drag-and-Drop bestätigt ist:
// Positionen der untergeordneten Elemente auf die Skala runden
gantt.attachEvent("onAfterTaskDrag", function(id, mode, e){
var modes = gantt.config.drag_mode;
if(mode == modes.move ){
gantt.eachSuccessor(function(child){
child.start_date = gantt.roundDate(new Date(child.start_date.valueOf() + diff));
child.end_date = gantt.calculateEndDate(child.start_date, child.duration);
gantt.updateTask(child.id);
},id );
}
});
Hier ist der vollständige Code für diesen Ansatz:
(function(){
var diff = 0;
gantt.attachEvent("onBeforeTaskChanged", function(id, mode, originalTask){
var modes = gantt.config.drag_mode;
if(mode == modes.move ){
var modifiedTask = gantt.getTask(id);
diff = modifiedTask.start_date - originalTask.start_date;
}
return true;
});
// Positionen der untergeordneten Elemente auf die Skala runden
gantt.attachEvent("onAfterTaskDrag", function(id, mode, e){
var modes = gantt.config.drag_mode;
if(mode == modes.move ){
gantt.eachSuccessor(function(child){
child.start_date = gantt.roundDate(new Date(child.start_date.valueOf() + diff));
child.end_date = gantt.calculateEndDate(child.start_date, child.duration);
gantt.updateTask(child.id);
},id );
}
});
})();
Zurück nach oben