v7.3.0

Upgrade guides for Scheduler v3.0.0+

Scheduler v3.0

"Core" package

All our basic classes have been moved from lib/Common/ to lib/Core/. Please update corresponding paths in your application in case you import classes from sources.

Examples

The Validation example now uses a themeable bryntum dialog box to confirm event changes. It also illustrates how to apply time constraints programmatically to events being dragged, and how to validate event drop gestures, returning an explanatory message if the drop point is found to be invalid.

Zooming and ViewPresets

The system-supplied set of ViewPresets, and the way these can be customized has changed slightly.

A ViewPreset describes the time units into which a timeline is split, and the on-screen size of the lowest level unit. It also contains a definition of the layout of a set of headers to display above the timeline.

The header definitions are now an array, headers instead of headerConfig. These are processed in top to bottom order. This is a change from before, when they were named properties in an object with the name "middle", wherever it was in the list, at the top or the bottom being the one which attracted the "main header" status. Now mainHeaderLevel and columnLinesFor are numeric configs which reference which header level is the main one, and which defines the column lines.

Events

Before the ViewPreset of a Scheduler is changed, the beforePresetChange event is fired. This is vetoable. The beforeZoomChange is fired too, but is deprecated and will be removed in version 4.0.0 After the ViewPreset of a Scheduler has changed, the presetChange event is fired. This is vetoable. The zoomChange is fired too, but is deprecated and will be removed in version 4.0.0

The system-supplied set of ViewPresets is still the same. There is a set of predefined ViewPresets stored in the PresetManager, which is now a PresetStore.

System-supplied ViewPresets

  • secondAndMinute - creates 2 level header - minute and seconds within it.
  • minuteAndHour - creates 2 level header - hour and minutes within it.
  • hourAndDay - creates 2 level header - day and hours within it.
  • dayAndWeek - creates 2 level header - week and days within it.
  • weekAndDay - just like dayAndWeek but with different formatting.
  • weekAndDayLetter - creates 2 level header - with weeks and day letters within it.
  • weekAndMonth - creates 2 level header - month and weeks within it.
  • weekDateAndMonth - creates 2 level header - month and weeks within it (weeks shown by first day only).
  • monthAndYear - creates 2 level header - year and months within it.
  • year - creates 2 level header - year and quarters within it.
  • manyYears - creates 2 level header - 5-years and year within it.

Presets automatically copied into each Scheduler

Schedulers now import an expanded, preconfigured set of these standard ViewPresets into their own PresetStore which is accessed using myScheduler.presets.

A PresetStore is automatically sorted into zoom order. That is, it is sorted according to the widths of events rendered to the screen as a result of their configurations.

These encapsulate the zoom levels which are available. A zoom level now is a ViewPreset. There is a direct mapping between a numeric zoom level and a ViewPreset in the Scheduler's presets - it is simply the index of the ViewPreset in the Scheduler's PresetStore.

A new ViewPreset may be added to a preset store which is either fully configured, or which is based upon one of the predefined presets mentioned in the PresetManager's API docs.

So you may extend existing preset and set it as current preset:

myScheduler.viewPreset = {
    base            : 'hourAndDay', // Based on existing preset id. See above or PresetManager docs
    id              : 'MyHourAndDay',
    tickWidth       : 25,
    columnLinesFor  : 0,
    mainHeaderLevel : 1,
    headers         : [
        {
            unit       : 'd',
            align      : 'center',
            dateFormat : 'ddd DD MMM'
        },
        {
            unit       : 'h',
            align      : 'center',
            dateFormat : 'HH'
        }
    ]
};

This adds a new ViewPreset to the Scheduler which is a slightly reconfigured version of the system-supplied hourAndDay preset. It will be inserted into the store in zoom-level order, and will become another zoom level.

Or you can add new preset to the store and set as current preset later if needed:

myScheduler.presets.add({
    base            : 'hourAndDay', // Based on existing preset id. See above or PresetManager docs
    id              : 'MyHourAndDay',
    tickWidth       : 25,
    columnLinesFor  : 0,
    mainHeaderLevel : 1,
    headers         : [
        {
            unit       : 'd',
            align      : 'center',
            dateFormat : 'ddd DD MMM'
        },
        {
            unit       : 'h',
            align      : 'center',
            dateFormat : 'HH'
        }
    ]
});

myScheduler.viewPreset = 'MyHourAndDay';

Notice that the headers are now configured as an array, and are displayed in the order specified.

The attachment of column lines to a specific header level is now explicit rather than relying on which header was configured under the property name "middle".

zoomLevels config

Scheduler's zoomLevels config was removed. Scheduler's PresetStore is now the source of zoom levels. To see specified levels you can dump in console:

myScheduler.presets.records

The line above returns an array of ViewPreset objects used for zooming.

To specify zoom levels for a Scheduler, you need to specify scheduler.presets, for example:

const myScheduler = new Scheduler({
    presets    : [
        {
            base : 'hourAndDay',
            id   : 'MyHourAndDay',
            // other preset configs....
        },
        {
            base : 'weekAndMonth',
            id   : 'MyWeekAndMonth',
            // other preset configs....
        }
    ],
    viewPreset : 'MyHourAndDay',
    // other scheduler configs....
});

So Scheduler is configured with 2 view presets (2 zoom levels) and one of them is set as the default.

The same can be done on the fly:

const myScheduler = new Scheduler({
    viewPreset : 'hourAndDay',
    // other scheduler configs....
});

myScheduler.presets.removeAll();

myScheduler.presets.add([
    {
        base : 'hourAndDay',
        id   : 'MyHourAndDay'
    },
    {
        base : 'weekAndMonth',
        id   : 'MyWeekAndMonth'
    }
]);

myScheduler.viewPreset = 'MyHourAndDay';

Making application-wide changes

For an application-wide addition of a new preset, use

const addedPresets = PresetManager.add({
    id              : 'myNewPreset',
    base            : 'hourAndDay', // Based on an existing preset
    tickWidth       : 25,
    columnLinesFor  : 0,
    mainHeaderLevel : 1,
    headers         : [
        {
            unit       : 'd',
            align      : 'center',
            dateFormat : 'ddd DD MMM'
        },
        {
            unit       : 'h',
            align      : 'center',
            dateFormat : 'HH'
        }
    ]
});

After that, all new created Schedulers will contain that preset in their presets which returns Scheduler's PresetStore, and it will be part of the available zoom levels. Not forgetting, above: "A PresetStore is automatically sorted into zoom order".

const myNewScheduler = new Scheduler({
    viewPreset : 'myNewPreset',
    // other scheduler configs....
});

Note, changes applied to PresetManager store do not affect existing Scheduler's PresetStore. You could then either add that new preset directly to a Scheduler:

myScheduler.presets.add(addedPresets);

Or add a preset to a Scheduler using base : 'myNewPreset' to create a slightly modified version of that preset:

myScheduler.presets.add({
    base : 'myNewPreset',
    id   : 'TheNewestPreset'
    // other preset configs....
});

Examples

Old code:

PresetManager.registerPreset('dayNightShift', {
    tickWidth         : 35,
    rowHeight         : 32,
    displayDateFormat : 'HH:mm',
    shiftIncrement    : 1,
    shiftUnit         : 'day',
    timeResolution    : {
        unit      : 'minute',
        increment : 15
    },
    defaultSpan  : 24,
    headerConfig : {
        bottom : {
            unit       : 'hour',
            increment  : 1,
            dateFormat : 'H'
        },
        middle : {
            unit      : 'hour',
            increment : 12,
            renderer(startDate, endDate, headerConfig, cellIdx) {
                if (startDate.getHours() === 0) {
                    // Setting a custom CSS on the header cell element
                    headerConfig.headerCellCls = 'b-fa b-fa-moon';
                    return DateHelper.format(startDate, 'MMM DD') + ' Night Shift';
                }
                else {
                    // Setting a custom CSS on the header cell element
                    headerConfig.headerCellCls = 'b-fa b-fa-sun';
                    return DateHelper.format(startDate, 'MMM DD') + ' Day Shift';
                }
            }
        },
        top : {
            unit       : 'day',
            increment  : 1,
            dateFormat : 'MMMM Do YYYY'
        }
    }
});

New code:

PresetManager.registerPreset('dayNightShift', {
    name              : 'Day/night shift (custom)',
    tickWidth         : 35,
    rowHeight         : 32,
    displayDateFormat : 'HH:mm',
    shiftIncrement    : 1,
    shiftUnit         : 'day',
    timeResolution    : {
        unit      : 'minute',
        increment : 15
    },
    defaultSpan     : 24,
    mainHeaderLevel : 1,
    headers         : [
        {
            unit       : 'day',
            increment  : 1,
            dateFormat : 'MMMM Do YYYY'
        },
        {
            unit      : 'hour',
            increment : 12,
            renderer(startDate, endDate, headerConfig, cellIdx) {
                if (startDate.getHours() === 0) {
                    // Setting a custom CSS on the header cell element
                    headerConfig.headerCellCls = 'b-fa b-fa-moon';
                    return DateHelper.format(startDate, 'MMM DD') + ' Night Shift';
                }
                else {
                    // Setting a custom CSS on the header cell element
                    headerConfig.headerCellCls = 'b-fa b-fa-sun';
                    return DateHelper.format(startDate, 'MMM DD') + ' Day Shift';
                }
            }
        },
        {
            unit       : 'hour',
            increment  : 1,
            dateFormat : 'H'
        }
    ]
});

Notice that the headers are configured as an array, and instead of the property name middle attracting "main header" status, and therefore dictating the tick size, the mainHeaderLevel is explicitly defined as an index.

Export to PDF/PNG

