import 'bootstrap.css';
import '@mescius/wijmo.styles/wijmo.css';
import './styles.css';
//
import * as wjcCore from '@mescius/wijmo';
import * as wjcScheduler from '@mescius/wijmo.scheduler';
import { getDisplayDate, getEvents, getTeams } from './data';
const events = getEvents();
const teams = getTeams();
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', init) : init();
function init() {
const scheduler = new wjcScheduler.FlexScheduler('#theScheduler', {
itemsSource: new wjcCore.CollectionView(events),
resources: [
{
fieldExpr: 'teamId',
label: 'team',
dataSource: teams,
valueExpr: 'id',
displayExpr: 'name',
backgroundColorExpr: 'backgroundColor',
foreColorExpr: 'foreColor',
},
],
definition: getWeekDefinition(),
displayDate: getDisplayDate(),
workHours: [{ start: '08:00', end: '18:00' }],
toolbarViewItems: [{ name: 'Week', key: wjcScheduler.SchedulerBuiltInViewItem.Week }],
});
const controls = Array.from(document.querySelectorAll('[data-query]'));
const resetButton = document.querySelector('#resetQuery');
controls.forEach((control) => {
control.addEventListener(control instanceof HTMLInputElement ? 'input' : 'change', () => runQuery(scheduler));
});
resetButton.addEventListener('click', () => {
controls.forEach((control) => (control.value = ''));
runQuery(scheduler);
controls[0].focus();
});
runQuery(scheduler);
}
function runQuery(scheduler) {
const state = readQueryState();
const activeConditions = countActiveConditions(state);
let matches;
let method;
if (activeConditions === 1 && (state.date || state.team)) {
const range = state.date ? getTimeRange(state.date) : null;
const resources = state.team
? [{ fieldExpr: 'teamId', value: state.team }]
: undefined;
matches = scheduler.getEvents(range === null || range === void 0 ? void 0 : range.start, range === null || range === void 0 ? void 0 : range.end, resources);
method = 'getEvents()';
}
else {
matches = scheduler.queryEvents((item) => matchesQuery(item, state));
method = 'queryEvents()';
}
updateQuerySummary(method, activeConditions);
document.querySelector('#resetQuery').disabled = activeConditions === 0;
renderResults(matches);
}
function readQueryState() {
return {
date: document.getElementById('dateQuery').value,
team: document.getElementById('teamQuery').value,
status: document.getElementById('statusQuery').value,
duration: document.getElementById('durationQuery').value,
subject: document.getElementById('subjectQuery').value.trim().toLocaleLowerCase(),
};
}
function countActiveConditions(state) {
return Object.values(state).filter(Boolean).length;
}
function matchesQuery(item, state) {
const range = state.date ? getTimeRange(state.date) : null;
const matchesDate = !range || (item.start < range.end && item.end > range.start);
const matchesTeam = !state.team || item.teamId === state.team;
const matchesStatus = !state.status || item.status === state.status;
const matchesSubject = !state.subject || item.subject.toLocaleLowerCase().includes(state.subject);
return matchesDate && matchesTeam && matchesStatus && matchesSubject && matchesDuration(item, state.duration);
}
function matchesDuration(item, duration) {
if (!duration)
return true;
const minutes = (item.end.getTime() - item.start.getTime()) / 60000;
if (duration === 'up-to-60')
return minutes <= 60;
if (duration === 'over-60')
return minutes > 60;
return minutes >= 90;
}
function getTimeRange(value) {
const day = Number(value);
if (Number.isFinite(day) && day >= 11 && day <= 15) {
return { start: new Date(2026, 4, day), end: new Date(2026, 4, day + 1) };
}
return { start: new Date(2026, 4, 11), end: new Date(2026, 4, 16) };
}
function updateQuerySummary(method, conditionCount) {
document.getElementById('queryMethod').textContent = method;
document.getElementById('queryDescription').textContent = conditionCount
? `${conditionCount} ${conditionCount === 1 ? 'condition' : 'conditions'} applied; Scheduler data remains unchanged`
: 'No conditions; all events returned and Scheduler data remains unchanged';
}
function renderResults(matches) {
const count = document.getElementById('resultCount');
const list = document.getElementById('resultList');
count.textContent = `${matches.length} ${matches.length === 1 ? 'event' : 'events'}`;
list.replaceChildren(...(matches.length ? matches.map(createResultItem) : [createEmptyResult()]));
}
function createEmptyResult() {
const empty = document.createElement('p');
empty.className = 'empty-result';
empty.textContent = 'No events match all active conditions.';
return empty;
}
function createResultItem(item) {
const result = document.createElement('article');
const subject = document.createElement('h3');
const details = document.createElement('p');
const team = getTeam(item.teamId);
result.className = 'result-item';
subject.textContent = item.subject;
details.textContent = `${formatEventTime(item)} | ${team.name} | ${item.status}`;
result.append(subject, details);
return result;
}
function getTeam(teamId) {
return (teams.find((team) => team.id === teamId) || {
id: teamId,
name: teamId,
backgroundColor: '#475569',
foreColor: '#ffffff',
});
}
function formatEventTime(item) {
const day = item.start.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' });
const start = item.start.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
const end = item.end.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
return `${day}, ${start} - ${end}`;
}
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 >= 7 && args.hour < 19,
},
],
} });
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>MESCIUS Wijmo Scheduler Event Queries</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="data:,">
<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="query-toolbar" aria-label="Event query conditions">
<label class="query-control" for="dateQuery"><span>Date</span><select id="dateQuery" class="form-select" data-query>
<option value="">All dates</option><option value="11">Mon, May 11</option><option value="12">Tue, May 12</option>
<option value="13">Wed, May 13</option><option value="14">Thu, May 14</option><option value="15">Fri, May 15</option>
<option value="work-week">Work week</option>
</select></label>
<label class="query-control" for="teamQuery"><span>Team</span><select id="teamQuery" class="form-select" data-query>
<option value="">All teams</option><option value="product">Product</option><option value="design">Design</option>
<option value="engineering">Engineering</option><option value="marketing">Marketing</option>
</select></label>
<label class="query-control" for="statusQuery"><span>Status</span><select id="statusQuery" class="form-select" data-query>
<option value="">All statuses</option><option value="Confirmed">Confirmed</option><option value="Tentative">Tentative</option>
</select></label>
<label class="query-control" for="durationQuery"><span>Duration</span><select id="durationQuery" class="form-select" data-query>
<option value="">Any duration</option><option value="up-to-60">60 minutes or less</option>
<option value="over-60">Longer than 60 minutes</option><option value="at-least-90">At least 90 minutes</option>
</select></label>
<label class="query-control subject-control" for="subjectQuery"><span>Subject</span><span class="subject-input"><i class="bi bi-search" aria-hidden="true"></i><input id="subjectQuery" class="form-control" type="search" placeholder="Contains text" data-query></span></label>
<div class="query-method" aria-live="polite"><strong id="queryMethod"></strong><span id="queryDescription"></span><button id="resetQuery" class="btn btn-sm btn-outline-secondary" type="button" disabled><i class="bi bi-arrow-counterclockwise" aria-hidden="true"></i> Reset</button></div>
</div>
<div class="query-workspace">
<div id="theScheduler"></div>
<aside class="query-results" aria-live="polite">
<div class="results-header"><h2><i class="bi bi-funnel" aria-hidden="true"></i> Query results</h2><span id="resultCount" class="result-count"></span></div>
<div id="resultList" class="result-list"></div>
</aside>
</div>
</main>
</body>
</html>
export function getDisplayDate() {
return new Date(2026, 4, 13, 9);
}
export function getTeams() {
return [
{ id: 'product', name: 'Product', backgroundColor: '#2563eb', foreColor: '#ffffff' },
{ id: 'design', name: 'Design', backgroundColor: '#7c3aed', foreColor: '#ffffff' },
{ id: 'engineering', name: 'Engineering', backgroundColor: '#0f766e', foreColor: '#ffffff' },
{ id: 'marketing', name: 'Marketing', backgroundColor: '#b45309', foreColor: '#ffffff' },
];
}
export function getEvents() {
return [
createEvent(1, 'Sprint Planning', 11, 9, 0, 10, 30, 'engineering', 'Confirmed'),
createEvent(2, 'Roadmap Review', 11, 11, 0, 12, 0, 'product', 'Confirmed'),
createEvent(3, 'Campaign Kickoff', 11, 14, 0, 15, 30, 'marketing', 'Tentative'),
createEvent(4, 'Design Critique', 12, 10, 0, 11, 30, 'design', 'Confirmed'),
createEvent(5, 'Customer Interview', 12, 13, 0, 14, 0, 'product', 'Tentative'),
createEvent(6, 'API Design Review', 13, 9, 0, 10, 30, 'engineering', 'Confirmed'),
createEvent(7, 'Launch Assets', 13, 11, 0, 12, 30, 'design', 'Tentative'),
createEvent(8, 'Partner Briefing', 13, 14, 0, 15, 0, 'marketing', 'Confirmed'),
createEvent(9, 'Release Readiness', 14, 9, 30, 11, 0, 'engineering', 'Confirmed'),
createEvent(10, 'Content Review', 14, 13, 0, 14, 30, 'marketing', 'Tentative'),
createEvent(11, 'Usability Testing', 15, 10, 0, 12, 0, 'design', 'Confirmed'),
createEvent(12, 'Weekly Wrap-up', 15, 15, 0, 16, 0, 'product', 'Confirmed'),
];
}
function createEvent(id, subject, day, startHour, startMinute, endHour, endMinute, teamId, status) {
return {
id,
subject,
start: new Date(2026, 4, day, startHour, startMinute),
end: new Date(2026, 4, day, endHour, endMinute),
teamId,
status,
};
}
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;
}
.query-toolbar {
display: grid;
grid-template-columns: repeat(4, minmax(130px, 1fr)) minmax(170px, 1.2fr);
gap: 7px 10px;
margin-bottom: 6px;
padding: 7px 10px;
border: 1px solid #dbe2ea;
background: #f8fafc;
}
.query-control {
display: flex;
min-width: 0;
flex-direction: column;
gap: 3px;
margin: 0;
}
.query-control > span:first-child {
color: #475569;
font-size: 12px;
font-weight: 650;
}
.form-select,
.form-control {
min-height: 34px;
border-color: #cbd5e1;
border-radius: 3px;
font-size: 13px;
}
.form-select:focus,
.form-control:focus {
border-color: #0f6cbd;
box-shadow: 0 0 0 2px rgb(15 108 189 / 18%);
}
.subject-input {
position: relative;
display: block;
}
.subject-input .bi {
position: absolute;
top: 50%;
left: 9px;
z-index: 1;
color: #64748b;
transform: translateY(-50%);
}
.subject-input input {
width: 100%;
padding-left: 29px;
}
.query-method {
display: flex;
min-width: 0;
grid-column: 1 / -1;
align-items: baseline;
gap: 8px;
}
.query-method strong {
color: #075ea8;
font-family: Consolas, "Courier New", monospace;
font-size: 12px;
white-space: nowrap;
}
.query-method span {
overflow: hidden;
color: #64748b;
font-size: 12px;
text-overflow: ellipsis;
white-space: nowrap;
}
.query-method .btn {
display: inline-flex;
min-width: 78px;
align-items: center;
justify-content: center;
gap: 5px;
margin-left: auto;
}
.query-workspace {
display: grid;
grid-template-columns: minmax(0, 1fr) 310px;
min-height: 0;
border: 1px solid #cbd5e1;
background: #ffffff;
}
#theScheduler {
min-width: 0;
height: calc(100vh - 104px);
min-height: 580px;
}
.query-results {
min-width: 0;
max-height: calc(100vh - 104px);
overflow: auto;
border-left: 1px solid #cbd5e1;
background: #f8fafc;
}
.results-header {
position: sticky;
top: 0;
z-index: 1;
display: flex;
min-height: 48px;
align-items: center;
justify-content: space-between;
padding: 0 12px;
border-bottom: 1px solid #dbe2ea;
background: #eef3f8;
}
.results-header h2 {
margin: 0;
color: #0f172a;
font-size: 14px;
font-weight: 700;
}
.result-count {
padding: 3px 7px;
border: 1px solid #bfdbfe;
border-radius: 3px;
background: #ffffff;
color: #075ea8;
font-size: 12px;
font-weight: 650;
}
.empty-result {
margin: 0;
padding: 18px 12px;
color: #64748b;
font-size: 13px;
}
.result-item {
padding: 11px 12px;
border-bottom: 1px solid #e2e8f0;
background: #ffffff;
}
.result-item:hover {
background: #f8fafc;
}
.result-item h3 {
margin: 0 0 3px;
color: #0f172a;
font-size: 13px;
font-weight: 650;
}
.result-item p {
margin: 0;
color: #64748b;
font-size: 12px;
line-height: 1.4;
}
@media (max-width: 1050px) {
.query-toolbar {
grid-template-columns: repeat(3, minmax(140px, 1fr));
}
.query-workspace {
grid-template-columns: 1fr;
}
.query-results {
max-height: none;
border-top: 1px solid #cbd5e1;
border-left: 0;
}
#theScheduler {
height: 600px;
min-height: 600px;
}
}
@media (max-width: 600px) {
.query-toolbar {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.subject-control {
grid-column: 1 / -1;
}
.query-method {
align-items: flex-start;
flex-direction: column;
gap: 2px;
}
.query-method span {
white-space: normal;
}
}
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);