---
title: "Javascript Timeline Prevent Event Overlap Example | Mobiscroll"
component: "Timeline"
framework: "JavaScript"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/javascript/timeline/prevent-double-booking-events"
---

# Prevent Event Overlap - JavaScript Timeline demo

Prevent double booking on the Javascript Timeline — block overlaps per event, per resource, or globally, and show a toast on conflict. Plain JavaScript API.

- [Live demo](https://demo.mobiscroll.com/javascript/timeline/prevent-double-booking-events)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-javascript/tree/main/src/demos/eventcalendar/timeline/prevent-double-booking-events)
- This demo in other frameworks: [jQuery](https://demo.mobiscroll.com/jquery/timeline/prevent-double-booking-events.md), [Angular](https://demo.mobiscroll.com/angular/timeline/prevent-double-booking-events.md), [React](https://demo.mobiscroll.com/react/timeline/prevent-double-booking-events.md), [Vue](https://demo.mobiscroll.com/vue/timeline/prevent-double-booking-events.md)

## Description

Sometimes it is necessary to guarantee that events don't overlap - eg. when scheduling workorders, interacting with a work calendar. You can reject the updates or additions and let the user know about it.

The event overlap can be turned on/off on an event basis, per resource or globally on the instance.

- On an [event](https://demo.mobiscroll.com/javascript/timeline/event-data-structure) basis - by setting the `overlap` property to `false` the specified event cannot overlap.
- Per [resource](https://demo.mobiscroll.com/javascript/timeline/resource-data-structure) - by setting the `eventOverlap` property to `false` the events in the specified resource cannot overlap.
- Globally on the instance - by setting [`eventOverlap`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-eventOverlap) option to `false` overlap is disbled globally.

If set to `false`, the [resource](https://demo.mobiscroll.com/javascript/timeline/resource-data-structure) and the [event](https://demo.mobiscroll.com/javascript/timeline/event-data-structure) settings have precedence over the global calendar [`eventOverlap`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-eventOverlap) option.

Give feedback to the user - optionally, a toast can be displayed to explain why an event cannot be dropped, moved or created. For this we can use the `onEventCreateFailed` and `onEventUpdateFailed` lifecycle events.

## What this demo shows

- A desktop daily timeline where hours are arranged horizontally and resources are listed as rows on the left.
- **Header navigation** The month and year label opens date navigation, while the previous and next arrows move between days and the Today button returns to the current date.
- **Day view** The strip below the header shows the selected day, with the current date highlighted. The timeline displays hourly columns from 12 AM to 12 PM.
- **Current time** A vertical blue line with a time label marks the current time.
- **Hover behavior** Hovering over the time grid shows a time indicator that follows the cursor in 15-minute increments.
- **Resources** Four resources are displayed: Resource 1, Resource 2, Resource 3, and Resource 4 - no event overlap allowed.
- **Event-level restrictions** Resource 1 and Resource 2 contain events with per-event overlap restrictions. Event 2 on Resource 1 and Event 4 on Resource 2 have `overlap: false`, meaning those specific events cannot overlap with any other event. Other events on the same resources can still overlap when the global overlap setting allows it.
- **Resource-level restrictions** Resource 4 - no event overlap allowed has `eventOverlap: false`, which applies a no-overlap rule to every event on that resource.
- **Global overlap control** A switch under this title: `Control the interaction globally (all events/resources)` lets users enable `Events cannot overlap eventOverlap=false` to prevent overlaps across all the timeline, by default it's disabled. 
- **Creation feedback** When a user tries to create an overlapping event in a restricted cell, a `Make sure not to overbook` toast appears at the bottom center of the calendar.
- **Event cards** Events are shown as colored cards with a left color stripe, a bold title, a description, and a bold time range.
- **Date positioning** Events are positioned by their assigned resource and exact date range.
- **Event interaction** Events highlight on hover and show drag and resize handles for repositioning or changing duration.
- **Event selection** Clicking an event selects and highlights it.
- **Event creation** New events can be created by double-clicking the timeline or by clicking and dragging across a time range.
- **Scrolling** The timeline supports horizontal and vertical scrolling for navigating through time and resources.

## Best for

- **Work orders and field service** Preventing technicians, crews, or jobs from being booked into the same time slot.
- **Availability-sensitive booking** Handling internal planning or booking workflows where double booking must be prevented for specific event types, resources, or the entire calendar.
- **Shared resource scheduling** Managing rooms, equipment, vehicles, or other resources that can only be assigned to one event at a time.
- **Interactive planning tools** Giving users immediate feedback when an action would create a scheduling conflict.
- **Mixed scheduling policies** Combining global, resource-level, and event-level overlap rules within the same timeline.

## Tutorial

### Control the interaction globally (all events/resources)

- [ ] Events cannot overlap `eventOverlap=false`

```js
mobiscroll.eventcalendar('#calendar', {
    view: {timeline: { type: 'day' }},
    // relevant events
    data: [{
        start: '2026-10-23T16:00',
        end: '2026-10-23T18:00',
        title: 'Event 2 (no event overlap)',
        overlap: false,
        resource: 1
    },{
        start: '2026-10-23T08:00',
        end: '2026-10-23T10:00',
        title: 'Event 4 (no event overlap)',
        overlap: false,
        resource: 2
    }],
    // relevant resource
    resources:[{
        id: 4,
        name: 'Resource 4 - no event overlap allowed',
        eventOverlap: false
    }],
    dragToMove: true,
    dragToResize: true,
    clickToCreate: true,
    dragToCreate: true,
    eventOverlap: true
});
```

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-themeVariant) - option
- [`view`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-view) - option
- [`clickToCreate`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-clickToCreate) - option
- [`dragToCreate`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-dragToCreate) - option
- [`dragToMove`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-dragToMove) - option
- [`dragToResize`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-dragToResize) - option
- [`eventOverlap`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-eventOverlap) - option
- [`data`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-data) - option
- [`resources`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-resources) - option
- [`onEventUpdateFailed`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventUpdateFailed) - event
- [`onEventCreateFailed`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventCreateFailed) - event

## Code

### JS

```js
mobiscroll.setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

function onEventFailed() {
  mobiscroll.toast({
    message: 'Make sure not to double book',
  });
}

var now = new Date();
var y = now.getFullYear();
var m = now.getMonth();
var d = now.getDate();

mobiscroll.eventcalendar('#demo', {
  view: {
    timeline: { type: 'day' },
  },
  clickToCreate: true,
  dragToCreate: true,
  dragToMove: true,
  dragToResize: true,
  eventOverlap: true,
  data: [
    {
      start: new Date(y, m, d, 11),
      end: new Date(y, m, d, 13),
      title: 'Event 1',
      resource: 1,
    },
    {
      start: new Date(y, m, d, 16),
      end: new Date(y, m, d, 17),
      title: 'Event 2 (no event overlap)',
      overlap: false,
      resource: 1,
    },
    {
      start: new Date(y, m, d, 14),
      end: new Date(y, m, d, 16),
      title: 'Event 3',
      resource: 2,
    },
    {
      start: new Date(y, m, d, 8),
      end: new Date(y, m, d, 10),
      title: 'Event 4 (no event overlap)',
      resource: 2,
      overlap: false,
    },
    {
      start: new Date(y, m, d, 10),
      end: new Date(y, m, d, 13),
      title: 'Event 5',
      resource: 3,
    },
    {
      start: new Date(y, m, d, 11),
      end: new Date(y, m, d, 16),
      title: 'Event 6',
      resource: 4,
    },
  ],
  resources: [
    {
      id: 1,
      name: 'Resource 1',
    },
    {
      id: 2,
      name: 'Resource 2',
    },
    {
      id: 3,
      name: 'Resource 3',
    },
    {
      id: 4,
      name: 'Resource 4 - no event overlap allowed',
      eventOverlap: false,
    },
  ],
  onEventUpdateFailed: onEventFailed,
  onEventCreateFailed: onEventFailed,
});
```

### HTML

```html
<div id="demo"></div>
```

## Implementation notes

- Use `timeline: { type: 'day' }` - a single-day view. Set `eventOverlap: true` globally so overlap is permitted by default; individual events and resources selectively restrict it.
- Define 4 resources. Resources 1-3 have no overlap restriction at the resource level. Resource 4 has `eventOverlap: false` - no event on this resource may overlap with another, regardless of per-event settings.
- Add 6 events (all `new Date(y, m, d, hour)` for today). Two events carry `overlap: false` to restrict them individually: Event 2 on Resource 1 and Event 4 on Resource 2. The remaining events have no `overlap` property and can overlap freely unless their resource blocks it.
- Enable all interactions: `clickToCreate: true`, `dragToCreate: true`, `dragToMove: true`, `dragToResize: true`.
- `onEventCreateFailed` fires when a new event (click/drag-to-create) would violate the overlap rule; `onEventUpdateFailed` fires when a drag or resize would cause overlap. In both cases the calendar automatically rejects and reverts the action - no manual revert is needed.
- **Precedence**: per-event `overlap: false` and per-resource `eventOverlap: false` both override the global `eventOverlap` option.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-javascript.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config javascript
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config javascript --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/javascript/getting-started/installation

## Related demos

- Previous: [Cross-Instance Drag and Drop](https://demo.mobiscroll.com/javascript/timeline/drag-drop-between-calendar-instances.md) - Drag and drop events between two Javascript Timeline views to reassign resources or coordinate schedules — enable cross-timeline transfers.
- Next: [Schedule & Unschedule from External Lists](https://demo.mobiscroll.com/javascript/timeline/external-drag-drop-sortable-dragula.md) - Connect SortableJS or Dragula lists to the Javascript Timeline — drag items onto the timeline to schedule them, drag them back off to unschedule.