Added a new feature which allows exporting Scheduler content into a PDF/PNG file. Several new demos are added: a generic JS example and demos for Angular, React and Vue frameworks. The feature uses a special export server, that can be found in examples/_shared/server folder. For more instruction please see README.md file in the demos folders.

Scheduler v3.0.1

Showing remote content with the EventTooltip feature

EventTooltip never properly supported loading async content. Support for this has now been added, which you can try out in the updated tooltips demo. To load remote data into an event tooltip, simply do

new Scheduler({
    features : {
        eventTooltip : {
            template : ({ eventRecord }) => AjaxHelper.get(`./tooltip.php?id=${eventRecord.id}`).then(response => response.text())
        }
    }
});

More details and examples in the updated EventTooltip docs.

Scheduler v3.1.0

Context menu

Base class

TimeSpanRecordContextMenuBase class was deprecated. Common functionality was moved to ContextMenuBase class, and functionality related to TimeAxis was moved to TimeSpanMenuBase class.

HeaderContextMenu feature for TimeAxis

HeaderContextMenu feature was replaced by TimeAxisHeaderMenu. TimeAxisHeaderMenu extends HeaderMenu to provide TimeAxis specific header menu items. extraItems config was turned into items which is a named object:

Old code:

const scheduler = new Scheduler({
    features : {
        headerContextMenu : {
            extraItems : [
                {
                    text : 'Extra',
                    onItem() { ... }
                }
            ],

            processItems({ items }) {
                items.push({
                    text : 'Cool action',
                    onItem() { ... }
                }
            }
        }
    }
});

New code:

const scheduler = new Scheduler({
    features : {
        timeAxisHeaderMenu : {
            items : {
                myExtraItem : {
                    text : 'Extra',
                    onItem() { ... }
                }
            },

            processItems({ items }) {
                items.coolItem = {
                    text : 'Cool action',
                    onItem() { ... }
                }
            }
        }
    }
});

Disable menu for locked grid

To disable header/cell context menu for locked grid, but leave it for normal grid please follow this way:

Old code:

const scheduler = new Scheduler({
    features : {
        contextMenu : {
            processHeaderItems : ({ column }) => column instanceof TimeAxisColumn,
            processCellItems   : () => false
        }
    }
});

New code:

const scheduler = new Scheduler({
    features : {
        headerMenu : false // it doesn't turn off context menu for time axis column header now
        cellMenu   : false
    }
});

There is no "Context" in naming

We got rid of Context in EventContextMenu and ScheduleContextMenu features to follow the same naming standards in all products. So now they are called EventMenu and ScheduleMenu correspondingly.

Context menu events

Some of Scheduler's events provided by EventContextMenu and ScheduleContextMenu features were replaced by EventMenu and ScheduleMenu features correspondingly.

Here is the list of changes:

  • eventContextMenuBeforeShow -> eventMenuBeforeShow;
  • eventContextMenuShow -> eventMenuShow;
  • eventContextMenuItem -> eventMenuItem;
  • scheduleContextMenuBeforeShow -> scheduleMenuBeforeShow;
  • scheduleContextMenuShow -> scheduleMenuShow;
  • scheduleContextMenuItem -> scheduleMenuItem;

For example:

Old code:

const scheduler = new Scheduler({
    listeners : {
        eventContextMenuBeforeShow : () => {...}
        eventContextMenuShow : () => {...}
        eventContextMenuItem : () => {...}
        scheduleContextMenuBeforeShow : () => {...}
        scheduleContextMenuShow : () => {...}
        scheduleContextMenuItem : () => {...}
    }
});

New code:

const scheduler = new Scheduler({
    listeners : {
        eventMenuBeforeShow : () => {...}
        eventMenuShow : () => {...}
        eventMenuItem : () => {...}
        scheduleMenuBeforeShow : () => {...}
        scheduleMenuShow : () => {...}
        scheduleMenuItem : () => {...}
    }
});

Scheduler v3.1.5

Customising the content of ScheduleTooltip generateTipContent

ScheduleTooltip´s getHoverTipHtml is now deprecated for public use and generateTipContent is the method to use to fully control the markup of each hovered date/resource point in the schedule. Example:

const scheduler = new Scheduler({
    features : {
        scheduleTooltip : {
            generateTipContent({ date, event, resourceRecord }) {
                return `
                    <dl>
                        <dt>Date</dt><dd> ${date}</dd>
                        <dt>Resource</dt><dd> ${resourceRecord.name}</dd>
                    </dl>
                `;
            }
        }
    }
});

Scheduler v3.1.6

Angular, React and Vue schedulerEngine has been renamed to schedulerInstance

To avoid confusing the calculating engine with the instance of Bryntum Scheduler, schedulerEngine has been renamed to schedulerInstance. The change is backwards compatible hence applications using schedulerEngine will still work, but with deprecation warning in the console.

Change all occurrences of schedulerEngine to schedulerInstance in your Angular, React or Vue application to get rid of the warning and to make the application consistent with Bryntum Scheduler wrapper naming.

Contents