# Event Links (JavaScript Scheduler) | DayPilot Pro for JavaScript Demo

> You can use links between Scheduler events to show dependencies. Links can be loaded from an API endpoint or created dynamically using drag and drop. Read more about the [event links](https://doc.daypilot.org/scheduler/event-links/).

## Links

- Canonical HTML: /demo/scheduler/eventlinks.html
- Source HTML folder: /demo/scheduler/
- Catalog root: /demo/
- Catalog: /demo/llms.txt

## Source

### Inline demo script 1

```javascript
const dp = new DayPilot.Scheduler("dp", {
            startDate: "2026-01-01",
            days: 365,
            scale: "Day",
            timeHeaders: [
                {groupBy: "Month", format: "MMMM yyyy"},
                {groupBy: "Cell", format: "d"}
            ],
            eventHeight: 40,
            treeEnabled: true,
            resources: [
                {name: "Room A", id: "A"},
                {name: "Room B", id: "B"},
                {name: "Room C", id: "C"},
                {name: "Room D", id: "D"},
                {name: "Room E", id: "E"},
                {name: "Room F", id: "F"},
                {name: "Room G", id: "G"},
                {name: "Room H", id: "H"},
                {name: "Room I", id: "I"},
                {name: "Room J", id: "J"},
                {name: "Room K", id: "K"},
            ],
            onTimeRangeSelected: async args => {
                const modal = await DayPilot.Modal.prompt("New event name:", "Event");
                dp.clearSelection();
                if (modal.canceled) return;
                dp.events.add({
                    start: args.start,
                    end: args.end,
                    id: DayPilot.guid(),
                    resource: args.resource,
                    text: modal.result
                });
                dp.message("Created");
            },
            linkBottomMargin: 20,
            linkShape: "Curved",
            linkWidth: "Auto",
            contextMenuLink: new DayPilot.Menu({
                items: [
                    { text: "Delete", onClick: args => dp.links.remove(args.source) }
                ]
            }),
            linkBubble: new DayPilot.Bubble({
                onLoad: args => {
                    if (!args.html) {
                        args.html = "Default link bubble text";
                    }
                }
            }),
            onLinkClick: args => console.log(args.link),
            linkCreateHandling: "Update",
            onBeforeEventRender: args => {
                if (args.data.start < new DayPilot.Date("2026-04-06")) {
                    args.data.linkCreateDisabled = true;
                }
            },
            onBeforeLinkRender: args => {
            },
            groupConcurrentEvents: true,
            height: 350,
        });
        dp.init();
        dp.scrollTo("2026-03-25");

        const app = {
            init() {
                this.loadData();
            },
            loadData() {

                const events = [];
                const links = [];

                createFinishToStartTouchDown();
                createFinishToStartTouchUp();
                createFinishToStartTouchSame();

                createFinishToStartBeforeDown();
                createFinishToStartBeforeUp();
                createFinishToStartBeforeSame();

                createFinishToStartAfterDown();
                createFinishToStartAfterUp();
                createFinishToStartAfterSame();

                createFinishToFinishSameEnd();

                dp.update({events, links});


                function createFinishToStartTouchDown() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-03-30T00:00:00"),
                        end: new DayPilot.Date("2026-04-02T00:00:00"),
                        id: firstId,
                        resource: "A",
                        text: "Main 1",
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-02T00:00:00"),
                        end: new DayPilot.Date("2026-04-05T12:00:00"),
                        id: secondId,
                        resource: "B",
                        text: "Linked 1"
                    });

                    links.push({
                        from: firstId,
                        to: secondId,
                        type: "FinishToStart",
                        bubbleHtml: "Bubble text",
                    });

                    const beforeId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-03-30T00:00:00"),
                        end: new DayPilot.Date("2026-04-02T00:00:00"),
                        id: beforeId,
                        resource: "A",
                        text: "Main 0",
                    });

                    links.push({
                        from: beforeId,
                        to: firstId,
                        type: "FinishToStart",
                        color: "orange",
                        style: "dashed",
                        text: "Link from the past",
                        textAlignment: "end",
                    });

                }

                function createFinishToStartTouchUp() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-04-07T00:00:00"),
                        end: new DayPilot.Date("2026-04-09T00:00:00"),
                        id: firstId,
                        resource: "B",
                        text: "Main 2"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-09T00:00:00"),
                        end: new DayPilot.Date("2026-04-11T12:00:00"),
                        id: secondId,
                        resource: "A",
                        text: "Linked 2"
                    });

                    links.push({from: firstId, to: secondId, type: "FinishToStart"});


                }

                function createFinishToStartTouchSame() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-04-16T00:00:00"),
                        end: new DayPilot.Date("2026-04-19T00:00:00"),
                        id: firstId,
                        resource: "A",
                        text: "Main 3"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-19T00:00:00"),
                        end: new DayPilot.Date("2026-04-22T00:00:00"),
                        id: secondId,
                        resource: "A",
                        text: "Linked 3"
                    });

                    links.push({from: firstId, to: secondId, type: "FinishToStart", color: "black"});

                    const afterId = DayPilot.guid();
                    events.push({
                        start: new DayPilot.Date("2026-04-18T00:00:00"),
                        end: new DayPilot.Date("2026-04-21T00:00:00"),
                        id: afterId,
                        resource: "H",
                        text: "Linked 4+",
                    });

                    links.push({
                        from: secondId,
                        to: afterId,
                        type: "FinishToStart",
                        color: "orange",
                        style: "dashed",
                        text: "Link to the past",
                        textAlignment: "start"
                    });

                }

                function createFinishToStartBeforeDown() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-03-29T00:00:00"),
                        end: new DayPilot.Date("2026-04-01T00:00:00"),
                        id: firstId,
                        resource: "C",
                        text: "Main 4"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-03T00:00:00"),
                        end: new DayPilot.Date("2026-04-05T12:00:00"),
                        id: secondId,
                        resource: "D",
                        text: "Linked 4"
                    });

                    links.push({
                      from: firstId,
                      to: secondId,
                      type: "FinishToStart",
                      text: "Link text A",
                      textAlignment: "start",
                    });

                }

                function createFinishToStartBeforeUp() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-04-07T00:00:00"),
                        end: new DayPilot.Date("2026-04-09T00:00:00"),
                        id: firstId,
                        resource: "D",
                        text: "Main 5"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-10T00:00:00"),
                        end: new DayPilot.Date("2026-04-14T00:00:00"),
                        id: secondId,
                        resource: "C",
                        text: "Linked 5"
                    });

                    links.push({
                        from: firstId,
                        to: secondId,
                        type: "FinishToStart",
                        color: "green",
                        style: "dashed"
                    });

                }

                function createFinishToStartBeforeSame() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-04-16T00:00:00"),
                        end: new DayPilot.Date("2026-04-18T00:00:00"),
                        id: firstId,
                        resource: "C",
                        text: "Main 6"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-19T00:00:00"),
                        end: new DayPilot.Date("2026-04-22T00:00:00"),
                        id: secondId,
                        resource: "C",
                        text: "Linked 6"
                    });

                    links.push({from: firstId, to: secondId, type: "FinishToStart"});

                }

                function createFinishToStartAfterDown() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-03-30T00:00:00"),
                        end: new DayPilot.Date("2026-04-02T00:00:00"),
                        id: DayPilot.guid(),
                        resource: "E",
                        text: "Main 7"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-03-30T00:00:00"),
                        end: new DayPilot.Date("2026-04-02T00:00:00"),
                        id: firstId,
                        resource: "E",
                        text: "Main 7"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-01T00:00:00"),
                        end: new DayPilot.Date("2026-04-05T12:00:00"),
                        id: secondId,
                        resource: "G",
                        text: "Linked 7"
                    });

                    links.push({
                        from: firstId,
                        to: secondId,
                        type: "FinishToStart",
                        color: "#606060",
                        style: "dotted",
                    });

                }

                function createFinishToStartAfterUp() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-04-07T00:00:00"),
                        end: new DayPilot.Date("2026-04-11T00:00:00"),
                        id: firstId,
                        resource: "G",
                        text: "Main 8"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-10T00:00:00"),
                        end: new DayPilot.Date("2026-04-14T00:00:00"),
                        id: secondId,
                        resource: "E",
                        text: "Linked 8"
                    });
                    links.push({
                        from: firstId,
                        to: secondId,
                        type: "FinishToStart",
                        color: "#f1c232",
                    });

                }

                function createFinishToStartAfterSame() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-04-16T00:00:00"),
                        end: new DayPilot.Date("2026-04-20T00:00:00"),
                        id: firstId,
                        resource: "E",
                        text: "Main 9"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-19T00:00:00"),
                        end: new DayPilot.Date("2026-04-22T00:00:00"),
                        id: secondId,
                        resource: "E",
                        text: "Linked 9"
                    });

                    links.push({from: firstId, to: secondId, type: "FinishToStart"});

                }

                function createFinishToFinishSameEnd() {
                    const firstId = DayPilot.guid();
                    const secondId = DayPilot.guid();

                    events.push({
                        start: new DayPilot.Date("2026-04-16T00:00:00"),
                        end: new DayPilot.Date("2026-04-20T00:00:00"),
                        id: firstId,
                        resource: "F",
                        text: "Main 10"
                    });
                    events.push({
                        start: new DayPilot.Date("2026-04-16T00:00:00"),
                        end: new DayPilot.Date("2026-04-20T00:00:00"),
                        id: secondId,
                        resource: "G",
                        text: "Linked 10"
                    });

                    links.push({from: firstId, to: secondId, type: "FinishToFinish"});

                }

            }
        };
        app.init();
```

