devextreme
Version:
JavaScript/TypeScript Component Suite for Responsive Web Development
170 lines (169 loc) • 7.3 kB
JavaScript
/**
* DevExtreme (esm/__internal/scheduler/m_compact_appointments_helper.js)
* Version: 25.2.7
* Build date: Tue May 05 2026
*
* Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import {
locate,
move
} from "../../common/core/animation/translator";
import dateLocalization from "../../common/core/localization/date";
import messageLocalization from "../../common/core/localization/message";
import $ from "../../core/renderer";
import {
FunctionTemplate
} from "../../core/templates/function_template";
import Button from "../../ui/button";
import {
APPOINTMENT_SETTINGS_KEY,
LIST_ITEM_CLASS,
LIST_ITEM_DATA_KEY
} from "./constants";
const APPOINTMENT_COLLECTOR_CLASS = "dx-scheduler-appointment-collector";
const COMPACT_APPOINTMENT_COLLECTOR_CLASS = `${APPOINTMENT_COLLECTOR_CLASS}-compact`;
const APPOINTMENT_COLLECTOR_CONTENT_CLASS = `${APPOINTMENT_COLLECTOR_CLASS}-content`;
export class CompactAppointmentsHelper {
constructor(instance) {
this.elements = [];
this.instance = instance
}
render(options) {
const {
isCompact: isCompact,
items: items
} = options;
const template = this.createTemplate(items.length, isCompact);
const button = this.createCompactButton(template, options);
const $button = button.$element();
this.elements.push($button);
$button.data("items", items);
return $button
}
clear() {
this.elements.forEach(button => {
button.detach();
button.remove()
});
this.elements = []
}
onButtonClick(e, options) {
const $button = $(e.element);
this.instance.showAppointmentTooltipCore($button, $button.data("items"), this.getExtraOptionsForTooltip(options, $button))
}
getExtraOptionsForTooltip(options, $appointmentCollector) {
return {
clickEvent: this.clickEvent(options.onAppointmentClick).bind(this),
dragBehavior: options.allowDrag && this.createTooltipDragBehavior($appointmentCollector).bind(this),
isButtonClick: true,
_loopFocus: true
}
}
clickEvent(onAppointmentClick) {
return e => {
const clickEventArgs = this.instance._createEventArgs(e);
onAppointmentClick(clickEventArgs)
}
}
createTooltipDragBehavior($appointmentCollector) {
return e => {
const $element = $(e.element);
const $schedulerElement = $(this.instance.element());
const workSpace = this.instance.getWorkSpace();
const initialPosition = locate($appointmentCollector);
const options = {
filter: `.${LIST_ITEM_CLASS}`,
isSetCursorOffset: true,
initialPosition: initialPosition,
getItemData: itemElement => {
var _$$data;
return null === (_$$data = $(itemElement).data(LIST_ITEM_DATA_KEY)) || void 0 === _$$data ? void 0 : _$$data.appointment
},
getItemSettings: (_, event) => event.itemSettings
};
workSpace.createDragBehaviorBase($element, $schedulerElement, options)
}
}
setPosition(element, position) {
move(element, {
top: position.top,
left: position.left
})
}
createCompactButton(template, options) {
const $button = this.createCompactButtonElement(options);
return this.instance._createComponent($button, Button, {
type: "default",
width: options.width,
height: options.height,
onClick: e => this.onButtonClick(e, options),
template: this.renderTemplate(template, options.items, options.isCompact)
})
}
static measureCollectorDimensions($container, isCompact) {
const $collector = $("<div>").addClass(APPOINTMENT_COLLECTOR_CLASS).toggleClass(COMPACT_APPOINTMENT_COLLECTOR_CLASS, isCompact).appendTo($container);
const styles = getComputedStyle($collector.get(0));
const geometry = {
width: styles.width,
height: styles.height,
marginLeft: styles.marginLeft,
marginRight: styles.marginRight,
marginTop: styles.marginTop,
marginBottom: styles.marginBottom
};
$collector.detach();
$collector.remove();
return geometry
}
createCompactButtonElement(_ref) {
let {
isCompact: isCompact,
$container: $container,
coordinates: coordinates,
sortedIndex: sortedIndex,
items: items
} = _ref;
const appointmentDate = this.getDateText(items[0].appointment, items[0].targetedAppointment);
const result = $("<div>").addClass(APPOINTMENT_COLLECTOR_CLASS).attr("aria-roledescription", appointmentDate).toggleClass(COMPACT_APPOINTMENT_COLLECTOR_CLASS, isCompact).appendTo($container);
result.data(APPOINTMENT_SETTINGS_KEY, {
sortedIndex: sortedIndex
});
this.setPosition(result, coordinates);
return result
}
renderTemplate(template, items, isCompact) {
return new FunctionTemplate(options => template.render({
model: {
appointmentCount: items.length,
items: items.map(item => item.appointment),
isCompact: isCompact
},
container: options.container
}))
}
createTemplate(count, isCompact) {
this.initButtonTemplate(count, isCompact);
return this.instance.getAppointmentTemplate("appointmentCollectorTemplate")
}
initButtonTemplate(count, isCompact) {
this.instance._templateManager.addDefaultTemplates({
appointmentCollector: new FunctionTemplate(options => this.createButtonTemplate(count, $(options.container), isCompact))
})
}
createButtonTemplate(appointmentCount, element, isCompact) {
const text = isCompact ? appointmentCount : messageLocalization.getFormatter("dxScheduler-moreAppointments")(appointmentCount);
return element.append($("<span>").text(text)).addClass(APPOINTMENT_COLLECTOR_CONTENT_CLASS)
}
localizeDate(date) {
return `${dateLocalization.format(date,"monthAndDay")}, ${dateLocalization.format(date,"year")}`
}
getDateText(appointment, targetedAppointment) {
const startDate = (null === targetedAppointment || void 0 === targetedAppointment ? void 0 : targetedAppointment.displayStartDate) ?? appointment.startDate;
const endDate = (null === targetedAppointment || void 0 === targetedAppointment ? void 0 : targetedAppointment.displayEndDate) ?? appointment.endDate;
const startDateText = this.localizeDate(startDate);
const endDateText = this.localizeDate(endDate);
return startDateText === endDateText ? startDateText : `${startDateText} - ${endDateText}`
}
}