Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,49 @@ const APPOINTMENT_TOOLTIP_WRAPPER_CLASS = 'dx-scheduler-appointment-tooltip-wrap
const MAX_TOOLTIP_HEIGHT = 200;

export class DesktopTooltipStrategy extends TooltipStrategyBase {
_prepareBeforeVisibleChanged(dataList) {
this._tooltip.option('position', {
protected override prepareBeforeVisibleChanged(dataList) {
this.tooltip.option('position', {
my: 'bottom',
at: 'top',
boundary: this._getBoundary(dataList),
offset: this._extraOptions.offset,
boundary: this.getBoundary(dataList),
offset: this.extraOptions.offset,
collision: 'fit flipfit',
});
}

_getBoundary(dataList) {
private getBoundary(dataList) {
return this._options.isAppointmentInAllDayPanel(dataList[0].appointment) ? this._options.container : this._options.getScrollableContainer();
}

_onShown() {
super._onShown();
if (this._extraOptions.isButtonClick) {
this._list.focus();
this._list.option('focusedElement', null);
protected override onShown() {
super.onShown();
if (this.extraOptions.isButtonClick) {
this.list.focus();
this.list.option('focusedElement', null);
}
}

// @ts-expect-error
_createListOption(target, dataList) {
protected override createListOption(target, dataList) {
// @ts-expect-error
const result: any = super._createListOption(target, dataList);
const result: any = super.createListOption(target, dataList);
// T724287 this condition is not covered by tests, because touch variable cannot be overridden.
// In the future, it is necessary to cover the tests
result.showScrollbar = supportUtils.touch ? 'always' : 'onHover';
return result;
}

_createTooltip(target, dataList) {
const tooltipElement = this._createTooltipElement(APPOINTMENT_TOOLTIP_WRAPPER_CLASS);
protected override createTooltip(target, dataList) {
const tooltipElement = this.createTooltipElement(APPOINTMENT_TOOLTIP_WRAPPER_CLASS);

const tooltip = this._options.createComponent(tooltipElement, Tooltip, {
target,
maxHeight: MAX_TOOLTIP_HEIGHT,
rtlEnabled: this._extraOptions.rtlEnabled,
onShown: this._onShown.bind(this),
contentTemplate: this._getContentTemplate(dataList),
rtlEnabled: this.extraOptions.rtlEnabled,
onShown: this.onShown.bind(this),
contentTemplate: this.getContentTemplate(dataList),
wrapperAttr: { class: APPOINTMENT_TOOLTIP_WRAPPER_CLASS },
_loopFocus: this._extraOptions._loopFocus,
_loopFocus: this.extraOptions._loopFocus,
});

tooltip.setAria({
Expand All @@ -61,11 +61,11 @@ export class DesktopTooltipStrategy extends TooltipStrategyBase {
return tooltip;
}

_onListRender(e) {
return this._extraOptions.dragBehavior && this._extraOptions.dragBehavior(e);
protected override onListRender(e) {
return this.extraOptions.dragBehavior && this.extraOptions.dragBehavior(e);
}

_onListItemContextMenu(e) {
protected override onListItemContextMenu(e) {
const contextMenuEventArgs = this._options.createEventArgs(e);
this._options.onItemContextMenu(contextMenuEventArgs);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,23 @@ const createTabletDeviceConfig = (listHeight) => {
};

export class MobileTooltipStrategy extends TooltipStrategyBase {
_shouldUseTarget() {
protected override shouldUseTarget() {
return false;
}

private setTooltipConfig(): void {
const isTabletWidth = getWidth(getWindow()) > 700;

const listHeight = getOuterHeight(this._list.$element().find(CLASS.scrollableContent));
this._tooltip.option(
const listHeight = getOuterHeight(this.list.$element().find(CLASS.scrollableContent));
this.tooltip.option(
isTabletWidth
? createTabletDeviceConfig(listHeight)
: createPhoneDeviceConfig(listHeight),
);
}

private async _onShowing(): Promise<void> {
this._tooltip.option('height', MAX_HEIGHT.DEFAULT);
private async onShowing(): Promise<void> {
this.tooltip.option('height', MAX_HEIGHT.DEFAULT);
/*
NOTE: there are two setTooltipConfig calls to reduce blinking of overlay.
The first one sets initial sizes, the second updates them after rendering async templates
Expand All @@ -91,17 +91,17 @@ export class MobileTooltipStrategy extends TooltipStrategyBase {
this.setTooltipConfig();
}

_createTooltip(target, dataList) {
const element = this._createTooltipElement(CLASS.slidePanel);
protected override createTooltip(target, dataList) {
const element = this.createTooltipElement(CLASS.slidePanel);

return this._options.createComponent(element, Overlay, {
target: getWindow(),
hideOnOutsideClick: true,
animation: animationConfig,

onShowing: () => this._onShowing(),
onShown: this._onShown.bind(this),
contentTemplate: this._getContentTemplate(dataList),
onShowing: () => this.onShowing(),
onShown: this.onShown.bind(this),
contentTemplate: this.getContentTemplate(dataList),
wrapperAttr: { class: CLASS.slidePanel },
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,121 +20,145 @@ const APPOINTMENT_TOOLTIP_TEMPLATE = 'appointmentTooltipTemplate';
export class TooltipStrategyBase {
protected asyncTemplatePromises = new Set<Promise<void>>();

_tooltip: any;
protected tooltip: any;

// TODO: make private once external usages in m_scheduler.ts are removed
_options: any;

_extraOptions: any;
protected extraOptions: any;

_list: any;
protected list: any;

constructor(options) {
this._tooltip = null;
this.tooltip = null;
this._options = options;
this._extraOptions = null;
this.extraOptions = null;
}

show(target, dataList, extraOptions) {
if (this._canShowTooltip(dataList)) {
if (this.canShowTooltip(dataList)) {
this.hide();
this._extraOptions = extraOptions;
this._showCore(target, dataList);
this.extraOptions = extraOptions;
this.showCore(target, dataList);
}
}

_showCore(target, dataList) {
private showCore(target, dataList) {
const describedByValue = isRenderer(target) && target.attr('aria-describedby') as string;

if (!this._tooltip) {
this._tooltip = this._createTooltip(target, dataList);
if (!this.tooltip) {
this.tooltip = this.createTooltip(target, dataList);
} else {
this._shouldUseTarget() && this._tooltip.option('target', target);
this._list.option('dataSource', dataList);
this.shouldUseTarget() && this.tooltip.option('target', target);
this.list.option('dataSource', dataList);
}

this._prepareBeforeVisibleChanged(dataList);
this._tooltip.option('visible', true);
this.prepareBeforeVisibleChanged(dataList);
this.tooltip.option('visible', true);

describedByValue && target.attr('aria-describedby', describedByValue);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
_prepareBeforeVisibleChanged(dataList) {
protected prepareBeforeVisibleChanged(dataList) {

}

_getContentTemplate(dataList) {
private isDeletingAllowed(appointment) {
const { editing } = this.extraOptions;
const disabled = this._options.getAppointmentDisabled(appointment);
const isDeletingAllowed = editing === true || editing?.allowDeleting === true;
return !disabled && isDeletingAllowed;
}

protected getContentTemplate(dataList) {
return (container) => {
const listElement = $('<div>');
$(container).append(listElement);
this._list = this._createList(listElement, dataList);
this._list.registerKeyHandler?.('escape', () => {
this.list = this.createList(listElement, dataList);
this.list.registerKeyHandler?.('escape', () => {
this.hide();
this._tooltip.option('target').focus();
this.tooltip.option('target').focus();
});
this.list.registerKeyHandler?.('del', () => {
const { focusedElement } = this.list.option();
if (!focusedElement) {
return;
}

const { appointment, targetedAppointment } = this.list._getItemData(focusedElement);
if (!appointment) {
return;
}

if (this.isDeletingAllowed(appointment)) {
this.hide();
this._options.checkAndDeleteAppointment(appointment, targetedAppointment);
}
});
};
}

isAlreadyShown(target) {
if (this._tooltip && this._tooltip.option('visible')) {
return this._tooltip.option('target')[0] === target[0];
if (this.tooltip && this.tooltip.option('visible')) {
return this.tooltip.option('target')[0] === target[0];
}
return undefined;
}

_onShown() {
this._list.option('focusStateEnabled', this._extraOptions.focusStateEnabled);
protected onShown() {
this.list.option('focusStateEnabled', this.extraOptions.focusStateEnabled);
}

dispose() {
}

hide() {
if (this._tooltip) {
this._tooltip.option('visible', false);
if (this.tooltip) {
this.tooltip.option('visible', false);
}
}

_shouldUseTarget() {
protected shouldUseTarget() {
return true;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
_createTooltip(target, dataList) {
protected createTooltip(target, dataList) {
}

_canShowTooltip(dataList) {
private canShowTooltip(dataList) {
if (!dataList.length) {
return false;
}
return true;
}

_createListOption(dataList) {
protected createListOption(dataList) {
return {
dataSource: dataList,
onContentReady: this._onListRender.bind(this),
onItemClick: (e) => this._onListItemClick(e),
onItemContextMenu: this._onListItemContextMenu.bind(this),
itemTemplate: (item, index) => this._renderTemplate(item.appointment, item.targetedAppointment, index, item.color),
onContentReady: this.onListRender.bind(this),
onItemClick: (e) => this.onListItemClick(e),
onItemContextMenu: this.onListItemContextMenu.bind(this),
itemTemplate: (item, index) => this.renderTemplate(item.appointment, item.targetedAppointment, index, item.color),
_swipeEnabled: false,
pageLoadMode: 'scrollBottom',
};
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
_onListRender(e) {}
protected onListRender(e) { }

_createTooltipElement(wrapperClass) {
protected createTooltipElement(wrapperClass) {
return $('<div>').appendTo(this._options.container).addClass(wrapperClass);
}

_createList(listElement, dataList) {
return this._options.createComponent(listElement, List, this._createListOption(dataList));
private createList(listElement, dataList) {
return this._options.createComponent(listElement, List, this.createListOption(dataList));
}

_renderTemplate(appointment, targetedAppointment, index, color) {
const itemListContent = this._createItemListContent(appointment, targetedAppointment, color);
private renderTemplate(appointment, targetedAppointment, index, color) {
const itemListContent = this.createItemListContent(appointment, targetedAppointment, color);
this._options.addDefaultTemplates({
// @ts-expect-error
appointmentTooltip: new FunctionTemplate((options) => {
Expand All @@ -145,11 +169,11 @@ export class TooltipStrategyBase {
});

const template = this._options.getAppointmentTemplate(APPOINTMENT_TOOLTIP_TEMPLATE);
return this._createFunctionTemplate(template, appointment, targetedAppointment, index);
return this.createFunctionTemplate(template, appointment, targetedAppointment, index);
}

_createFunctionTemplate(template, appointmentData, targetedAppointmentData, index) {
const isButtonClicked = Boolean(this._extraOptions.isButtonClick);
private createFunctionTemplate(template, appointmentData, targetedAppointmentData, index) {
const isButtonClicked = Boolean(this.extraOptions.isButtonClick);

// @ts-expect-error
return new FunctionTemplate((options) => {
Expand All @@ -172,31 +196,28 @@ export class TooltipStrategyBase {
});
}

_onListItemClick(e) {
private onListItemClick(e) {
this.hide();
this._extraOptions.clickEvent && this._extraOptions.clickEvent(e);
this.extraOptions.clickEvent && this.extraOptions.clickEvent(e);
this._options.showAppointmentPopup(e.itemData.appointment, false, e.itemData.targetedAppointment);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
_onListItemContextMenu(e) {}
protected onListItemContextMenu(e) { }

_createItemListContent(appointment, targetedAppointment, color) {
const { editing } = this._extraOptions;
private createItemListContent(appointment, targetedAppointment, color) {
const $itemElement = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM);
$itemElement.append(this._createItemListMarker(color));
$itemElement.append(this._createItemListInfo(this._options.createFormattedDateText(appointment, targetedAppointment)));

const disabled = this._options.getAppointmentDisabled(appointment);
$itemElement.append(this.createItemListMarker(color));
$itemElement.append(this.createItemListInfo(this._options.createFormattedDateText(appointment, targetedAppointment)));

if (!disabled && (editing && editing.allowDeleting === true || editing === true)) {
$itemElement.append(this._createDeleteButton(appointment, targetedAppointment));
if (this.isDeletingAllowed(appointment)) {
$itemElement.append(this.createDeleteButton(appointment, targetedAppointment));
}

return $itemElement;
}

_createItemListMarker(color) {
private createItemListMarker(color) {
const $marker = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM_MARKER);
const $markerBody = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM_MARKER_BODY);

Expand All @@ -210,15 +231,15 @@ export class TooltipStrategyBase {
return $marker;
}

_createItemListInfo(object) {
private createItemListInfo(object) {
const result = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM_CONTENT);
const $title = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM_CONTENT_SUBJECT).text(object.text);
const $date = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM_CONTENT_DATE).text(object.formatDate);

return result.append($title).append($date);
}

_createDeleteButton(appointment, targetedAppointment) {
private createDeleteButton(appointment, targetedAppointment) {
const $container = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM_DELETE_BUTTON_CONTAINER);
const $deleteButton = $('<div>').addClass(TOOLTIP_APPOINTMENT_ITEM_DELETE_BUTTON);

Expand Down
Loading
Loading