Features

  • The Scheduler checks for any overlapping events during drag and drop moving - the existing events are pushed back to make space for the dragged event.

  • Includes the open-source DayPilot Lite for JavaScript

Automatic Moving of Existing Events

The JavaScript Scheduler fires onEventMove event when an event is dropped at the target location.

We will use to it find any events that are already displayed at the target location. The overlapping events will be pushed back automatically. It also stores the automatically-moved events in an array so you send the changes to the server.

Drag and drop moving:

JavaScript Scheduler - Push Existing Events Back during Drag and Drop

After drop:

JavaScript Scheduler - Push Existing Events Back - After Drop

Source code:

<div class="main">
  <div id="scheduler"></div>
</div>

<script>
  const scheduler = new DayPilot.Scheduler("scheduler", {
    timeHeaders: [{groupBy: "Month"},{groupBy: "Day", format: "d"}],
    scale: "Day",
    days: 30,
    startDate: "2026-11-01",
    cellWidth: 60,
    durationBarVisible: false,
    eventBorderRadius: 6,
    onBeforeEventRender: args => {
      const color = args.data.color ?? "#fcb711";
      args.data.backColor = color + "99";
      args.data.borderColor = "darker";
    },
    rowMarginTop: 2,
    rowMarginBottom: 2,
    onTimeRangeSelected: async (args) => {
      const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
      scheduler.clearSelection();
      if (!modal.result) {
        return;
      }
      scheduler.events.add({
        start: args.start,
        end: args.end,
        id: DayPilot.guid(),
        resource: args.resource,
        text: modal.result
      });
    },
    onEventMove: (args) => {

      // a list of events to be pushed
      const eventsToBeMoved = [];

      // find events in the target row, starting at the new event location
      const events = scheduler.rows.find(args.newResource).events.forRange(args.newStart).filter((e) => e.id() !== args.e.id() );

      // check the events
      let end = args.newEnd;
      events.every((e) => {

        // the last movement didn't affect the next event, stop the every() processing here
        if (end <= e.start()) {
          return false;
        }

        // this event needs to be pushed
        const offset = end.getTime() - e.start().getTime();
        const item = {};
        item.e = e;
        item.newStart = e.start().addTime(offset);
        item.newEnd = e.end().addTime(offset);
        eventsToBeMoved.push(item);
        end = item.newEnd;

        // continue
        return true;
      });

      // this is to be sent to the server
      console.log(eventsToBeMoved);

      // move events in the list
      eventsToBeMoved.forEach((item) => {
        const e = item.e;
        e.start(item.newStart);
        e.end(item.newEnd);
        scheduler.events.update(e);
      });

    }
  });
  scheduler.init();

  const app = {
    init() {
      this.loadEventData();
    },
    loadEventData() {
      const resources = [
        {name: "Resource 1", id: "R1"},
        {name: "Resource 2", id: "R2"},
        {name: "Resource 3", id: "R3"},
        {name: "Resource 4", id: "R4"},
        {name: "Resource 5", id: "R5"},
        {name: "Resource 6", id: "R6"},
        {name: "Resource 7", id: "R7"},
        {name: "Resource 8", id: "R8"}
      ];

      const events = [
        {id: 1, text: "Event 1", start: "2026-11-05", end: "2026-11-07", resource: "R1"},
        {id: 2, text: "Event 2", start: "2026-11-07", end: "2026-11-10", resource: "R1"},
        {id: 3, text: "Event 3", start: "2026-11-10", end: "2026-11-15", resource: "R1"},
        {id: 4, text: "Event 4", start: "2026-11-10", end: "2026-11-15", resource: "R2"}
      ];

      scheduler.update({resources, events});
    },
  };
  app.init();


</script>