Explore
Gantt chart task links with SVG right-angled or curved shapes. Adjust the line width, arrow size and hover target width, then hover over or right-click a link.
Link shape:
Right-angled
Curved
Link width:
Auto
1 px
2 px
4 px
Arrow size:
Auto
5 px
8 px
12 px
Hover target width:
3 px
8 px
16 px
Agent-readable demo data
Title Task Links (JavaScript Gantt Chart) | DayPilot Pro for JavaScript Demo
Tree DayPilot JavaScript Demo
Catalog root Default
Description Explore Gantt chart task links with SVG right-angled or curved shapes. Adjust the line width, arrow size and hover target width, then hover over or right-click a link.
Inline demo script 1
const dp = new DayPilot.Gantt("dp", {
linkShape: "RightAngled",
linkWidth: "Auto",
linkArrowSize: "Auto",
linkHitAreaMinWidth: 8,
days: 30,
columns: [
{
title: "Name",
width: 50,
property: "text"
},
{
title: "Info",
width: 50,
property: "info"
},
{
title: "Duration",
width: 50
}
],
onBeforeRowHeaderRender: function (args) {
const duration = args.task.duration();
const html = duration.toString("d") + "d " + duration.toString("h") + "h";
args.row.columns[2].html = html;
},
contextMenuLink: new DayPilot.Menu({
items: [
{
text: "Show link ID",
onClick: function (args) {
DayPilot.Modal.alert("Link ID: " + args.source.data.id);
}
},
{
text: "Delete link",
onClick: function (args) {
dp.links.remove(args.source);
}
}
]
}),
contextMenuTask: new DayPilot.Menu({
items: [
{
text: "Show task ID",
onClick: function (args) {
DayPilot.Modal.alert("Task ID: " + args.source.id());
}
},
{
text: "Delete task",
onClick: function (args) {
dp.tasks.remove(args.source);
}
}
]
}),
contextMenuRow: new DayPilot.Menu({
items: [
{
text: "Show task ID",
onClick: function (args) {
DayPilot.Modal.alert("Task ID: " + args.source.id());
}
},
{
text: "Delete task",
onClick: function (args) {
dp.tasks.remove(args.source);
}
}
]
})
});
dp.init();
const app = {
init() {
this.loadData();
this.addEventHandlers();
},
loadData() {
const tasks = [];
const links = [];
const colors = ["blue", "red", "green", "black"];
const styles = ["solid", "dotted", "dashed", "double"];
let start = new DayPilot.Date().getDatePart();
let last = null;
for (let i = 0; i < 5; i++) {
const duration = Math.floor(Math.random() * 3) + 1; // 1 to 3
const end = start.addDays(duration);
const task = {
start: start,
end: end,
id: DayPilot.guid(),
text: "Task " + i,
box: {
linkCreateDisabled: true
},
tags: {
info: "info text"
},
children: [
{
start: start,
end: end,
id: DayPilot.guid(),
text: "Subtask 1",
complete: Math.floor(Math.random() * 101) // 0 to 100
},
{
start: start,
end: end,
id: DayPilot.guid(),
text: "Subtask 2",
complete: Math.floor(Math.random() * 101) // 0 to 100
},
{
start: end,
id: DayPilot.guid(),
text: "Milestone 1",
type: "Milestone"
}
]
};
tasks.push(task);
if (last) {
links.push({
id: DayPilot.guid(), // optional
from: last,
to: task.id,
color: colors[i - 1],
style: styles[i - 1],
type: "FinishToStart"
});
}
last = task.id;
start = end;
}
dp.update({tasks, links});
},
addEventHandlers() {
document.getElementById("linkShape").addEventListener("change", (ev) => {
dp.update({linkShape: ev.target.value});
});
for (const property of ["linkWidth", "linkArrowSize", "linkHitAreaMinWidth"]) {
document.getElementById(property).addEventListener("change", (ev) => {
const value = ev.target.value;
dp.update({[property]: value === "Auto" ? "Auto" : Number(value)});
});
}
}
};
app.init();