Interactive Bootstrap 5 Event Calendar Plugin - jQuery bs-calendar

File Size: 343 KB
Views Total: 280
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Interactive Bootstrap 5 Event Calendar Plugin - jQuery bs-calendar

bsCalendar is a simple yet robust jQuery plugin for creating responsive, customizable, full-featured event calendars styled with the latest Bootstrap 5 framework.

It handles the basics well: rendering the calendar grid, switching calendar views, basic localization, and fetching event data from a backend.

You get controls for navigation, adding events (by clicking empty areas), and interacting with existing events (click to update/remove). 

Key Features:

  • Bootstrap 5 based: Uses Bootstrap's grid, components, and styling for a consistent look.
  • Multiple Views: Switch between day, week, month, and year displays.
  • Dynamic Data Loading: Fetch appointments/events from a backend API using the url option.
  • Interactive Events: Click empty cells to add events, click existing events for potential updates/removals (requires custom handling).
  • Customizable Options: Configure locale, start day of the week, colors, icons, available views, and more.
  • Light/Dark Mode: Adapts to Bootstrap's color modes.
  • Localization: Translate labels like 'Day', 'Week', 'Today', etc., via the translations option.
  • Search Functionality: Basic appointment search capability (if enabled).
  • API Methods: Programmatically refresh, clear, update options, or destroy the calendar instance.

How to use it:

1. To get started, make sure you have jQuery library, Bootstrap framework, and Bootstrap Icons loaded in your document.

<!-- jQuery -->
<script src="/path/to/cdn/jquery.min.js"></script>

<!-- Bootstrap -->
<link rel="stylesheet" href="/path/to/cdn/bootstrap.min.css" />
<script src="/path/to/cdn/bootstrap.bundle.min.js"></script>

<!-- Bootstrap Icons -->
<link rel="stylesheet" href="/path/to/cdn/bootstrap-icons.min.css">

2. Download the plugin and add the 'bs-calendar.min.js' script to the document.

<script src="/path/to/dist/bs-calendar.min.js"></script>

3. Create a container to hold the event calendar.

<div id="myCalendar">
</div>

4. Initialize bs-calendar with default options.

$(document).ready(function() {
  $('#myCalendar').bsCalendar({
    // options here
  });
});

5. Add custom holidays to the calendar. It also supports for public holidays API integration. See 'openHolidays.js' in the zip for details.

$('#myCalendar').bsCalendar({
  holidays: function (data) {
    return new Promise((resolve, reject) => {
      Extract the start and end years from the input
      const startYear = new Date(data.start).getFullYear();
      const endYear = new Date(data.end).getFullYear();
      const locale = getLanguageAndCountry(data.locale);
      const openHolidays = new OpenHolidays();
      openHolidays.getPublicHolidays(locale.country, startYear + '-01-01', endYear + '-12-31', locale.language)
      .then(response => {
        console.log(response);
        const holidays = [];
        for (const holiday of response) {
          holidays.push({
            startDate: holiday.startDate,
            endDate: holiday.endDate,
            title: holiday.name[0].text,
          });
        }
        resolve(holidays); 
      })
      .catch(error => {
        reject(error); 
      });
    });
  },
});

6. Fetch data dynamically via the url option. When the view changes or the calendar loads initially, the internal fetchAppointments function kicks in:

  • It determines the required date range (fromDate, toDate) based on the current view or the year for the year view. If searching, it uses the search term.
  • It constructs a requestData object containing these parameters (view, fromDate, toDate or year or search).
  • If queryParams is defined, it calls that function to potentially add more data to the request (like user IDs, filters).
  • It makes an AJAX request (or calls your provided function) using the url and the requestData. It expects a JSON response containing an array of appointment objects, including id, title, start, end, allDay, color, etc.
  • On success, it processes the returned appointments and renders them onto the calendar grid. It positions them based on their start/end dates and times.
  • Error handling is included, and debug: true helps trace this process.
