---
title: "Javascript Event calendar Add, Edit and Delete Events Example | Mobiscroll"
component: "Event calendar"
framework: "JavaScript"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/javascript/eventcalendar/create-read-update-delete-CRUD"
---

# Add, Edit and Delete Events - JavaScript Event calendar demo

Add full event management to a Javascript event calendar — create events by drag or click, edit them in a custom dialog, and delete with undo. Plain JS api for usage everywhere.

- [Live demo](https://demo.mobiscroll.com/javascript/eventcalendar/create-read-update-delete-CRUD)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-javascript/tree/main/src/demos/eventcalendar/calendar-view/create-read-update-delete-CRUD)
- This demo in other frameworks: [jQuery](https://demo.mobiscroll.com/jquery/eventcalendar/create-read-update-delete-CRUD.md), [Angular](https://demo.mobiscroll.com/angular/eventcalendar/create-read-update-delete-CRUD.md), [React](https://demo.mobiscroll.com/react/eventcalendar/create-read-update-delete-CRUD.md), [Vue](https://demo.mobiscroll.com/vue/eventcalendar/create-read-update-delete-CRUD.md)

## Description

**Create new events**

Drag to create and click to create is enabled. Events can be created by dragging or with double clicks. As soon as the initial position is confirmed, a temporary event is created and a custom edit dialog is shown for refinement. On cancel the temporary event will be removed and on confirmation the event will stay in the calendar.

**Edit existing events**

Drag to resize and drag to move is enabled. Events can be reordered and resized. In addition to that, clicking on the event will open a custom dialog that enables editing the various properties.

**Delete events**

Delete can be implemented inside the edit dialog with a button. It's just a matter of removing it from the data object. If a dialog is not shown on click, focused events can be deleted with the *backspace* and *delete* keys.

**Interested in adding recurrence configuration?** [Check out the next example →](https://demo.mobiscroll.com/javascript/eventcalendar/recurring-event-add-edit-dialog)

## What this demo shows

- A full month event calendar with multiple events and the standard header controls for month and year navigation, previous and next arrows, and a Today button.
- **Event creation** Users can create events by clicking and dragging across calendar cells or by double-clicking a day cell.
- **New event dialog** Creating an event opens a dialog with fields for title, description, all-day, start and end date selection, travel time, event color, and busy or free status.
- **Date selection** The start and end inputs open a date picker calendar with range selection.
- **Cancel behavior** Clicking outside the dialog or pressing Cancel closes it and removes the temporary event from the calendar.
- **Event editing** Clicking or tapping an existing event opens the same dialog in edit mode with the current values prefilled.
- **Editable properties** In edit mode, the event details and event color can be changed before saving.
- **Save and close behavior** Clicking outside the dialog or pressing Cancel closes the editor without applying changes, while Save updates the event.
- **Delete flow** The edit dialog includes a Delete event action that removes the event from the calendar.
- **Undo feedback** After deletion, a centered bottom toast appears with an Undo action so the deleted event can be restored.
- **Responsive behavior** The dialog adapts to screen size and device type, using touch-optimized controls such as scrollers on smaller or touch devices.
- **Mobile presentation** On smaller screens, the dialog is shown as a sheet instead of a popover.
- **Day cell states** Hovering a day cell highlights the day number with a gray background, while clicking the empty part of the cell selects the day and highlights the day number with a blue background.

## Best for

- **Monthly event management** Managing create, read, update, and delete workflows in a month-based calendar view.
- **General scheduling** Applications where users need to add, edit, and remove events directly from the calendar.
- **Mixed event types** Calendars that need to handle single-day, multi-day, all-day, and timed events in the same interface.
- **Responsive scheduling UIs** Products that need the same event management flow to work well on desktop and touch devices.

## 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
- [`setOptions`](https://mobiscroll.com/docs/javascript/datepicker/api#method-setOptions) - method
- [`controls`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-controls) - option
- [`responsive`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-responsive) - option
- [`touchUi`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-touchUi) - option
- [`setOptions`](https://mobiscroll.com/docs/javascript/popup/api#method-setOptions) - method
- [`anchor`](https://mobiscroll.com/docs/javascript/popup/api#opt-anchor) - option
- [`headerText`](https://mobiscroll.com/docs/javascript/popup/api#opt-headerText) - option
- [`buttons`](https://mobiscroll.com/docs/javascript/popup/api#opt-buttons) - option
- [`updateEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-updateEvent) - method
- [`navigateToEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-navigateToEvent) - method
- [`close`](https://mobiscroll.com/docs/javascript/popup/api#method-close) - method
- [`cssClass`](https://mobiscroll.com/docs/javascript/popup/api#opt-cssClass) - option
- [`onClose`](https://mobiscroll.com/docs/javascript/popup/api#event-onClose) - event
- [`removeEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-removeEvent) - method
- [`open`](https://mobiscroll.com/docs/javascript/popup/api#method-open) - method
- [`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
- [`view`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-view) - option
- [`labels`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-labels) - option
- [`data`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-data) - option
- [`onEventClick`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventClick) - event
- [`onEventCreated`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventCreated) - event
- [`onEventDeleted`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventDeleted) - event
- [`addEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-addEvent) - method
- [`select`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-select) - option
- [`startInput`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-startInput) - option
- [`endInput`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-endInput) - option
- [`showRangeLabels`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-showRangeLabels) - option
- [`onChange`](https://mobiscroll.com/docs/javascript/datepicker/api#event-onChange) - event
- [`display`](https://mobiscroll.com/docs/javascript/popup/api#opt-display) - option
- [`showArrow`](https://mobiscroll.com/docs/javascript/popup/api#opt-showArrow) - option
- [`showOverlay`](https://mobiscroll.com/docs/javascript/popup/api#opt-showOverlay) - option
- [`responsive`](https://mobiscroll.com/docs/javascript/popup/api#opt-responsive) - option
- [`fullScreen`](https://mobiscroll.com/docs/javascript/popup/api#opt-fullScreen) - option
- [`scrollLock`](https://mobiscroll.com/docs/javascript/popup/api#opt-scrollLock) - option
- [`width`](https://mobiscroll.com/docs/javascript/popup/api#opt-width) - option
- [`touchUi`](https://mobiscroll.com/docs/javascript/popup/api#opt-touchUi) - option

## Code

### JS

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

function toggleDatetimePicker(allDay) {
  // Toggle between date and datetime picker
  eventStartEndPicker.setOptions({
    controls: allDay ? ['date'] : ['datetime'],
    responsive: allDay
      ? { medium: { controls: ['calendar'], touchUi: false } }
      : { medium: { controls: ['calendar', 'time'], touchUi: false } },
  });
}

function toggleTravelTime(allDay) {
  if (allDay) {
    timeGroupElm.remove();
  } else {
    timeGroupParent.appendChild(timeGroupElm);
  }
}

// Fills the popup with the event's data
function fillPopup(event) {
  // Load event properties
  eventId = event.id;
  eventTitle = event.title || '';
  eventDescription = event.description || '';
  eventAllDay = event.allDay;
  eventStart = event.start;
  eventEnd = event.end;
  eventBuffer = event.bufferBefore || 0;
  eventColor = event.color || '';
  eventStatus = event.free;

  // Set event fields
  mobiscroll.getInst(eventTitleElm).value = eventTitle;
  mobiscroll.getInst(eventDescriptionElm).value = eventDescription;
  mobiscroll.getInst(eventAllDayElm).checked = eventAllDay;
  eventStartEndPicker.setVal([eventStart, eventEnd]);
  mobiscroll.getInst(eventBufferElm).value = eventBuffer;
  highlightColor(eventColor);
  updateColorPreview(eventColor);
  if (eventStatus) {
    mobiscroll.getInst(eventStatusFreeElm).checked = true;
  } else {
    mobiscroll.getInst(eventStatusBusyElm).checked = true;
  }
  toggleDatetimePicker(eventAllDay);
  toggleTravelTime(eventAllDay);
}

function getEventData() {
  return {
    id: eventId,
    title: eventTitle,
    description: eventDescription,
    allDay: eventAllDay,
    start: eventStart,
    end: eventEnd,
    bufferBefore: eventBuffer,
    color: eventColor,
    free: eventStatus,
  };
}

function createAddPopup(event, target) {
  var success = false;

  // Hide delete button inside add popup
  eventDeleteButtonElm.parentElement.style.display = 'none';

  // Set popup header text and buttons for adding
  addEditPopup.setOptions({
    anchor: target,
    headerText: 'New event',
    buttons: [
      'cancel',
      {
        text: 'Add',
        keyCode: 'enter',
        handler: function () {
          var newEvent = getEventData();
          calendar.updateEvent(newEvent);
          calendar.navigateToEvent(newEvent);
          success = true;
          addEditPopup.close();
        },
        cssClass: 'mbsc-popup-button-primary',
      },
    ],
    onClose: function () {
      // Remove event if popup is cancelled
      if (!success) {
        calendar.removeEvent(event);
      }
    },
  });

  fillPopup(Object.assign({}, event, { allDay: false }));
  addEditPopup.open();
}

function createEditPopup(event, target) {
  // Show delete button inside edit popup
  eventDeleteButtonElm.parentElement.style.display = 'block';

  editedEvent = event;

  // Set popup header text and buttons
  addEditPopup.setOptions({
    headerText: 'Edit event',
    anchor: target,
    buttons: [
      'cancel',
      {
        text: 'Save',
        keyCode: 'enter',
        handler: function () {
          var updatedEvent = getEventData();
          calendar.updateEvent(updatedEvent);
          calendar.navigateToEvent(updatedEvent);
          addEditPopup.close();
        },
        cssClass: 'mbsc-popup-button-primary',
      },
    ],
  });

  fillPopup(event);
  addEditPopup.open();
}

function highlightColor(color) {
  document.querySelectorAll('.mds-crud-color-value').forEach(function (elm) {
    elm.classList.remove('mds-crud-color-value-selected');
  });
  document.querySelector('.mds-crud-color-value[data-value="' + color + '"]').classList.add('mds-crud-color-value-selected');
}

function updateColorPreview(color) {
  colorPreviewElm.style.background = color || '';
}

function applySelectedColor(color) {
  eventColor = color;
  updateColorPreview(color);
  eventColorPicker.close();
}

var editedEvent;
var selectedColor;

var eventId;
var eventTitle;
var eventDescription;
var eventAllDay;
var eventStart;
var eventEnd;
var eventBuffer;
var eventColor;
var eventStatus;

var eventTitleElm = document.getElementById('crud-popup-event-title');
var eventDescriptionElm = document.getElementById('crud-popup-event-desc');
var eventAllDayElm = document.getElementById('crud-popup-event-all-day');
var eventBufferElm = document.getElementById('crud-popup-event-buffer');
var eventColorElm = document.getElementById('crud-popup-event-color');
var colorPreviewElm = document.getElementById('crud-popup-event-color-preview');
var colorValueElms = document.querySelectorAll('.mds-crud-color-value');
var eventStatusBusyElm = document.getElementById('crud-popup-event-status-busy');
var eventStatusFreeElm = document.getElementById('crud-popup-event-status-free');
var eventDeleteButtonElm = document.getElementById('crud-popup-event-delete');
var timeGroupElm = document.getElementById('crud-popup-time-group');
var timeGroupParent = timeGroupElm.parentNode;

var myEvents = [
  {
    id: 1,
    start: '2026-10-08T13:00',
    end: '2026-10-08T13:45',
    title: "Lunch @ Butcher's",
    description: '',
    allDay: false,
    bufferBefore: 15,
    free: true,
    color: '#009788',
  },
  {
    id: 2,
    start: '2026-10-20T15:00',
    end: '2026-10-20T16:00',
    title: 'Conference',
    description: '',
    allDay: false,
    bufferBefore: 30,
    free: false,
    color: '#ff9900',
  },
  {
    id: 3,
    start: '2026-10-19T18:00',
    end: '2026-10-19T22:00',
    title: 'Site Visit',
    description: '',
    allDay: false,
    bufferBefore: 60,
    free: true,
    color: '#3f51b5',
  },
  {
    id: 4,
    start: '2026-10-21T10:30',
    end: '2026-10-21T11:30',
    title: 'Stakeholder mtg.',
    description: '',
    allDay: false,
    free: false,
    color: '#f44437',
  },
];

// Init the event calendar
var calendar = mobiscroll.eventcalendar('#demo-crud-event-calendar', {
  clickToCreate: 'double',
  dragToCreate: true,
  dragToMove: true,
  dragToResize: true,
  view: {
    calendar: { labels: true },
  },
  data: myEvents,
  onEventClick: function (args) {
    createEditPopup(args.event, args.domEvent.currentTarget);
  },
  onEventCreated: function (args) {
    createAddPopup(args.event, args.target);
  },
  onEventDeleted: function (args) {
    mobiscroll.snackbar({
      button: {
        action: function () {
          calendar.addEvent(args.event);
        },
        text: 'Undo',
      },
      message: 'Event deleted',
    });
  },
});

// Init event start/end date picker
var eventStartEndPicker = mobiscroll.datepicker('#crud-popup-event-dates', {
  controls: ['date'],
  select: 'range',
  startInput: '#crud-popup-event-start',
  endInput: '#crud-popup-event-end',
  showRangeLabels: false,
  touchUi: true,
  responsive: { medium: { touchUi: false } },
  onChange: function (args) {
    var dates = args.value;
    eventStart = dates[0];
    eventEnd = dates[1];
  },
});

// Init event color picker
var eventColorPicker = mobiscroll.popup('#crud-color-picker-popup', {
  display: 'bottom',
  contentPadding: false,
  showArrow: false,
  showOverlay: false,
  buttons: [
    'cancel',
    {
      text: 'Set',
      keyCode: 'enter',
      handler: function () {
        applySelectedColor(selectedColor);
      },
      cssClass: 'mbsc-popup-button-primary',
    },
  ],
  responsive: {
    medium: {
      display: 'anchored',
      anchor: eventColorElm,
      buttons: [],
    },
  },
});

var addEditPopup = mobiscroll.popup('#crud-add-edit-popup', {
  display: 'bottom',
  contentPadding: false,
  fullScreen: true,
  scrollLock: false,
  responsive: {
    medium: {
      display: 'anchored',
      width: 400,
      fullScreen: false,
      touchUi: false,
    },
  },
});

eventTitleElm.addEventListener('input', function (ev) {
  eventTitle = ev.target.value;
});

eventDescriptionElm.addEventListener('change', function (ev) {
  eventDescription = ev.target.value;
});

eventAllDayElm.addEventListener('change', function (ev) {
  eventAllDay = ev.target.checked;
  toggleDatetimePicker(eventAllDay);
  toggleTravelTime(eventAllDay);
});

eventBufferElm.addEventListener('change', function (ev) {
  eventBuffer = +ev.target.value;
});

document.querySelectorAll('.mds-crud-popup-event-status').forEach(function (elm) {
  elm.addEventListener('change', function (ev) {
    eventStatus = ev.target.value === 'free';
  });
});

eventDeleteButtonElm.addEventListener('click', function () {
  calendar.removeEvent(editedEvent);
  addEditPopup.close();

  mobiscroll.snackbar({
    button: {
      action: function () {
        calendar.addEvent(editedEvent);
      },
      text: 'Undo',
    },
    message: 'Event deleted',
  });
});

eventColorElm.addEventListener('click', function () {
  highlightColor(eventColor || '');
  eventColorPicker.open();
});

colorValueElms.forEach(function (elm) {
  elm.addEventListener('click', function () {
    var color = elm.getAttribute('data-value');
    selectedColor = color;
    highlightColor(color);

    if (!eventColorPicker.s.buttons.length) {
      applySelectedColor(color);
    }
  });
});
```

### HTML

```html
<div id="demo-crud-event-calendar"></div>

<div style="display: none">
  <div id="crud-add-edit-popup">
    <div class="mbsc-form-group">
      <label>
        Title
        <input mbsc-input id="crud-popup-event-title" />
      </label>
      <label>
        Description
        <textarea mbsc-textarea id="crud-popup-event-desc"></textarea>
      </label>
    </div>
    <div class="mbsc-form-group">
      <div>
        <label>
          All-day
          <input mbsc-switch id="crud-popup-event-all-day" type="checkbox" />
        </label>
        <label>
          Starts
          <input mbsc-input id="crud-popup-event-start" />
        </label>
        <label>
          Ends
          <input mbsc-input id="crud-popup-event-end" />
        </label>
        <label id="crud-popup-time-group">
          <select data-label="Travel time" mbsc-dropdown id="crud-popup-event-buffer">
            <option value="0">None</option>
            <option value="5">5 minutes</option>
            <option value="15">15 minutes</option>
            <option value="30">30 minutes</option>
            <option value="60">1 hour</option>
            <option value="90">1.5 hours</option>
            <option value="120">2 hours</option>
          </select>
        </label>
      </div>
      <div id="crud-popup-event-dates"></div>
      <div id="crud-event-color-picker" class="mbsc-flex mds-crud-event-color-cont">
        <div class="mbsc-flex-1-0">Color</div>
        <div id="crud-popup-event-color">
          <div id="crud-popup-event-color-preview" class="mds-crud-selected-event-color"></div>
        </div>
      </div>
      <label>
        Show as busy
        <input id="crud-popup-event-status-busy" class="mds-crud-popup-event-status" mbsc-segmented type="radio" name="event-status" value="busy" />
      </label>
      <label>
        Show as free
        <input id="crud-popup-event-status-free" class="mds-crud-popup-event-status" mbsc-segmented type="radio" name="event-status" value="free" />
      </label>
      <div class="mbsc-button-group">
        <button class="mbsc-button-block" id="crud-popup-event-delete" mbsc-button data-color="danger" data-variant="outline">
          Delete event
        </button>
      </div>
    </div>
  </div>

  <div id="crud-color-picker-popup">
    <div class="mbsc-flex mds-crud-color-row">
      <div class="mds-crud-color-value" data-value="#ffeb3c">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #ffeb3c"></div>
      </div>
      <div class="mds-crud-color-value" data-value="#ff9900">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #ff9900"></div>
      </div>
      <div class="mds-crud-color-value" data-value="#f44437">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #f44437"></div>
      </div>
      <div class="mds-crud-color-value" data-value="#ea1e63">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #ea1e63"></div>
      </div>
      <div class="mds-crud-color-value" data-value="#9c26b0">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #9c26b0"></div>
      </div>
    </div>
    <div class="mbsc-flex mds-crud-color-row">
      <div class="mds-crud-color-value" data-value="#3f51b5">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #3f51b5"></div>
      </div>
      <div class="mds-crud-color-value" data-value="">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check"></div>
      </div>
      <div class="mds-crud-color-value" data-value="#009788">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #009788"></div>
      </div>
      <div class="mds-crud-color-value" data-value="#4baf4f">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #4baf4f"></div>
      </div>
      <div class="mds-crud-color-value" data-value="#7e5d4e">
        <div class="mds-crud-color mbsc-icon mbsc-font-icon mbsc-icon-material-check" style="background: #7e5d4e"></div>
      </div>
    </div>
  </div>
</div>
```

### CSS

```css
.mds-crud-event-color-cont {
  margin: 16px;
  align-items: center;
  cursor: pointer;
}

.mds-crud-selected-event-color {
  width: 30px;
  height: 30px;
  border-radius: 15px;
  margin-right: 10px;
  margin-left: 240px;
  background: #5ac8fa;
}

.mds-crud-color-row {
  justify-content: center;
  margin: 5px;
}

.mds-crud-color {
  position: relative;
  min-width: 46px;
  min-height: 46px;
  margin: 2px;
  cursor: pointer;
  border-radius: 23px;
  background: #5ac8fa;
}

.mds-crud-color:before {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -10px;
  margin-left: -10px;
  color: #f7f7f7;
  font-size: 20px;
  text-shadow: 0 0 3px #000;
  display: none;
}

.mds-crud-color-value {
  padding: 3px;
  margin: 2px;
}

.mds-crud-color-value.mds-crud-color-value-selected,
.mds-crud-color-value:hover {
  box-shadow: inset 0 0 0 3px #007bff;
  border-radius: 48px;
}

.mds-crud-color-value.mds-crud-color-value-selected .mds-crud-color:before {
  display: block;
}
```

## Implementation notes

- Use `view: { calendar: { labels: true } }`. Enable all four interaction modes: `clickToCreate` (React/Vue/Angular: `true`; JS/jQuery: `'double'`), `dragToCreate: true`, `dragToMove: true`, `dragToResize: true`.
- Start with 4 sample events using `dyndatetime` offsets. Each event carries: `id`, `title`, `description`, `allDay`, `start`, `end`, `bufferBefore`, `free`, and `color`.
- Handle three calendar events: `onEventClick` → opens the edit popup; `onEventCreated` → opens the add popup (the event is already temporarily placed on the calendar); `onEventDeleted` → shows a snackbar ("Event deleted") with an "Undo" button that adds the event back. Angular: use the `Notifications` service for the snackbar.
- Maintain an `isEdit` flag and an `editedEvent` reference. A `fillPopup(event)` helper populates all form fields from the event object.
- **Edit mode**: set `isEdit = true`, store `editedEvent`, set popup anchor to the clicked element, call `fillPopup`, open with "Edit event" header and a "Save" button.
- **Add mode**: set `isEdit = false`, set `isSuccess = false`, call `fillPopup`, open with "New Event" header and an "Add" button.
- **On popup close (add mode, not confirmed)**: if `isEdit` is false and `isSuccess` is false, refresh the events array (spread trick) to strip the temporary event; for the imperative API, call `calendar.removeEvent(event)` in the popup's `onClose` handler.
- **"Add" button**: build the event from form state, append to the events array, set `isSuccess = true`, call `inst.navigateToEvent(newEvent)`, close popup.
- **"Save" button**: build updated event from form state, find by `id` and splice in place, call `inst.navigateToEvent(updatedEvent)`, close popup.
- **Popup form fields**: **Title** (`Input`), **Description** (`Textarea`), **All-day** (`Switch` - when on, switches the date picker to date-only and removes the Travel time row), **Start/End** (a `Datepicker` in range mode with `startInput`/`endInput`; controls are `['datetime']` normally, `['date']` for all-day), **Travel time** (`Dropdown` with None/5/15/30 min/1 h/1.5 h/2 h options mapped to `bufferBefore` in minutes - hidden when all-day), **Color** (a clickable row opening a color picker popup with 10 swatches), **Show as busy / free** (`SegmentedGroup` mapping to the `free` boolean), and a **Delete event** button (visible in edit mode only).
- The color picker is a separate `Popup` with 10 color swatches in 2 rows of 5: `#ffeb3c`, `#ff9900`, `#f44437`, `#ea1e63`, `#9c26b0` / `#3f51b5`, empty string (no color), `#009788`, `#4baf4f`, `#7e5d4e`. On desktop (`display: 'anchored'`, no buttons): clicking applies and closes immediately. On mobile: bottom-sheet with "Set"/"Cancel". The active swatch is highlighted.
- **Delete from popup**: filter the event from the array by `id`, close the popup, show a snackbar with "Undo".

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

- Next: [Recurring Events Editor](https://demo.mobiscroll.com/javascript/eventcalendar/recurring-event-add-edit-dialog.md) - Add recurring event management to a Javascript event calendar — use preset daily, weekly, monthly, and yearly rules or a custom recurrence editor.
