---
title: "Javascript Event calendar Outlook Integration Example | Mobiscroll"
component: "Event calendar"
framework: "JavaScript"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/javascript/eventcalendar/sync-events-outlook-calendar"
---

# Outlook Integration - JavaScript Event calendar demo

Connect the Javascript event calendar to Outlook via plugin — sign in users, load calendars, and add, edit, or delete events with optional write-back. Plain JavaScript API.

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

## Description

The event calendar comes with third party calendar integration support through the [**integration plugin**](https://mobiscroll.com/docs/javascript/eventcalendar/calendar-integrations). This needs to be added to the download package or installed separately from a dedicated NPM package.

It includes everything you need to authenticate your users, get their Outlook calendars and provides functions for CRUD operations. It takes care of loading the events and converts them to the required format so that they can be displayed on the Mobiscroll calendar separately or mixed with other calendars and events.

Customizing the interaction, event workflows, whether the events are read-only is up to you. In this live demo, newly created events will land in the `primary calendar` of the authenticated user.

This example uses the [**integration plugin**](https://mobiscroll.com/docs/javascript/eventcalendar/calendar-integrations) to connect to and load events from Outlook Calendars and it is not available in the trial. Give the live demo a try and see how it can be configured.

## What this demo shows

- Shows how Mobiscroll event calendar can load and display events from a signed-in Outlook Calendar account in a desktop month view.
- **Initial state** The month grid is visible with no events loaded by default.
- **Side panel** A separate panel on the left invites the user to sign in with the text `Log into your Outlook account to view and edit your Outlook Calendar events` and a `Sync My Outlook Calendar` button.
- **Authentication flow** Clicking `Sync My Outlook Calendar` opens a new browser tab where the user signs in to their Microsoft account.
- **Connected state** After sign-in, the side panel updates to show the text `Editing events sync back to your calendar when enabled. You'll be asked for confirmation on every action.`
- **Editing toggle** The connected panel includes an `Enable editing` switch that is off by default.
- **Editing toggle enabled** Editing and event opens a popup with the following message `Are you sure you want to update this event? This actin will affect your Google Calendar event.` and below that ther is a `Cancel` and `Update` button, by clicking the firs one, the popup closes and the event editing won't happen and by clicking the second button will update the event on Mobiscroll calendar and sync back to the Outlook Calendar as well. 
- **Event creation or update** If a new event is created or an existing one updated, a `Event created/updated/ deleted in [the name of your Outlook Calendar] calendar` toast appears at the bottom center of the calendar.
- **Calendar selection** The connected panel includes a `My Calendars` section with separate switches for the available Outlook calendars.
- **Sign-out** The bottom of the side panel includes a `Log Out Of My Account` button for disconnecting the Outlook account.
- **Event rendering** Once Outlook events are loaded, day cells display event labels, and the labels can have different visual styles based on the type of event.
- **Event selection** Hovering over or clicking an event label highlights the selected event.
- **Day hover state** Hovering over a day cell highlights the day number in the top-right corner with a gray background.
- **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.
- **Header navigation** The calendar header shows the current month and year on the left, and blue month navigation arrows with a `Today` button between them on the right.
- **Swipe navigation** When event editing is disabled, the displayed month can also be changed by dragging the calendar left or right.

## Best for

- **User-controlled calendar sync** Experiences where users need to connect their own Outlook account, choose which calendars to display, and disconnect when needed.
- **Optional write-back workflows** Scenarios where external calendar events should stay read-only by default, with editing enabled only when the user explicitly turns it on.
- **Multi-calendar visibility** Interfaces that need to surface multiple Outlook calendars, such as personal calendars, shared calendars, or regional holiday calendars, in a single month view.

## 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
- [`setEvents`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-setEvents) - method
- [`view`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-view) - option
- [`labels`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-labels) - option
- [`extendDefaultEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-extendDefaultEvent) - option
- [`exclusiveEndDates`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-exclusiveEndDates) - 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
- [`renderHeader`](https://mobiscroll.com/docs/javascript/eventcalendar/api#renderer-renderHeader) - renderer
- [`onPageLoading`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onPageLoading) - event
- [`onEventCreate`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventCreate) - event
- [`removeEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-removeEvent) - method
- [`addEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-addEvent) - method
- [`onEventUpdate`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventUpdate) - event
- [`updateEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-updateEvent) - method
- [`onEventDelete`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onEventDelete) - event
- [`setOptions`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-setOptions) - method

## Code

### JS

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

var outlookCalendarSync = mobiscroll.outlookCalendarSync;

var loginButton = document.getElementById('demo-outlook-cal-sign-in');
var logoutButton = document.getElementById('demo-outlook-cal-sign-out');

var calendarList = document.getElementById('demo-outlook-cal-list');
var loggedOutCont = document.getElementById('demo-logged-out-cont');
var loggedInCont = document.getElementById('demo-logged-in-cont');
var cont = document.getElementById('demo-outlook-calendar-cont');
var editButton = document.getElementById('demo-outlook-cal-edit');

var startDate;
var endDate;
var calendarIds = [];
var events = [];
var calendarData = {};
var primaryCalendarId;
var debounce;

function toggleContainers(loggedIn) {
  if (loggedIn) {
    loggedOutCont.style.display = 'none';
    loggedInCont.style.display = 'block';
  } else {
    loggedInCont.style.display = 'none';
    loggedOutCont.style.display = 'block';
  }
}

function loadEvents(checked, calendarId) {
  if (checked) {
    loadingEvents(true);
    calendarIds.push(calendarId);
    outlookCalendarSync
      .getEvents([calendarId], startDate, endDate)
      .then(function (resp) {
        loadingEvents(false);
        events = events.concat(resp);
        inst.setEvents(events);
      })
      .catch(onError);
  } else {
    var index = calendarIds.indexOf(calendarId);
    if (index !== -1) {
      calendarIds.splice(index, 1);
    }
    events = events.filter(function (event) {
      return event.outlookCalendarId !== calendarId;
    });
    inst.setEvents(events);
  }
}

function onSignedIn() {
  toggleContainers(true);
  outlookCalendarSync
    .getCalendars()
    .then(function (calendars) {
      var calList = '<div class="mbsc-form-group-title">My Calendars</div>';

      calendars.sort(function (c) {
        return c.isDefaultCalendar ? -1 : 1;
      });
      primaryCalendarId = calendars[0].id;
      calendarIds.push(primaryCalendarId);

      for (var i = 0; i < calendars.length; ++i) {
        var c = calendars[i];
        calList +=
          '<label>' +
          '<input mbsc-switch id="' +
          i +
          '" value="' +
          c.id +
          '" data-label="' +
          c.name +
          '" type="checkbox" class="outlook-calendar-switch"' +
          (i == 0 ? 'checked' : '') +
          ' />' +
          '</label>';

        calendarData[c.id] = { name: c.name, color: c.hexColor };
      }

      calendarList.innerHTML = calList;
      mobiscroll.enhance(calendarList);

      loadingEvents(true);

      outlookCalendarSync
        .getEvents([primaryCalendarId], startDate, endDate)
        .then(function (resp) {
          loadingEvents(false);
          events = resp;
          inst.setEvents(events);
        })
        .catch(onError);
    })
    .catch(onError);
}

function onSignedOut() {
  toggleContainers(false);
  calendarIds = [];
  calendarData = [];
  events = [];
  inst.setEvents([]);
  calendarList.innerHTML = '';
}

function onError(resp) {
  mobiscroll.toast({
    message: resp.message,
  });
}

function loadingEvents(show) {
  if (show) {
    cont.classList.add('md-loading-events');
  } else {
    cont.classList.remove('md-loading-events');
  }
}

var inst = mobiscroll.eventcalendar('#demo-outlook-calendar', {
  view: {
    calendar: { labels: true },
  },
  extendDefaultEvent: function () {
    if (primaryCalendarId) {
      return {
        color: calendarData[primaryCalendarId].color,
      };
    }
  },
  exclusiveEndDates: true,
  clickToCreate: false,
  dragToCreate: false,
  dragToMove: false,
  dragToResize: false,
  renderHeader: function () {
    return (
      '<div mbsc-calendar-nav></div>' +
      '<div class="md-spinner">' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '<div class="md-spinner-blade"></div>' +
      '</div>' +
      '<div class="md-outlook-calendar-header">' +
      '<button mbsc-calendar-prev></button>' +
      '<button mbsc-calendar-today>Today</button>' +
      '<button mbsc-calendar-next></button></div>'
    );
  },
  onPageLoading: function (args) {
    startDate = args.viewStart;
    endDate = args.viewEnd;
    clearTimeout(debounce);
    debounce = setTimeout(function () {
      if (outlookCalendarSync.isSignedIn()) {
        loadingEvents(true);
        outlookCalendarSync
          .getEvents(calendarIds, startDate, endDate)
          .then(function (resp) {
            loadingEvents(false);
            events = resp;
            inst.setEvents(events);
          })
          .catch(onError);
      }
    }, 200);
  },
  onEventCreate: function (args) {
    if (outlookCalendarSync.isSignedIn()) {
      var event = args.event;
      outlookCalendarSync
        .addEvent(primaryCalendarId, event)
        .then(function (resp) {
          inst.removeEvent(event);
          resp.color = event.color;
          inst.addEvent(resp);
          events.push(resp);
          mobiscroll.toast({
            message: 'Event created in "' + calendarData[primaryCalendarId].name + '" calendar',
          });
        })
        .catch(function (error) {
          onError(error);
          inst.removeEvent(args.event);
        });
    }
  },
  onEventUpdate: function (args) {
    if (outlookCalendarSync.isSignedIn()) {
      mobiscroll
        .confirm({
          title: 'Are you sure you want to update this event?',
          message: 'This action will affect your Outlook Calendar event.',
          okText: 'Update',
        })
        .then(function (result) {
          if (result) {
            var event = args.event;
            var calendarId = event.outlookCalendarId;
            outlookCalendarSync
              .updateEvent(calendarId, event)
              .then(function () {
                mobiscroll.toast({
                  message: 'Event updated on "' + calendarData[calendarId].name + '" calendar',
                });
              })
              .catch(function (error) {
                inst.updateEvent(args.oldEvent);
                onError(error);
              });
          } else {
            inst.updateEvent(args.oldEvent);
          }
        });
    }
  },
  onEventDelete: function (args) {
    if (outlookCalendarSync.isSignedIn()) {
      mobiscroll
        .confirm({
          title: 'Are you sure you want to delete this event?',
          message: 'This action will remove the event from your Outlook Calendar as well.',
          okText: 'Delete',
        })
        .then(function (result) {
          if (result) {
            var event = args.event;
            var calendarId = event.outlookCalendarId;
            outlookCalendarSync
              .deleteEvent(calendarId, event)
              .then(function () {
                inst.removeEvent(event);
                events = events.filter(function (ev) {
                  return event.id !== ev.id;
                });
                mobiscroll.toast({
                  message: 'Event deleted from "' + calendarData[calendarId].name + '" calendar',
                });
              })
              .catch(onError);
          }
        })
        .catch(onError);
    }
    return false;
  },
});

// Sign in
loginButton.addEventListener('click', function () {
  if (!outlookCalendarSync.isSignedIn()) {
    outlookCalendarSync.signIn().catch(onError);
  }
});

// Switch click
loggedInCont.addEventListener('change', function (ev) {
  if (ev.target.classList.contains('outlook-calendar-switch')) {
    loadEvents(ev.target.checked, ev.target.value);
  }
});

// Edit click
editButton.addEventListener('change', function (ev) {
  var isEditable = ev.target.checked;
  inst.setOptions({
    clickToCreate: isEditable,
    dragToCreate: isEditable,
    dragToMove: isEditable,
    dragToResize: isEditable,
  });
});

// Sign out
logoutButton.addEventListener('click', function () {
  outlookCalendarSync.signOut().catch(onError);
});

// Init outlook client
outlookCalendarSync.init({
  clientId: '<YOUR_OUTLOOK_CLIENT_ID>',
  redirectUri: '<YOUR_OUTLOOK_REDIRECT_URI>',
  onSignedIn: onSignedIn,
  onSignedOut: onSignedOut,
});
```

### HTML

```html
<div mbsc-page class="md-sync-events-outlook-cont">
    <div class="md-sync-events-outlook-menu">
        <div id="demo-logged-out-cont">
            <div class="mbsc-form-group-inset mbsc-align-center">
                <p class="mbsc-italic mbsc-txt-muted">Log into your outlook account to view and edit your outlook Calendar events</p>
                <button mbsc-button id="demo-outlook-cal-sign-in" class="md-sync-events-outlook-button mbsc-button-block">Sync my outlook calendars</button>
            </div>
        </div>
        <div id="demo-logged-in-cont" style="display:none">
            <div class="mbsc-form-group-inset mbsc-align-center">
                <p class="mbsc-italic mbsc-txt-muted">Editing events sync back to your calendar when enabled. You'll be asked for confirmation on every action.</p>
            </div>
            <div class="mbsc-form-group-inset">
                <label>
                    <input id="demo-outlook-cal-edit" mbsc-switch data-label="Enable editing" />
                </label>
            </div>
            <div id="demo-outlook-cal-list" class="mbsc-form-group-inset md-sync-events-outlook-inset"></div>
            <div class="mbsc-form-group-inset">
                <button mbsc-button id="demo-outlook-cal-sign-out" class="md-sync-events-outlook-button mbsc-button-block">Log out of my account</button>
            </div>
        </div>
    </div>
    <div id="demo-outlook-calendar-cont" class="md-sync-events-outlook-calendar">
        <div class="md-sync-events-overlay"></div>
        <div id="demo-outlook-calendar"></div>
    </div>
</div>
```

### CSS

```css
.md-sync-events-outlook-cont.mbsc-page {
    display: flex;
    height: 600px;
}

.md-sync-events-outlook-menu {
    flex: 0 0 350px;
    height: 100%;
    overflow: auto;
}

.md-sync-events-outlook-calendar {
    flex: 1 1 auto;
    border-left: 1px solid #ccc;
}

.md-outlook-calendar-header {
    flex: 1 0 auto;
    display: flex;
    justify-content: flex-end;
}

.md-sync-events-outlook-button.mbsc-button {
    text-transform: capitalize;
}

.md-sync-events-outlook-inset {
    margin-bottom: 0;
}

@media (max-width: 800px) {
    .md-sync-events-outlook-cont.mbsc-page {
        display: block;
        height: auto;
    }
}

/* loading spinner and overlay */

.md-loading-events .md-sync-events-overlay {
    position: absolute;
    z-index: 2;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}

.md-spinner {
    visibility: hidden;
    position: relative;
    width: 20px;
    height: 20px;
}

.md-loading-events .md-spinner {
    visibility: visible;
}

.md-spinner .md-spinner-blade {
    position: absolute;
    left: 44.5%;
    top: 37%;
    width: 10%;
    height: 25%;
    border-radius: 50%/20%;
    background-color: #8C8C8C;
    -webkit-animation: md-spinner-fade 1s linear infinite;
    animation: md-spinner-fade 1s linear infinite;
    -webkit-animation-play-state: paused;
    animation-play-state: paused;
}

.md-spinner .md-spinner-blade:nth-child(1) {
    -webkit-animation-delay: -1.66667s;
    animation-delay: -1.66667s;
    -webkit-transform: rotate(30deg) translate(0, -150%);
    transform: rotate(30deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(2) {
    -webkit-animation-delay: -1.58333s;
    animation-delay: -1.58333s;
    -webkit-transform: rotate(60deg) translate(0, -150%);
    transform: rotate(60deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(3) {
    -webkit-animation-delay: -1.5s;
    animation-delay: -1.5s;
    -webkit-transform: rotate(90deg) translate(0, -150%);
    transform: rotate(90deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(4) {
    -webkit-animation-delay: -1.41667s;
    animation-delay: -1.41667s;
    -webkit-transform: rotate(120deg) translate(0, -150%);
    transform: rotate(120deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(5) {
    -webkit-animation-delay: -1.33333s;
    animation-delay: -1.33333s;
    -webkit-transform: rotate(150deg) translate(0, -150%);
    transform: rotate(150deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(6) {
    -webkit-animation-delay: -1.25s;
    animation-delay: -1.25s;
    -webkit-transform: rotate(180deg) translate(0, -150%);
    transform: rotate(180deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(7) {
    -webkit-animation-delay: -1.16667s;
    animation-delay: -1.16667s;
    -webkit-transform: rotate(210deg) translate(0, -150%);
    transform: rotate(210deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(8) {
    -webkit-animation-delay: -1.08333s;
    animation-delay: -1.08333s;
    -webkit-transform: rotate(240deg) translate(0, -150%);
    transform: rotate(240deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(9) {
    -webkit-animation-delay: -1s;
    animation-delay: -1s;
    -webkit-transform: rotate(270deg) translate(0, -150%);
    transform: rotate(270deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(10) {
    -webkit-animation-delay: -0.91667s;
    animation-delay: -0.91667s;
    -webkit-transform: rotate(300deg) translate(0, -150%);
    transform: rotate(300deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(11) {
    -webkit-animation-delay: -0.83333s;
    animation-delay: -0.83333s;
    -webkit-transform: rotate(330deg) translate(0, -150%);
    transform: rotate(330deg) translate(0, -150%);
}

.md-spinner .md-spinner-blade:nth-child(12) {
    -webkit-animation-delay: -0.75s;
    animation-delay: -0.75s;
    -webkit-transform: rotate(360deg) translate(0, -150%);
    transform: rotate(360deg) translate(0, -150%);
}

.md-loading-events .md-spinner-blade {
    -webkit-animation-play-state: running;
    animation-play-state: running;
}

@-webkit-keyframes md-spinner-fade {
    0% {
        opacity: 0.85;
    }
    50% {
        opacity: 0.25;
    }
    100% {
        opacity: 0.25;
    }
}

@keyframes md-spinner-fade {
    0% {
        opacity: 0.85;
    }
    50% {
        opacity: 0.25;
    }
    100% {
        opacity: 0.25;
    }
}
```

## Implementation notes

- Use `view: { calendar: { labels: true } }` with `exclusiveEndDates: true`. Start with empty `data` - no resources are used; all calendar events appear in a single view.
- Import `outlookCalendarSync` from `@mobiscroll/calendar-integration` (a separately installed package).
- Call `outlookCalendarSync.init()` on mount with `clientId`, `redirectUri`, `onSignedIn`, and `onSignedOut`.
- **`onSignedIn`**: call `outlookCalendarSync.getCalendars()` and sort so the default calendar appears first (`c.isDefaultCalendar ? -1 : 1`). Build a `calendarData` map keyed by `c.id` storing `name` (`c.name`), `color` (`c.hexColor`), and `checked`. Set `calendarIds` to `[primaryCalId]` initially, then call `getEvents([primaryCalId], startDate, endDate)`. Angular: wrap `.then()` callbacks in `NgZone.run()`.
- **`onSignedOut`**: clear events, calendarIds, calendarData, and calendars list.
- **`onPageLoading`**: debounce by 200ms; if `outlookCalendarSync.isSignedIn()`, call `getEvents(calendarIds, args.viewStart, args.viewEnd)` and replace events. Store `args.viewStart`/`args.viewEnd` in refs for use in toggle handlers.
- **Toggle calendar** (per-calendar Switch in sidebar): enabling - push to `calendarIds`, call `getEvents([calendarId], startDate, endDate)`, append returned events; disabling - filter calendarId and events out by `event.outlookCalendarId`.
- Set `extendDefaultEvent` to return `{ color: calendarData[primaryCalendarId].color }` so newly created events use the primary calendar's color.
- **CRUD** - all four options (`clickToCreate`, `dragToCreate`, `dragToMove`, `dragToResize`) controlled by an "Enable editing" Switch (off by default):
  - **Create** (`onEventCreate`): call `outlookCalendarSync.addEvent(primaryCalendarId, event)`. On success, set the new event's color and append it; on failure, show an error toast.
  - **Update** (`onEventUpdate`): `Confirm` dialog ("Are you sure you want to update this event?" / "This action will affect your Outlook Calendar event." / "Update") → `outlookCalendarSync.updateEvent(event.outlookCalendarId, event)`. On cancel or failure, restore `args.oldEvent`.
  - **Delete** (`onEventDelete`): return `false`, `Confirm` dialog ("Delete") → `outlookCalendarSync.deleteEvent(event.outlookCalendarId, event)`, filter the event out on success.
- **Layout**: a persistent sidebar panel alongside the calendar. When not logged in: "Sync my outlook calendars" sign-in button. When logged in: editing note, "Enable editing" Switch, per-calendar Switches (label: `cal.name`), "Log out" button.
- **Custom header** (`renderHeader`, Angular: `headerTemplate`, Vue: `#header` slot): `CalendarNav` (left), loading spinner (visible while events load), then `CalendarPrev`, `CalendarToday`, `CalendarNext` (right).

## Run it in your project

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: [Google Calendar Sync](https://demo.mobiscroll.com/javascript/eventcalendar/sync-events-google-calendar.md) - Connect Google Calendar to a Javascript event calendar — authenticate users, load events, and sync create, edit, and delete actions to Google Calendar.
- Next: [Public Google Calendar Integration](https://demo.mobiscroll.com/javascript/eventcalendar/load-events-from-google-calendar.md) - Load events from a public Google Calendar into a Javascript event calendar using the integration plugin — provide your Calendar ID and API key.