$(document).ready(function() {
  $('#myCalendar').bsCalendar({
    url: url
  });
});
// Example
async function url(query) {
  console.log('index url', query);
  await sleep(Math.floor(Math.random()));
  return new Promise((resolve, reject) => {
    try {
      const fromDate = query.fromDate ? new Date(`${query.fromDate}T00:00:00`) : null;
      const toDate = query.toDate ? new Date(`${query.toDate}T23:59:59`) : null;
      const search = query.search;
      if (search && !fromDate && !toDate) {
        const limit = query.limit;
        const offset = query.offset;
        return resolve(getAppointmentsBySearch(search, limit, offset));
      }

      if (query.view === 'year') {
        return resolve(generateDates(query.year));
      }
      const appointments = generateRandomAppointments(
        (fromDate || new Date('1970-01-01T00:00:00')).toISOString(),
        (toDate || new Date('9999-12-31T23:59:59')).toISOString(),
        query.view
      );
      const filteredAppointments = appointments.filter(appointment => {
        const appointmentStart = new Date(appointment.start);
        const appointmentEnd = new Date(appointment.end);
        return (
          (!fromDate || appointmentStart >= fromDate) &&
          (!toDate || appointmentEnd <= toDate)
        );
      });
      if (search) {
        const searchFilteredAppointments = filteredAppointments.filter(appointment => {
          return appointment.title.toLowerCase().includes(search.toLowerCase());
        });
        return resolve(searchFilteredAppointments);
      }
      resolve(filteredAppointments);
    } catch (error) {
        reject(error);
    }
  });
}

7. More configuration options:

$('#myCalendar').bsCalendar({
  locale: 'en-UK',
  title: 'Calendar',
  startWeekOnSunday: true,
  navigateOnWheel: true,
  rounded: 5, // 1-5
  search: {
    limit: 10,
    offset: 0
  },
  startDate: new Date(),
  startView: 'month', // day, week, month, year
  defaultColor: 'primary',
  views: ['year', 'month', 'week', 'day'],
  holidays: null, //  an object containing 'federalState', 'country', and 'language'
  translations: {
    day: 'Day',
    week: 'Week',
    month: 'Month',
    year: 'Year',
    today: 'Today',
    appointment: 'Appointment',
    search: 'Type and press Enter',
    searchNoResult: 'No appointment found'
  },
  icons: {
    day: 'bi bi-calendar-day',
    week: 'bi bi-kanban',
    month: 'bi bi-calendar-month',
    year: 'bi bi-calendar4',
    add: 'bi bi-plus-lg',
    menu: 'bi bi-list',
    search: 'bi bi-search',
    prev: 'bi bi-chevron-left',
    next: 'bi bi-chevron-right',
    link: 'bi bi-box-arrow-up-right',
    appointment: 'bi bi-clock',
    appointmentAllDay: 'bi bi-brightness-high'
  },
  url: null,
  queryParams: null,
  topbarAddons: null,
  sidebarAddons: null,
  debug: false,
  formatter: {
    day: formatterDay,
    week: formatterWeek,
    month: formatterMonth,
    search: formatterSearch,
    holiday: formatterHoliday,
    window: formatInfoWindow,
    duration: formatDuration,
  },
  hourSlots: {
    height: 30, // one hour in px
    start: 0, // starting hour as integer
    end: 24 // ending hour as integer
  }
});

8. API methods.

// Reloads the current view data.
$('#myCalendar').bsCalendar('refresh');

// Removes all displayed appointments.
$('#myCalendar').bsCalendar('clear');

// Change options on the fly.
$('#myCalendar').bsCalendar('updateOptions', { startView: 'week' });

// Remove the calendar instance and clean up.
$('#myCalendar').bsCalendar('destroy');

// Jump to a specific date.
$('#myCalendar').bsCalendar('setDate', '2025-04-11');

// Jump back to the current date.
$('#myCalendar').bsCalendar('setToday');

9. Event handlers.

$('#myCalendar').on('add.bs.calendar', function (event, data) {
  // ...
})

$('#myCalendar').on('edit.bs.calendar', function (event, appointment, extras) {
  // ...
})

$('#myCalendar').on('view.bs.calendar', function (event, view) {
  // ...
})

Changelog:

2025-04-17

  • Removed the unused OpenHolidays.js file and adjusted the bs-calendar defaults including locale, wheel navigation, and title formatting. 

2025-04-16

  • Add dynamic current-time indicator and refactor slot handling

2025-04-15

  • Enhance holiday settings and rendering logic.

2025-04-14

  • Refactor holiday loading and improve settings structure

2025-04-12

  • Add support for school holidays in calendar

This awesome jQuery plugin is developed by ThomasDev-de. For more Advanced Usages, please check the demo page or visit the official website.