TimeRanges
This feature provides an easy way to highlight ranges of time in a calendar's day and week views. Each time range is represented using the TimeRangeModel.
//<code-header>
fiddle.title = 'Time ranges';
//</code-header>
const calendar = new Calendar({
// Features named by the properties are included.
features : {
// Enable and optionally configure the timeRanges feature:
timeRanges : {
// configuration goes here
}
},
// Start life in day view at this date
date : '2020-03-03',
mode : 'day',
// Modes are the views available in the Calendar.
// An object is used to configure the view.
modes : {
day : {
dayStartTime : 8
},
week : {
dayStartTime : 8
},
agenda : null,
month : null,
year : null
},
// Used to create view titles
dateFormat : 'DD MMM YYYY',
hideNonWorkingDays : true,
// The utility panel which is at the left by default.
// Not enough width here, so don't include it.
sidebar : false,
// CrudManager arranges loading and syncing of data in JSON form from/to a web service
crudManager : {
autoLoad : true,
loadUrl : 'data/Calendar/examples/feature/time-ranges.json'
},
appendTo : targetElement,
height : 700
});TimeRange types
Time ranges can take a few different forms:
- A line at the startDate with optional tooltip based on the name.
- A styled region between the startDate and endDate. The cls field is used to apply the desired style to the time range element.
- A titled region based on the name field, between the startDate and endDate. The cls field can be used to apply the styling to the time range element. The color and iconCls fields can be used to apply a background color and icon to the header element. An optional footer can also be added.
TimeRange DOM structure
A rendered time range element is divided into three sections: a header, body, and footer laid out horizontally across
the day cell. This is achieved using flexbox column layout, but rotating the writing-mode to be vertical-rl or
vertical-lr so that text is displayed vertically and the primary axis is horizontal.
The time range's cls field is applied to the encapsulating element
in addition to the b-cal-time-range class. The arrangement is as follows:
<inset>px flexed <inset>px
┌────────────┬──────────────────────────────────┬────────────┐
│ │ │ │
│ H │ │ F │
│ e │ │ o │
│ a │ │ o │
│ d │ │ t │
│ e │ │ e │
│ r │ │ r │
│ │ │ │
└────────────┴──────────────────────────────────┴────────────┘
The visual order can be reversed by setting the alignment field to 'end'.
If the time range has a name, the header section will be rendered with that name
and will be inset pixels wide. The header section may also include an icon if the
time range has an iconCls field. The header section is rendered with the
b-cal-time-range-header CSS class.
The body section occupies the space between the header and footer sections and is rendered with the
b-cal-time-range-body CSS class.
If the time range has an footer, a footer section will also be rendered
inset pixels wide containing that text. The footer section is rendered with the
b-cal-time-range-footer CSS class.
The sections are rendered across the day cell with the name and footer text rotated. The whole element leaves the
end gutter area free. To have time ranges render across the gutter
area too, apply the CSS class b-cal-time-range-overlay-gutter to a cls time range's cls field.
The body section has no rendition by default, but can be styled using the cls
field in addition to the b-cal-time-range-body class.
A header and footer will occupy space on the inline-start and inline-end sides of the time range. This can be
reversed by specifying the alignment as 'end'.
The width of the header and footer is determined by the inset configuration of the view's layout.
The three sections of a time range can be customized using the following CSS classes:
.b-cal-time-range-header: The header element.b-cal-time-range-body: The body element.b-cal-time-range-footer: The footer element
A "part" renderer can return null to suppress visibility of a header or a footer.
Integration with ScheduleTooltip feature
The ScheduleTooltip feature's renderer will be passed hovered time ranges by default. The content may be customized as in the example below.
Resource-specific TimeRanges
To display time range elements for individual resources, you can include resourceTimeRanges in the loaded data.
You can use this feature to visualize resource specific working times for example. The results are shown in views
which display resources, such as DayResourceView or subviews of a
ResourceView. As with regular time ranges, you can include a recurrenceRule to specify
repeating patterns.
//<code-header>
fiddle.title = 'Resource time ranges';
CSSHelper.insertRule(`
.non-working-time {
.b-cal-time-range-body {
background-color : var(--b-day-view-outside-core-hours-color);
}
}
`, targetElement.getRootNode());
CSSHelper.insertRule(`.b-cal-schedule-tooltip .b-icon.fa-warning {
&::before {
color : #ae2929;
}
}
`, targetElement.getRootNode());
//</code-header>
new SlideToggle({
insertFirst : targetElement,
label : 'Show time ranges',
checked : true,
onChange({ value }) {
calendar.features.timeRanges.enabled = value;
}
});
const calendar = new Calendar({
sidebar : false,
appendTo : targetElement,
height : 700,
// Features named by the properties are included.
features : {
// Enable and optionally configure the timeRanges feature:
timeRanges : true,
scheduleTooltip : {
renderer(view, date, preciseDate, events, timeRanges) {
// Are we over non working time ranges?
const inNonWorkingTime = timeRanges.some(({ cls }) => cls['non-working-time']);
// Return the default tooltip content plus our custom info if any
return [
{ tag : 'span', html : this.defaultRenderer(view, preciseDate, events, timeRanges) },
inNonWorkingTime && {
text : 'Non-working time',
class : 'b-icon fa-warning'
}
];
}
},
// One feature, "drag" handles move, resize and create drag gestures.
drag : {
// Each drag mode has a separate validation callback.
// We route them all to one on the calendar instance
validateCreateFn : 'up.validateDrag',
validateMoveFn : 'up.validateDrag',
validateResizeFn : 'up.validateDrag'
}
},
// Called when double-click, or context menu's "New event" is triggered
onBeforeAutoCreate({ view, startDate, endDate, domEvent }) {
return this.validateEventDates(view, startDate, endDate, view.getResourceRecord?.(domEvent));
},
// Check that we never schedule anything that intersects with a disabled timeRange
validateDrag({ drag, eventRecord, event }) {
return this.validateEventDates(drag.target.view, eventRecord.startDate, eventRecord.endDate, drag.target.view.getResourceRecord?.(event));
},
validateEventDates(view, startDate, endDate, resource) {
// If creating in a DayView, enforce disabled time ranges.
if (view.isDayView) {
// If any of the disabled time ranges intersect with the event being created or moved,
// then we cannot allow the drag.
if (view.getTimeRanges(view.startDate, view.endDate, resource).some(timeRange => {
if (timeRange.cls['non-working-time']) {
if (DateHelper.intersectSpans(startDate, endDate, timeRange.startDate, timeRange.endDate)) {
Toast.show(`That is in non working time ${DateHelper.format(timeRange.startDate, 'HH:mm')} to ${DateHelper.format(timeRange.endDate, 'HH:mm')}`);
return true;
}
}
})) {
return false;
}
}
return true;
},
date : '2026-01-27',
resourceImagePath : '../examples/_shared/images/transparent-users/',
// CrudManager arranges loading and syncing of data in JSON form from/to a web service
crudManager : {
inlineData : {
resources : [
{
id : 1,
name : 'Don Taylor',
eventColor : 'blue',
image : 'dan.png'
},
{
id : 2,
name : 'Jenny Brown',
eventColor : 'deep-orange',
image : 'linda.png'
},
{
id : 3,
name : 'John Adams',
eventColor : 'orange',
image : 'malik.png'
}
],
events : [
{
id : 1,
resourceId : 1,
name : 'Make marketing plan',
startDate : '2026-01-26 11:00',
endDate : '2026-01-26 12:00',
eventType : 'Meeting'
},
{
id : 2,
resourceId : 2,
name : 'Read spec.',
startDate : '2026-01-26 12:00',
endDate : '2026-01-26 15:00'
},
{
id : 3,
resourceId : 1,
name : 'Sign documents',
startDate : '2026-01-27 13:00',
endDate : '2026-01-27 16:00'
},
{
id : 4,
resourceId : 3,
name : 'Board meeting',
startDate : '2026-01-28 09:00',
endDate : '2026-01-28 11:00',
eventType : 'Meeting'
},
{
id : 5,
resourceId : 2,
name : 'Sales call',
startDate : '2026-01-29 10:00',
endDate : '2026-01-29 12:00'
},
{
id : 6,
resourceId : 3,
name : 'Customer visit',
startDate : '2026-01-26 11:00',
endDate : '2026-01-26 13:00',
location : 'Customer office'
},
{
id : 7,
resourceId : 1,
name : 'Prepare happy hour',
startDate : '2026-01-30 14:00',
endDate : '2026-01-30 17:00'
}
],
resourceTimeRanges : [
{
id : 1,
resourceId : 1,
cls : 'non-working-time b-cal-time-range-overlay-gutter',
startDate : '2026-01-26 00:00',
endDate : '2026-01-26 09:00',
recurrenceRule : 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR'
},
{
id : 2,
resourceId : 1,
cls : 'non-working-time b-cal-time-range-overlay-gutter',
startDate : '2026-01-26 17:00',
endDate : '2026-01-27 00:00',
recurrenceRule : 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR'
},
{
id : 3,
resourceId : 2,
cls : 'non-working-time b-cal-time-range-overlay-gutter',
startDate : '2026-01-26 00:00',
endDate : '2026-01-26 10:00',
recurrenceRule : 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR'
},
{
id : 4,
resourceId : 2,
cls : 'non-working-time b-cal-time-range-overlay-gutter',
startDate : '2026-01-26 18:00',
endDate : '2026-01-27 00:00',
recurrenceRule : 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR'
}
]
}
},
tbar : null,
modes : {
day : null,
week : null,
month : null,
year : null,
agenda : null,
dayresource : {
dayStartTime : 7,
dayEndTime : 20,
hourHeight : 50,
// Save a little space by hiding weekends.
hideNonWorkingDays : true,
// Configure a nice min-width for the resource columns
minResourceWidth : '12em'
}
}
});Example data showing Resource 1 with shaded days until 9am, and Resource 2 shaded until 8am in the morning.
"resourceTimeRanges" : {
"rows" : [
{
"id" : 1,
"resourceId" : 1,
"startDate" : "2026-01-26 00:00",
"endDate" : "2026-01-26 09:00",
"recurrenceRule" : "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"
},
{
"id" : 2,
"resourceId" : 2,
"startDate" : "2026-01-26 00:00",
"endDate" : "2026-01-27 08:00",
"recurrenceRule" : "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"
}
]
}
This feature is disabled by default.
Configs
23
Configs
23Common
Other
The number of pixels or proportion of the overall width to allocate for time range headers.
Values less than 1 are the fractional proportion of the width (for example, 0.04 is 4% of the width), while values greater than or equal to 1 are a number of pixels.
An empty function by default, but provided so that you can override it.
This function is called each time a time range is rendered to allow developers to mutate the element metadata, or the CSS classes to be applied to the rendered element.
It's called with a TimeRangeRenderInfo object containing the time span record, and a
renderData object which allows you to mutate event metadata such as
cls and style.
A non-null return value from the renderer is used as the element body content. A nullish return value results in the default renderer for the element.
timeRanges : {
renderer ({ timeRange, renderData }) {
if (timeRange.name === 'Doctors appointment') {
renderData.style.fontWeight = 'bold';
renderData.cls['custom-cls'] = 1;
return 'Special doctors appointment';
}
}
}
For example:
timeRanges : {
renderer ({ timeRange, renderData }) {
return StringHelper.xss`Special ${timeRange.name}`;
}
}
For advanced rendering, this config can be a TimeRangeRenderer object with rendering
functions for individual elements: header, body, footer, and outer. When a function is provided,
that is equivalent to passing the header renderer. In other words, the above example is equivalent to
the following:
timeRanges : {
renderer : {
header({ timeRange, renderData }) {
return StringHelper.xss`Special ${timeRange.name}`;
}
}
}
Note that if the TimeRange has zero duration, it will be rendered as a line, and the header, body and footer
renderers will not add any content. The outer renderer may mutate the domConfig property to affect how
the line will be rendered.
| Parameter | Type | Description |
|---|---|---|
info | TimeRangeRenderInfo | An object that contains data about the time span being rendered. |
Misc
Properties
22
Properties
22Class hierarchy
Misc
Functions
31
Functions
31Configuration
Events
Misc
Other
Events
9
Events
9Event handlers
9
Event handlers
9Typedefs
5
Typedefs
5A mutable object used to render an element of the time range.
| Parameter | Type | Description |
|---|---|---|
record | TimeRangeModel | The record being rendered |
isLine | Boolean | This is |
color | String | The color to be applied to the element |
cls | Object | An object whose truthy property names will be added to the element's CSS |
style | Object | An object containing style properties for the element |
outer | TimeRangeRenderData | The render data for the outermost element. This property is present when rendering any of the inner elements. The outer element is rendered after all inner elements, meaning this object can be modified by an inner element renderer function. |
header | TimeRangeRenderData | The render data for the header element. This property is present when rendering the outermost element. The corresponding element has already been rendered, meaning that this object should be considered read only. |
body | TimeRangeRenderData | The render data for the body element. This property is present when rendering the outermost element. The corresponding element has already been rendered, meaning that this object should be considered read only. |
footer | TimeRangeRenderData | The render data for the footer element. This property is present when rendering the outermost element. The corresponding element has already been rendered, meaning that this object should be considered read only. |
An object containing rendering methods for the various elements of a time range. All functions are optional. The
footer function is special in that there is no footer element by default. If a footer is desired, a footer
renderer function must be provided.
| Parameter | Type | Description |
|---|---|---|
outer | function | An optional function to be called to render the outermost element. This function is passed a TimeRangeRenderInfo object. |
body | function | An optional function to be called to render the body element. This function is passed a TimeRangeRenderInfo object. |
header | function | An optional function to be called to render the header element. This function is passed a TimeRangeRenderInfo object. |
footer | function | An optional function to be called to render the footer element. This function is passed a TimeRangeRenderInfo object. |
The object passed to a renderer function.
| Parameter | Type | Description |
|---|---|---|
renderData | TimeRangeRenderData | The render data object to modify |
timeRange | TimeRangeModel | The record being rendered |
domConfig | DomConfig | The default DOM config. This is only passed to the |
CSS variables
31
CSS variables
31| Name | Description |
|---|---|
--b-calendar-time-range-border-width | Time range border width |
--b-calendar-time-range-line-size | Time range line size |
--b-calendar-time-range-line-zoom-scale | Time range line zoom scale |
--b-calendar-time-range-header-background | Time range header background |
--b-calendar-time-range-border-color | Time range border color |