From f97a5840b57eb85f1bd8ffbe0be7fc05ba685005 Mon Sep 17 00:00:00 2001 From: Aleksey Semikozov Date: Sun, 15 Mar 2026 10:01:46 -0300 Subject: [PATCH 1/3] Scheduler - Replace underscore-prefixed: m_appointment.ts + m_tooltip_strategy_base.ts --- .../appointment/agenda_appointment.ts | 4 +- .../appointments/appointment/m_appointment.ts | 56 +++++++------- .../js/__internal/scheduler/m_scheduler.ts | 2 +- .../m_desktop_tooltip_strategy.ts | 24 +++--- .../m_mobile_tooltip_strategy.ts | 12 +-- .../m_tooltip_strategy_base.ts | 74 +++++++++---------- 6 files changed, 86 insertions(+), 86 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/appointments/appointment/agenda_appointment.ts b/packages/devextreme/js/__internal/scheduler/appointments/appointment/agenda_appointment.ts index 74cb4afee7e1..4a64ea14d966 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/appointment/agenda_appointment.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/appointment/agenda_appointment.ts @@ -11,7 +11,7 @@ export class AgendaAppointment extends Appointment { return this.$element().find(`.${APPOINTMENT_CONTENT_CLASSES.AGENDA_MARKER}`); } - _renderResourceList(): void { + private renderResourceList(): void { const resourceManager = this.option('getResourceManager')(); // eslint-disable-next-line no-void @@ -42,6 +42,6 @@ export class AgendaAppointment extends Appointment { _render(): void { super._render(); - this._renderResourceList(); + this.renderResourceList(); } } diff --git a/packages/devextreme/js/__internal/scheduler/appointments/appointment/m_appointment.ts b/packages/devextreme/js/__internal/scheduler/appointments/appointment/m_appointment.ts index b00534f0106a..a44a6c55d44c 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/appointment/m_appointment.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/appointment/m_appointment.ts @@ -111,7 +111,7 @@ export class Appointment extends DOMComponent { this._invalidate(); break; case 'isDragSource': - this._renderDragSourceClass(); + this.renderDragSourceClass(); break; default: // @ts-expect-error @@ -119,7 +119,7 @@ export class Appointment extends DOMComponent { } } - _getHorizontalResizingRule() { + private getHorizontalResizingRule() { const reducedHandles = { head: this.option('rtlEnabled') ? 'right' : 'left', body: '', @@ -137,7 +137,7 @@ export class Appointment extends DOMComponent { }; } - _getVerticalResizingRule() { + private getVerticalResizingRule() { const height = Math.round(this.invoke('getCellHeight')); return { @@ -153,24 +153,24 @@ export class Appointment extends DOMComponent { // @ts-expect-error super._render(); - this._renderAppointmentGeometry(); - this._renderAriaLabel(); - this._renderEmptyClass(); - this._renderReducedAppointment(); - this._renderAllDayClass(); - this._renderDragSourceClass(); - this._renderDirection(); + this.renderAppointmentGeometry(); + this.renderAriaLabel(); + this.renderEmptyClass(); + this.renderReducedAppointment(); + this.renderAllDayClass(); + this.renderDragSourceClass(); + this.renderDirection(); this.$element().data('dxAppointmentStartDate', this.option('startDate')); this.$element().attr('role', 'button'); - this._renderRecurrenceClass(); - this._renderResizable(); + this.renderRecurrenceClass(); + this.renderResizable(); - this._setResourceColor(); + this.setResourceColor(); } - _setResourceColor() { + private setResourceColor() { const appointmentConfig = { itemData: this.rawAppointment, groupIndex: this.option('groupIndex') ?? 0, @@ -186,7 +186,7 @@ export class Appointment extends DOMComponent { }); } - _renderAriaLabel(): void { + private renderAriaLabel(): void { const $element: dxElementWrapper = this.$element(); $element.attr('aria-label', getAriaLabel(this.option())); @@ -205,7 +205,7 @@ export class Appointment extends DOMComponent { }); } - _renderAppointmentGeometry(): void { + private renderAppointmentGeometry(): void { const geometry: any = this.option('geometry'); const $element: any = this.$element(); move($element, { @@ -219,7 +219,7 @@ export class Appointment extends DOMComponent { }); } - _renderEmptyClass() { + private renderEmptyClass() { const geometry: any = this.option('geometry'); if (geometry.empty || this.option('isCompact')) { @@ -227,7 +227,7 @@ export class Appointment extends DOMComponent { } } - _renderReducedAppointment() { + private renderReducedAppointment() { const reducedPart: any = this.option('reduced'); if (!reducedPart) { @@ -238,10 +238,10 @@ export class Appointment extends DOMComponent { .toggleClass(REDUCED_APPOINTMENT_CLASS, true) .toggleClass(REDUCED_APPOINTMENT_PARTS_CLASSES[reducedPart], true); - this._renderAppointmentReducedIcon(); + this.renderAppointmentReducedIcon(); } - _renderAppointmentReducedIcon() { + private renderAppointmentReducedIcon() { const $icon = $('
') .addClass(REDUCED_APPOINTMENT_ICON) .appendTo(this.$element()); @@ -259,15 +259,15 @@ export class Appointment extends DOMComponent { }); } - _renderAllDayClass() { + private renderAllDayClass() { (this.$element() as any).toggleClass(ALL_DAY_APPOINTMENT_CLASS, Boolean(this.option('allDay'))); } - _renderDragSourceClass() { + private renderDragSourceClass() { (this.$element() as any).toggleClass(APPOINTMENT_DRAG_SOURCE_CLASS, Boolean(this.option('isDragSource'))); } - _renderRecurrenceClass() { + private renderRecurrenceClass() { const rule = this.dataAccessors.get('recurrenceRule', this.rawAppointment); if (validateRRule(rule)) { @@ -275,12 +275,12 @@ export class Appointment extends DOMComponent { } } - _renderDirection() { + private renderDirection() { (this.$element() as any).addClass(DIRECTION_APPOINTMENT_CLASSES[this.option('direction') as any]); } - _createResizingConfig() { - const config: any = this.option('direction') === 'vertical' ? this._getVerticalResizingRule() : this._getHorizontalResizingRule(); + private createResizingConfig() { + const config: any = this.option('direction') === 'vertical' ? this.getVerticalResizingRule() : this.getHorizontalResizingRule(); if (!this.invoke('isGroupedByDate')) { config.stepPrecision = 'strict'; @@ -289,14 +289,14 @@ export class Appointment extends DOMComponent { return config; } - _renderResizable() { + private renderResizable() { if (this.option('allowResize')) { // @ts-expect-error this._createComponent( this.$element(), Resizable, extend( - this._createResizingConfig(), + this.createResizingConfig(), this.option('resizableConfig'), ), ); diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index de3f4a0fe049..bd3c12119c9b 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -400,7 +400,7 @@ class Scheduler extends SchedulerOptionsBaseWidget { break; case 'onAppointmentContextMenu': this._appointments.option('onItemContextMenu', this._createActionByOption(name)); - this.appointmentTooltip._options.onItemContextMenu = this._createActionByOption(name); + this.appointmentTooltip.options.onItemContextMenu = this._createActionByOption(name); break; case 'noDataText': case 'allowMultipleCellSelection': diff --git a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_desktop_tooltip_strategy.ts b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_desktop_tooltip_strategy.ts index fa181c0b6140..1718e25cf382 100644 --- a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_desktop_tooltip_strategy.ts +++ b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_desktop_tooltip_strategy.ts @@ -9,24 +9,24 @@ const MAX_TOOLTIP_HEIGHT = 200; export class DesktopTooltipStrategy extends TooltipStrategyBase { protected override prepareBeforeVisibleChanged(dataList) { - this._tooltip.option('position', { + this.tooltip.option('position', { my: 'bottom', at: 'top', boundary: this.getBoundary(dataList), - offset: this._extraOptions.offset, + offset: this.extraOptions.offset, collision: 'fit flipfit', }); } private getBoundary(dataList) { - return this._options.isAppointmentInAllDayPanel(dataList[0].appointment) ? this._options.container : this._options.getScrollableContainer(); + return this.options.isAppointmentInAllDayPanel(dataList[0].appointment) ? this.options.container : this.options.getScrollableContainer(); } protected override onShown() { super.onShown(); - if (this._extraOptions.isButtonClick) { - this._list.focus(); - this._list.option('focusedElement', null); + if (this.extraOptions.isButtonClick) { + this.list.focus(); + this.list.option('focusedElement', null); } } @@ -43,14 +43,14 @@ export class DesktopTooltipStrategy extends TooltipStrategyBase { protected override createTooltip(target, dataList) { const tooltipElement = this.createTooltipElement(APPOINTMENT_TOOLTIP_WRAPPER_CLASS); - const tooltip = this._options.createComponent(tooltipElement, Tooltip, { + const tooltip = this.options.createComponent(tooltipElement, Tooltip, { target, maxHeight: MAX_TOOLTIP_HEIGHT, - rtlEnabled: this._extraOptions.rtlEnabled, + 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({ @@ -62,11 +62,11 @@ export class DesktopTooltipStrategy extends TooltipStrategyBase { } protected override onListRender(e) { - return this._extraOptions.dragBehavior && this._extraOptions.dragBehavior(e); + return this.extraOptions.dragBehavior && this.extraOptions.dragBehavior(e); } protected override onListItemContextMenu(e) { - const contextMenuEventArgs = this._options.createEventArgs(e); - this._options.onItemContextMenu(contextMenuEventArgs); + const contextMenuEventArgs = this.options.createEventArgs(e); + this.options.onItemContextMenu(contextMenuEventArgs); } } diff --git a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_mobile_tooltip_strategy.ts b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_mobile_tooltip_strategy.ts index 69668b54f68e..c716e25dec43 100644 --- a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_mobile_tooltip_strategy.ts +++ b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_mobile_tooltip_strategy.ts @@ -71,16 +71,16 @@ export class MobileTooltipStrategy extends TooltipStrategyBase { 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 { - this._tooltip.option('height', MAX_HEIGHT.DEFAULT); + private async onShowingHandler(): Promise { + 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 @@ -94,12 +94,12 @@ export class MobileTooltipStrategy extends TooltipStrategyBase { protected override createTooltip(target, dataList) { const element = this.createTooltipElement(CLASS.slidePanel); - return this._options.createComponent(element, Overlay, { + return this.options.createComponent(element, Overlay, { target: getWindow(), hideOnOutsideClick: true, animation: animationConfig, - onShowing: () => this._onShowing(), + onShowing: () => this.onShowingHandler(), onShown: this.onShown.bind(this), contentTemplate: this.getContentTemplate(dataList), wrapperAttr: { class: CLASS.slidePanel }, diff --git a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts index dfe055939599..8c7d0aca96b2 100644 --- a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts +++ b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts @@ -20,24 +20,24 @@ const APPOINTMENT_TOOLTIP_TEMPLATE = 'appointmentTooltipTemplate'; export class TooltipStrategyBase { protected asyncTemplatePromises = new Set>(); - _tooltip: any; + protected tooltip: any; - _options: any; + protected options: any; - _extraOptions: any; + protected extraOptions: any; - _list: any; + protected list: any; constructor(options) { - this._tooltip = null; - this._options = options; - this._extraOptions = null; + this.tooltip = null; + this.options = options; + this.extraOptions = null; } show(target, dataList, extraOptions) { if (this.canShowTooltip(dataList)) { this.hide(); - this._extraOptions = extraOptions; + this.extraOptions = extraOptions; this.showCore(target, dataList); } } @@ -45,15 +45,15 @@ export class TooltipStrategyBase { 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.tooltip.option('visible', true); describedByValue && target.attr('aria-describedby', describedByValue); } @@ -64,8 +64,8 @@ export class TooltipStrategyBase { } private isDeletingAllowed(appointment) { - const { editing } = this._extraOptions; - const disabled = this._options.getAppointmentDisabled(appointment); + const { editing } = this.extraOptions; + const disabled = this.options.getAppointmentDisabled(appointment); const isDeletingAllowed = editing === true || editing?.allowDeleting === true; return !disabled && isDeletingAllowed; } @@ -74,47 +74,47 @@ export class TooltipStrategyBase { return (container) => { const listElement = $('
'); $(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(); + this.list.registerKeyHandler?.('del', () => { + const { focusedElement } = this.list.option(); if (!focusedElement) { return; } - const { appointment, targetedAppointment } = this._list._getItemData(focusedElement); + const { appointment, targetedAppointment } = this.list._getItemData(focusedElement); if (!appointment) { return; } if (this.isDeletingAllowed(appointment)) { this.hide(); - this._options.checkAndDeleteAppointment(appointment, targetedAppointment); + 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; } protected onShown() { - this._list.option('focusStateEnabled', this._extraOptions.focusStateEnabled); + 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); } } @@ -148,16 +148,16 @@ export class TooltipStrategyBase { protected onListRender(e) { } protected createTooltipElement(wrapperClass) { - return $('
').appendTo(this._options.container).addClass(wrapperClass); + return $('
').appendTo(this.options.container).addClass(wrapperClass); } private createList(listElement, dataList) { - return this._options.createComponent(listElement, List, this.createListOption(dataList)); + return this.options.createComponent(listElement, List, this.createListOption(dataList)); } private renderTemplate(appointment, targetedAppointment, index, color) { const itemListContent = this.createItemListContent(appointment, targetedAppointment, color); - this._options.addDefaultTemplates({ + this.options.addDefaultTemplates({ // @ts-expect-error appointmentTooltip: new FunctionTemplate((options) => { const $container = $(options.container); @@ -166,12 +166,12 @@ export class TooltipStrategyBase { }), }); - const template = this._options.getAppointmentTemplate(APPOINTMENT_TOOLTIP_TEMPLATE); + const template = this.options.getAppointmentTemplate(APPOINTMENT_TOOLTIP_TEMPLATE); return this.createFunctionTemplate(template, appointment, targetedAppointment, index); } private createFunctionTemplate(template, appointmentData, targetedAppointmentData, index) { - const isButtonClicked = Boolean(this._extraOptions.isButtonClick); + const isButtonClicked = Boolean(this.extraOptions.isButtonClick); // @ts-expect-error return new FunctionTemplate((options) => { @@ -196,8 +196,8 @@ export class TooltipStrategyBase { private onListItemClick(e) { this.hide(); - this._extraOptions.clickEvent && this._extraOptions.clickEvent(e); - this._options.showAppointmentPopup(e.itemData.appointment, false, e.itemData.targetedAppointment); + 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 @@ -206,7 +206,7 @@ export class TooltipStrategyBase { private createItemListContent(appointment, targetedAppointment, color) { const $itemElement = $('
').addClass(TOOLTIP_APPOINTMENT_ITEM); $itemElement.append(this.createItemListMarker(color)); - $itemElement.append(this.createItemListInfo(this._options.createFormattedDateText(appointment, targetedAppointment))); + $itemElement.append(this.createItemListInfo(this.options.createFormattedDateText(appointment, targetedAppointment))); if (this.isDeletingAllowed(appointment)) { $itemElement.append(this.createDeleteButton(appointment, targetedAppointment)); @@ -242,14 +242,14 @@ export class TooltipStrategyBase { const $deleteButton = $('
').addClass(TOOLTIP_APPOINTMENT_ITEM_DELETE_BUTTON); $container.append($deleteButton); - this._options.createComponent($deleteButton, Button, { + this.options.createComponent($deleteButton, Button, { icon: 'trash', stylingMode: 'text', tabIndex: -1, onClick: (e) => { this.hide(); e.event.stopPropagation(); - this._options.checkAndDeleteAppointment(appointment, targetedAppointment); + this.options.checkAndDeleteAppointment(appointment, targetedAppointment); }, }); From cdc06cf929fb0ea413e0dfa7ff71e26729659a6d Mon Sep 17 00:00:00 2001 From: Aleksey Semikozov Date: Sun, 15 Mar 2026 10:19:24 -0300 Subject: [PATCH 2/3] Scheduler - Fix options visibility to public (accessed externally by m_scheduler) --- .../scheduler/tooltip_strategies/m_tooltip_strategy_base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts index 8c7d0aca96b2..7d67a2eba6fb 100644 --- a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts +++ b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts @@ -22,7 +22,7 @@ export class TooltipStrategyBase { protected tooltip: any; - protected options: any; + public options: any; protected extraOptions: any; From 2dbfafd7417c6afab5ac430e83c702d1b215ecf7 Mon Sep 17 00:00:00 2001 From: Aleksey Semikozov Date: Sun, 15 Mar 2026 10:42:21 -0300 Subject: [PATCH 3/3] Scheduler - Fix QUnit tests accessing renamed tooltip strategy properties --- .../scheduler/tooltip_strategies/m_tooltip_strategy_base.ts | 2 +- .../appointment.tooltip.tests.js | 2 +- .../keyboardNavigation.tests.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts index 7d67a2eba6fb..f7d0df576bbf 100644 --- a/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts +++ b/packages/devextreme/js/__internal/scheduler/tooltip_strategies/m_tooltip_strategy_base.ts @@ -26,7 +26,7 @@ export class TooltipStrategyBase { protected extraOptions: any; - protected list: any; + public list: any; constructor(options) { this.tooltip = null; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.tooltip.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.tooltip.tests.js index 73a4e410542b..74ff184ea3bc 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.tooltip.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.tooltip.tests.js @@ -55,7 +55,7 @@ module('Integration: Appointment tooltip', { height: 600 }); - const getAppointmentDisabled = sinon.spy(scheduler.instance.appointmentTooltip._options, 'getAppointmentDisabled'); + const getAppointmentDisabled = sinon.spy(scheduler.instance.appointmentTooltip.options, 'getAppointmentDisabled'); const clock = sinon.useFakeTimers(); await scheduler.appointments.click(0, clock); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/keyboardNavigation.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/keyboardNavigation.tests.js index 9dcf6abff81f..67b6b86de713 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/keyboardNavigation.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/keyboardNavigation.tests.js @@ -88,13 +88,13 @@ QUnit.module('Keyboard Navigation', { }); scheduler.appointments.compact.click(); - assert.notOk(scheduler.instance.appointmentTooltip._list.option('focusStateEnabled'), 'focusStateEnabled was passed correctly'); + assert.notOk(scheduler.instance.appointmentTooltip.list.option('focusStateEnabled'), 'focusStateEnabled was passed correctly'); scheduler.instance.appointmentTooltip.hide(); scheduler.instance.option('focusStateEnabled', true); scheduler.appointments.compact.click(); - assert.ok(scheduler.instance.appointmentTooltip._list.option('focusStateEnabled'), 'focusStateEnabled was passed correctly'); + assert.ok(scheduler.instance.appointmentTooltip.list.option('focusStateEnabled'), 'focusStateEnabled was passed correctly'); }); QUnit.test('Workspace navigation by arrows should work correctly with opened dropDown appointments', async function(assert) {