import 'bootstrap.css';
import '@mescius/wijmo.styles/wijmo.css';
import './styles.css';
//
import { CollectionView } from '@mescius/wijmo';
import * as wjcScheduler from '@mescius/wijmo.scheduler';
import { getDisplayDate, getEvents, getTeams } from './data';
//
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', init) : init();
function init() {
const events = new CollectionView(getEvents());
const searchInput = document.querySelector('#searchInput');
const statusFilter = document.querySelector('#statusFilter');
const teamFilter = document.querySelector('#teamFilter');
const summary = document.querySelector('#filterSummary');
new wjcScheduler.FlexScheduler('#theScheduler', {
itemsSource: events,
resources: [
{
fieldExpr: 'teamId',
label: 'Team',
dataSource: getTeams(),
valueExpr: 'id',
displayExpr: 'name',
backgroundColorExpr: 'color',
foreColorExpr: 'textColor',
},
],
definition: getWeekDefinition(),
displayDate: getDisplayDate(),
workHours: [{ start: '08:00', end: '17:00' }],
toolbarViewItems: [{ name: 'Week', key: wjcScheduler.SchedulerBuiltInViewItem.Week }],
});
const applyFilter = () => {
const query = searchInput.value.trim().toLocaleLowerCase();
const status = statusFilter.value;
const team = teamFilter.value;
events.filter = (item) => (!query || item.subject.toLocaleLowerCase().includes(query)) &&
(!status || item.status === status) &&
(!team || item.teamId === team);
summary.value = `CollectionView filter | ${events.items.length} of ${events.sourceCollection.length} visible`;
};
searchInput.addEventListener('input', applyFilter);
statusFilter.addEventListener('change', applyFilter);
teamFilter.addEventListener('change', applyFilter);
applyFilter();
}
function getWeekDefinition() {
const definition = wjcScheduler.createSchedulerDefinitionPreset(wjcScheduler.SchedulerBuiltInViewItem.Week);
return Object.assign(Object.assign({}, definition), { rows: {
bindings: [
{
type: wjcScheduler.SchedulerAxisBindingType.Time,
unit: wjcScheduler.SchedulerTimeUnit.Hour,
visible: (args) => args.hour >= 8 && args.hour < 17,
},
],
} });
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>MESCIUS Wijmo Scheduler Filtering</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/systemjs@0.21.5/dist/system.src.js" integrity="sha512-skZbMyvYdNoZfLmiGn5ii6KmklM82rYX2uWctBhzaXPxJgiv4XBwJnFGr5k8s+6tE1pcR1nuTKghozJHyzMcoA==" crossorigin="anonymous"></script>
<script src="systemjs.config.js"></script>
<script>System.import('./src/app');</script>
</head>
<body>
<main class="container-fluid">
<div class="filter-toolbar" aria-label="Schedule filters">
<label class="search-field" for="searchInput">
<i class="bi bi-search" aria-hidden="true"></i>
<input id="searchInput" class="form-control form-control-sm" type="search" placeholder="Search events">
</label>
<label class="filter-field" for="statusFilter">
<span>Status</span>
<select id="statusFilter" class="form-select form-select-sm">
<option value="">All statuses</option>
<option value="confirmed">Confirmed</option>
<option value="tentative">Tentative</option>
<option value="attention">Needs attention</option>
</select>
</label>
<label class="filter-field" for="teamFilter">
<span>Team</span>
<select id="teamFilter" class="form-select form-select-sm">
<option value="">All teams</option>
<option value="operations">Operations</option>
<option value="product">Product</option>
<option value="customer">Customer success</option>
</select>
</label>
<output id="filterSummary" class="filter-summary" aria-live="polite"></output>
</div>
<div id="theScheduler"></div>
</main>
</body>
</html>
function date(day, hour, minute = 0) {
return new Date(2026, 4, day, hour, minute);
}
export function getDisplayDate() {
return date(13, 9);
}
export function getTeams() {
return [
{ id: 'operations', name: 'Operations', color: '#2563eb', textColor: '#ffffff' },
{ id: 'product', name: 'Product', color: '#0f766e', textColor: '#ffffff' },
{ id: 'customer', name: 'Customer success', color: '#a3460a', textColor: '#ffffff' },
];
}
export function getEvents() {
return [
{
id: 1,
subject: 'Dispatch Review',
start: date(11, 9),
end: date(11, 10, 30),
teamId: 'operations',
status: 'confirmed',
},
{
id: 2,
subject: 'Release Planning',
start: date(11, 13),
end: date(11, 14, 30),
teamId: 'product',
status: 'tentative',
},
{
id: 3,
subject: 'Customer Onboarding',
start: date(12, 10),
end: date(12, 11, 30),
teamId: 'customer',
status: 'confirmed',
},
{
id: 4,
subject: 'Capacity Review',
start: date(12, 14),
end: date(12, 15),
teamId: 'operations',
status: 'attention',
},
{
id: 5,
subject: 'Design Critique',
start: date(13, 9),
end: date(13, 10, 30),
teamId: 'product',
status: 'confirmed',
},
{
id: 6,
subject: 'Renewal Workshop',
start: date(13, 13),
end: date(13, 14, 30),
teamId: 'customer',
status: 'tentative',
},
{
id: 7,
subject: 'Service Readiness',
start: date(14, 10),
end: date(14, 11),
teamId: 'operations',
status: 'confirmed',
},
{
id: 8,
subject: 'Roadmap Review',
start: date(14, 14),
end: date(14, 15, 30),
teamId: 'product',
status: 'attention',
},
{
id: 9,
subject: 'Account Planning',
start: date(15, 9, 30),
end: date(15, 11),
teamId: 'customer',
status: 'confirmed',
},
{
id: 10,
subject: 'Weekly Handoff',
start: date(15, 14),
end: date(15, 15),
teamId: 'operations',
status: 'tentative',
},
];
}
body {
color: #1f2937;
font-size: 15px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
user-select: none;
margin: 0;
}
.container-fluid {
box-sizing: border-box;
margin: 0;
padding: 5px;
}
.filter-toolbar {
display: flex;
align-items: flex-end;
gap: 8px 12px;
min-height: 54px;
margin-bottom: 6px;
padding: 6px 9px;
border: 1px solid #dbe2ea;
background: #f8fafc;
}
.search-field {
position: relative;
flex: 1 1 220px;
max-width: 300px;
}
.search-field .bi {
position: absolute;
top: 50%;
left: 10px;
z-index: 1;
color: #64748b;
transform: translateY(-50%);
}
.search-field input {
padding-left: 31px;
}
.filter-field {
display: flex;
flex-direction: column;
gap: 3px;
min-width: 165px;
margin: 0;
}
.filter-field span {
color: #475569;
font-size: 12px;
font-weight: 600;
}
.filter-summary {
margin: 0 2px 7px auto;
color: #475569;
font-size: 13px;
font-weight: 600;
white-space: nowrap;
}
.form-control:focus,
.form-select:focus {
border-color: #0f6cbd;
box-shadow: 0 0 0 2px rgb(15 108 189 / 20%);
}
#theScheduler {
height: calc(100vh - 62px);
min-height: 600px;
}
@media (max-width: 720px) {
.filter-toolbar {
align-items: stretch;
flex-wrap: wrap;
}
.search-field {
flex-basis: 100%;
max-width: none;
}
.filter-field {
flex: 1 1 140px;
min-width: 0;
}
.filter-summary {
flex: 1 1 100%;
margin: 0;
}
#theScheduler {
height: 680px;
min-height: 680px;
}
}
input,
textarea,
[contenteditable="true"] {
user-select: text;
}
(function (global) {
System.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true,
},
meta: {
'*.css': { loader: 'css' },
},
paths: {
// paths serve as alias
'npm:': 'node_modules/',
'cdn:': 'https://cdn.mescius.io/demoapps/packages/wijmojs/5.20262.60-rc/',
'pcdn:': 'https://cdn.jsdelivr.net/npm/',
},
// map tells the System loader where to look for things
map: {
'@mescius/wijmo': 'cdn:@mescius/wijmo/index.js',
'@mescius/wijmo.input': 'cdn:@mescius/wijmo.input/index.js',
'@mescius/wijmo.scheduler': 'cdn:@mescius/wijmo.scheduler/index.js',
'@mescius/wijmo.styles': 'cdn:@mescius/wijmo.styles',
'@mescius/wijmo.cultures': 'cdn:@mescius/wijmo.cultures',
jszip: 'pcdn:jszip@3.8.0/dist/jszip.js',
'bootstrap.css': 'pcdn:bootstrap@5.3.8/dist/css/bootstrap.min.css',
css: 'pcdn:systemjs-plugin-css@0.1.37/css.js',
'plugin-babel': 'pcdn:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'pcdn:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
},
packages: {
src: {
defaultExtension: 'js',
},
node_modules: {
defaultExtension: 'js',
},
},
});
})(this);