Features

This tutorial uses the event calendarmonthly calendar, and date picker components from the open-source DayPilot Lite for javaScript package to build a simple HTML5/JavaScript calendar application with integrated day, week, and month views.

  • Daily, weekly and monthly event calendars that provide different views of the same data

  • Date navigator for changing the current date

  • All calendar components support drag and drop event creating, moving and resizing

  • Simplified calendar data loading using the built-in events.load() method

  • PHP backend that provides access to the database using REST API

  • MySQL and SQLite database

License

Apache License 2.0

Online Calendar Configurator

With the UI Builder app, you can configure calendar features and download a ready-to-run project for JavaScript, TypeScript, Angular, React, or Vue.

HTML5/JavaScript Daily Calendar

html5 javascript daily event calendar php mysql

The daily calendar view is built using DayPilot.Calendar class with viewType set to "Day". This view displays a calendar for 24 hours of a single day. By default, the viewport is limited to business hours (predefined as 9 a.m. to 6 p.m.). Users can access the remaining hours using a vertical scrollbar.

The daily calendar will be rendered in a placeholder <div> which is marked with id="dpDay". The DayPilot.Calendar instance is stored in day JavaScript variable.

HTML5

<div id="dpDay"></div>

JavaScript

<script type="text/javascript">

  const day = new DayPilot.Calendar("dpDay");
  day.viewType = "Day";
  day.init();

</script>

HTML5/JavaScript Weekly Calendar

html5 javascript weekly event calendar php mysql

The weekly calendar is built using DayPilot.Calendar class with viewType set to "Week". You can see that the weekly calendar is built using the same DayPilot.Calendar component. However, this time it uses a different placeholder div (id="dpWeek") and it creates a different instance (stored as week variable). This allows us to work with both instances at once. When switching between view, we will simply hide or show the instances as needed. This way, we will avoid the overhead of creating and destroying the calendar instances when switching views.

As you can see, the configuration is very simple - the only property we define is the viewType.

HTML5

<div id="dpWeek"></div>

JavaScript

<script type="text/javascript">

  const week = new DayPilot.Calendar("dpWeek");
  week.viewType = "Week";
  week.init();

</script>

HTML5/JavaScript Monthly Calendar

html5 javascript monthly event calendar php mysql

The monthly calendar view is built using DayPilot.Month class. This time it's a different class that represents the month view which uses a different layout. As in the previous cases, we use a special placeholder (id="dpMonth") and store the instance as month variable.

HTML5

<div id="dpMonth"></div>

JavaScript

<script type="text/javascript">

  const month = new DayPilot.Month("dpMonth");
  month.init();

</script>

Loading Calendar Event Data

html5 javascript event calendar day week month loading data

The day/week (DayPilot.Calendar) and month (DayPilot.Month) calendar components support events.load() shortcut method for loading events:

dp.events.load("calendar_events.php");

You can use this method to load events from a remote data source. It expects a JSON array with calendar event data as a response.

It automatically adds the start and end of the current view as query string parameters to the specified URL. You can use these parameters to limit the SQL query on the server side.

PHP (calendar_events.php)

<?php
require_once '_db.php';

// .events.load() passes start and end as query string parameters by default
$start = $_GET["start"];
$end = $_GET["end"];
    
$stmt = $db->prepare('SELECT * FROM events WHERE NOT ((end <= :start) OR (start >= :end))');

$stmt->bindParam(':start', $start);
$stmt->bindParam(':end', $end);

$stmt->execute();
$result = $stmt->fetchAll();

class Event {}
$events = array();

foreach($result as $row) {
  $e = new Event();
  $e->id = $row['id'];
  $e->text = $row['name'];
  $e->start = $row['start'];
  $e->end = $row['end'];
  $e->backColor = $row['color'];
  $events[] = $e;
}

header('Content-Type: application/json');
echo json_encode($events);

The sample MySQL database uses a simple schema with just one table called events:

