Apply a complex filter to rooms and reservations displayed using JavaScript Scheduler component. The filter has two parameters:

  • Select the target date range using drag and drop

  • Select room size using a drop down list

If you select a date range, only rooms that are available between these days will be displayed.

The project includes a trial version of DayPilot Pro for JavaScript (see License below).


Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.

Filter Available Rooms by Date

We will keep the room filter parameters in a global variable called filter. The variable has two properties (range, size).

  • The filter.range property will hold the selected date range.

  • The filter.size property will hold the requested room size.

var filter = {
  range: null,
  size: null

Our users will be able to select a date range using the Navigator component:. The Navigator lets them select a date range unit defined by selectMode property (day/week/month). In addition to that, we will also enable a free-hand selection of a custom date range using freeHandSelectionEnabled property.


The Scheduler will use the dates to check availability of each room and hide rooms that are not available.

var nav = new DayPilot.Navigator("nav");
nav.freeHandSelectionEnabled = true;
nav.onTimeRangeSelected = function(args) {
  filter.range = {
    start: args.start,
    end: args.end

The onTimeRangeSelected event handler of the DayPilot.Navigator object is fired when the user selects a date range. It saves the selected dates in range property of the filter object and calls applyRoomFilter() to update the Scheduler.

Note that the freeHandSelectionEnabled property allows selecting custom date range using drag and drop in the Navigator.


The applyRoomFilter() method calls rows.filter() method to apply the filter to the Scheduler and displays a label with the selected dates:

function applyRoomFilter() {

  // apply the filter

  // display the label
  if (filter.range) {
    elements.filterDate.style.display = "inline-block";
    elements.filterDateString.innerText = filter.range.start.toString("M/d/yyyy") + " - " + filter.range.end.addDays(-1).toString("M/d/yyyy");
  else {
    elements.filterDate.style.display = "none";


Filter Rooms by Size


The room size filter is created using a simple <select> element:

<select id="filter-size">
  <option value="0">All rooms</option>
  <option value="2">2+ beds</option>
  <option value="3">3+ beds</option>
  <option value="4">4+ beds</option>

We will watch for changes of the selected value and store the filter value in filter.size. The applyRoomFilter() call updates the Scheduler.

elements.filterSize.addEventListener("change", function(ev) {
  filter.size = elements.filterSize.value;

Room Filtering Logic

Whenever the rows.filter() method is called from applyRoomFilter() the Scheduler updates itself and calls onRowFilter event handler for each room (row) to determine the visibility. See also row filtering [doc.daypilot.org].

Each condition is tested separately and the row is only marked visible if both of them are met.

  • The dateMatches value is calculated by checking the if there are any events (reservations). The args.row.events.forRange() method returns all reservations that overlap the specified range. The room is available if there are no reservations found.

  • The sizeMatches value is calculated by comparing the size filter parameter with room size stored in resources.

Note: In this case, we access the filter parameters using the global variable (filter). The applyRoomFilter() method uses the filter as a parameter for rows.filter() call. That makes it available as args.filter inside onRowFilter event handler.

dp.onRowFilter = function(args) {
  var sizeMatches = args.row.data.size >= filter.size;
  var dateMatches = !filter.range || args.row.events.forRange(filter.range.start, filter.range.end).length === 0;

  args.visible = sizeMatches && dateMatches;

The room sizes are stored in resources array as an additional property:

dp.resources = [
  {name: "Room 101", id: "R101", size: 1},
  {name: "Room 102", id: "R102", size: 3},
  {name: "Room 103", id: "R103", size: 2},
  {name: "Room 104", id: "R104", size: 4},
  {name: "Room 105", id: "R105", size: 2},
  {name: "Room 106", id: "R106", size: 2},
  {name: "Room 107", id: "R107", size: 2},
  {name: "Room 108", id: "R108", size: 2},
  {name: "Room 109", id: "R109", size: 4},
  {name: "Room 110", id: "R110", size: 3},
  {name: "Room 111", id: "R111", size: 2},
  {name: "Room 112", id: "R112", size: 2},

Highlighting the Date Range in the Scheduler


The selected range is highlighted in the time header using onBeforeTimeHeaderRender event handler:

dp.onBeforeTimeHeaderRender = function(args) {
  if (filter.range) {
    if (args.header.level === 1 && DayPilot.Util.overlaps(filter.range.start, filter.range.end, args.header.start, args.header.end)) {
      args.header.backColor = "#6aa84f";
      args.header.fontColor = "#fff";

The Scheduler grid cells are highlighted using onBeforeCellRender event handler:

dp.onBeforeCellRender = function(args) {
  if (filter.range) {
    if (DayPilot.Util.overlaps(args.cell.start, args.cell.end, filter.range.start, filter.range.end)) {
      args.cell.backColor = "#b6d7a8";

Both event handlers access the filter global variable that stores the filter parameters.