Agent-readable demo data
- Title
- Link Creation and Editing (JavaScript Scheduler) | DayPilot Pro for JavaScript Demo
- Tree
- DayPilot JavaScript Demo
- Catalog root
- Default
- Description
- Create links by dragging between event handles.
Click a link to edit its color and text, or right-click for Edit and Delete.
Inline demo script 1
/* global DayPilot */
/* eslint-disable no-use-before-define -- Callbacks run after app initialization. */
const dp = new DayPilot.Scheduler("dp", {
startDate: "2027-04-01",
days: 18,
scale: "Day",
timeHeaders: [
{groupBy: "Month", format: "MMMM yyyy"},
{groupBy: "Day", format: "d"}
],
cellWidthSpec: "Auto",
cellWidthMin: 45,
rowHeaderWidth: 150,
eventHeight: 40,
heightSpec: "Max",
height: 400,
resources: [
{id: "design", name: "Design"},
{id: "build", name: "Development"},
{id: "test", name: "Quality assurance"},
{id: "ops", name: "Operations"},
{id: "release", name: "Release"}
],
timeRangeSelectedHandling: "Disabled",
linkCreateHandling: "Update",
linkBubble: new DayPilot.Bubble({
onLoad: args => {
const data = args.source.data;
args.html = app.escapeHtml(app.linkTitle(data));
if (data.text) {
args.html += "<br>" + app.escapeHtml(data.text);
}
}
}),
contextMenuLink: new DayPilot.Menu({
items: [
{text: "Edit…", onClick: args => app.editLink(args.source.data)},
{text: "Delete", onClick: args => app.deleteLink(args.source)}
]
}),
onLinkClick: args => app.editLink(args.link.data),
onLinkCreate: async args => {
args.preventDefault();
const duplicate = dp.links.list.some(link => link.from === args.from && link.to === args.to && link.type === args.type);
if (args.from === args.to || duplicate) {
dp.message("This dependency already exists. Choose another connection.");
return;
}
await app.editLink({
id: DayPilot.guid(),
from: args.from,
to: args.to,
type: args.type,
color: "#3c78d8",
text: ""
}, true);
}
});
/* eslint-enable no-use-before-define */
dp.init();
const app = {
init() {
this.loadData();
this.addEventHandlers();
},
addEventHandlers() {
document.querySelector("#reset").addEventListener("click", () => this.loadData());
},
linkTitle(link) {
return dp.events.find(link.from).text() + " → " + dp.events.find(link.to).text();
},
escapeHtml(value) {
const element = document.createElement("div");
element.textContent = value;
return element.innerHTML;
},
deleteLink(link) {
dp.links.remove(link);
dp.message("Link deleted");
},
async editLink(data, create = false) {
const form = [
{name: this.linkTitle(data), type: "title"},
{name: "Color", id: "color", type: "select", options: [
{id: "#3c78d8", name: "Blue"},
{id: "#6aa84f", name: "Green"},
{id: "#c98512", name: "Orange"},
{id: "#8e63b5", name: "Purple"},
{id: "#606060", name: "Gray"}
]},
{name: "Text", id: "text"}
];
if (data.type !== "FinishToStart") {
form.push({type: "html", html: "Text appears in the hover bubble. On-path labels are available for finish-to-start links."});
}
const modal = await DayPilot.Modal.form(form, {
color: data.color || "#3c78d8",
text: data.text || ""
}, {
width: 480,
okText: create ? "Create link" : "Save"
});
if (modal.canceled) {
return;
}
const updated = {...data, color: modal.result.color, text: modal.result.text.trim()};
if (create) {
dp.links.add(updated);
} else if (dp.links.find(data.id)) {
dp.links.update(updated);
}
},
loadData() {
const events = [
{id: "design", resource: "design", text: "Design", start: "2027-04-02", end: "2027-04-05"},
{id: "docs", resource: "design", text: "Documentation", start: "2027-04-12", end: "2027-04-16"},
{id: "build", resource: "build", text: "Build", start: "2027-04-06", end: "2027-04-10"},
{id: "integration", resource: "build", text: "Integration", start: "2027-04-11", end: "2027-04-14"},
{id: "test", resource: "test", text: "Test", start: "2027-04-11", end: "2027-04-15"},
{id: "prepare", resource: "ops", text: "Prepare release", start: "2027-04-09", end: "2027-04-12"},
{id: "deploy", resource: "release", text: "Deploy", start: "2027-04-16", end: "2027-04-18"}
];
const links = [
{id: "design-build", from: "design", to: "build", type: "FinishToStart", color: "#3c78d8", text: "Ready"},
{id: "build-test", from: "build", to: "test", type: "FinishToStart", color: "#6aa84f"},
{id: "build-integration", from: "build", to: "integration", type: "FinishToStart", color: "#606060"},
{id: "docs-deploy", from: "docs", to: "deploy", type: "FinishToStart", color: "#c98512"},
{id: "test-deploy", from: "test", to: "deploy", type: "FinishToStart", color: "#3c78d8"},
{id: "prepare-deploy", from: "prepare", to: "deploy", type: "FinishToStart", color: "#8e63b5"}
];
dp.update({events, links});
}
};
app.init();