CREATE TABLE `events` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` TEXT NULL,
	`start` DATETIME NOT NULL,
	`end` DATETIME NOT NULL,
        `color` VARCHAR(30),
	PRIMARY KEY (`id`)
);

How Does events.load() Work

The dp.events.load() method is a shortcut method that updates the calendar data using an HTTP call.

The calendar event data is stored in dp.events.list array. Example:

dp.events.list = [
  {
    "start": "2023-09-16T10:30:00",
    "end": "2023-09-16T12:00:00",
    "id": "2",
    "text": "Meeting"
  }
];

You can load the data during the initial page load:

<div id="dp"></div>

<script type="text/javascript">

  const dp = new DayPilot.Calendar("dp");
  dp.viewType = "Week";
  dp.events.list = [
   {
    "start": "2023-09-16T10:30:00",
    "end": "2023-09-16T12:00:00",
    "id": "2",
    "text": "Meeting"
   }
  ];
  dp.init();

</script>

You can also load the data using a separate HTTP call (this example uses jQuery $.get() method):

<div id="dp"></div>

<script type="text/javascript">

  var dp = new DayPilot.Calendar("dp");
  dp.viewType = "Week";
  dp.init();

  $.get(
    "calendar_events.php?start=" + dp.visibleStart() + "&end=" + dp.visibleEnd(),
    function(data) {
      dp.events.list = data;
      dp.update();
    }
   );

</script>

The jQuery $.get() call can be replaced with dp.events.load():

  1. It sends a GET HTTP request that loads the calendar data in JSON format. It sends the visibleStart() date as start query string parameter and visibleEnd() date as end query string parameter.

  2. It assigns the data to dp.events.list.

  3. It updates the calendar using dp.update().

  4. You can configure the HTTP method ("POST" | "GET") using eventsLoadMethod property

JavaScript

dp.events.load("calendar_events.php");

Calendar Drag and Drop Support

We will add four events handlers:

  • onEventMoved

  • onEventResized

  • onTimeRangeSelected

  • onEventClick

The syntax of all event handlers is the same in the DayPilot.Calendar and DayPilot.Month. We can use a help method that will add the event handlers to all views.

JavaScript

function configureCalendar(dp) {

    dp.onEventMoved = async args => {
      const params = {
        id: args.e.id(),
        newStart: args.newStart,
        newEnd: args.newEnd
      };
      await DayPilot.Http.post("calendar_move.php", params);
      console.log("Moved.");
    };

    dp.onEventResized = async args => {
      const params = {
        id: args.e.id(),
        newStart: args.newStart,
        newEnd: args.newEnd
      };
      await DayPilot.Http.post("calendar_move.php", params);
      console.log("Resized.");
    };

    dp.onTimeRangeSelected = async args => {

      const form = [
        {name: "Name", id: "text"},
        {name: "Start", id: "start", dateFormat: "MMMM d, yyyy h:mm tt", disabled: true},
        {name: "End", id: "end", dateFormat: "MMMM d, yyyy h:mm tt", disabled: true},
      ];

      const data = {
        start: args.start,
        end: args.end,
        text: "Event"
      };

      const dp = switcher.active.control;

      const modal = await DayPilot.Modal.form(form, data);
      dp.clearSelection();

      if (modal.canceled) {
        return;
      }

      const {data: result} = await DayPilot.Http.post("calendar_create.php", modal.result);

      dp.events.add({
        start: data.start,
        end: data.end,
        id: result.id,
        text: data.text
      });

    };

    dp.onEventClick = args => {
      DayPilot.Modal.alert(args.e.data.text);
    };

}

Date Navigator

html5 javascript date picket calendar navigator

The last missing piece of the UI is a date navigator (date picker) that will let the users switch the visible date.

HTML5

<div id="nav"></div>

JavaScript

<script type="text/javascript">
  const nav = new DayPilot.Navigator("nav");
  nav.showMonths = 3;
  nav.skipMonths = 3;
  nav.init();
</script>

Switching the Day/Week/Month Views

html5 javascript event calendar day week month php mysql switching

Now it's time to assemble all components and views into a complex calendar view. We have the following components:

  • buttons for switching the current view (simple <a> links with "Day", "Week", and "Month" text)

  • day, week, and month views (DayPilot.Calendar, DayPilot.Month objects)

  • navigator (DayPilot.Navigator)

We will use the DayPilot.Switcher helper to bind all calendar components together.

HTML5

<div style="display:flex">
  <div style="">
    <div id="nav"></div>
  </div>
  <div style="flex-grow: 1; margin-left: 10px;">
    <div class="toolbar buttons">
      <span class="toolbar-item"><a id="buttonDay" href="#">Day</a></span>
      <span class="toolbar-item"><a id="buttonWeek" href="#">Week</a></span>
      <span class="toolbar-item"><a id="buttonMonth" href="#">Month</a></span>
    </div>
    <div id="dpDay"></div>
    <div id="dpWeek"></div>
    <div id="dpMonth"></div>
  </div>
</div>

JavaScript

<script type="text/javascript">

  // initialize the date navigator
  const nav = new DayPilot.Navigator("nav");
  nav.showMonths = 3;
  nav.skipMonths = 3;
  nav.init();
                 
  // initialize the day view
  const day = new DayPilot.Calendar("dpDay");
  day.viewType = "Day";
  configureCalendar(day);
  day.init();

  // initialize the week view
  const week = new DayPilot.Calendar("dpWeek");
  week.viewType = "Week";
  configureCalendar(week);
  week.init();

  // initialize the month view
  const month = new DayPilot.Month("dpMonth");
  configureCalendar(month);
  month.init();

  // ...

  const switcher = new DayPilot.Switcher({
      triggers: [
          {id: "buttonDay", view: day },    // link buttonDay to day view
          {id: "buttonWeek", view: week},   // link buttonWeek to week view
          {id: "buttonMonth", view: month}  // link buttonMonth to month view
      ],
      navigator: nav,
      selectedClass: "selected-button",  // add this class to the selected trigger
      onChanged: args => {
          switcher.events.load("calendar_events.php");   // action to be performed when the view or date changes - reload the events for the current view
      }
  });
  
  switcher.select("buttonWeek");

</script>

History

  • April 4, 2023: Switched to the open-source DayPilot Lite for JavaScript 2023.2.452.

  • June 4, 2021: Upgraded to DayPilot Pro for JavaScript 2021.2.5000. Using ES6+ syntax, including async/await. DayPilot.Http.get() and DayPilot.Http.post() methods instead of DayPilot.Http.ajax().

  • August 6, 2020: Upgraded to DayPilot Pro for JavaScript 2020.3.4619. Context menu added (color, event deleting). jQuery dependency removed. CSS styles updated.

  • September 19, 2019: Upgraded to DayPilot Pro for JavaScript 2019.3.4012. Support for MySQL. Using DayPilot.Modal.prompt().

  • June 27, 2017: Upgraded to DayPilot Pro for JavaScript 8.4.2911

  • June 15, 2015: Initial release