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:
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>