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, getMeetings, getRooms } from './data';
const dateTimeFormat = new Intl.DateTimeFormat(undefined, {
weekday: 'short',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit',
});
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', init) : init();
function init() {
const scheduler = new wjcScheduler.FlexScheduler('#theScheduler', {
itemsSource: new wjcCore.CollectionView(getMeetings()),
resources: [
{
fieldExpr: 'roomId',
label: 'Room',
dataSource: getRooms(),
valueExpr: 'id',
displayExpr: 'name',
backgroundColorExpr: 'backgroundColor',
foreColorExpr: 'foreColor',
},
],
definition: getDefinition(),
displayDate: getDisplayDate(),
workHours: [{ start: '08:00', end: '17:00' }],
toolbarViewItems: [{ name: 'Day', key: wjcScheduler.SchedulerBuiltInViewItem.Day }],
});
scheduler.hostElement.addEventListener('pointermove', (event) => renderHit(scheduler.hitTest(event)));
document.addEventListener('click', (event) => renderHit(scheduler.hitTest(event)));
}
function getDefinition() {
return {
key: 'hitTesting',
rows: {
bindings: [
{
type: wjcScheduler.SchedulerAxisBindingType.Time,
unit: wjcScheduler.SchedulerTimeUnit.Hour,
visible: (args) => args.hour >= 8 && args.hour < 17,
},
],
},
columns: {
bindings: [
{
type: wjcScheduler.SchedulerAxisBindingType.Resource,
fieldExpr: 'roomId',
},
],
},
cellSemantic: wjcScheduler.SchedulerCellSemantic.Timed,
};
}
function renderHit(hit) {
const type = hit.hitTestType;
const model = hit.getHitInfo();
const hitType = document.getElementById('hitType');
hitType.textContent = getHitTypeName(type);
hitType.className = `is-${getHitTypeName(type).toLowerCase()}`;
renderDetails(getDetails(type, model));
}
function getDetails(type, model) {
switch (type) {
case wjcScheduler.SchedulerHitTestType.Cell:
return getCellDetails(model);
case wjcScheduler.SchedulerHitTestType.Item:
return getItemDetails(model);
case wjcScheduler.SchedulerHitTestType.ColumnHeader:
case wjcScheduler.SchedulerHitTestType.RowHeader:
return getHeaderDetails(model);
case wjcScheduler.SchedulerHitTestType.Corner:
return [{ label: 'Target', value: 'Header corner' }];
default:
return [{ label: 'Target', value: 'Outside the Scheduler' }];
}
}
function getCellDetails(cell) {
return [
{ label: 'Start', value: formatDate(cell.start) },
{ label: 'End', value: formatDate(cell.end) },
{ label: 'Resources', value: formatResources(cell.resources) },
];
}
function getItemDetails(item) {
const sourceItem = item.item;
return [
{ label: 'Subject', value: (sourceItem === null || sourceItem === void 0 ? void 0 : sourceItem.subject) || 'None' },
{ label: 'Start', value: formatDate(sourceItem === null || sourceItem === void 0 ? void 0 : sourceItem.start) },
{ label: 'End', value: formatDate(sourceItem === null || sourceItem === void 0 ? void 0 : sourceItem.end) },
{ label: 'Room ID', value: (sourceItem === null || sourceItem === void 0 ? void 0 : sourceItem.roomId) || 'None' },
];
}
function getHeaderDetails(header) {
return [
{ label: 'Axis', value: header.axis },
{ label: 'Text', value: header.text || 'None' },
{ label: 'Level', value: String(header.level) },
];
}
function renderDetails(details) {
const list = document.getElementById('hitDetails');
const content = [];
details.forEach((detail) => {
const term = document.createElement('dt');
const description = document.createElement('dd');
term.textContent = detail.label;
description.textContent = detail.value;
content.push(term, description);
});
list.replaceChildren(...content);
}
function getHitTypeName(type) {
const names = {
[wjcScheduler.SchedulerHitTestType.None]: 'None',
[wjcScheduler.SchedulerHitTestType.Cell]: 'Cell',
[wjcScheduler.SchedulerHitTestType.Item]: 'Item',
[wjcScheduler.SchedulerHitTestType.ColumnHeader]: 'ColumnHeader',
[wjcScheduler.SchedulerHitTestType.RowHeader]: 'RowHeader',
[wjcScheduler.SchedulerHitTestType.Corner]: 'Corner',
};
return names[type] || 'None';
}
function formatDate(value) {
return value instanceof Date ? dateTimeFormat.format(value) : 'None';
}
function formatResources(resources) {
const entries = Object.keys(resources || {}).map((field) => `${field}: ${String(resources[field])}`);
return entries.join(', ') || 'None';
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>MESCIUS Wijmo Scheduler Hit Testing</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="data:,">
<!-- SystemJS -->
<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">
<section class="hit-result" aria-live="polite">
<div class="result-heading">
<span>Hit type</span>
<strong id="hitType">None</strong>
</div>
<dl id="hitDetails" class="result-details">
<dt>Target</dt>
<dd>Move over a cell, header, or event.</dd>
</dl>
</section>
<div id="theScheduler"></div>
</main>
</body>
</html>
function createDate(hour, minute = 0) {
return new Date(2026, 4, 13, hour, minute);
}
export function getDisplayDate() {
return createDate(9);
}
export function getRooms() {
return [
{ id: 'atlas', name: 'Atlas Room', backgroundColor: '#2563eb', foreColor: '#ffffff' },
{ id: 'cedar', name: 'Cedar Room', backgroundColor: '#0f766e', foreColor: '#ffffff' },
{ id: 'studio', name: 'Design Studio', backgroundColor: '#a21caf', foreColor: '#ffffff' },
];
}
export function getMeetings() {
return [
{ id: 1, subject: 'Product Sync', start: createDate(9), end: createDate(10), roomId: 'atlas' },
{ id: 2, subject: 'Design Review', start: createDate(10, 30), end: createDate(12), roomId: 'studio' },
{ id: 3, subject: 'Hiring Panel', start: createDate(13), end: createDate(14, 30), roomId: 'cedar' },
{ id: 4, subject: 'Release Readiness', start: createDate(15), end: createDate(16), roomId: 'atlas' },
];
}
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;
}
.hit-result {
display: flex;
align-items: stretch;
min-height: 64px;
margin-bottom: 6px;
border: 1px solid #cbd5e1;
background: #f8fafc;
}
.result-heading {
display: flex;
flex: 0 0 160px;
flex-direction: column;
justify-content: center;
padding: 9px 14px;
border-right: 1px solid #cbd5e1;
color: #475569;
font-size: 12px;
}
.result-heading strong {
color: #0f766e;
font-size: 18px;
font-weight: 600;
}
.result-heading strong.is-item {
color: #0f6cbd;
}
.result-heading strong.is-cell {
color: #237b4b;
}
.result-heading strong.is-columnheader,
.result-heading strong.is-rowheader,
.result-heading strong.is-corner {
color: #76520e;
}
.result-details {
display: grid;
flex: 1 1 auto;
grid-template-columns: repeat(4, max-content minmax(80px, 1fr));
align-content: center;
min-width: 0;
margin: 0;
padding: 9px 14px;
column-gap: 8px;
row-gap: 2px;
}
.result-details dt {
color: #64748b;
font-size: 12px;
font-weight: 600;
}
.result-details dd {
overflow: hidden;
min-width: 0;
margin: 0;
color: #1f2937;
font-size: 13px;
text-overflow: ellipsis;
white-space: nowrap;
}
#theScheduler {
height: 720px;
min-height: 560px;
}
@media (max-width: 768px) {
.hit-result {
display: block;
min-height: 138px;
}
.result-heading {
flex-direction: row;
align-items: baseline;
justify-content: space-between;
min-height: 42px;
padding: 6px 10px;
border-right: 0;
border-bottom: 1px solid #cbd5e1;
}
.result-heading strong {
font-size: 16px;
}
.result-details {
grid-template-columns: max-content minmax(0, 1fr);
min-height: 96px;
padding: 7px 10px;
}
#theScheduler {
height: 640px;
min-height: 620px;
}
}
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);