diff --git a/.github/actions/get-changed-files/action.yml b/.github/actions/get-changed-files/action.yml deleted file mode 100644 index 105f010561a5..000000000000 --- a/.github/actions/get-changed-files/action.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: 'Get changed files' -description: 'Get a list of the pull request files and save it to the file system as a JSON file' - -inputs: - path: - description: 'Path where find a changes' - required: true - result: - description: 'PAth to the result file' - required: true - -runs: - using: composite - steps: - - name: Get changed files - shell: bash - run: | - gh api \ - -H "Accept: application/vnd.github+json" \ - "/repos/{owner}/{repo}/pulls/${{github.event.pull_request.number}}/files" --paginate \ - --jq '.[] | select(.filename | contains("${{ inputs.path }}")) | {filename:.filename}' | jq -s > ${{ inputs.result }} diff --git a/.github/workflows/demos_visual_tests_frameworks.yml b/.github/workflows/demos_visual_tests_frameworks.yml index d3afed223523..e909f943d89d 100644 --- a/.github/workflows/demos_visual_tests_frameworks.yml +++ b/.github/workflows/demos_visual_tests_frameworks.yml @@ -165,13 +165,12 @@ jobs: uses: actions/checkout@v4 - name: Get changed files - uses: ./.github/actions/get-changed-files + uses: DevExpress/github-actions/get-changed-files@v1 if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'force all tests') - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - path: apps/demos/Demos - result: apps/demos/changed-files.json + gh-token: ${{ secrets.GITHUB_TOKEN }} + paths: 'apps/demos/Demos/**/*' + output: apps/demos/changed-files.json - name: Upload artifacts uses: actions/upload-artifact@v4 diff --git a/apps/demos/configs/Angular/config.js b/apps/demos/configs/Angular/config.js index 72cb67751f8c..cc0ffeb9b20c 100644 --- a/apps/demos/configs/Angular/config.js +++ b/apps/demos/configs/Angular/config.js @@ -45,6 +45,7 @@ const componentNames = [ 'multi-view', 'nested', 'number-box', + 'pagination', 'pie-chart', 'pivot-grid-field-chooser', 'pivot-grid', diff --git a/apps/react-storybook/project.json b/apps/react-storybook/project.json index 1fb6402ec1e7..43b123283ec2 100644 --- a/apps/react-storybook/project.json +++ b/apps/react-storybook/project.json @@ -9,14 +9,14 @@ "options": { "script": "build" }, - "outputs": ["storybook-static"] + "outputs": ["{projectRoot}/storybook-static"] }, "start": { "executor": "nx:run-script", "options": { "script": "start" }, - "dependsOn": [] + "dependsOn": ["^build"] } }, "tags": [] diff --git a/apps/react-storybook/stories/chat/Chat.stories.tsx b/apps/react-storybook/stories/chat/Chat.stories.tsx index 6333208d128d..11131fb6ac0a 100644 --- a/apps/react-storybook/stories/chat/Chat.stories.tsx +++ b/apps/react-storybook/stories/chat/Chat.stories.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback } from 'react'; +import React, { useState, useCallback, useEffect } from 'react'; import {Chat, ChatTypes} from 'devextreme-react/chat' import type {Meta, StoryObj} from '@storybook/react'; import { firstAuthor, secondAuthor, initialMessages } from './data'; @@ -44,6 +44,7 @@ export const Overview: Story = { [firstAuthor.name]: firstAuthor, [secondAuthor.name]: secondAuthor, }, + defaultValue: firstAuthor.name, }, hint: { control: 'text', @@ -65,8 +66,14 @@ export const Overview: Story = { const [messages, setMessages] = useState(items); const onMessageSend = useCallback(({ message }) => { - setMessages((prevMessages) => [...prevMessages, message]); - }, []); + const updatedMessages = [...messages, message]; + + setMessages(updatedMessages); + }, [messages]); + + useEffect(() => { + setMessages(items); + }, [items]); return (
@@ -90,6 +97,76 @@ export const Overview: Story = { } } +export const EmptyView: Story = { + args: { + items: [], + user: firstAuthor, + ...commonArgs, + }, + argTypes: { + user: { + control: 'select', + options: [firstAuthor.name, secondAuthor.name], + mapping: { + [firstAuthor.name]: firstAuthor, + [secondAuthor.name]: secondAuthor, + }, + defaultValue: firstAuthor.name, + }, + hint: { + control: 'text', + } + }, + render: ({ + width, + height, + disabled, + rtlEnabled, + user, + items, + onItemsChange, + visible, + hint, + activeStateEnabled, + hoverStateEnabled, + focusStateEnabled, + }) => { + const [messages, setMessages] = useState(items); + + const onMessageSend = useCallback(({ message }) => { + const updatedMessages = [...messages, message]; + + setMessages(updatedMessages); + }, [messages]); + + useEffect(() => { + console.log(2); + setMessages(items); + }, [items]); + + return ( +
+ + +
+ ); + } +} + export const PopupIntegration: Story = { args: { items: initialMessages, @@ -106,6 +183,7 @@ export const PopupIntegration: Story = { [firstAuthor.name]: firstAuthor, [secondAuthor.name]: secondAuthor, }, + defaultValue: firstAuthor.name, }, hint: { control: 'text', @@ -130,6 +208,10 @@ export const PopupIntegration: Story = { setMessages((prevMessages) => [...prevMessages, message]); }, []); + useEffect(() => { + setMessages(items); + }, [items]); + return ( { user: userSecond, width: 400, height: 600, + onMessageSend: (e) => { + const { component, message } = e; + + component.renderMessage(message); + }, }); }); diff --git a/e2e/testcafe-devextreme/tests/pager/accessibility.ts b/e2e/testcafe-devextreme/tests/pager/accessibility.ts index a3b9cbf441cb..154d67239d86 100644 --- a/e2e/testcafe-devextreme/tests/pager/accessibility.ts +++ b/e2e/testcafe-devextreme/tests/pager/accessibility.ts @@ -9,7 +9,7 @@ fixture.disablePageReloads`Pager` .page(url(__dirname, '../container.html')); const options: Options = { - totalCount: [50], + itemCount: [50], displayMode: ['full', 'compact'], infoText: [undefined, 'Total {2} items. Page {0} of {1}'], @@ -52,7 +52,7 @@ const a11yCheckConfig = { }; const configuration: Configuration = { - component: 'dxPager', + component: 'dxPagination', a11yCheckConfig, options, created, diff --git a/e2e/testcafe-devextreme/tests/pager/baseProperties.ts b/e2e/testcafe-devextreme/tests/pager/baseProperties.ts index 9018abb08a47..095785218d1c 100644 --- a/e2e/testcafe-devextreme/tests/pager/baseProperties.ts +++ b/e2e/testcafe-devextreme/tests/pager/baseProperties.ts @@ -17,10 +17,10 @@ test('Pager width and height property', async (t) => { .eql(null) .expect(pager.element.getAttribute('height')) .eql(null); -}).before(async () => createWidget('dxPager', { +}).before(async () => createWidget('dxPagination', { width: 270, height: '95px', - totalCount: 50, + itemCount: 50, })); test('Pager elementAttr property', async (t) => { @@ -30,7 +30,7 @@ test('Pager elementAttr property', async (t) => { .eql('some description') .expect(pager.element.getAttribute('data-test')) .eql('custom data'); -}).before(async () => createWidget('dxPager', { +}).before(async () => createWidget('dxPagination', { elementAttr: { 'aria-label': 'some description', 'data-test': 'custom data', @@ -48,11 +48,11 @@ test('Pager hint, disabled and accessKey properties', async (t) => { .eql('F') .expect(pager.element.getAttribute('title')) .eql('Best Pager'); -}).before(async () => createWidget('dxPager', { +}).before(async () => createWidget('dxPagination', { hint: 'Best Pager', disabled: true, accessKey: 'F', - totalCount: 50, + itemCount: 50, })); test('Pager tabindex and state properties', async (t) => { @@ -80,8 +80,8 @@ test('Pager tabindex and state properties', async (t) => { await t .expect(pager.element.hasClass('dx-state-active')) .ok(); -}).before(async () => createWidget('dxPager', { - totalCount: 50, +}).before(async () => createWidget('dxPagination', { + itemCount: 50, disabled: false, width: '100%', focusStateEnabled: true, @@ -103,9 +103,9 @@ test('Pager focus method without focusStateEnabled', async (t) => { await t .expect(pager.getPageSize(0).element.focused) .ok(); -}).before(async () => createWidget('dxPager', { +}).before(async () => createWidget('dxPagination', { focusStateEnabled: false, - totalCount: 50, + itemCount: 50, })); test('Pager focus method with focusStateEnabled', async (t) => { @@ -121,7 +121,7 @@ test('Pager focus method with focusStateEnabled', async (t) => { await t .expect(pager.element.focused) .ok(); -}).before(async () => createWidget('dxPager', { +}).before(async () => createWidget('dxPagination', { focusStateEnabled: true, - totalCount: 50, + itemCount: 50, })); diff --git a/e2e/testcafe-devextreme/tests/pager/index.ts b/e2e/testcafe-devextreme/tests/pager/index.ts index ae1f19955ae8..d0efb07614f2 100644 --- a/e2e/testcafe-devextreme/tests/pager/index.ts +++ b/e2e/testcafe-devextreme/tests/pager/index.ts @@ -10,8 +10,8 @@ test('Pager visibile property', async (t) => { await t .expect(pager.element.hasClass('dx-state-invisible')) .ok(); -}).before(async () => createWidget('dxPager', { - totalCount: 50, +}).before(async () => createWidget('dxPagination', { + itemCount: 50, visible: false, })); @@ -22,8 +22,8 @@ test('PageSize selector test', async (t) => { .click(pager.getPageSize(1).element) .expect(pager.option('pageCount')) .eql(13); -}).before(async () => createWidget('dxPager', { - totalCount: 50, +}).before(async () => createWidget('dxPagination', { + itemCount: 50, pageIndex: 2, pageSize: 8, // pageCount: 7 allowedPageSizes: [2, 4, 8], @@ -38,8 +38,8 @@ test('PageIndex test', async (t) => { .click(pager.getNavPage('5').element) .expect(pager.option('pageIndex')) .eql(5); -}).before(async () => createWidget('dxPager', { - totalCount: 50, +}).before(async () => createWidget('dxPagination', { + itemCount: 50, pageIndex: 1, pageSize: 5, // pageCount: 10 })); @@ -53,8 +53,8 @@ test('PageIndex correction test', async (t) => { .click(pager.getPageSize(1).element) .expect(pager.option('pageIndex')) .eql(5); -}).before(async () => createWidget('dxPager', { - totalCount: 50, +}).before(async () => createWidget('dxPagination', { + itemCount: 50, pageIndex: 10, pageSize: 5, // pageCount: 10 })); diff --git a/e2e/testcafe-devextreme/tests/scheduler/a11y/appointment.ts b/e2e/testcafe-devextreme/tests/scheduler/a11y/appointment.ts index 92cc200deae6..767157199d79 100644 --- a/e2e/testcafe-devextreme/tests/scheduler/a11y/appointment.ts +++ b/e2e/testcafe-devextreme/tests/scheduler/a11y/appointment.ts @@ -32,7 +32,7 @@ fixture.disablePageReloads`a11y - appointment` const attrs = await scheduler.getAppointment('App 1').element.attributes; await t - .expect(attrs['aria-label']) + .expect(attrs['aria-roledescription']) .eql('February 1, 2021, Group: resource1, '); }).before(async () => { await createWidget('dxScheduler', { @@ -63,7 +63,7 @@ fixture.disablePageReloads`a11y - appointment` const attrs = await scheduler.getAppointment('App 1').element.attributes; await t - .expect(attrs['aria-label']) + .expect(attrs['aria-roledescription']) .eql('February 1, 2021, Group: resource11, resource21, '); }).before(async () => { await createWidget('dxScheduler', { @@ -128,7 +128,7 @@ fixture.disablePageReloads`a11y - appointment` async (i) => { const appt = scheduler.getAppointment('App 1', i); const attrs = await appt.element.attributes; - return attrs['aria-label']; + return attrs['aria-roledescription']; }, )); @@ -231,3 +231,28 @@ test('appointments & collector buttons can be navigated', async (t) => { currentDate: new Date(2021, 1, 1), }); }); + +test('Scheduler a11y: appointments does not have info about reccurence', async (t) => { + const scheduler = new Scheduler('#container'); + const recurrenceIcon = scheduler.getAppointment('Website Re-Design Plan').getRecurrenceElement(); + + await t + .expect(recurrenceIcon.getAttribute('aria-label')) + .eql('Recurring appointment'); +}).before(async () => { + await createWidget('dxScheduler', { + timeZone: 'America/Los_Angeles', + dataSource: [ + { + text: 'Website Re-Design Plan', + startDate: new Date('2021-04-26T16:30:00.000Z'), + endDate: new Date('2021-04-26T18:30:00.000Z'), + recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10', + }, + ], + views: ['day', 'week', 'workWeek', 'month'], + currentView: 'day', + currentDate: new Date(2021, 3, 29), + startDayHour: 9, + }); +}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/virtualScrolling/appointments.ts b/e2e/testcafe-devextreme/tests/scheduler/virtualScrolling/appointments.ts index 6ea4f660d34b..7f38bce43cc3 100644 --- a/e2e/testcafe-devextreme/tests/scheduler/virtualScrolling/appointments.ts +++ b/e2e/testcafe-devextreme/tests/scheduler/virtualScrolling/appointments.ts @@ -7,7 +7,7 @@ import { scrollTo } from './utils'; fixture.disablePageReloads`Scheduler: Virtual Scrolling` .page(url(__dirname, '../../container.html')); -test('Appointment should not repaint after scrolling if present on viewport', async (t) => { +test.skip('Appointment should not repaint after scrolling if present on viewport', async (t) => { const scheduler = new Scheduler('#container'); const { element } = scheduler.getAppointment('', 0); diff --git a/package.json b/package.json index 717c26c911a3..69cedf74f94f 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "axe-core": "4.10.0", "cheerio": "1.0.0-rc.10", "codelyzer": "6.0.2", - "devextreme-internal-tools": "16.0.0-beta.4", + "devextreme-internal-tools": "16.0.0-beta.5", "http-server": "14.1.1", "husky": "8.0.3", "jest": "29.7.0", @@ -65,5 +65,5 @@ "lint-staged", "pre-commit" ], - "packageManager": "pnpm@9.9.0" + "packageManager": "pnpm@9.11.0" } diff --git a/packages/devextreme-angular/src/common/grids/index.ts b/packages/devextreme-angular/src/common/grids/index.ts index 12ccf6a627f5..e06086eb7045 100644 --- a/packages/devextreme-angular/src/common/grids/index.ts +++ b/packages/devextreme-angular/src/common/grids/index.ts @@ -47,7 +47,6 @@ export { NewRowInfo, NewRowPosition, Pager, - PagerDisplayMode, PagerPageSize, PagingBase, RowDragging, diff --git a/packages/devextreme-angular/src/common/index.ts b/packages/devextreme-angular/src/common/index.ts index 8bf03d75991c..ccdb9057c493 100644 --- a/packages/devextreme-angular/src/common/index.ts +++ b/packages/devextreme-angular/src/common/index.ts @@ -9,6 +9,7 @@ export { DataStructure, DataType, Direction, + DisplayMode, DragDirection, Draggable, DragHighlight, @@ -28,6 +29,7 @@ export { Orientation, PageLoadMode, PageOrientation, + PagerBase, PatternRule, Position, PositionAlignment, diff --git a/packages/devextreme-angular/src/index.ts b/packages/devextreme-angular/src/index.ts index 9a2c7a1d805f..15285133dca8 100644 --- a/packages/devextreme-angular/src/index.ts +++ b/packages/devextreme-angular/src/index.ts @@ -44,6 +44,7 @@ export { DxMapComponent, DxMapModule } from 'devextreme-angular/ui/map'; export { DxMenuComponent, DxMenuModule } from 'devextreme-angular/ui/menu'; export { DxMultiViewComponent, DxMultiViewModule } from 'devextreme-angular/ui/multi-view'; export { DxNumberBoxComponent, DxNumberBoxModule } from 'devextreme-angular/ui/number-box'; +export { DxPaginationComponent, DxPaginationModule } from 'devextreme-angular/ui/pagination'; export { DxPieChartComponent, DxPieChartModule } from 'devextreme-angular/ui/pie-chart'; export { DxPivotGridComponent, DxPivotGridModule } from 'devextreme-angular/ui/pivot-grid'; export { DxPivotGridFieldChooserComponent, DxPivotGridFieldChooserModule } from 'devextreme-angular/ui/pivot-grid-field-chooser'; diff --git a/packages/devextreme-angular/src/ui/all.ts b/packages/devextreme-angular/src/ui/all.ts index add997831774..7bf2dc159c06 100644 --- a/packages/devextreme-angular/src/ui/all.ts +++ b/packages/devextreme-angular/src/ui/all.ts @@ -40,6 +40,7 @@ import { DxMapModule } from 'devextreme-angular/ui/map'; import { DxMenuModule } from 'devextreme-angular/ui/menu'; import { DxMultiViewModule } from 'devextreme-angular/ui/multi-view'; import { DxNumberBoxModule } from 'devextreme-angular/ui/number-box'; +import { DxPaginationModule } from 'devextreme-angular/ui/pagination'; import { DxPieChartModule } from 'devextreme-angular/ui/pie-chart'; import { DxPivotGridModule } from 'devextreme-angular/ui/pivot-grid'; import { DxPivotGridFieldChooserModule } from 'devextreme-angular/ui/pivot-grid-field-chooser'; @@ -124,6 +125,7 @@ import { DxTemplateModule } from 'devextreme-angular/core'; DxMenuModule, DxMultiViewModule, DxNumberBoxModule, + DxPaginationModule, DxPieChartModule, DxPivotGridModule, DxPivotGridFieldChooserModule, @@ -207,6 +209,7 @@ import { DxTemplateModule } from 'devextreme-angular/core'; DxMenuModule, DxMultiViewModule, DxNumberBoxModule, + DxPaginationModule, DxPieChartModule, DxPivotGridModule, DxPivotGridFieldChooserModule, diff --git a/packages/devextreme-angular/src/ui/data-grid/index.ts b/packages/devextreme-angular/src/ui/data-grid/index.ts index cfadb69dfedd..4de189c0edd4 100644 --- a/packages/devextreme-angular/src/ui/data-grid/index.ts +++ b/packages/devextreme-angular/src/ui/data-grid/index.ts @@ -25,7 +25,7 @@ export { ExplicitTypes } from 'devextreme/ui/data_grid'; import { PositionConfig } from 'devextreme/animation/position'; import { DragDirection, DragHighlight, HorizontalAlignment, Mode, ScrollbarMode, SelectAllMode, SingleMultipleOrNone, SortOrder } from 'devextreme/common'; -import { ApplyFilterMode, ColumnChooserMode, ColumnChooserSearchConfig, ColumnChooserSelectionConfig, ColumnResizeMode, DataChange, DataRenderMode, EnterKeyAction, EnterKeyDirection, GridsEditMode, GridsEditRefreshMode, GroupExpandMode, HeaderFilterSearchConfig, NewRowPosition, PagerDisplayMode, PagerPageSize, SelectionColumnDisplayMode, StartEditAction, StateStoreType, SummaryType } from 'devextreme/common/grids'; +import { ApplyFilterMode, ColumnChooserMode, ColumnChooserSearchConfig, ColumnChooserSelectionConfig, ColumnResizeMode, DataChange, DataRenderMode, EnterKeyAction, EnterKeyDirection, GridsEditMode, GridsEditRefreshMode, GroupExpandMode, HeaderFilterSearchConfig, NewRowPosition, Pager, SelectionColumnDisplayMode, StartEditAction, StateStoreType, SummaryType } from 'devextreme/common/grids'; import { UserDefinedElement } from 'devextreme/core/element'; import { Store } from 'devextreme/data'; import DataSource, { Options as DataSourceOptions } from 'devextreme/data/data_source'; @@ -325,10 +325,10 @@ export class DxDataGridComponent extends DxComponent */ @Input() - get columnFixing(): { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } } { + get columnFixing(): { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } } { return this._getOption('columnFixing'); } - set columnFixing(value: { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } }) { + set columnFixing(value: { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } }) { this._setOption('columnFixing', value); } @@ -806,10 +806,10 @@ export class DxDataGridComponent extends DxComponent */ @Input() - get pager(): { allowedPageSizes?: Mode | Array, displayMode?: PagerDisplayMode, infoText?: string, label?: string, showInfo?: boolean, showNavigationButtons?: boolean, showPageSizeSelector?: boolean, visible?: Mode | boolean } { + get pager(): Pager { return this._getOption('pager'); } - set pager(value: { allowedPageSizes?: Mode | Array, displayMode?: PagerDisplayMode, infoText?: string, label?: string, showInfo?: boolean, showNavigationButtons?: boolean, showPageSizeSelector?: boolean, visible?: Mode | boolean }) { + set pager(value: Pager) { this._setOption('pager', value); } @@ -1575,7 +1575,7 @@ export class DxDataGridComponent extends DxComponent * This member supports the internal infrastructure and is not intended to be used directly from your code. */ - @Output() columnFixingChange: EventEmitter<{ enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } }>; + @Output() columnFixingChange: EventEmitter<{ enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } }>; /** @@ -1834,7 +1834,7 @@ export class DxDataGridComponent extends DxComponent * This member supports the internal infrastructure and is not intended to be used directly from your code. */ - @Output() pagerChange: EventEmitter<{ allowedPageSizes?: Mode | Array, displayMode?: PagerDisplayMode, infoText?: string, label?: string, showInfo?: boolean, showNavigationButtons?: boolean, showPageSizeSelector?: boolean, visible?: Mode | boolean }>; + @Output() pagerChange: EventEmitter; /** diff --git a/packages/devextreme-angular/src/ui/data-grid/nested/column-fixing.ts b/packages/devextreme-angular/src/ui/data-grid/nested/column-fixing.ts index c01974e14669..9668a71571bf 100644 --- a/packages/devextreme-angular/src/ui/data-grid/nested/column-fixing.ts +++ b/packages/devextreme-angular/src/ui/data-grid/nested/column-fixing.ts @@ -45,10 +45,10 @@ export class DxoDataGridColumnFixingComponent extends NestedOption implements On } @Input() - get texts(): { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } { + get texts(): { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } { return this._getOption('texts'); } - set texts(value: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string }) { + set texts(value: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }) { this._setOption('texts', value); } diff --git a/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts b/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts index 9a07d8340370..15ce83328560 100644 --- a/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts +++ b/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts @@ -14,8 +14,8 @@ import { -import { Mode } from 'devextreme/common'; -import { PagerDisplayMode, PagerPageSize } from 'devextreme/common/grids'; +import { DisplayMode, Mode } from 'devextreme/common'; +import { PagerPageSize } from 'devextreme/common/grids'; import { NestedOptionHost, @@ -39,10 +39,10 @@ export class DxoDataGridPagerComponent extends NestedOption implements OnDestroy } @Input() - get displayMode(): PagerDisplayMode { + get displayMode(): DisplayMode { return this._getOption('displayMode'); } - set displayMode(value: PagerDisplayMode) { + set displayMode(value: DisplayMode) { this._setOption('displayMode', value); } diff --git a/packages/devextreme-angular/src/ui/data-grid/nested/texts.ts b/packages/devextreme-angular/src/ui/data-grid/nested/texts.ts index 74309699dbbc..7656993be0c2 100644 --- a/packages/devextreme-angular/src/ui/data-grid/nested/texts.ts +++ b/packages/devextreme-angular/src/ui/data-grid/nested/texts.ts @@ -53,11 +53,11 @@ export class DxoDataGridTextsComponent extends NestedOption implements OnDestroy } @Input() - get stickPosition(): string { - return this._getOption('stickPosition'); + get stickyPosition(): string { + return this._getOption('stickyPosition'); } - set stickPosition(value: string) { - this._setOption('stickPosition', value); + set stickyPosition(value: string) { + this._setOption('stickyPosition', value); } @Input() diff --git a/packages/devextreme-angular/src/ui/map/index.ts b/packages/devextreme-angular/src/ui/map/index.ts index c9667ba59cbf..a209bdf56532 100644 --- a/packages/devextreme-angular/src/ui/map/index.ts +++ b/packages/devextreme-angular/src/ui/map/index.ts @@ -110,10 +110,10 @@ export class DxMapComponent extends DxComponent implements OnDestroy, OnChanges, */ @Input() - get apiKey(): string | { bing?: string, google?: string, googleStatic?: string } { + get apiKey(): string | { azure?: string, bing?: string, google?: string, googleStatic?: string } { return this._getOption('apiKey'); } - set apiKey(value: string | { bing?: string, google?: string, googleStatic?: string }) { + set apiKey(value: string | { azure?: string, bing?: string, google?: string, googleStatic?: string }) { this._setOption('apiKey', value); } @@ -468,7 +468,7 @@ export class DxMapComponent extends DxComponent implements OnDestroy, OnChanges, * This member supports the internal infrastructure and is not intended to be used directly from your code. */ - @Output() apiKeyChange: EventEmitter; + @Output() apiKeyChange: EventEmitter; /** diff --git a/packages/devextreme-angular/src/ui/map/nested/api-key.ts b/packages/devextreme-angular/src/ui/map/nested/api-key.ts index 13761a4f7831..5ce72e446002 100644 --- a/packages/devextreme-angular/src/ui/map/nested/api-key.ts +++ b/packages/devextreme-angular/src/ui/map/nested/api-key.ts @@ -28,6 +28,14 @@ import { NestedOption } from 'devextreme-angular/core'; providers: [NestedOptionHost] }) export class DxoMapApiKeyComponent extends NestedOption implements OnDestroy, OnInit { + @Input() + get azure(): string { + return this._getOption('azure'); + } + set azure(value: string) { + this._setOption('azure', value); + } + @Input() get bing(): string { return this._getOption('bing'); diff --git a/packages/devextreme-angular/src/ui/nested/api-key.ts b/packages/devextreme-angular/src/ui/nested/api-key.ts index e6adb976bb5b..0afaff05282d 100644 --- a/packages/devextreme-angular/src/ui/nested/api-key.ts +++ b/packages/devextreme-angular/src/ui/nested/api-key.ts @@ -28,6 +28,14 @@ import { NestedOption } from 'devextreme-angular/core'; providers: [NestedOptionHost] }) export class DxoApiKeyComponent extends NestedOption implements OnDestroy, OnInit { + @Input() + get azure(): string { + return this._getOption('azure'); + } + set azure(value: string) { + this._setOption('azure', value); + } + @Input() get bing(): string { return this._getOption('bing'); diff --git a/packages/devextreme-angular/src/ui/nested/base/gantt-header-filter-texts.ts b/packages/devextreme-angular/src/ui/nested/base/gantt-header-filter-texts.ts index 86804456713c..971b9bb58687 100644 --- a/packages/devextreme-angular/src/ui/nested/base/gantt-header-filter-texts.ts +++ b/packages/devextreme-angular/src/ui/nested/base/gantt-header-filter-texts.ts @@ -31,11 +31,11 @@ export abstract class DxoGanttHeaderFilterTexts extends NestedOption { this._setOption('rightPosition', value); } - get stickPosition(): string { - return this._getOption('stickPosition'); + get stickyPosition(): string { + return this._getOption('stickyPosition'); } - set stickPosition(value: string) { - this._setOption('stickPosition', value); + set stickyPosition(value: string) { + this._setOption('stickyPosition', value); } get unfix(): string { diff --git a/packages/devextreme-angular/src/ui/nested/base/index.ts b/packages/devextreme-angular/src/ui/nested/base/index.ts index 91ec17641925..6e9515165ed5 100644 --- a/packages/devextreme-angular/src/ui/nested/base/index.ts +++ b/packages/devextreme-angular/src/ui/nested/base/index.ts @@ -38,6 +38,7 @@ export * from './html-editor-mention-dxi'; export * from './html-editor-table-context-menu'; export * from './html-editor-table-resizing'; export * from './html-editor-variables'; +export * from './pager'; export * from './pivot-grid-data-source'; export * from './popup-options'; export * from './position-config'; diff --git a/packages/devextreme-angular/src/ui/nested/base/pager.ts b/packages/devextreme-angular/src/ui/nested/base/pager.ts new file mode 100644 index 000000000000..974018feb34c --- /dev/null +++ b/packages/devextreme-angular/src/ui/nested/base/pager.ts @@ -0,0 +1,70 @@ +/* tslint:disable:max-line-length */ + +import { NestedOption } from 'devextreme-angular/core'; +import { + Component, +} from '@angular/core'; + +import { DisplayMode, Mode } from 'devextreme/common'; +import { PagerPageSize } from 'devextreme/common/grids'; + +@Component({ + template: '' +}) +export abstract class DxoPager extends NestedOption { + get allowedPageSizes(): Mode | Array { + return this._getOption('allowedPageSizes'); + } + set allowedPageSizes(value: Mode | Array) { + this._setOption('allowedPageSizes', value); + } + + get displayMode(): DisplayMode { + return this._getOption('displayMode'); + } + set displayMode(value: DisplayMode) { + this._setOption('displayMode', value); + } + + get infoText(): string { + return this._getOption('infoText'); + } + set infoText(value: string) { + this._setOption('infoText', value); + } + + get label(): string { + return this._getOption('label'); + } + set label(value: string) { + this._setOption('label', value); + } + + get showInfo(): boolean { + return this._getOption('showInfo'); + } + set showInfo(value: boolean) { + this._setOption('showInfo', value); + } + + get showNavigationButtons(): boolean { + return this._getOption('showNavigationButtons'); + } + set showNavigationButtons(value: boolean) { + this._setOption('showNavigationButtons', value); + } + + get showPageSizeSelector(): boolean { + return this._getOption('showPageSizeSelector'); + } + set showPageSizeSelector(value: boolean) { + this._setOption('showPageSizeSelector', value); + } + + get visible(): Mode | boolean { + return this._getOption('visible'); + } + set visible(value: Mode | boolean) { + this._setOption('visible', value); + } +} diff --git a/packages/devextreme-angular/src/ui/nested/column-fixing.ts b/packages/devextreme-angular/src/ui/nested/column-fixing.ts index b001770c3206..a3edfbfd21ff 100644 --- a/packages/devextreme-angular/src/ui/nested/column-fixing.ts +++ b/packages/devextreme-angular/src/ui/nested/column-fixing.ts @@ -45,10 +45,10 @@ export class DxoColumnFixingComponent extends NestedOption implements OnDestroy, } @Input() - get texts(): { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } { + get texts(): { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } { return this._getOption('texts'); } - set texts(value: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string }) { + set texts(value: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }) { this._setOption('texts', value); } diff --git a/packages/devextreme-angular/src/ui/nested/pager.ts b/packages/devextreme-angular/src/ui/nested/pager.ts index 33cc7c4da21e..e90a65cd7a0b 100644 --- a/packages/devextreme-angular/src/ui/nested/pager.ts +++ b/packages/devextreme-angular/src/ui/nested/pager.ts @@ -1,5 +1,6 @@ /* tslint:disable:max-line-length */ +/* tslint:disable:use-input-property-decorator */ import { Component, @@ -7,93 +8,36 @@ import { OnDestroy, NgModule, Host, - SkipSelf, - Input + SkipSelf } from '@angular/core'; -import { Mode } from 'devextreme/common'; -import { PagerDisplayMode, PagerPageSize } from 'devextreme/common/grids'; import { NestedOptionHost, } from 'devextreme-angular/core'; -import { NestedOption } from 'devextreme-angular/core'; +import { DxoPager } from './base/pager'; @Component({ selector: 'dxo-pager', template: '', styles: [''], - providers: [NestedOptionHost] + providers: [NestedOptionHost], + inputs: [ + 'allowedPageSizes', + 'displayMode', + 'infoText', + 'label', + 'showInfo', + 'showNavigationButtons', + 'showPageSizeSelector', + 'visible' + ] }) -export class DxoPagerComponent extends NestedOption implements OnDestroy, OnInit { - @Input() - get allowedPageSizes(): Mode | Array { - return this._getOption('allowedPageSizes'); - } - set allowedPageSizes(value: Mode | Array) { - this._setOption('allowedPageSizes', value); - } - - @Input() - get displayMode(): PagerDisplayMode { - return this._getOption('displayMode'); - } - set displayMode(value: PagerDisplayMode) { - this._setOption('displayMode', value); - } - - @Input() - get infoText(): string { - return this._getOption('infoText'); - } - set infoText(value: string) { - this._setOption('infoText', value); - } - - @Input() - get label(): string { - return this._getOption('label'); - } - set label(value: string) { - this._setOption('label', value); - } - - @Input() - get showInfo(): boolean { - return this._getOption('showInfo'); - } - set showInfo(value: boolean) { - this._setOption('showInfo', value); - } - - @Input() - get showNavigationButtons(): boolean { - return this._getOption('showNavigationButtons'); - } - set showNavigationButtons(value: boolean) { - this._setOption('showNavigationButtons', value); - } - - @Input() - get showPageSizeSelector(): boolean { - return this._getOption('showPageSizeSelector'); - } - set showPageSizeSelector(value: boolean) { - this._setOption('showPageSizeSelector', value); - } - - @Input() - get visible(): Mode | boolean { - return this._getOption('visible'); - } - set visible(value: Mode | boolean) { - this._setOption('visible', value); - } - +export class DxoPagerComponent extends DxoPager implements OnDestroy, OnInit { protected get _optionPath() { return 'pager'; diff --git a/packages/devextreme-angular/src/ui/nested/texts.ts b/packages/devextreme-angular/src/ui/nested/texts.ts index ede4d951a6c9..6f180dc3087f 100644 --- a/packages/devextreme-angular/src/ui/nested/texts.ts +++ b/packages/devextreme-angular/src/ui/nested/texts.ts @@ -30,7 +30,7 @@ import { DxoGanttHeaderFilterTexts } from './base/gantt-header-filter-texts'; 'fix', 'leftPosition', 'rightPosition', - 'stickPosition', + 'stickyPosition', 'unfix', 'addRow', 'cancelAllChanges', diff --git a/packages/devextreme-angular/src/ui/pagination/index.ts b/packages/devextreme-angular/src/ui/pagination/index.ts new file mode 100644 index 000000000000..361d6798ab94 --- /dev/null +++ b/packages/devextreme-angular/src/ui/pagination/index.ts @@ -0,0 +1,636 @@ +/* tslint:disable:max-line-length */ + + +import { + TransferState, + Component, + NgModule, + ElementRef, + NgZone, + PLATFORM_ID, + Inject, + + Input, + Output, + OnDestroy, + EventEmitter, + OnChanges, + DoCheck, + SimpleChanges +} from '@angular/core'; + + +import { DisplayMode } from 'devextreme/common'; + +import DxPagination from 'devextreme/ui/pagination'; + + +import { + DxComponent, + DxTemplateHost, + DxIntegrationModule, + DxTemplateModule, + NestedOptionHost, + IterableDifferHelper, + WatcherHelper +} from 'devextreme-angular/core'; + + + + + + +/** + * [descr:dxPagination] + + */ +@Component({ + selector: 'dx-pagination', + template: '', + providers: [ + DxTemplateHost, + WatcherHelper, + NestedOptionHost, + IterableDifferHelper + ] +}) +export class DxPaginationComponent extends DxComponent implements OnDestroy, OnChanges, DoCheck { + instance: DxPagination = null; + + /** + * [descr:WidgetOptions.accessKey] + + */ + @Input() + get accessKey(): string | undefined { + return this._getOption('accessKey'); + } + set accessKey(value: string | undefined) { + this._setOption('accessKey', value); + } + + + /** + * [descr:WidgetOptions.activeStateEnabled] + + */ + @Input() + get activeStateEnabled(): boolean { + return this._getOption('activeStateEnabled'); + } + set activeStateEnabled(value: boolean) { + this._setOption('activeStateEnabled', value); + } + + + /** + * [descr:dxPaginationOptions.allowedPageSizes] + + */ + @Input() + get allowedPageSizes(): Array { + return this._getOption('allowedPageSizes'); + } + set allowedPageSizes(value: Array) { + this._setOption('allowedPageSizes', value); + } + + + /** + * [descr:WidgetOptions.disabled] + + */ + @Input() + get disabled(): boolean { + return this._getOption('disabled'); + } + set disabled(value: boolean) { + this._setOption('disabled', value); + } + + + /** + * [descr:PagerBase.displayMode] + + */ + @Input() + get displayMode(): DisplayMode { + return this._getOption('displayMode'); + } + set displayMode(value: DisplayMode) { + this._setOption('displayMode', value); + } + + + /** + * [descr:DOMComponentOptions.elementAttr] + + */ + @Input() + get elementAttr(): any { + return this._getOption('elementAttr'); + } + set elementAttr(value: any) { + this._setOption('elementAttr', value); + } + + + /** + * [descr:WidgetOptions.focusStateEnabled] + + */ + @Input() + get focusStateEnabled(): boolean { + return this._getOption('focusStateEnabled'); + } + set focusStateEnabled(value: boolean) { + this._setOption('focusStateEnabled', value); + } + + + /** + * [descr:DOMComponentOptions.height] + + */ + @Input() + get height(): number | Function | string | undefined { + return this._getOption('height'); + } + set height(value: number | Function | string | undefined) { + this._setOption('height', value); + } + + + /** + * [descr:WidgetOptions.hint] + + */ + @Input() + get hint(): string | undefined { + return this._getOption('hint'); + } + set hint(value: string | undefined) { + this._setOption('hint', value); + } + + + /** + * [descr:WidgetOptions.hoverStateEnabled] + + */ + @Input() + get hoverStateEnabled(): boolean { + return this._getOption('hoverStateEnabled'); + } + set hoverStateEnabled(value: boolean) { + this._setOption('hoverStateEnabled', value); + } + + + /** + * [descr:PagerBase.infoText] + + */ + @Input() + get infoText(): string { + return this._getOption('infoText'); + } + set infoText(value: string) { + this._setOption('infoText', value); + } + + + /** + * [descr:dxPaginationOptions.itemCount] + + */ + @Input() + get itemCount(): number { + return this._getOption('itemCount'); + } + set itemCount(value: number) { + this._setOption('itemCount', value); + } + + + /** + * [descr:PagerBase.label] + + */ + @Input() + get label(): string { + return this._getOption('label'); + } + set label(value: string) { + this._setOption('label', value); + } + + + /** + * [descr:dxPaginationOptions.pageIndex] + + */ + @Input() + get pageIndex(): number { + return this._getOption('pageIndex'); + } + set pageIndex(value: number) { + this._setOption('pageIndex', value); + } + + + /** + * [descr:dxPaginationOptions.pageSize] + + */ + @Input() + get pageSize(): number { + return this._getOption('pageSize'); + } + set pageSize(value: number) { + this._setOption('pageSize', value); + } + + + /** + * [descr:DOMComponentOptions.rtlEnabled] + + */ + @Input() + get rtlEnabled(): boolean { + return this._getOption('rtlEnabled'); + } + set rtlEnabled(value: boolean) { + this._setOption('rtlEnabled', value); + } + + + /** + * [descr:PagerBase.showInfo] + + */ + @Input() + get showInfo(): boolean { + return this._getOption('showInfo'); + } + set showInfo(value: boolean) { + this._setOption('showInfo', value); + } + + + /** + * [descr:PagerBase.showNavigationButtons] + + */ + @Input() + get showNavigationButtons(): boolean { + return this._getOption('showNavigationButtons'); + } + set showNavigationButtons(value: boolean) { + this._setOption('showNavigationButtons', value); + } + + + /** + * [descr:PagerBase.showPageSizeSelector] + + */ + @Input() + get showPageSizeSelector(): boolean { + return this._getOption('showPageSizeSelector'); + } + set showPageSizeSelector(value: boolean) { + this._setOption('showPageSizeSelector', value); + } + + + /** + * [descr:WidgetOptions.tabIndex] + + */ + @Input() + get tabIndex(): number { + return this._getOption('tabIndex'); + } + set tabIndex(value: number) { + this._setOption('tabIndex', value); + } + + + /** + * [descr:WidgetOptions.visible] + + */ + @Input() + get visible(): boolean { + return this._getOption('visible'); + } + set visible(value: boolean) { + this._setOption('visible', value); + } + + + /** + * [descr:DOMComponentOptions.width] + + */ + @Input() + get width(): number | Function | string | undefined { + return this._getOption('width'); + } + set width(value: number | Function | string | undefined) { + this._setOption('width', value); + } + + /** + + * [descr:WidgetOptions.onContentReady] + + + */ + @Output() onContentReady: EventEmitter; + + /** + + * [descr:DOMComponentOptions.onDisposing] + + + */ + @Output() onDisposing: EventEmitter; + + /** + + * [descr:ComponentOptions.onInitialized] + + + */ + @Output() onInitialized: EventEmitter; + + /** + + * [descr:DOMComponentOptions.onOptionChanged] + + + */ + @Output() onOptionChanged: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() accessKeyChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() activeStateEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() allowedPageSizesChange: EventEmitter>; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() disabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() displayModeChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() elementAttrChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() focusStateEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() heightChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() hintChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() hoverStateEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() infoTextChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() itemCountChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() labelChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() pageIndexChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() pageSizeChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() rtlEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() showInfoChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() showNavigationButtonsChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() showPageSizeSelectorChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() tabIndexChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() visibleChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() widthChange: EventEmitter; + + + + + + + + + constructor(elementRef: ElementRef, ngZone: NgZone, templateHost: DxTemplateHost, + private _watcherHelper: WatcherHelper, + private _idh: IterableDifferHelper, + optionHost: NestedOptionHost, + transferState: TransferState, + @Inject(PLATFORM_ID) platformId: any) { + + super(elementRef, ngZone, templateHost, _watcherHelper, transferState, platformId); + + this._createEventEmitters([ + { subscribe: 'contentReady', emit: 'onContentReady' }, + { subscribe: 'disposing', emit: 'onDisposing' }, + { subscribe: 'initialized', emit: 'onInitialized' }, + { subscribe: 'optionChanged', emit: 'onOptionChanged' }, + { emit: 'accessKeyChange' }, + { emit: 'activeStateEnabledChange' }, + { emit: 'allowedPageSizesChange' }, + { emit: 'disabledChange' }, + { emit: 'displayModeChange' }, + { emit: 'elementAttrChange' }, + { emit: 'focusStateEnabledChange' }, + { emit: 'heightChange' }, + { emit: 'hintChange' }, + { emit: 'hoverStateEnabledChange' }, + { emit: 'infoTextChange' }, + { emit: 'itemCountChange' }, + { emit: 'labelChange' }, + { emit: 'pageIndexChange' }, + { emit: 'pageSizeChange' }, + { emit: 'rtlEnabledChange' }, + { emit: 'showInfoChange' }, + { emit: 'showNavigationButtonsChange' }, + { emit: 'showPageSizeSelectorChange' }, + { emit: 'tabIndexChange' }, + { emit: 'visibleChange' }, + { emit: 'widthChange' } + ]); + + this._idh.setHost(this); + optionHost.setHost(this); + } + + protected _createInstance(element, options) { + + return new DxPagination(element, options); + } + + + ngOnDestroy() { + this._destroyWidget(); + } + + ngOnChanges(changes: SimpleChanges) { + super.ngOnChanges(changes); + this.setupChanges('allowedPageSizes', changes); + } + + setupChanges(prop: string, changes: SimpleChanges) { + if (!(prop in this._optionsToUpdate)) { + this._idh.setup(prop, changes); + } + } + + ngDoCheck() { + this._idh.doCheck('allowedPageSizes'); + this._watcherHelper.checkWatchers(); + super.ngDoCheck(); + super.clearChangedOptions(); + } + + _setOption(name: string, value: any) { + let isSetup = this._idh.setupSingle(name, value); + let isChanged = this._idh.getChanges(name, value) !== null; + + if (isSetup || isChanged) { + super._setOption(name, value); + } + } +} + +@NgModule({ + imports: [ + DxIntegrationModule, + DxTemplateModule + ], + declarations: [ + DxPaginationComponent + ], + exports: [ + DxPaginationComponent, + DxTemplateModule + ] +}) +export class DxPaginationModule { } + +import type * as DxPaginationTypes from "devextreme/ui/pagination_types"; +export { DxPaginationTypes }; + + diff --git a/packages/devextreme-angular/src/ui/pagination/ng-package.json b/packages/devextreme-angular/src/ui/pagination/ng-package.json new file mode 100644 index 000000000000..3360c83b3395 --- /dev/null +++ b/packages/devextreme-angular/src/ui/pagination/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "index.ts" + } +} \ No newline at end of file diff --git a/packages/devextreme-angular/src/ui/tree-list/index.ts b/packages/devextreme-angular/src/ui/tree-list/index.ts index 3042b0492c8d..ee49c6509278 100644 --- a/packages/devextreme-angular/src/ui/tree-list/index.ts +++ b/packages/devextreme-angular/src/ui/tree-list/index.ts @@ -25,7 +25,7 @@ export { ExplicitTypes } from 'devextreme/ui/tree_list'; import { PositionConfig } from 'devextreme/animation/position'; import { DataStructure, DragDirection, DragHighlight, Mode, ScrollbarMode, ScrollMode, SingleMultipleOrNone, SortOrder } from 'devextreme/common'; -import { ApplyFilterMode, ColumnChooserMode, ColumnChooserSearchConfig, ColumnChooserSelectionConfig, ColumnResizeMode, DataChange, DataRenderMode, EnterKeyAction, EnterKeyDirection, GridsEditMode, GridsEditRefreshMode, HeaderFilterSearchConfig, PagerDisplayMode, PagerPageSize, StartEditAction, StateStoreType } from 'devextreme/common/grids'; +import { ApplyFilterMode, ColumnChooserMode, ColumnChooserSearchConfig, ColumnChooserSelectionConfig, ColumnResizeMode, DataChange, DataRenderMode, EnterKeyAction, EnterKeyDirection, GridsEditMode, GridsEditRefreshMode, HeaderFilterSearchConfig, Pager, StartEditAction, StateStoreType } from 'devextreme/common/grids'; import { UserDefinedElement } from 'devextreme/core/element'; import { Store } from 'devextreme/data'; import DataSource, { Options as DataSourceOptions } from 'devextreme/data/data_source'; @@ -317,10 +317,10 @@ export class DxTreeListComponent extends DxComponent */ @Input() - get columnFixing(): { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } } { + get columnFixing(): { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } } { return this._getOption('columnFixing'); } - set columnFixing(value: { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } }) { + set columnFixing(value: { enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } }) { this._setOption('columnFixing', value); } @@ -811,10 +811,10 @@ export class DxTreeListComponent extends DxComponent */ @Input() - get pager(): { allowedPageSizes?: Mode | Array, displayMode?: PagerDisplayMode, infoText?: string, label?: string, showInfo?: boolean, showNavigationButtons?: boolean, showPageSizeSelector?: boolean, visible?: Mode | boolean } { + get pager(): Pager { return this._getOption('pager'); } - set pager(value: { allowedPageSizes?: Mode | Array, displayMode?: PagerDisplayMode, infoText?: string, label?: string, showInfo?: boolean, showNavigationButtons?: boolean, showPageSizeSelector?: boolean, visible?: Mode | boolean }) { + set pager(value: Pager) { this._setOption('pager', value); } @@ -1559,7 +1559,7 @@ export class DxTreeListComponent extends DxComponent * This member supports the internal infrastructure and is not intended to be used directly from your code. */ - @Output() columnFixingChange: EventEmitter<{ enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } }>; + @Output() columnFixingChange: EventEmitter<{ enabled?: boolean, icons?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }, texts?: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } }>; /** @@ -1825,7 +1825,7 @@ export class DxTreeListComponent extends DxComponent * This member supports the internal infrastructure and is not intended to be used directly from your code. */ - @Output() pagerChange: EventEmitter<{ allowedPageSizes?: Mode | Array, displayMode?: PagerDisplayMode, infoText?: string, label?: string, showInfo?: boolean, showNavigationButtons?: boolean, showPageSizeSelector?: boolean, visible?: Mode | boolean }>; + @Output() pagerChange: EventEmitter; /** diff --git a/packages/devextreme-angular/src/ui/tree-list/nested/column-fixing.ts b/packages/devextreme-angular/src/ui/tree-list/nested/column-fixing.ts index 22c1642260ac..77b0387981b1 100644 --- a/packages/devextreme-angular/src/ui/tree-list/nested/column-fixing.ts +++ b/packages/devextreme-angular/src/ui/tree-list/nested/column-fixing.ts @@ -45,10 +45,10 @@ export class DxoTreeListColumnFixingComponent extends NestedOption implements On } @Input() - get texts(): { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string } { + get texts(): { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string } { return this._getOption('texts'); } - set texts(value: { fix?: string, leftPosition?: string, rightPosition?: string, stickPosition?: string, unfix?: string }) { + set texts(value: { fix?: string, leftPosition?: string, rightPosition?: string, stickyPosition?: string, unfix?: string }) { this._setOption('texts', value); } diff --git a/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts b/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts index ad7c08c84324..b87c16aa8592 100644 --- a/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts +++ b/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts @@ -14,8 +14,8 @@ import { -import { Mode } from 'devextreme/common'; -import { PagerDisplayMode, PagerPageSize } from 'devextreme/common/grids'; +import { DisplayMode, Mode } from 'devextreme/common'; +import { PagerPageSize } from 'devextreme/common/grids'; import { NestedOptionHost, @@ -39,10 +39,10 @@ export class DxoTreeListPagerComponent extends NestedOption implements OnDestroy } @Input() - get displayMode(): PagerDisplayMode { + get displayMode(): DisplayMode { return this._getOption('displayMode'); } - set displayMode(value: PagerDisplayMode) { + set displayMode(value: DisplayMode) { this._setOption('displayMode', value); } diff --git a/packages/devextreme-angular/src/ui/tree-list/nested/texts.ts b/packages/devextreme-angular/src/ui/tree-list/nested/texts.ts index e22735678401..31aa1dfab6dc 100644 --- a/packages/devextreme-angular/src/ui/tree-list/nested/texts.ts +++ b/packages/devextreme-angular/src/ui/tree-list/nested/texts.ts @@ -53,11 +53,11 @@ export class DxoTreeListTextsComponent extends NestedOption implements OnDestroy } @Input() - get stickPosition(): string { - return this._getOption('stickPosition'); + get stickyPosition(): string { + return this._getOption('stickyPosition'); } - set stickPosition(value: string) { - this._setOption('stickPosition', value); + set stickyPosition(value: string) { + this._setOption('stickyPosition', value); } @Input() diff --git a/packages/devextreme-angular/tests/src/server/component-names.ts b/packages/devextreme-angular/tests/src/server/component-names.ts index 29f9d764046f..d5914606f2ba 100644 --- a/packages/devextreme-angular/tests/src/server/component-names.ts +++ b/packages/devextreme-angular/tests/src/server/component-names.ts @@ -37,6 +37,7 @@ export const componentNames = [ 'menu', 'multi-view', 'number-box', + 'pagination', 'pie-chart', 'pivot-grid', 'pivot-grid-field-chooser', diff --git a/packages/devextreme-monorepo-tools/src/version-utils.ts b/packages/devextreme-monorepo-tools/src/version-utils.ts index f4ee61855060..ce6861413919 100644 --- a/packages/devextreme-monorepo-tools/src/version-utils.ts +++ b/packages/devextreme-monorepo-tools/src/version-utils.ts @@ -7,6 +7,10 @@ export function validateVersion(version: string | undefined): string { } export function formatVersion(version: string | undefined): string | undefined { + if (version?.length && version.length > 1000) { + throw new Error("version string is too long"); + } + return version?.match(/(\d+\.\d+\.\d+)(\D|$)/)?.[1]; } diff --git a/packages/devextreme-react/project.json b/packages/devextreme-react/project.json index 630ee7b22b8c..a276195129d8 100644 --- a/packages/devextreme-react/project.json +++ b/packages/devextreme-react/project.json @@ -4,6 +4,20 @@ "sourceRoot": "packages/devextreme-react", "projectType": "library", "targets": { + "build": { + "executor": "nx:run-script", + "dependsOn": ["^build"], + "options": { + "script": "pack" + }, + "inputs": [ + "default" + ], + "outputs": [ + "{projectRoot}/npm" + ], + "cache": true + }, "pack": { "executor": "nx:run-script", "options": { diff --git a/packages/devextreme-react/src/common/grids.ts b/packages/devextreme-react/src/common/grids.ts index e3528b335795..3c50f9be5a98 100644 --- a/packages/devextreme-react/src/common/grids.ts +++ b/packages/devextreme-react/src/common/grids.ts @@ -47,7 +47,6 @@ export { NewRowInfo, NewRowPosition, Pager, - PagerDisplayMode, PagerPageSize, PagingBase, RowDragging, diff --git a/packages/devextreme-react/src/common/index.ts b/packages/devextreme-react/src/common/index.ts index 83397af54a21..4cddfd8869c9 100644 --- a/packages/devextreme-react/src/common/index.ts +++ b/packages/devextreme-react/src/common/index.ts @@ -9,6 +9,7 @@ export { DataStructure, DataType, Direction, + DisplayMode, DragDirection, Draggable, DragHighlight, @@ -28,6 +29,7 @@ export { Orientation, PageLoadMode, PageOrientation, + PagerBase, PatternRule, Position, PositionAlignment, diff --git a/packages/devextreme-react/src/data-grid.ts b/packages/devextreme-react/src/data-grid.ts index df01a3bf03ea..674bccb9e00c 100644 --- a/packages/devextreme-react/src/data-grid.ts +++ b/packages/devextreme-react/src/data-grid.ts @@ -613,7 +613,7 @@ type IColumnFixingProps = React.PropsWithChildren<{ fix?: string; leftPosition?: string; rightPosition?: string; - stickPosition?: string; + stickyPosition?: string; unfix?: string; }; }> @@ -638,7 +638,7 @@ type IColumnFixingTextsProps = React.PropsWithChildren<{ fix?: string; leftPosition?: string; rightPosition?: string; - stickPosition?: string; + stickyPosition?: string; unfix?: string; }> const _componentColumnFixingTexts = memo( @@ -2623,7 +2623,7 @@ type ITextsProps = React.PropsWithChildren<{ fix?: string; leftPosition?: string; rightPosition?: string; - stickPosition?: string; + stickyPosition?: string; unfix?: string; clearFilter?: string; createFilter?: string; diff --git a/packages/devextreme-react/src/index.ts b/packages/devextreme-react/src/index.ts index 375b8e90f902..7854d6a05322 100644 --- a/packages/devextreme-react/src/index.ts +++ b/packages/devextreme-react/src/index.ts @@ -40,6 +40,7 @@ export { Map } from "./map"; export { Menu } from "./menu"; export { MultiView } from "./multi-view"; export { NumberBox } from "./number-box"; +export { Pagination } from "./pagination"; export { PieChart } from "./pie-chart"; export { PivotGrid } from "./pivot-grid"; export { PivotGridFieldChooser } from "./pivot-grid-field-chooser"; diff --git a/packages/devextreme-react/src/map.ts b/packages/devextreme-react/src/map.ts index 9cc6d20bb57f..1004ad12ea97 100644 --- a/packages/devextreme-react/src/map.ts +++ b/packages/devextreme-react/src/map.ts @@ -90,6 +90,7 @@ const Map = memo( // owners: // Map type IApiKeyProps = React.PropsWithChildren<{ + azure?: string; bing?: string; google?: string; googleStatic?: string; diff --git a/packages/devextreme-react/src/pagination.ts b/packages/devextreme-react/src/pagination.ts new file mode 100644 index 000000000000..13322f811f0d --- /dev/null +++ b/packages/devextreme-react/src/pagination.ts @@ -0,0 +1,63 @@ +"use client" +import * as React from "react"; +import { memo, forwardRef, useImperativeHandle, useRef, useMemo, ForwardedRef, Ref, ReactElement } from "react"; +import dxPagination, { + Properties +} from "devextreme/ui/pagination"; + +import { Component as BaseComponent, IHtmlOptions, ComponentRef } from "./core/component"; + +type IPaginationOptions = React.PropsWithChildren void; + onPageSizeChange?: (value: number) => void; +}> + +interface PaginationRef { + instance: () => dxPagination; +} + +const Pagination = memo( + forwardRef( + (props: React.PropsWithChildren, ref: ForwardedRef) => { + const baseRef = useRef(null); + + useImperativeHandle(ref, () => ( + { + instance() { + return baseRef.current?.getInstance(); + } + } + ), [baseRef.current]); + + const subscribableOptions = useMemo(() => (["pageIndex","pageSize"]), []); + const independentEvents = useMemo(() => (["onContentReady","onDisposing","onInitialized"]), []); + + const defaults = useMemo(() => ({ + defaultPageIndex: "pageIndex", + defaultPageSize: "pageSize", + }), []); + + return ( + React.createElement(BaseComponent>, { + WidgetClass: dxPagination, + ref: baseRef, + subscribableOptions, + independentEvents, + defaults, + ...props, + }) + ); + }, + ), +) as (props: React.PropsWithChildren & { ref?: Ref }) => ReactElement | null; +export default Pagination; +export { + Pagination, + IPaginationOptions, + PaginationRef +}; +import type * as PaginationTypes from 'devextreme/ui/pagination_types'; +export { PaginationTypes }; + diff --git a/packages/devextreme-react/src/tree-list.ts b/packages/devextreme-react/src/tree-list.ts index 8adc96b620f9..5949ec1a6145 100644 --- a/packages/devextreme-react/src/tree-list.ts +++ b/packages/devextreme-react/src/tree-list.ts @@ -569,7 +569,7 @@ type IColumnFixingProps = React.PropsWithChildren<{ fix?: string; leftPosition?: string; rightPosition?: string; - stickPosition?: string; + stickyPosition?: string; unfix?: string; }; }> @@ -594,7 +594,7 @@ type IColumnFixingTextsProps = React.PropsWithChildren<{ fix?: string; leftPosition?: string; rightPosition?: string; - stickPosition?: string; + stickyPosition?: string; unfix?: string; }> const _componentColumnFixingTexts = memo( @@ -2203,7 +2203,7 @@ type ITextsProps = React.PropsWithChildren<{ fix?: string; leftPosition?: string; rightPosition?: string; - stickPosition?: string; + stickyPosition?: string; unfix?: string; clearFilter?: string; createFilter?: string; diff --git a/packages/devextreme-scss/scss/widgets/base/_map.scss b/packages/devextreme-scss/scss/widgets/base/_map.scss index f3ce7f0a3df5..2e3346c486f4 100644 --- a/packages/devextreme-scss/scss/widgets/base/_map.scss +++ b/packages/devextreme-scss/scss/widgets/base/_map.scss @@ -13,6 +13,7 @@ left: 0; background: rgba(0, 0, 0, 0.01); opacity: 0.01; + pointer-events: all; } .dx-map-marker { diff --git a/packages/devextreme-vue/src/common/grids.ts b/packages/devextreme-vue/src/common/grids.ts index e3528b335795..3c50f9be5a98 100644 --- a/packages/devextreme-vue/src/common/grids.ts +++ b/packages/devextreme-vue/src/common/grids.ts @@ -47,7 +47,6 @@ export { NewRowInfo, NewRowPosition, Pager, - PagerDisplayMode, PagerPageSize, PagingBase, RowDragging, diff --git a/packages/devextreme-vue/src/common/index.ts b/packages/devextreme-vue/src/common/index.ts index 83397af54a21..4cddfd8869c9 100644 --- a/packages/devextreme-vue/src/common/index.ts +++ b/packages/devextreme-vue/src/common/index.ts @@ -9,6 +9,7 @@ export { DataStructure, DataType, Direction, + DisplayMode, DragDirection, Draggable, DragHighlight, @@ -28,6 +29,7 @@ export { Orientation, PageLoadMode, PageOrientation, + PagerBase, PatternRule, Position, PositionAlignment, diff --git a/packages/devextreme-vue/src/data-grid.ts b/packages/devextreme-vue/src/data-grid.ts index 08c72615ffe9..fe7a8b105f4a 100644 --- a/packages/devextreme-vue/src/data-grid.ts +++ b/packages/devextreme-vue/src/data-grid.ts @@ -887,14 +887,14 @@ const DxColumnFixingTextsConfig = { "update:fix": null, "update:leftPosition": null, "update:rightPosition": null, - "update:stickPosition": null, + "update:stickyPosition": null, "update:unfix": null, }, props: { fix: String, leftPosition: String, rightPosition: String, - stickPosition: String, + stickyPosition: String, unfix: String } }; @@ -3212,7 +3212,7 @@ const DxTextsConfig = { "update:rightPosition": null, "update:saveAllChanges": null, "update:saveRowChanges": null, - "update:stickPosition": null, + "update:stickyPosition": null, "update:sum": null, "update:sumOtherColumn": null, "update:undeleteRow": null, @@ -3253,7 +3253,7 @@ const DxTextsConfig = { rightPosition: String, saveAllChanges: String, saveRowChanges: String, - stickPosition: String, + stickyPosition: String, sum: String, sumOtherColumn: String, undeleteRow: String, diff --git a/packages/devextreme-vue/src/index.ts b/packages/devextreme-vue/src/index.ts index 2bb75ddc7a98..ab1ec1f3428a 100644 --- a/packages/devextreme-vue/src/index.ts +++ b/packages/devextreme-vue/src/index.ts @@ -39,6 +39,7 @@ export { DxMap } from "./map"; export { DxMenu } from "./menu"; export { DxMultiView } from "./multi-view"; export { DxNumberBox } from "./number-box"; +export { DxPagination } from "./pagination"; export { DxPieChart } from "./pie-chart"; export { DxPivotGrid } from "./pivot-grid"; export { DxPivotGridFieldChooser } from "./pivot-grid-field-chooser"; diff --git a/packages/devextreme-vue/src/map.ts b/packages/devextreme-vue/src/map.ts index 14b692e19241..c01916dc0f82 100644 --- a/packages/devextreme-vue/src/map.ts +++ b/packages/devextreme-vue/src/map.ts @@ -140,11 +140,13 @@ const DxApiKeyConfig = { emits: { "update:isActive": null, "update:hoveredElement": null, + "update:azure": null, "update:bing": null, "update:google": null, "update:googleStatic": null, }, props: { + azure: String, bing: String, google: String, googleStatic: String diff --git a/packages/devextreme-vue/src/pagination.ts b/packages/devextreme-vue/src/pagination.ts new file mode 100644 index 000000000000..833c54e5f62a --- /dev/null +++ b/packages/devextreme-vue/src/pagination.ts @@ -0,0 +1,117 @@ +import Pagination, { Properties } from "devextreme/ui/pagination"; +import { defineComponent } from "vue"; +import { prepareComponentConfig } from "./core/index"; + +type AccessibleOptions = Pick; + +interface DxPagination extends AccessibleOptions { + readonly instance?: Pagination; +} + +const componentConfig = { + props: { + accessKey: String, + activeStateEnabled: Boolean, + allowedPageSizes: Array, + disabled: Boolean, + displayMode: String, + elementAttr: Object, + focusStateEnabled: Boolean, + height: [Function, Number, String], + hint: String, + hoverStateEnabled: Boolean, + infoText: String, + itemCount: Number, + label: String, + onContentReady: Function, + onDisposing: Function, + onInitialized: Function, + onOptionChanged: Function, + pageIndex: Number, + pageSize: Number, + rtlEnabled: Boolean, + showInfo: Boolean, + showNavigationButtons: Boolean, + showPageSizeSelector: Boolean, + tabIndex: Number, + visible: Boolean, + width: [Function, Number, String] + }, + emits: { + "update:isActive": null, + "update:hoveredElement": null, + "update:accessKey": null, + "update:activeStateEnabled": null, + "update:allowedPageSizes": null, + "update:disabled": null, + "update:displayMode": null, + "update:elementAttr": null, + "update:focusStateEnabled": null, + "update:height": null, + "update:hint": null, + "update:hoverStateEnabled": null, + "update:infoText": null, + "update:itemCount": null, + "update:label": null, + "update:onContentReady": null, + "update:onDisposing": null, + "update:onInitialized": null, + "update:onOptionChanged": null, + "update:pageIndex": null, + "update:pageSize": null, + "update:rtlEnabled": null, + "update:showInfo": null, + "update:showNavigationButtons": null, + "update:showPageSizeSelector": null, + "update:tabIndex": null, + "update:visible": null, + "update:width": null, + }, + computed: { + instance(): Pagination { + return (this as any).$_instance; + } + }, + beforeCreate() { + (this as any).$_WidgetClass = Pagination; + (this as any).$_hasAsyncTemplate = true; + } +}; + +prepareComponentConfig(componentConfig); + +const DxPagination = defineComponent(componentConfig); + +export default DxPagination; +export { + DxPagination +}; +import type * as DxPaginationTypes from "devextreme/ui/pagination_types"; +export { DxPaginationTypes }; diff --git a/packages/devextreme-vue/src/tree-list.ts b/packages/devextreme-vue/src/tree-list.ts index f595c0768d8e..ceda5ec28454 100644 --- a/packages/devextreme-vue/src/tree-list.ts +++ b/packages/devextreme-vue/src/tree-list.ts @@ -867,14 +867,14 @@ const DxColumnFixingTextsConfig = { "update:fix": null, "update:leftPosition": null, "update:rightPosition": null, - "update:stickPosition": null, + "update:stickyPosition": null, "update:unfix": null, }, props: { fix: String, leftPosition: String, rightPosition: String, - stickPosition: String, + stickyPosition: String, unfix: String } }; @@ -2787,7 +2787,7 @@ const DxTextsConfig = { "update:rightPosition": null, "update:saveAllChanges": null, "update:saveRowChanges": null, - "update:stickPosition": null, + "update:stickyPosition": null, "update:undeleteRow": null, "update:unfix": null, "update:validationCancelChanges": null, @@ -2812,7 +2812,7 @@ const DxTextsConfig = { rightPosition: String, saveAllChanges: String, saveRowChanges: String, - stickPosition: String, + stickyPosition: String, undeleteRow: String, unfix: String, validationCancelChanges: String diff --git a/packages/devextreme/build/gulp/modules_metadata.json b/packages/devextreme/build/gulp/modules_metadata.json index fd38d7bccb83..b29735d5bebe 100644 --- a/packages/devextreme/build/gulp/modules_metadata.json +++ b/packages/devextreme/build/gulp/modules_metadata.json @@ -500,6 +500,12 @@ "baseZIndex": { "path": "ui.dxOverlay.baseZIndex" } } }, + { + "name": "ui/pagination", + "exports": { + "default": { "path": "ui.dxPagination", "isWidget": true } + } + }, { "name": "ui/pivot_grid", "exports": { diff --git a/packages/devextreme/js/__internal/.eslintrc.js b/packages/devextreme/js/__internal/.eslintrc.js index 433e1d5cd23e..0e5f380ec468 100644 --- a/packages/devextreme/js/__internal/.eslintrc.js +++ b/packages/devextreme/js/__internal/.eslintrc.js @@ -199,6 +199,28 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 'warn' } }, + // Rules for migrated core files. + { + files: [ + '**/core/**/m_*.ts', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + createDefaultProgram: true, + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, + rules: { + 'guard-for-in': 'off', + 'no-restricted-syntax': 'off', + 'func-style': 'off', + 'wrap-iife': 'off', + 'prefer-arrow-callback': 'off', + '@typescript-eslint/prefer-optional-chain': 'off', + 'radix': 'off', + 'object-shorthand': 'off' + }, + }, ], settings: { 'import/resolver': { diff --git a/packages/devextreme/js/__internal/core/m_action.ts b/packages/devextreme/js/__internal/core/m_action.ts index 1f9ad111ab46..9e1e1e09caf0 100644 --- a/packages/devextreme/js/__internal/core/m_action.ts +++ b/packages/devextreme/js/__internal/core/m_action.ts @@ -1,154 +1,174 @@ -import $ from './renderer'; -import { getWindow } from './utils/window'; -import { isPlainObject, isFunction } from './utils/type'; -import { each } from './utils/iterator'; - -export default class Action { - constructor(action, config) { - config = config || {}; - this._action = action; - this._context = config.context || getWindow(); - this._beforeExecute = config.beforeExecute; - this._afterExecute = config.afterExecute; - this._component = config.component; - this._validatingTargetName = config.validatingTargetName; - const excludeValidators = this._excludeValidators = {}; - - if(config.excludeValidators) { - for(let i = 0; i < config.excludeValidators.length; i++) { - excludeValidators[config.excludeValidators[i]] = true; - } - } - } +/* eslint-disable guard-for-in */ +/* eslint-disable @typescript-eslint/prefer-for-of */ +/* eslint-disable no-restricted-syntax */ +import $ from '@js/core/renderer'; +import { each } from '@js/core/utils/iterator'; +import { isFunction, isPlainObject } from '@js/core/utils/type'; +import { getWindow } from '@js/core/utils/window'; - execute() { - const e = { - action: this._action, - args: Array.prototype.slice.call(arguments), - context: this._context, - component: this._component, - validatingTargetName: this._validatingTargetName, - cancel: false, - handled: false - }; +class Action { + _action: any; - const beforeExecute = this._beforeExecute; - const afterExecute = this._afterExecute; + _context: any; - const argsBag = e.args[0] || {}; + _beforeExecute: any; - if(!this._validateAction(e)) { - return; - } + _afterExecute: any; - beforeExecute?.call(this._context, e); + _component: any; - if(e.cancel) { - return; - } + _validatingTargetName: any; - const result = this._executeAction(e); + _excludeValidators: any; - if(argsBag.cancel) { - return; - } + static executors: any; - afterExecute?.call(this._context, e); + constructor(action, config?) { + config = config || {}; + this._action = action; + this._context = config.context || getWindow(); + this._beforeExecute = config.beforeExecute; + this._afterExecute = config.afterExecute; + this._component = config.component; + this._validatingTargetName = config.validatingTargetName; + const excludeValidators = this._excludeValidators = {}; - return result; + if (config.excludeValidators) { + for (let i = 0; i < config.excludeValidators.length; i++) { + excludeValidators[config.excludeValidators[i]] = true; + } + } + } + + execute(...args) { + const e = { + action: this._action, + args: Array.prototype.slice.call(args), + context: this._context, + component: this._component, + validatingTargetName: this._validatingTargetName, + cancel: false, + handled: false, + }; + + const beforeExecute = this._beforeExecute; + const afterExecute = this._afterExecute; + + const argsBag = e.args[0] || {}; + + if (!this._validateAction(e)) { + return; } - _validateAction(e) { - const excludeValidators = this._excludeValidators; - const { executors } = Action; + beforeExecute?.call(this._context, e); - for(const name in executors) { - if(!excludeValidators[name]) { - const executor = executors[name]; - executor.validate?.(e); + if (e.cancel) { + return; + } - if(e.cancel) { - return false; - } - } - } + const result = this._executeAction(e); - return true; + if (argsBag.cancel) { + return; } - _executeAction(e) { - let result; - const { executors } = Action; + afterExecute?.call(this._context, e); - for(const name in executors) { - const executor = executors[name]; - executor.execute?.(e); + return result; + } - if(e.handled) { - result = e.result; - break; - } - } + _validateAction(e) { + const excludeValidators = this._excludeValidators; + const { executors } = Action; - return result; - } + // eslint-disable-next-line no-restricted-syntax + for (const name in executors) { + if (!excludeValidators[name]) { + const executor = executors[name]; + executor.validate?.(e); - static registerExecutor(name, executor) { - if(isPlainObject(name)) { - each(name, Action.registerExecutor); - return; + if (e.cancel) { + return false; } - Action.executors[name] = executor; + } } - static unregisterExecutor(...args) { - each(args, function() { - delete Action.executors[this]; - }); + return true; + } + + _executeAction(e) { + let result; + const { executors } = Action; + + for (const name in executors) { + const executor = executors[name]; + executor.execute?.(e); + + if (e.handled) { + result = e.result; + break; + } } + + return result; + } + + static registerExecutor(name, executor) { + if (isPlainObject(name)) { + each(name, Action.registerExecutor); + return; + } + Action.executors[name] = executor; + } + + static unregisterExecutor(...args) { + each(args, function () { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete Action.executors[this]; + }); + } } Action.executors = {}; const createValidatorByTargetElement = (condition) => (e) => { - if(!e.args.length) { - return; - } + if (!e.args.length) { + return; + } - const args = e.args[0]; - const element = args[e.validatingTargetName] || args.element; + const args = e.args[0]; + const element = args[e.validatingTargetName] || args.element; - if(element && condition($(element))) { - e.cancel = true; - } + if (element && condition($(element))) { + e.cancel = true; + } }; - +// @ts-expect-error expect name and executor Action.registerExecutor({ - 'disabled': { - validate: createValidatorByTargetElement(($target) => - $target.is('.dx-state-disabled, .dx-state-disabled *') - ) + disabled: { + validate: createValidatorByTargetElement(($target) => $target.is('.dx-state-disabled, .dx-state-disabled *')), + }, + + readOnly: { + validate: createValidatorByTargetElement(($target) => $target.is('.dx-state-readonly, .dx-state-readonly *:not(.dx-state-independent)')), + }, + undefined: { + execute: (e) => { + if (!e.action) { + e.result = undefined; + e.handled = true; + } }, - - 'readOnly': { - validate: createValidatorByTargetElement(($target) => - $target.is('.dx-state-readonly, .dx-state-readonly *:not(.dx-state-independent)') - ) - }, - 'undefined': { - execute: (e) => { - if(!e.action) { - e.result = undefined; - e.handled = true; - } - } + }, + func: { + execute: (e) => { + if (isFunction(e.action)) { + e.result = e.action.call(e.context, e.args[0]); + e.handled = true; + } }, - 'func': { - execute: (e) => { - if(isFunction(e.action)) { - e.result = e.action.call(e.context, e.args[0]); - e.handled = true; - } - } - } + }, }); + +export { Action }; +export default Action; diff --git a/packages/devextreme/js/__internal/core/m_class.ts b/packages/devextreme/js/__internal/core/m_class.ts index ec74b4165604..d6717599258d 100644 --- a/packages/devextreme/js/__internal/core/m_class.ts +++ b/packages/devextreme/js/__internal/core/m_class.ts @@ -1,154 +1,155 @@ -import errors from './errors'; -import { isWindow } from './utils/type'; - -const wrapOverridden = function(baseProto, methodName, method) { - return function() { - const prevCallBase = this.callBase; - this.callBase = baseProto[methodName]; - try { - return method.apply(this, arguments); - } finally { - this.callBase = prevCallBase; - } - }; +import errors from '@js/core/errors'; +import { isWindow } from '@js/core/utils/type'; + +const wrapOverridden = function (baseProto, methodName, method) { + return function () { + const prevCallBase = this.callBase; + this.callBase = baseProto[methodName]; + try { + return method.apply(this, arguments); + } finally { + this.callBase = prevCallBase; + } + }; }; -const clonePrototype = function(obj) { - const func = function() { }; - func.prototype = obj.prototype; - return new func(); +const clonePrototype = function (obj) { + const func = function () { }; + func.prototype = obj.prototype; + // eslint-disable-next-line new-cap + return new func(); }; -const redefine = function(members) { - const that = this; - let overridden; - let memberName; - let member; - - if(!members) { - return that; - } - - for(memberName in members) { - member = members[memberName]; - overridden = typeof that.prototype[memberName] === 'function' && typeof member === 'function'; - that.prototype[memberName] = overridden ? wrapOverridden(that.parent.prototype, memberName, member) : member; - } +const redefine = function (members) { + const that = this; + let overridden; + let memberName; + let member; + if (!members) { return that; -}; + } -const include = function() { - const classObj = this; - let argument; - let name; - let i; + for (memberName in members) { + member = members[memberName]; + overridden = typeof that.prototype[memberName] === 'function' && typeof member === 'function'; + that.prototype[memberName] = overridden ? wrapOverridden(that.parent.prototype, memberName, member) : member; + } - // NOTE: For ES6 classes. They don't have _includedCtors/_includedPostCtors - // properties and get them from the ancestor class. - const hasClassObjOwnProperty = Object.prototype.hasOwnProperty.bind(classObj); - const isES6Class = !hasClassObjOwnProperty('_includedCtors') && !hasClassObjOwnProperty('_includedPostCtors'); + return that; +}; - if(isES6Class) { - classObj._includedCtors = classObj._includedCtors.slice(0); - classObj._includedPostCtors = classObj._includedPostCtors.slice(0); +const include = function (...args) { + const classObj = this; + let argument; + let name; + let i; + + // NOTE: For ES6 classes. They don't have _includedCtors/_includedPostCtors + // properties and get them from the ancestor class. + const hasClassObjOwnProperty = Object.prototype.hasOwnProperty.bind(classObj); + const isES6Class = !hasClassObjOwnProperty('_includedCtors') && !hasClassObjOwnProperty('_includedPostCtors'); + + if (isES6Class) { + classObj._includedCtors = classObj._includedCtors.slice(0); + classObj._includedPostCtors = classObj._includedPostCtors.slice(0); + } + + for (i = 0; i < args.length; i++) { + argument = args[i]; + if (argument.ctor) { + classObj._includedCtors.push(argument.ctor); + } + if (argument.postCtor) { + classObj._includedPostCtors.push(argument.postCtor); } - for(i = 0; i < arguments.length; i++) { - argument = arguments[i]; - if(argument.ctor) { - classObj._includedCtors.push(argument.ctor); - } - if(argument.postCtor) { - classObj._includedPostCtors.push(argument.postCtor); - } - - for(name in argument) { - if(name === 'ctor' || name === 'postCtor' || name === 'default') { - continue; - } - ///#DEBUG - if(name in classObj.prototype) { - throw errors.Error('E0002', name); - } - ///#ENDDEBUG - classObj.prototype[name] = argument[name]; - } + // eslint-disable-next-line no-restricted-syntax + for (name in argument) { + if (name === 'ctor' || name === 'postCtor' || name === 'default') { + continue; + } + /// #DEBUG + if (name in classObj.prototype) { + throw errors.Error('E0002', name); + } + /// #ENDDEBUG + classObj.prototype[name] = argument[name]; } + } - return classObj; + return classObj; }; -const subclassOf = function(parentClass) { - const hasParentProperty = Object.prototype.hasOwnProperty.bind(this)('parent'); - const isES6Class = !hasParentProperty && this.parent; +const subclassOf = function (parentClass) { + const hasParentProperty = Object.prototype.hasOwnProperty.bind(this)('parent'); + const isES6Class = !hasParentProperty && this.parent; - if(isES6Class) { - const baseClass = Object.getPrototypeOf(this); + if (isES6Class) { + const baseClass = Object.getPrototypeOf(this); - return baseClass === parentClass || baseClass.subclassOf(parentClass); - } else { - if(this.parent === parentClass) { - return true; - } + return baseClass === parentClass || baseClass.subclassOf(parentClass); + } + if (this.parent === parentClass) { + return true; + } - if(!this.parent || !this.parent.subclassOf) { - return false; - } + if (!this.parent || !this.parent.subclassOf) { + return false; + } - return this.parent.subclassOf(parentClass); - } + return this.parent.subclassOf(parentClass); }; -const abstract = function() { - throw errors.Error('E0001'); +const abstract = function () { + throw errors.Error('E0001'); }; -const classImpl = function() { }; +const classImpl = function () { }; -classImpl.inherit = function(members) { - const inheritor = function() { - if(!this || isWindow(this) || typeof this.constructor !== 'function') { - throw errors.Error('E0003'); - } +classImpl.inherit = function (members) { + const inheritor = function (...args) { + if (!this || isWindow(this) || typeof this.constructor !== 'function') { + throw errors.Error('E0003'); + } - const instance = this; - const ctor = instance.ctor; - const includedCtors = instance.constructor._includedCtors; - const includedPostCtors = instance.constructor._includedPostCtors; - let i; + const instance = this; + const { ctor } = instance; + const includedCtors = instance.constructor._includedCtors; + const includedPostCtors = instance.constructor._includedPostCtors; + let i; - for(i = 0; i < includedCtors.length; i++) { - includedCtors[i].call(instance); - } + for (i = 0; i < includedCtors.length; i++) { + includedCtors[i].call(instance); + } - if(ctor) { - ctor.apply(instance, arguments); - } + if (ctor) { + ctor.apply(instance, args); + } - for(i = 0; i < includedPostCtors.length; i++) { - includedPostCtors[i].call(instance); - } - }; + for (i = 0; i < includedPostCtors.length; i++) { + includedPostCtors[i].call(instance); + } + }; - inheritor.prototype = clonePrototype(this); + inheritor.prototype = clonePrototype(this); - Object.setPrototypeOf(inheritor, this); + Object.setPrototypeOf(inheritor, this); - inheritor.inherit = this.inherit; - inheritor.abstract = abstract; - inheritor.redefine = redefine; - inheritor.include = include; - inheritor.subclassOf = subclassOf; + inheritor.inherit = this.inherit; + inheritor.abstract = abstract; + inheritor.redefine = redefine; + inheritor.include = include; + inheritor.subclassOf = subclassOf; - inheritor.parent = this; - inheritor._includedCtors = this._includedCtors ? this._includedCtors.slice(0) : []; - inheritor._includedPostCtors = this._includedPostCtors ? this._includedPostCtors.slice(0) : []; - inheritor.prototype.constructor = inheritor; + inheritor.parent = this; + inheritor._includedCtors = this._includedCtors ? this._includedCtors.slice(0) : []; + inheritor._includedPostCtors = this._includedPostCtors ? this._includedPostCtors.slice(0) : []; + inheritor.prototype.constructor = inheritor; - inheritor.redefine(members); + inheritor.redefine(members); - return inheritor; + return inheritor; }; classImpl.abstract = abstract; diff --git a/packages/devextreme/js/__internal/core/m_component_registrator.ts b/packages/devextreme/js/__internal/core/m_component_registrator.ts index c16268d492c7..388195eea768 100644 --- a/packages/devextreme/js/__internal/core/m_component_registrator.ts +++ b/packages/devextreme/js/__internal/core/m_component_registrator.ts @@ -1,59 +1,61 @@ -import $ from './renderer'; -import callbacks from './component_registrator_callbacks'; -import errors from './errors'; -import { name as publicComponentName } from './utils/public_component'; - -const registerComponent = function(name, namespace, componentClass) { - if(!componentClass) { - componentClass = namespace; - } else { - namespace[name] = componentClass; - } - - publicComponentName(componentClass, name); - callbacks.fire(name, componentClass); +import callbacks from '@js/core/component_registrator_callbacks'; +import errors from '@js/core/errors'; +import $ from '@js/core/renderer'; +import { name as publicComponentName } from '@js/core/utils/public_component'; + +const registerComponent = function (name, namespace, componentClass) { + if (!componentClass) { + componentClass = namespace; + } else { + namespace[name] = componentClass; + } + + publicComponentName(componentClass, name); + callbacks.fire(name, componentClass); }; -const registerRendererComponent = function(name, componentClass) { - $.fn[name] = function(options) { - const isMemberInvoke = typeof options === 'string'; - let result; +const registerRendererComponent = function (name, componentClass) { + // @ts-expect-error 'fn' does not exist on type '(selector?: string | Element | dxElementWrapper | undefined) => dxElementWrapper' + $.fn[name] = function (options) { + const isMemberInvoke = typeof options === 'string'; + let result; - if(isMemberInvoke) { - const memberName = options; - const memberArgs = [].slice.call(arguments).slice(1); + if (isMemberInvoke) { + const memberName = options; + const memberArgs = [].slice.call(arguments).slice(1); - this.each(function() { - const instance = componentClass.getInstance(this); + this.each(function () { + const instance = componentClass.getInstance(this); - if(!instance) { - throw errors.Error('E0009', name); - } + if (!instance) { + throw errors.Error('E0009', name); + } - const member = instance[memberName]; - const memberValue = member.apply(instance, memberArgs); + const member = instance[memberName]; + const memberValue = member.apply(instance, memberArgs); - if(result === undefined) { - result = memberValue; - } - }); + if (result === undefined) { + result = memberValue; + } + }); + } else { + this.each(function () { + const instance = componentClass.getInstance(this); + if (instance) { + instance.option(options); } else { - this.each(function() { - const instance = componentClass.getInstance(this); - if(instance) { - instance.option(options); - } else { - new componentClass(this, options); - } - }); - - result = this; + // eslint-disable-next-line new-cap, no-new + new componentClass(this, options); } + }); + + result = this; + } - return result; - }; + return result; + }; }; callbacks.add(registerRendererComponent); -export default registerComponent; +export { registerComponent }; diff --git a/packages/devextreme/js/__internal/core/m_component_registrator_callbacks.ts b/packages/devextreme/js/__internal/core/m_component_registrator_callbacks.ts index 8cb226142cdf..a9f78cf82814 100644 --- a/packages/devextreme/js/__internal/core/m_component_registrator_callbacks.ts +++ b/packages/devextreme/js/__internal/core/m_component_registrator_callbacks.ts @@ -1,3 +1,4 @@ -import MemorizedCallbacks from './memorized_callbacks'; +import MemorizedCallbacks from '@js/core/memorized_callbacks'; -export default new MemorizedCallbacks(); +const componentRegistratorCallbacks = new MemorizedCallbacks(); +export { componentRegistratorCallbacks }; diff --git a/packages/devextreme/js/__internal/core/m_config.ts b/packages/devextreme/js/__internal/core/m_config.ts index 4ef561bb0ded..f068dba256ac 100644 --- a/packages/devextreme/js/__internal/core/m_config.ts +++ b/packages/devextreme/js/__internal/core/m_config.ts @@ -1,90 +1,85 @@ /* global DevExpress */ -import { extend } from './utils/extend'; -import errors from './errors'; +import errors from '@js/core/errors'; +import { extend } from '@js/core/utils/extend'; const config = { - rtlEnabled: false, - defaultCurrency: 'USD', - defaultUseCurrencyAccountingStyle: true, - oDataFilterToLower: true, - serverDecimalSeparator: '.', - decimalSeparator: '.', - thousandsSeparator: ',', - forceIsoDateParsing: true, - wrapActionsBeforeExecute: true, - useLegacyStoreResult: false, - /** - * @name GlobalConfig.useJQuery - * @type boolean - * @hidden - */ - useJQuery: undefined, - editorStylingMode: undefined, - useLegacyVisibleIndex: false, + rtlEnabled: false, + defaultCurrency: 'USD', + defaultUseCurrencyAccountingStyle: true, + oDataFilterToLower: true, + serverDecimalSeparator: '.', + decimalSeparator: '.', + thousandsSeparator: ',', + forceIsoDateParsing: true, + wrapActionsBeforeExecute: true, + useLegacyStoreResult: false, + useJQuery: undefined, + editorStylingMode: undefined, + useLegacyVisibleIndex: false, - floatingActionButtonConfig: { - icon: 'add', - closeIcon: 'close', - label: '', - position: { - at: 'right bottom', - my: 'right bottom', - offset: { - x: -16, - y: -16 - } - }, - maxSpeedDialActionCount: 5, - shading: false, - direction: 'auto' + floatingActionButtonConfig: { + icon: 'add', + closeIcon: 'close', + label: '', + position: { + at: 'right bottom', + my: 'right bottom', + offset: { + x: -16, + y: -16, + }, }, + maxSpeedDialActionCount: 5, + shading: false, + direction: 'auto', + }, - optionsParser: (optionsString) => { - if(optionsString.trim().charAt(0) !== '{') { - optionsString = '{' + optionsString + '}'; - } + optionsParser: (optionsString) => { + if (optionsString.trim().charAt(0) !== '{') { + optionsString = `{${optionsString}}`; + } - try { - return JSON.parse(optionsString); - } catch(ex) { - try { - return JSON.parse(normalizeToJSONString(optionsString)); - } catch(exNormalize) { - throw errors.Error('E3018', ex, optionsString); - } - } - }, + try { + return JSON.parse(optionsString); + } catch (ex) { + try { + return JSON.parse(normalizeToJSONString(optionsString)); + } catch (exNormalize) { + throw errors.Error('E3018', ex, optionsString); + } + } + }, }; -const normalizeToJSONString = (optionsString) => { - return optionsString - .replace(/'/g, '"') // replace all ' to " - .replace(/,\s*([\]}])/g, '$1') // remove trailing commas - .replace(/([{,])\s*([^":\s]+)\s*:/g, '$1"$2":'); // add quotes for unquoted keys -}; +const normalizeToJSONString = (optionsString) => optionsString + .replace(/'/g, '"') // replace all ' to " + .replace(/,\s*([\]}])/g, '$1') // remove trailing commas + .replace(/([{,])\s*([^":\s]+)\s*:/g, '$1"$2":'); // add quotes for unquoted keys -const deprecatedFields = [ 'decimalSeparator', 'thousandsSeparator' ]; +const deprecatedFields = ['decimalSeparator', 'thousandsSeparator']; +// @ts-expect-error not all code paths return value const configMethod = (...args) => { - if(!args.length) { - return config; - } + if (!args.length) { + return config; + } - const newConfig = args[0]; + const newConfig = args[0]; - deprecatedFields.forEach((deprecatedField) => { - if(newConfig[deprecatedField]) { - const message = `Now, the ${deprecatedField} is selected based on the specified locale.`; - errors.log('W0003', 'config', deprecatedField, '19.2', message); - } - }); + deprecatedFields.forEach((deprecatedField) => { + if (newConfig[deprecatedField]) { + const message = `Now, the ${deprecatedField} is selected based on the specified locale.`; + errors.log('W0003', 'config', deprecatedField, '19.2', message); + } + }); - extend(config, newConfig); + extend(config, newConfig); }; - -if(typeof DevExpress !== 'undefined' && DevExpress.config) { - configMethod(DevExpress.config); +// @ts-expect-error typescript cant see global +if (typeof DevExpress !== 'undefined' && DevExpress.config) { +// @ts-expect-error typescript cant see global + configMethod(DevExpress.config); } export default configMethod; diff --git a/packages/devextreme/js/__internal/core/m_devices.ts b/packages/devextreme/js/__internal/core/m_devices.ts index 7714dbf38be5..2f6ed66f07eb 100644 --- a/packages/devextreme/js/__internal/core/m_devices.ts +++ b/packages/devextreme/js/__internal/core/m_devices.ts @@ -1,377 +1,405 @@ -import { getHeight, getWidth } from './utils/size'; -import $ from '../core/renderer'; -import { getWindow, getNavigator, hasWindow } from './utils/window'; -import { extend } from './utils/extend'; -import { isPlainObject } from './utils/type'; -import errors from './errors'; -import Callbacks from './utils/callbacks'; -import readyCallbacks from './utils/ready_callbacks'; -import resizeCallbacks from './utils/resize_callbacks'; -import { EventsStrategy } from './events_strategy'; -import { sessionStorage as SessionStorage } from './utils/storage'; -import { changeCallback, value as viewPort } from './utils/view_port'; -import Config from './config'; +import Config from '@js/core/config'; +import errors from '@js/core/errors'; +import { EventsStrategy } from '@js/core/events_strategy'; +import $ from '@js/core/renderer'; +import type { Callback } from '@js/core/utils/callbacks'; +import Callbacks from '@js/core/utils/callbacks'; +import { extend } from '@js/core/utils/extend'; +import readyCallbacks from '@js/core/utils/ready_callbacks'; +import resizeCallbacks from '@js/core/utils/resize_callbacks'; +import { getHeight, getWidth } from '@js/core/utils/size'; +import { sessionStorage as SessionStorage } from '@js/core/utils/storage'; +import { isPlainObject } from '@js/core/utils/type'; +import { changeCallback, value as viewPort } from '@js/core/utils/view_port'; +import { getNavigator, getWindow, hasWindow } from '@js/core/utils/window'; + +export interface Device { + android?: boolean; + deviceType?: 'phone' | 'tablet' | 'desktop'; + generic?: boolean; + grade?: 'A' | 'B' | 'C'; + ios?: boolean; + phone?: boolean; + platform?: 'android' | 'ios' | 'generic'; + tablet?: boolean; + version?: number[]; +} const window = getWindow(); const KNOWN_UA_TABLE = { - 'iPhone': 'iPhone', - 'iPhone5': 'iPhone', - 'iPhone6': 'iPhone', - 'iPhone6plus': 'iPhone', - 'iPad': 'iPad', - 'iPadMini': 'iPad Mini', - 'androidPhone': 'Android Mobile', - 'androidTablet': 'Android', - 'msSurface': 'Windows ARM Tablet PC', - 'desktop': 'desktop' + iPhone: 'iPhone', + iPhone5: 'iPhone', + iPhone6: 'iPhone', + iPhone6plus: 'iPhone', + iPad: 'iPad', + iPadMini: 'iPad Mini', + androidPhone: 'Android Mobile', + androidTablet: 'Android', + msSurface: 'Windows ARM Tablet PC', + desktop: 'desktop', }; const DEFAULT_DEVICE = { - deviceType: 'desktop', - platform: 'generic', - version: [], - phone: false, - tablet: false, - android: false, - ios: false, - generic: true, - grade: 'A', - - // TODO: For internal use (draft, do not document these options!) - mac: false + deviceType: 'desktop', + platform: 'generic', + version: [], + phone: false, + tablet: false, + android: false, + ios: false, + generic: true, + grade: 'A', + + // TODO: For internal use (draft, do not document these options!) + mac: false, }; const UA_PARSERS = { - generic(userAgent) { - const isPhone = /windows phone/i.test(userAgent) || userAgent.match(/WPDesktop/); - const isTablet = !isPhone && /Windows(.*)arm(.*)Tablet PC/i.test(userAgent); - const isDesktop = !isPhone && !isTablet && /msapphost/i.test(userAgent); - const isMac = /((intel|ppc) mac os x)/.test(userAgent.toLowerCase()); - - if(!(isPhone || isTablet || isDesktop || isMac)) { - return null; - } - - return { - deviceType: isPhone ? 'phone' : isTablet ? 'tablet' : 'desktop', - platform: 'generic', - version: [], - grade: 'A', - mac: isMac - }; - }, - - appleTouchDevice(userAgent) { - const navigator = getNavigator(); - const isIpadOs = /Macintosh/i.test(userAgent) && navigator?.maxTouchPoints > 2; - const isAppleDevice = /ip(hone|od|ad)/i.test(userAgent); - - if(!isAppleDevice && !isIpadOs) { - return null; - } + generic(userAgent) { + const isPhone = /windows phone/i.test(userAgent) || userAgent.match(/WPDesktop/); + const isTablet = !isPhone && /Windows(.*)arm(.*)Tablet PC/i.test(userAgent); + const isDesktop = !isPhone && !isTablet && /msapphost/i.test(userAgent); + const isMac = /((intel|ppc) mac os x)/.test(userAgent.toLowerCase()); + + if (!(isPhone || isTablet || isDesktop || isMac)) { + return null; + } - const isPhone = /ip(hone|od)/i.test(userAgent); - const matches = userAgent.match(/os\s{0,}X? (\d+)_(\d+)_?(\d+)?/i); - const version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : []; - const isIPhone4 = (window.screen.height === (960 / 2)); - const grade = isIPhone4 ? 'B' : 'A'; - - return { - deviceType: isPhone ? 'phone' : 'tablet', - platform: 'ios', - version, - grade - }; - }, - - android(userAgent) { - // TODO: Check this RegExp. - // It looks like there may be missing android user agents. - const isAndroid = /android|htc_|silk/i.test(userAgent); - const isWinPhone = /windows phone/i.test(userAgent); - - if(!isAndroid || isWinPhone) { - return null; - } + return { + deviceType: isPhone ? 'phone' : isTablet ? 'tablet' : 'desktop', + platform: 'generic', + version: [], + grade: 'A', + mac: isMac, + }; + }, + + appleTouchDevice(userAgent) { + const navigator = getNavigator(); + const isIpadOs = /Macintosh/i.test(userAgent) && navigator?.maxTouchPoints > 2; + const isAppleDevice = /ip(hone|od|ad)/i.test(userAgent); + + if (!isAppleDevice && !isIpadOs) { + return null; + } - const isPhone = /mobile/i.test(userAgent); - const matches = userAgent.match(/android (\d+)\.?(\d+)?\.?(\d+)?/i); - const version = matches ? [parseInt(matches[1], 10), parseInt(matches[2] || 0, 10), parseInt(matches[3] || 0, 10)] : []; - const worseThan4_4 = version.length > 1 && (version[0] < 4 || version[0] === 4 && version[1] < 4); - const grade = worseThan4_4 ? 'B' : 'A'; - - return { - deviceType: isPhone ? 'phone' : 'tablet', - platform: 'android', - version, - grade - }; + const isPhone = /ip(hone|od)/i.test(userAgent); + const matches = userAgent.match(/os\s{0,}X? (\d+)_(\d+)_?(\d+)?/i); + const version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : []; + const isIPhone4 = window.screen.height === (960 / 2); + const grade = isIPhone4 ? 'B' : 'A'; + + return { + deviceType: isPhone ? 'phone' : 'tablet', + platform: 'ios', + version, + grade, + }; + }, + + android(userAgent) { + // TODO: Check this RegExp. + // It looks like there may be missing android user agents. + const isAndroid = /android|htc_|silk/i.test(userAgent); + const isWinPhone = /windows phone/i.test(userAgent); + + if (!isAndroid || isWinPhone) { + return null; } + + const isPhone = /mobile/i.test(userAgent); + const matches = userAgent.match(/android (\d+)\.?(\d+)?\.?(\d+)?/i); + const version = matches ? [parseInt(matches[1], 10), parseInt(matches[2] || 0, 10), parseInt(matches[3] || 0, 10)] : []; + // eslint-disable-next-line @typescript-eslint/naming-convention + const worseThan4_4 = version.length > 1 && (version[0] < 4 || version[0] === 4 && version[1] < 4); + const grade = worseThan4_4 ? 'B' : 'A'; + + return { + deviceType: isPhone ? 'phone' : 'tablet', + platform: 'android', + version, + grade, + }; + }, }; const UA_PARSERS_ARRAY = [ - UA_PARSERS.appleTouchDevice, - UA_PARSERS.android, - UA_PARSERS.generic + UA_PARSERS.appleTouchDevice, + UA_PARSERS.android, + UA_PARSERS.generic, ]; class Devices { - /** - * @name DevicesObject.ctor - * @publicName ctor(options) - * @param1 options:object - * @param1_field1 window:Window - * @hidden - */ - constructor(options) { - this._window = options?.window || window; - - this._realDevice = this._getDevice(); - this._currentDevice = undefined; - this._currentOrientation = undefined; - this._eventsStrategy = new EventsStrategy(this); - - this.changed = Callbacks(); - if(hasWindow()) { - readyCallbacks.add(this._recalculateOrientation.bind(this)); - resizeCallbacks.add(this._recalculateOrientation.bind(this)); - } - } + _window: Window; - current(deviceOrName) { - if(deviceOrName) { - this._currentDevice = this._getDevice(deviceOrName); - this._forced = true; - this.changed.fire(); + _realDevice: any; - return; - } + _currentDevice: any; - if(!this._currentDevice) { - deviceOrName = undefined; - try { - deviceOrName = this._getDeviceOrNameFromWindowScope(); - } catch(e) { - deviceOrName = this._getDeviceNameFromSessionStorage(); - } finally { - if(!deviceOrName) { - deviceOrName = this._getDeviceNameFromSessionStorage(); - } - if(deviceOrName) { - this._forced = true; - } - } - this._currentDevice = this._getDevice(deviceOrName); - } + _currentOrientation: any; - return this._currentDevice; - } + _eventsStrategy: EventsStrategy; - real(forceDevice) { - ///#DEBUG - if(isPlainObject(forceDevice)) { - extend(this._realDevice, forceDevice); - return; - } - ///#ENDDEBUG - return extend({}, this._realDevice); - } + changed: Callback; - orientation() { - return this._currentOrientation; - } + _forced?: boolean; - isForced() { - return this._forced; - } + _deviceClasses?: string; - isRippleEmulator() { - return !!this._window.tinyHippos; - } + _isSimulator: any; - _getCssClasses(device) { - const result = []; - const realDevice = this._realDevice; + _currentWidth: any; - device = device || this.current(); + constructor(options?: { window?: Window }) { + this._window = options?.window ?? window; - // TODO: use real device here? - if(device.deviceType) { - result.push(`dx-device-${device.deviceType}`); - if(device.deviceType !== 'desktop') { - result.push('dx-device-mobile'); - } - } + this._realDevice = this._getDevice(); + this._currentDevice = undefined; + this._currentOrientation = undefined; + this._eventsStrategy = new EventsStrategy(this); - result.push(`dx-device-${realDevice.platform}`); + this.changed = Callbacks(); + if (hasWindow()) { + readyCallbacks.add(this._recalculateOrientation.bind(this)); + resizeCallbacks.add(this._recalculateOrientation.bind(this)); + } + } - if(realDevice.version && realDevice.version.length) { - result.push(`dx-device-${realDevice.platform}-${realDevice.version[0]}`); - } + current(deviceOrName?: string | Device) { + if (deviceOrName) { + this._currentDevice = this._getDevice(deviceOrName); + this._forced = true; + this.changed.fire(); - if(this.isSimulator()) { - result.push('dx-simulator'); - } + return; + } - if(Config().rtlEnabled) { - result.push('dx-rtl'); + if (!this._currentDevice) { + deviceOrName = undefined; + try { + deviceOrName = this._getDeviceOrNameFromWindowScope(); + } catch (e) { + deviceOrName = this._getDeviceNameFromSessionStorage(); + } finally { + if (!deviceOrName) { + deviceOrName = this._getDeviceNameFromSessionStorage(); } - - return result; + if (deviceOrName) { + this._forced = true; + } + } + this._currentDevice = this._getDevice(deviceOrName); } - attachCssClasses(element, device) { - this._deviceClasses = this._getCssClasses(device).join(' '); - $(element).addClass(this._deviceClasses); + return this._currentDevice; + } + + real(forceDevice?) { + /// #DEBUG + if (isPlainObject(forceDevice)) { + extend(this._realDevice, forceDevice); + return; + } + /// #ENDDEBUG + return extend({}, this._realDevice); + } + + orientation() { + return this._currentOrientation; + } + + isForced() { + return this._forced; + } + + isRippleEmulator() { + // @ts-expect-error + return !!this._window.tinyHippos; + } + + _getCssClasses(device) { + const result: any[] = []; + const realDevice = this._realDevice; + + device = device || this.current(); + + // TODO: use real device here? + if (device.deviceType) { + result.push(`dx-device-${device.deviceType}`); + if (device.deviceType !== 'desktop') { + result.push('dx-device-mobile'); + } } - detachCssClasses(element) { - $(element).removeClass(this._deviceClasses); + result.push(`dx-device-${realDevice.platform}`); + + if (realDevice.version && realDevice.version.length) { + result.push(`dx-device-${realDevice.platform}-${realDevice.version[0]}`); } - isSimulator() { - // NOTE: error may happen due to same-origin policy - try { - return this._isSimulator || hasWindow() && this._window.top !== this._window.self && this._window.top['dx-force-device'] || this.isRippleEmulator(); - } catch(e) { - return false; - } + if (this.isSimulator()) { + result.push('dx-simulator'); } - forceSimulator() { - this._isSimulator = true; + if (Config().rtlEnabled) { + result.push('dx-rtl'); } - _getDevice(deviceName) { - if(deviceName === 'genericPhone') { - deviceName = { - deviceType: 'phone', - platform: 'generic', - generic: true - }; - } + return result; + } - if(isPlainObject(deviceName)) { - return this._fromConfig(deviceName); - } else { - let ua; - if(deviceName) { - ua = KNOWN_UA_TABLE[deviceName]; - if(!ua) { - throw errors.Error('E0005'); - } - } else { - const navigator = getNavigator(); - ua = navigator.userAgent; - } - return this._fromUA(ua); - } - } + attachCssClasses(element, device?) { + this._deviceClasses = this._getCssClasses(device).join(' '); + $(element).addClass(this._deviceClasses); + } - _getDeviceOrNameFromWindowScope() { - let result; + detachCssClasses(element) { + $(element).removeClass(this._deviceClasses!); + } - if(hasWindow() && (this._window.top['dx-force-device-object'] || this._window.top['dx-force-device'])) { - result = this._window.top['dx-force-device-object'] || this._window.top['dx-force-device']; - } + isSimulator() { + // NOTE: error may happen due to same-origin policy + try { + return this._isSimulator || hasWindow() && this._window.top !== this._window.self && this._window.top?.['dx-force-device'] || this.isRippleEmulator(); + } catch (e) { + return false; + } + } + + forceSimulator() { + this._isSimulator = true; + } + + _getDevice(deviceName?) { + if (deviceName === 'genericPhone') { + deviceName = { + deviceType: 'phone', + platform: 'generic', + generic: true, + }; + } - return result; + if (isPlainObject(deviceName)) { + return this._fromConfig(deviceName); + } + let ua; + if (deviceName) { + ua = KNOWN_UA_TABLE[deviceName]; + if (!ua) { + throw errors.Error('E0005'); + } + } else { + const navigator = getNavigator(); + ua = navigator.userAgent; } + return this._fromUA(ua); + } - _getDeviceNameFromSessionStorage() { - const sessionStorage = SessionStorage(); + _getDeviceOrNameFromWindowScope() { + let result; - if(!sessionStorage) { - return; - } + if (hasWindow() && (this._window.top?.['dx-force-device-object'] || this._window.top?.['dx-force-device'])) { + result = this._window.top?.['dx-force-device-object'] || this._window.top?.['dx-force-device']; + } - const deviceOrName = sessionStorage.getItem('dx-force-device'); + return result; + } - try { - return JSON.parse(deviceOrName); - } catch(ex) { - return deviceOrName; - } - } + _getDeviceNameFromSessionStorage() { + const sessionStorage = SessionStorage(); - _fromConfig(config) { - const result = extend({}, DEFAULT_DEVICE, this._currentDevice, config); - const shortcuts = { - phone: result.deviceType === 'phone', - tablet: result.deviceType === 'tablet', - android: result.platform === 'android', - ios: result.platform === 'ios', - generic: result.platform === 'generic' - }; - - return extend(result, shortcuts); + if (!sessionStorage) { + return; } - _fromUA(ua) { - for(let idx = 0; idx < UA_PARSERS_ARRAY.length; idx += 1) { - const parser = UA_PARSERS_ARRAY[idx]; - const config = parser(ua); + const deviceOrName = sessionStorage.getItem('dx-force-device'); - if(config) { - return this._fromConfig(config); - } - } - - return DEFAULT_DEVICE; + try { + return JSON.parse(deviceOrName); + } catch (ex) { + return deviceOrName; + } + } + + _fromConfig(config) { + const result = extend({}, DEFAULT_DEVICE, this._currentDevice, config); + const shortcuts = { + phone: result.deviceType === 'phone', + tablet: result.deviceType === 'tablet', + android: result.platform === 'android', + ios: result.platform === 'ios', + generic: result.platform === 'generic', + }; + + return extend(result, shortcuts); + } + + _fromUA(ua) { + for (let idx = 0; idx < UA_PARSERS_ARRAY.length; idx += 1) { + const parser = UA_PARSERS_ARRAY[idx]; + const config = parser(ua); + + if (config) { + return this._fromConfig(config); + } } - _changeOrientation() { - const $window = $(this._window); - const orientation = getHeight($window) > getWidth($window) ? 'portrait' : 'landscape'; - - if(this._currentOrientation === orientation) { - return; - } + return DEFAULT_DEVICE; + } - this._currentOrientation = orientation; + _changeOrientation() { + // @ts-expect-error + const $window = $(this._window); + const orientation = getHeight($window) > getWidth($window) ? 'portrait' : 'landscape'; - this._eventsStrategy.fireEvent('orientationChanged', [{ - orientation: orientation - }]); + if (this._currentOrientation === orientation) { + return; } - _recalculateOrientation() { - const windowWidth = getWidth(this._window); + this._currentOrientation = orientation; - if(this._currentWidth === windowWidth) { - return; - } - this._currentWidth = windowWidth; + this._eventsStrategy.fireEvent('orientationChanged', [{ + orientation, + }]); + } - this._changeOrientation(); + _recalculateOrientation() { + const windowWidth = getWidth(this._window); + if (this._currentWidth === windowWidth) { + return; } + this._currentWidth = windowWidth; - on(eventName, eventHandler) { - this._eventsStrategy.on(eventName, eventHandler); - return this; - } + this._changeOrientation(); + } - off(eventName, eventHandler) { - this._eventsStrategy.off(eventName, eventHandler); - return this; - } + on(eventName, eventHandler) { + this._eventsStrategy.on(eventName, eventHandler); + return this; + } + + off(eventName, eventHandler) { + this._eventsStrategy.off(eventName, eventHandler); + return this; + } } const devices = new Devices(); const viewPortElement = viewPort(); -if(viewPortElement) { - devices.attachCssClasses(viewPortElement); +if (viewPortElement) { + devices.attachCssClasses(viewPortElement); } changeCallback.add((viewPort, prevViewport) => { - devices.detachCssClasses(prevViewport); - devices.attachCssClasses(viewPort); + devices.detachCssClasses(prevViewport); + devices.attachCssClasses(viewPort); }); -///#DEBUG +/// #DEBUG +// @ts-expect-error devices.Devices = Devices; -///#ENDDEBUG +/// #ENDDEBUG export default devices; diff --git a/packages/devextreme/js/__internal/core/m_dom_adapter.ts b/packages/devextreme/js/__internal/core/m_dom_adapter.ts index c5bfa3bd59ff..21e3b1d544e1 100644 --- a/packages/devextreme/js/__internal/core/m_dom_adapter.ts +++ b/packages/devextreme/js/__internal/core/m_dom_adapter.ts @@ -1,204 +1,244 @@ /* global document */ -import injector from './utils/dependency_injector'; -import { noop } from './utils/common'; -import { getShadowElementsFromPoint } from './utils/shadow_dom'; +import { noop } from '@js/core/utils/common'; +import injector from '@js/core/utils/dependency_injector'; +import { getShadowElementsFromPoint } from '@js/core/utils/shadow_dom'; const ELEMENT_NODE = 1; const TEXT_NODE = 3; const DOCUMENT_NODE = 9; const DOCUMENT_FRAGMENT_NODE = 11; -const nativeDOMAdapterStrategy = { - querySelectorAll(element, selector) { - return element.querySelectorAll(selector); - }, +export interface DomAdapter { + querySelectorAll: (element, selector) => any; + elementMatches: (element, selector) => any; + getActiveElement: (element?: HTMLElement | null) => HTMLElement; + getDocument: () => Document; + getDocumentElement: () => HTMLDocument & { + scrollLeft: number; + scrollTop: number; + clientWidth: number; + scrollHeight: number; + offsetHeight: number; + clientHeight: number; + }; + getHead: () => any; + listen: (element, event, callback, options?) => any; + getReadyState: () => DocumentReadyState; + isNode: (node: unknown) => boolean; + isDocument: (element: any) => boolean; + isDocumentFragment: (element: any) => boolean; + getBody: () => HTMLBodyElement; + getRootNode: (element: HTMLElement) => Document | DocumentFragment; + getAttribute: (element, name) => any; + setAttribute: (element, name, value) => void; + removeAttribute: (element, name) => void; + isElementNode: (element: any) => boolean; + createElement: (tagName: string, context?: Document) => HTMLElement; + createDocumentFragment: () => DocumentFragment; + createTextNode: (text: any, context?: any) => any; + setClass: (element: HTMLElement, className: string, isAdd: boolean) => void; + setText: (element, text) => void; + setProperty: (element, name, value) => void; + removeElement: (element: HTMLElement) => void; + inject: (obj: Record) => void; + setStyle: (element: HTMLElement, name: string, value: string) => void; + insertElement: (parentElement: HTMLElement, newElement: HTMLElement, nextSiblingElement?: HTMLElement) => void; +} + +const nativeDOMAdapterStrategy: DomAdapter = { + querySelectorAll(element, selector) { + return element.querySelectorAll(selector); + }, + + elementMatches(element, selector) { + const matches = element.matches || element.matchesSelector || element.mozMatchesSelector + || element.msMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector + // @ts-expect-error not all code paths return value + || ((selector) => { + const doc = element.document || element.ownerDocument; + + if (!doc) { + return false; + } + + const items = this.querySelectorAll(doc, selector); + + for (let i = 0; i < items.length; i++) { + if (items[i] === element) { + return true; + } + } + }); - elementMatches(element, selector) { - const matches = element.matches || element.matchesSelector || element.mozMatchesSelector || - element.msMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector || - (selector => { - const doc = element.document || element.ownerDocument; + return matches.call(element, selector); + }, + + createElement(tagName, context) { + context = context ?? this._document; + return context!.createElement(tagName); + }, + + createElementNS(ns, tagName, context) { + context = context || this._document; + return context.createElementNS(ns, tagName); + }, + + createTextNode(text, context) { + context = context || this._document; + return context.createTextNode(text); + }, + + createAttribute(text, context) { + context = context || this._document; + return context.createAttribute(text); + }, + + isNode(element) { + return !!element && typeof element === 'object' && 'nodeType' in element && 'nodeName' in element; + }, + + isElementNode(element) { + return !!element && element.nodeType === ELEMENT_NODE; + }, + + isTextNode(element) { + return element && element.nodeType === TEXT_NODE; + }, + + isDocument(element) { + return element && element.nodeType === DOCUMENT_NODE; + }, + + isDocumentFragment(element) { + return element && element.nodeType === DOCUMENT_FRAGMENT_NODE; + }, + + removeElement(element) { + const parentNode = element && element.parentNode; + if (parentNode) { + parentNode.removeChild(element); + } + }, + + insertElement(parentElement, newElement, nextSiblingElement) { + if (parentElement && newElement && parentElement !== newElement) { + if (nextSiblingElement) { + parentElement.insertBefore(newElement, nextSiblingElement); + } else { + parentElement.appendChild(newElement); + } + } + }, - if(!doc) { - return false; - } + getAttribute(element, name) { + return element.getAttribute(name); + }, - const items = this.querySelectorAll(doc, selector); + setAttribute(element, name, value) { + if (name === 'style') { + element.style.cssText = value; + } else { + element.setAttribute(name, value); + } + }, - for(let i = 0; i < items.length; i++) { - if(items[i] === element) { - return true; - } - } - }); + removeAttribute(element, name) { + element.removeAttribute(name); + }, + + setProperty(element, name, value) { + element[name] = value; + }, + + setText(element, text) { + if (element) { + element.textContent = text; + } + }, + + setClass(element, className, isAdd) { + if (element.nodeType === 1 && className) { + isAdd + ? element.classList.add(className) + : element.classList.remove(className); + } + }, + + setStyle(element, name, value) { + element.style[name] = value || ''; + }, + + _document: typeof document === 'undefined' ? undefined : document, + + getDocument() { + return this._document; + }, - return matches.call(element, selector); - }, - - createElement(tagName, context) { - context = context || this._document; - return context.createElement(tagName); - }, - - createElementNS(ns, tagName, context) { - context = context || this._document; - return context.createElementNS(ns, tagName); - }, - - createTextNode(text, context) { - context = context || this._document; - return context.createTextNode(text); - }, - - createAttribute(text, context) { - context = context || this._document; - return context.createAttribute(text); - }, - - isNode(element) { - return element && typeof element === 'object' && 'nodeType' in element && 'nodeName' in element; - }, - - isElementNode(element) { - return element && element.nodeType === ELEMENT_NODE; - }, - - isTextNode(element) { - return element && element.nodeType === TEXT_NODE; - }, - - isDocument(element) { - return element && element.nodeType === DOCUMENT_NODE; - }, - - isDocumentFragment(element) { - return element && element.nodeType === DOCUMENT_FRAGMENT_NODE; - }, - - removeElement(element) { - const parentNode = element && element.parentNode; - if(parentNode) { - parentNode.removeChild(element); - } - }, - - insertElement(parentElement, newElement, nextSiblingElement) { - if(parentElement && newElement && parentElement !== newElement) { - if(nextSiblingElement) { - parentElement.insertBefore(newElement, nextSiblingElement); - } else { - parentElement.appendChild(newElement); - } - } - }, - - getAttribute(element, name) { - return element.getAttribute(name); - }, - - setAttribute(element, name, value) { - if(name === 'style') { - element.style.cssText = value; - } else { - element.setAttribute(name, value); - } - }, - - removeAttribute(element, name) { - element.removeAttribute(name); - }, - - setProperty(element, name, value) { - element[name] = value; - }, - - setText(element, text) { - if(element) { - element.textContent = text; - } - }, - - setClass(element, className, isAdd) { - if(element.nodeType === 1 && className) { - isAdd - ? element.classList.add(className) - : element.classList.remove(className); - } - }, - - setStyle(element, name, value) { - element.style[name] = value || ''; - }, - - _document: typeof document === 'undefined' ? undefined : document, - - getDocument() { - return this._document; - }, - - getActiveElement(element) { - const activeElementHolder = this.getRootNode(element); - - return activeElementHolder.activeElement; - }, - - getRootNode(element) { - return element?.getRootNode?.() ?? this._document; - }, - - getBody() { - return this._document.body; - }, - - createDocumentFragment() { - return this._document.createDocumentFragment(); - }, - - getDocumentElement() { - return this._document.documentElement; - }, - - getLocation() { - return this._document.location; - }, - - getSelection() { - return this._document.selection; - }, - - getReadyState() { - return this._document.readyState; - }, - - getHead() { - return this._document.head; - }, - - hasDocumentProperty(property) { - return property in this._document; - }, - - listen(element, event, callback, options) { - if(!element || !('addEventListener' in element)) { - return noop; - } - - element.addEventListener(event, callback, options); - - return () => { - element.removeEventListener(event, callback); - }; - }, - - elementsFromPoint(x, y, element) { - const activeElementHolder = this.getRootNode(element); - - if(activeElementHolder.host) { - return getShadowElementsFromPoint(x, y, activeElementHolder); - } - - return activeElementHolder.elementsFromPoint(x, y); + getActiveElement(element) { + const activeElementHolder = this.getRootNode(element); + + return activeElementHolder.activeElement; + }, + // @ts-expect-error return type is not assignable + getRootNode(element) { + return element?.getRootNode?.() ?? this._document; + }, + + getBody() { + return this._document.body; + }, + + createDocumentFragment() { + return this._document.createDocumentFragment(); + }, + + getDocumentElement() { + return this._document.documentElement; + }, + + getLocation() { + return this._document.location; + }, + + getSelection() { + return this._document.selection; + }, + + getReadyState(): DocumentReadyState { + return this._document.readyState; + }, + + getHead() { + return this._document.head; + }, + + hasDocumentProperty(property) { + return property in this._document; + }, + + listen(element, event, callback, options) { + if (!element || !('addEventListener' in element)) { + return noop; + } + + element.addEventListener(event, callback, options); + + return () => { + element.removeEventListener(event, callback); + }; + }, + + elementsFromPoint(x, y, element) { + const activeElementHolder = this.getRootNode(element); + + if (activeElementHolder.host) { + return getShadowElementsFromPoint(x, y, activeElementHolder); } + + return activeElementHolder.elementsFromPoint(x, y); + }, }; -export default injector(nativeDOMAdapterStrategy); +const domAdapter: DomAdapter = injector(nativeDOMAdapterStrategy); +export { domAdapter }; +export default domAdapter; diff --git a/packages/devextreme/js/__internal/core/m_element.ts b/packages/devextreme/js/__internal/core/m_element.ts index 883baef9e3f9..77d449aa9cf1 100644 --- a/packages/devextreme/js/__internal/core/m_element.ts +++ b/packages/devextreme/js/__internal/core/m_element.ts @@ -1,16 +1,16 @@ export function getPublicElementNonJquery(element) { - if(element && element.get) { - return element.get(0); - } - return element; + if (element && element.get) { + return element.get(0); + } + return element; } let strategy = getPublicElementNonJquery; export function getPublicElement(element) { - return strategy(element); + return strategy(element); } export function setPublicElementWrapper(newStrategy) { - strategy = newStrategy; + strategy = newStrategy; } diff --git a/packages/devextreme/js/__internal/core/m_element_data.ts b/packages/devextreme/js/__internal/core/m_element_data.ts index 53f23203643c..8af4d1935a13 100644 --- a/packages/devextreme/js/__internal/core/m_element_data.ts +++ b/packages/devextreme/js/__internal/core/m_element_data.ts @@ -1,113 +1,115 @@ -import domAdapter from './dom_adapter'; -import eventsEngine from '../events/core/events_engine'; -import MemorizedCallbacks from './memorized_callbacks'; +/* eslint-disable object-shorthand */ +import domAdapter from '@js/core/dom_adapter'; +import MemorizedCallbacks from '@js/core/memorized_callbacks'; +import eventsEngine from '@js/events/core/events_engine'; const dataMap = new WeakMap(); let strategy; export const strategyChanging = new MemorizedCallbacks(); -let beforeCleanDataFunc = function() {}; -let afterCleanDataFunc = function() {}; +let beforeCleanDataFunc: any = function () {}; +let afterCleanDataFunc: any = function () {}; -export const setDataStrategy = function(value) { - strategyChanging.fire(value); +export const setDataStrategy = function (value) { + strategyChanging.fire(value); - strategy = value; + strategy = value; - const cleanData = strategy.cleanData; + const { cleanData } = strategy; - strategy.cleanData = function(nodes) { - beforeCleanDataFunc(nodes); + strategy.cleanData = function (nodes) { + beforeCleanDataFunc(nodes); - const result = cleanData.call(this, nodes); + const result = cleanData.call(this, nodes); - afterCleanDataFunc(nodes); + afterCleanDataFunc(nodes); - return result; - }; + return result; + }; }; setDataStrategy({ - data: function() { - const element = arguments[0]; - const key = arguments[1]; - const value = arguments[2]; - - if(!element) return; - - let elementData = dataMap.get(element); - - if(!elementData) { - elementData = {}; - dataMap.set(element, elementData); - } - - if(key === undefined) { - return elementData; - } - - if(arguments.length === 2) { - return elementData[key]; - } - - elementData[key] = value; - return value; - }, - - removeData: function(element, key) { - if(!element) return; - if(key === undefined) { - dataMap.delete(element); - } else { - const elementData = dataMap.get(element); - if(elementData) { - delete elementData[key]; - } - } - }, - - cleanData: function(elements) { - for(let i = 0; i < elements.length; i++) { - eventsEngine.off(elements[i]); - dataMap.delete(elements[i]); - } + data: function (...args) { + const element = args[0]; + const key = args[1]; + const value = args[2]; + + if (!element) return; + + let elementData = dataMap.get(element); + + if (!elementData) { + elementData = {}; + dataMap.set(element, elementData); + } + + if (key === undefined) { + return elementData; + } + + if (args.length === 2) { + return elementData[key]; } + + elementData[key] = value; + return value; + }, + + removeData: function (element, key) { + if (!element) return; + if (key === undefined) { + dataMap.delete(element); + } else { + const elementData = dataMap.get(element); + if (elementData) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete elementData[key]; + } + } + }, + + cleanData: function (elements) { + for (let i = 0; i < elements.length; i++) { + eventsEngine.off(elements[i]); + dataMap.delete(elements[i]); + } + }, }); export function getDataStrategy() { - return strategy; + return strategy; } -export function data() { - return strategy.data.apply(this, arguments); +export function data(...args) { + return strategy.data.apply(this, args); } export function beforeCleanData(callback) { - beforeCleanDataFunc = callback; + beforeCleanDataFunc = callback; } export function afterCleanData(callback) { - afterCleanDataFunc = callback; + afterCleanDataFunc = callback; } export function cleanData(nodes) { - return strategy.cleanData.call(this, nodes); + return strategy.cleanData.call(this, nodes); } export function removeData(element, key) { - return strategy.removeData.call(this, element, key); + return strategy.removeData.call(this, element, key); } -export function cleanDataRecursive(element, cleanSelf) { - if(!domAdapter.isElementNode(element)) { - return; - } +export function cleanDataRecursive(element, cleanSelf?: boolean) { + if (!domAdapter.isElementNode(element)) { + return; + } - const childElements = element.getElementsByTagName('*'); + const childElements = element.getElementsByTagName('*'); - strategy.cleanData(childElements); + strategy.cleanData(childElements); - if(cleanSelf) { - strategy.cleanData([element]); - } + if (cleanSelf) { + strategy.cleanData([element]); + } } diff --git a/packages/devextreme/js/__internal/core/m_errors.ts b/packages/devextreme/js/__internal/core/m_errors.ts index 28b58e4fe1fb..be0e27983955 100644 --- a/packages/devextreme/js/__internal/core/m_errors.ts +++ b/packages/devextreme/js/__internal/core/m_errors.ts @@ -1,290 +1,129 @@ -import errorUtils from './utils/error'; +import errorUtils from '@js/core/utils/error'; -/** -* @docid -* @name ErrorsCore -*/ export default errorUtils({ - /** - * @name ErrorsCore.E0001 - */ - E0001: 'Method is not implemented', - - /** - * @name ErrorsCore.E0002 - */ - E0002: 'Member name collision: {0}', - - /** - * @name ErrorsCore.E0003 - */ - E0003: 'A class must be instantiated using the \'new\' keyword', - - /** - * @name ErrorsCore.E0004 - */ - E0004: 'The NAME property of the component is not specified', - - /** - * @name ErrorsCore.E0005 - */ - E0005: 'Unknown device', - - /** - * @name ErrorsCore.E0006 - */ - E0006: 'Unknown endpoint key is requested', - - /** - * @name ErrorsCore.E0007 - */ - E0007: '\'Invalidate\' method is called outside the update transaction', - - /** - * @name ErrorsCore.E0008 - */ - E0008: 'Type of the option name is not appropriate to create an action', - - /** - * @name ErrorsCore.E0009 - */ - E0009: 'Component \'{0}\' has not been initialized for an element', - - /** - * @name ErrorsCore.E0010 - */ - E0010: 'Animation configuration with the \'{0}\' type requires \'{1}\' configuration as {2}', - - /** - * @name ErrorsCore.E0011 - */ - E0011: 'Unknown animation type \'{0}\'', - - /** - * @name ErrorsCore.E0012 - */ - E0012: 'jQuery version is too old. Please upgrade jQuery to 1.10.0 or later', - - /** - * @name ErrorsCore.E0013 - */ - E0013: 'KnockoutJS version is too old. Please upgrade KnockoutJS to 2.3.0 or later', - - /** - * @name ErrorsCore.E0014 - */ - E0014: 'The \'release\' method shouldn\'t be called for an unlocked Lock object', - - /** - * @name ErrorsCore.E0015 - */ - E0015: 'Queued task returned an unexpected result', - - /** - * @name ErrorsCore.E0017 - */ - E0017: 'Event namespace is not defined', - - /** - * @name ErrorsCore.E0018 - */ - E0018: 'DevExpress.ui.DevExpressPopup widget is required', - - /** - * @name ErrorsCore.E0020 - */ - E0020: 'Template engine \'{0}\' is not supported', - - /** - * @name ErrorsCore.E0021 - */ - E0021: 'Unknown theme is set: {0}', - - /** - * @name ErrorsCore.E0022 - */ - E0022: 'LINK[rel=DevExpress-theme] tags must go before DevExpress included scripts', - - /** - * @name ErrorsCore.E0023 - */ - E0023: 'Template name is not specified', - - /** - * @name ErrorsCore.E0024 - */ - E0024: 'DevExtreme bundle already included', - - /** - * @name ErrorsCore.E0025 - */ - E0025: 'Unexpected argument type', - - /** - * @name ErrorsCore.E0100 - */ - E0100: 'Unknown validation type is detected', - - /** - * @name ErrorsCore.E0101 - */ - E0101: 'Misconfigured range validation rule is detected', - - - /** - * @name ErrorsCore.E0102 - */ - E0102: 'Misconfigured comparison validation rule is detected', - - /** - * @name ErrorsCore.E0103 - */ - E0103: 'validationCallback of an asynchronous rule should return a jQuery or a native promise', - - /** - * @name ErrorsCore.E0110 - */ - E0110: 'Unknown validation group is detected', - - /** - * @name ErrorsCore.E0120 - */ - E0120: 'Adapter for a DevExpressValidator component cannot be configured', - - /** - * @name ErrorsCore.E0121 - */ - E0121: 'The \'customItem\' parameter of the \'onCustomItemCreating\' function is empty or contains invalid data. Assign a custom object or a Promise that is resolved after the item is created.', - - - /** - * @name ErrorsCore.W0000 - */ - W0000: '\'{0}\' is deprecated in {1}. {2}', - - /** - * @name ErrorsCore.W0001 - */ - W0001: '{0} - \'{1}\' option is deprecated in {2}. {3}', - - /** - * @name ErrorsCore.W0002 - */ - W0002: '{0} - \'{1}\' method is deprecated in {2}. {3}', - - /** - * @name ErrorsCore.W0003 - */ - W0003: '{0} - \'{1}\' property is deprecated in {2}. {3}', - - /** - * @name ErrorsCore.W0004 - */ - W0004: 'Timeout for theme loading is over: {0}', - - /** - * @name ErrorsCore.W0005 - */ - W0005: '\'{0}\' event is deprecated in {1}. {2}', - - /** - * @name ErrorsCore.W0006 - */ - W0006: 'Invalid recurrence rule: \'{0}\'', - - /** - * @name ErrorsCore.W0007 - */ - W0007: '\'{0}\' Globalize culture is not defined', - - /** - * @name ErrorsCore.W0008 - */ - W0008: 'Invalid view name: \'{0}\'', - - /** - * @name ErrorsCore.W0009 - */ - W0009: 'Invalid time zone name: \'{0}\'', - - /** - * @name ErrorsCore.W0010 - */ - W0010: '{0} is deprecated in {1}. {2}', - - /** - * @name ErrorsCore.W0011 - */ - W0011: 'Number parsing is invoked while the parser is not defined', - - /** - * @name ErrorsCore.W0012 - */ - W0012: 'Date parsing is invoked while the parser is not defined', - - /** - * @name ErrorsCore.W0013 - */ - W0013: '\'{0}\' file is deprecated in {1}. {2}', - - /** - * @name ErrorsCore.W0014 - */ - W0014: '{0} - \'{1}\' type is deprecated in {2}. {3}', - - /** - * @name ErrorsCore.W0015 - */ - W0015: 'Instead of returning a value from the \'{0}\' function, write it into the \'{1}\' field of the function\'s parameter.', - - /** - * @name ErrorsCore.W0016 - */ - W0016: 'The "{0}" option does not accept the "{1}" value since v{2}. {3}.', - /** - * @name ErrorsCore.W0017 - */ - W0017: 'Setting the "{0}" property with a function is deprecated since v21.2', - /** - * @name ErrorsCore.W0018 - */ - W0018: 'Setting the "position" property with a function is deprecated since v21.2', - /** - * @name ErrorsCore.W0019 - */ - W0019: 'DevExtreme: Unable to Locate a Valid License Key.\n\n' + - 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + - 'If you are using a 30-day trial version of DevExtreme, you must uninstall all copies of DevExtreme once your 30-day trial period expires. For terms and conditions that govern use of DevExtreme UI components/libraries, please refer to the DevExtreme End User License Agreement: https://js.devexpress.com/EULAs/DevExtremeComplete.\n\n' + - 'To use DevExtreme in a commercial project, you must purchase a license. For pricing/licensing options, please visit: https://js.devexpress.com/Buy.\n\n' + - 'If you have licensing-related questions or need help with a purchase, please email clientservices@devexpress.com.\n\n', - /** - * @name ErrorsCore.W0020 - */ - W0020: 'DevExtreme: License Key Has Expired.\n\n' + - 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + - 'A mismatch exists between the license key used and the DevExtreme version referenced in this project.\n\n' + - 'To proceed, you can:\n' + - '• use a version of DevExtreme linked to your license key: https://www.devexpress.com/ClientCenter/DownloadManager\n' + - '• renew your DevExpress Subscription: https://www.devexpress.com/buy/renew (once you renew your subscription, you will be entitled to product updates and support service as defined in the DevExtreme End User License Agreement)\n\n' + - 'If you have licensing-related questions or need help with a renewal, please email clientservices@devexpress.com.\n\n', - /** - * @name ErrorsCore.W0021 - */ - W0021: 'DevExtreme: License Key Verification Has Failed.\n\n' + - 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + - 'To verify your DevExtreme license, make certain to specify a correct key in the GlobalConfig. If you continue to encounter this error, please visit https://www.devexpress.com/ClientCenter/DownloadManager to obtain a valid license key.\n\n' + - 'If you have a valid license and this problem persists, please submit a support ticket via the DevExpress Support Center. We will be happy to follow-up: https://supportcenter.devexpress.com/ticket/create.\n\n', - /** - * @name ErrorsCore.W0022 - */ - W0022: 'DevExtreme: Pre-release software. Not suitable for commercial use.\n\n' + - 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + - 'Pre-release software may contain deficiencies and as such, should not be considered for use or integrated in any mission critical application.\n\n', - /** - * @name ErrorsCore.W0023 - */ - W0023: 'DevExtreme: the following \'devextreme\' package version does not match versions of other DevExpress products used in this application:\n\n' + - '{0}\n\n' + - 'Interoperability between different versions of the products listed herein cannot be guaranteed.\n\n', + E0001: 'Method is not implemented', + + E0002: 'Member name collision: {0}', + + E0003: 'A class must be instantiated using the \'new\' keyword', + + E0004: 'The NAME property of the component is not specified', + + E0005: 'Unknown device', + + E0006: 'Unknown endpoint key is requested', + + E0007: '\'Invalidate\' method is called outside the update transaction', + + E0008: 'Type of the option name is not appropriate to create an action', + + E0009: 'Component \'{0}\' has not been initialized for an element', + + E0010: 'Animation configuration with the \'{0}\' type requires \'{1}\' configuration as {2}', + + E0011: 'Unknown animation type \'{0}\'', + + E0012: 'jQuery version is too old. Please upgrade jQuery to 1.10.0 or later', + + E0013: 'KnockoutJS version is too old. Please upgrade KnockoutJS to 2.3.0 or later', + + E0014: 'The \'release\' method shouldn\'t be called for an unlocked Lock object', + + E0015: 'Queued task returned an unexpected result', + + E0017: 'Event namespace is not defined', + + E0018: 'DevExpress.ui.DevExpressPopup widget is required', + + E0020: 'Template engine \'{0}\' is not supported', + + E0021: 'Unknown theme is set: {0}', + + E0022: 'LINK[rel=DevExpress-theme] tags must go before DevExpress included scripts', + + E0023: 'Template name is not specified', + + E0024: 'DevExtreme bundle already included', + + E0025: 'Unexpected argument type', + + E0100: 'Unknown validation type is detected', + + E0101: 'Misconfigured range validation rule is detected', + + E0102: 'Misconfigured comparison validation rule is detected', + + E0103: 'validationCallback of an asynchronous rule should return a jQuery or a native promise', + + E0110: 'Unknown validation group is detected', + + E0120: 'Adapter for a DevExpressValidator component cannot be configured', + + E0121: 'The \'customItem\' parameter of the \'onCustomItemCreating\' function is empty or contains invalid data. Assign a custom object or a Promise that is resolved after the item is created.', + + W0000: '\'{0}\' is deprecated in {1}. {2}', + + W0001: '{0} - \'{1}\' option is deprecated in {2}. {3}', + + W0002: '{0} - \'{1}\' method is deprecated in {2}. {3}', + + W0003: '{0} - \'{1}\' property is deprecated in {2}. {3}', + + W0004: 'Timeout for theme loading is over: {0}', + + W0005: '\'{0}\' event is deprecated in {1}. {2}', + + W0006: 'Invalid recurrence rule: \'{0}\'', + + W0007: '\'{0}\' Globalize culture is not defined', + + W0008: 'Invalid view name: \'{0}\'', + + W0009: 'Invalid time zone name: \'{0}\'', + + W0010: '{0} is deprecated in {1}. {2}', + + W0011: 'Number parsing is invoked while the parser is not defined', + + W0012: 'Date parsing is invoked while the parser is not defined', + + W0013: '\'{0}\' file is deprecated in {1}. {2}', + + W0014: '{0} - \'{1}\' type is deprecated in {2}. {3}', + + W0015: 'Instead of returning a value from the \'{0}\' function, write it into the \'{1}\' field of the function\'s parameter.', + + W0016: 'The "{0}" option does not accept the "{1}" value since v{2}. {3}.', + + W0017: 'Setting the "{0}" property with a function is deprecated since v21.2', + + W0018: 'Setting the "position" property with a function is deprecated since v21.2', + + W0019: 'DevExtreme: Unable to Locate a Valid License Key.\n\n' + + 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + + 'If you are using a 30-day trial version of DevExtreme, you must uninstall all copies of DevExtreme once your 30-day trial period expires. For terms and conditions that govern use of DevExtreme UI components/libraries, please refer to the DevExtreme End User License Agreement: https://js.devexpress.com/EULAs/DevExtremeComplete.\n\n' + + 'To use DevExtreme in a commercial project, you must purchase a license. For pricing/licensing options, please visit: https://js.devexpress.com/Buy.\n\n' + + 'If you have licensing-related questions or need help with a purchase, please email clientservices@devexpress.com.\n\n', + + W0020: 'DevExtreme: License Key Has Expired.\n\n' + + 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + + 'A mismatch exists between the license key used and the DevExtreme version referenced in this project.\n\n' + + 'To proceed, you can:\n' + + '• use a version of DevExtreme linked to your license key: https://www.devexpress.com/ClientCenter/DownloadManager\n' + + '• renew your DevExpress Subscription: https://www.devexpress.com/buy/renew (once you renew your subscription, you will be entitled to product updates and support service as defined in the DevExtreme End User License Agreement)\n\n' + + 'If you have licensing-related questions or need help with a renewal, please email clientservices@devexpress.com.\n\n', + + W0021: 'DevExtreme: License Key Verification Has Failed.\n\n' + + 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + + 'To verify your DevExtreme license, make certain to specify a correct key in the GlobalConfig. If you continue to encounter this error, please visit https://www.devexpress.com/ClientCenter/DownloadManager to obtain a valid license key.\n\n' + + 'If you have a valid license and this problem persists, please submit a support ticket via the DevExpress Support Center. We will be happy to follow-up: https://supportcenter.devexpress.com/ticket/create.\n\n', + + W0022: 'DevExtreme: Pre-release software. Not suitable for commercial use.\n\n' + + 'Detailed license/registration related information and instructions: https://js.devexpress.com/Documentation/Licensing/.\n\n' + + 'Pre-release software may contain deficiencies and as such, should not be considered for use or integrated in any mission critical application.\n\n', + + W0023: 'DevExtreme: the following \'devextreme\' package version does not match versions of other DevExpress products used in this application:\n\n' + + '{0}\n\n' + + 'Interoperability between different versions of the products listed herein cannot be guaranteed.\n\n', }); diff --git a/packages/devextreme/js/__internal/core/m_events_strategy.ts b/packages/devextreme/js/__internal/core/m_events_strategy.ts index 8f8556739827..b5468f71ad6f 100644 --- a/packages/devextreme/js/__internal/core/m_events_strategy.ts +++ b/packages/devextreme/js/__internal/core/m_events_strategy.ts @@ -1,68 +1,74 @@ -import Callbacks from './utils/callbacks'; -import { each } from './utils/iterator'; -import { isFunction, isPlainObject } from './utils/type'; +import Callbacks from '@js/core/utils/callbacks'; +import { each } from '@js/core/utils/iterator'; +import { isFunction, isPlainObject } from '@js/core/utils/type'; export class EventsStrategy { - constructor(owner, options = {}) { - this._events = {}; - this._owner = owner; - this._options = options; - } - static create(owner, strategy) { - if(strategy) { - return isFunction(strategy) ? strategy(owner) : strategy; - } else { - return new EventsStrategy(owner); - } - } + _events: any; + + _owner: any; + + _options: any; + + constructor(owner, options = {}) { + this._events = {}; + this._owner = owner; + this._options = options; + } - hasEvent(eventName) { - const callbacks = this._events[eventName]; - return callbacks ? callbacks.has() : false; + static create(owner, strategy) { + if (strategy) { + return isFunction(strategy) ? strategy(owner) : strategy; } + return new EventsStrategy(owner); + } - fireEvent(eventName, eventArgs) { - const callbacks = this._events[eventName]; - if(callbacks) { - callbacks.fireWith(this._owner, eventArgs); - } - return this._owner; + hasEvent(eventName) { + const callbacks = this._events[eventName]; + return callbacks ? callbacks.has() : false; + } + + fireEvent(eventName, eventArgs) { + const callbacks = this._events[eventName]; + if (callbacks) { + callbacks.fireWith(this._owner, eventArgs); } + return this._owner; + } - on(eventName, eventHandler) { - if(isPlainObject(eventName)) { - each(eventName, (e, h) => { - this.on(e, h); - }); - } else { - let callbacks = this._events[eventName]; + on(eventName, eventHandler) { + if (isPlainObject(eventName)) { + each(eventName, (e, h) => { + this.on(e, h); + }); + } else { + let callbacks = this._events[eventName]; - if(!callbacks) { - callbacks = Callbacks({ - syncStrategy: this._options.syncStrategy - }); - this._events[eventName] = callbacks; - } + if (!callbacks) { + callbacks = Callbacks({ + syncStrategy: this._options.syncStrategy, + }); + this._events[eventName] = callbacks; + } - const addFn = callbacks.originalAdd || callbacks.add; - addFn.call(callbacks, eventHandler); - } + const addFn = callbacks.originalAdd || callbacks.add; + addFn.call(callbacks, eventHandler); } + } - off(eventName, eventHandler) { - const callbacks = this._events[eventName]; - if(callbacks) { - if(isFunction(eventHandler)) { - callbacks.remove(eventHandler); - } else { - callbacks.empty(); - } - } + off(eventName, eventHandler) { + const callbacks = this._events[eventName]; + if (callbacks) { + if (isFunction(eventHandler)) { + callbacks.remove(eventHandler); + } else { + callbacks.empty(); + } } + } - dispose() { - each(this._events, (eventName, event) => { - event.empty(); - }); - } + dispose() { + each(this._events, (eventName, event) => { + event.empty(); + }); + } } diff --git a/packages/devextreme/js/__internal/core/m_guid.ts b/packages/devextreme/js/__internal/core/m_guid.ts index 231b30918b6b..13e922b3d1a0 100644 --- a/packages/devextreme/js/__internal/core/m_guid.ts +++ b/packages/devextreme/js/__internal/core/m_guid.ts @@ -1,57 +1,47 @@ -import Class from './class'; +import Class from '@js/core/class'; const Guid = Class.inherit({ + ctor: function (value) { + if (value) { + value = String(value); + } + this._value = this._normalize(value || this._generate()); + }, - /** - * @name Guid.ctor - * @publicName ctor() - */ - /** - * @name Guid.ctor - * @publicName ctor(value) - * @param1 value:string - */ - ctor: function(value) { - if(value) { - value = String(value); - } - this._value = this._normalize(value || this._generate()); - }, - - _normalize: function(value) { - value = value.replace(/[^a-f0-9]/ig, '').toLowerCase(); - while(value.length < 32) { - value += '0'; - } - return [ - value.substr(0, 8), - value.substr(8, 4), - value.substr(12, 4), - value.substr(16, 4), - value.substr(20, 12) - ].join('-'); - }, - - _generate: function() { - let value = ''; - for(let i = 0; i < 32; i++) { - value += Math.round(Math.random() * 15).toString(16); - } - return value; - }, - - toString: function() { - return this._value; - }, - - valueOf: function() { - return this._value; - }, - - toJSON: function() { - return this._value; + _normalize: function (value) { + value = value.replace(/[^a-f0-9]/ig, '').toLowerCase(); + while (value.length < 32) { + value += '0'; + } + return [ + value.substr(0, 8), + value.substr(8, 4), + value.substr(12, 4), + value.substr(16, 4), + value.substr(20, 12), + ].join('-'); + }, + + _generate: function () { + let value = ''; + for (let i = 0; i < 32; i++) { + value += Math.round(Math.random() * 15).toString(16); } + return value; + }, + + toString: function () { + return this._value; + }, + + valueOf: function () { + return this._value; + }, + + toJSON: function () { + return this._value; + }, }); -export default Guid; +export { Guid }; diff --git a/packages/devextreme/js/__internal/core/m_http_request.ts b/packages/devextreme/js/__internal/core/m_http_request.ts index 63bc35b8e6c4..3f97f535c574 100644 --- a/packages/devextreme/js/__internal/core/m_http_request.ts +++ b/packages/devextreme/js/__internal/core/m_http_request.ts @@ -1,11 +1,15 @@ -import { getWindow } from './utils/window'; +import injector from '@js/core/utils/dependency_injector'; +import { getWindow } from '@js/core/utils/window'; + const window = getWindow(); -import injector from './utils/dependency_injector'; const nativeXMLHttpRequest = { - getXhr: function() { - return new window.XMLHttpRequest(); - } + getXhr() { + // @ts-expect-error no XMLHttpRequest on Window + return new window.XMLHttpRequest(); + }, }; -export default injector(nativeXMLHttpRequest); +const httpRequest = injector(nativeXMLHttpRequest); + +export { httpRequest }; diff --git a/packages/devextreme/js/__internal/core/m_inferno_renderer.ts b/packages/devextreme/js/__internal/core/m_inferno_renderer.ts index 8ed00e8f44c3..81e3b68e8ac3 100644 --- a/packages/devextreme/js/__internal/core/m_inferno_renderer.ts +++ b/packages/devextreme/js/__internal/core/m_inferno_renderer.ts @@ -1,63 +1,64 @@ +import { hydrate, InfernoEffectHost } from '@devextreme/runtime/inferno'; +import domAdapter from '@js/core/dom_adapter'; +import { cleanDataRecursive } from '@js/core/element_data'; +import injector from '@js/core/utils/dependency_injector'; import { render } from 'inferno'; -import { InfernoEffectHost, hydrate } from '@devextreme/runtime/inferno'; +// eslint-disable-next-line import/no-extraneous-dependencies import { createElement } from 'inferno-create-element'; -import domAdapter from './dom_adapter'; -import { cleanDataRecursive } from './element_data'; -import injector from './utils/dependency_injector'; const remove = (element) => { - const { parentNode } = element; - - if(parentNode) { - const nextSibling = element.nextSibling; - cleanDataRecursive(element); - parentNode.$V = element.$V; - render(null, parentNode); - parentNode.insertBefore(element, nextSibling); - element.innerHTML = ''; - delete parentNode.$V; - } + const { parentNode } = element; + + if (parentNode) { + const { nextSibling } = element; + cleanDataRecursive(element); + parentNode.$V = element.$V; + render(null, parentNode); + parentNode.insertBefore(element, nextSibling); + element.innerHTML = ''; + delete parentNode.$V; + } - delete element.$V; + delete element.$V; }; -export default injector({ - createElement: (component, props) => createElement(component, props), - - remove, - - onAfterRender: () => { - InfernoEffectHost.callEffects(); - }, - - onPreRender: () => { - InfernoEffectHost.lock(); - }, - - render: (component, props, container, replace) => { - if(!replace) { - const { parentNode } = container; - const nextNode = container?.nextSibling; - const rootNode = domAdapter.createElement('div'); - rootNode.appendChild(container); - const mountNode = domAdapter.createDocumentFragment().appendChild(rootNode); - const vNodeAlreadyExists = !!container.$V; - - vNodeAlreadyExists && remove(container); - - hydrate( - createElement(component, props), - mountNode, - ); - container.$V = mountNode.$V; - if(parentNode) { - parentNode.insertBefore(container, nextNode); - } - } else { - render( - createElement(component, props), container, - ); - } - }, +const infernoRenderer = injector({ + createElement: (component, props) => createElement(component, props), + + remove, + + onAfterRender: () => { + InfernoEffectHost.callEffects(); + }, + + onPreRender: () => { + InfernoEffectHost.lock(); + }, + + render: (component, props, container, replace) => { + if (!replace) { + const { parentNode } = container; + const nextNode = container?.nextSibling; + const rootNode = domAdapter.createElement('div'); + rootNode.appendChild(container); + const mountNode = domAdapter.createDocumentFragment().appendChild(rootNode); + const vNodeAlreadyExists = !!container.$V; + + vNodeAlreadyExists && remove(container); + + hydrate( + createElement(component, props), + mountNode, + ); + // @ts-expect-error need to change type to inferno element + container.$V = mountNode.$V; + if (parentNode) { + parentNode.insertBefore(container, nextNode); + } + } else { + render(createElement(component, props), container); + } + }, }); +export { infernoRenderer }; diff --git a/packages/devextreme/js/__internal/core/m_memorized_callbacks.ts b/packages/devextreme/js/__internal/core/m_memorized_callbacks.ts index d40a930b66fe..4e1b2ea4700a 100644 --- a/packages/devextreme/js/__internal/core/m_memorized_callbacks.ts +++ b/packages/devextreme/js/__internal/core/m_memorized_callbacks.ts @@ -1,23 +1,31 @@ -import { each } from '../core/utils/iterator'; -import Callbacks from './utils/callbacks'; - -export default class MemorizedCallbacks { - constructor() { - this.memory = []; - this.callbacks = Callbacks(); - } - - add(fn) { - each(this.memory, (_, item) => fn.apply(fn, item)); - this.callbacks.add(fn); - } - - remove(fn) { - this.callbacks.remove(fn); - } - - fire(...args) { - this.memory.push(args); - this.callbacks.fire.apply(this.callbacks, args); - } +import Callbacks from '@js/core/utils/callbacks'; +import { each } from '@js/core/utils/iterator'; + +import type { CallbackInterface } from './utils/m_callbacks'; + +class MemorizedCallbacks { + memory: any[]; + + callbacks: CallbackInterface; + + constructor() { + this.memory = []; + this.callbacks = Callbacks(); + } + + add(fn) { + each(this.memory, (_, item) => fn.apply(fn, item)); + this.callbacks.add(fn); + } + + remove(fn) { + this.callbacks.remove(fn); + } + + fire(...args) { + this.memory.push(args); + this.callbacks.fire.apply(this.callbacks, args); + } } + +export { MemorizedCallbacks }; diff --git a/packages/devextreme/js/__internal/core/m_postponed_operations.ts b/packages/devextreme/js/__internal/core/m_postponed_operations.ts index 91bbfa6d7da8..e7d76d3ed423 100644 --- a/packages/devextreme/js/__internal/core/m_postponed_operations.ts +++ b/packages/devextreme/js/__internal/core/m_postponed_operations.ts @@ -1,38 +1,41 @@ -import { Deferred, when } from './utils/deferred'; -import { isDefined } from './utils/type'; +import { Deferred, when } from '@js/core/utils/deferred'; +import { isDefined } from '@js/core/utils/type'; export class PostponedOperations { - constructor() { - this._postponedOperations = {}; - } + _postponedOperations: any; - add(key, fn, postponedPromise) { - if(key in this._postponedOperations) { - postponedPromise && this._postponedOperations[key].promises.push(postponedPromise); - } else { - const completePromise = new Deferred(); - this._postponedOperations[key] = { - fn: fn, - completePromise: completePromise, - promises: postponedPromise ? [postponedPromise] : [] - }; - } + constructor() { + this._postponedOperations = {}; + } - return this._postponedOperations[key].completePromise.promise(); + add(key, fn, postponedPromise) { + if (key in this._postponedOperations) { + postponedPromise && this._postponedOperations[key].promises.push(postponedPromise); + } else { + // @ts-expect-error only void function can be called with new + const completePromise = new Deferred(); + this._postponedOperations[key] = { + fn, + completePromise, + promises: postponedPromise ? [postponedPromise] : [], + }; } - callPostponedOperations() { - for(const key in this._postponedOperations) { - const operation = this._postponedOperations[key]; + return this._postponedOperations[key].completePromise.promise(); + } - if(isDefined(operation)) { - if(operation.promises && operation.promises.length) { - when(...operation.promises).done(operation.fn).then(operation.completePromise.resolve); - } else { - operation.fn().done(operation.completePromise.resolve); - } - } + callPostponedOperations() { + for (const key in this._postponedOperations) { + const operation = this._postponedOperations[key]; + + if (isDefined(operation)) { + if (operation.promises && operation.promises.length) { + when(...operation.promises).done(operation.fn).then(operation.completePromise.resolve); + } else { + operation.fn().done(operation.completePromise.resolve); } - this._postponedOperations = {}; + } } + this._postponedOperations = {}; + } } diff --git a/packages/devextreme/js/__internal/core/m_renderer.ts b/packages/devextreme/js/__internal/core/m_renderer.ts index a226a7e9fb55..408bc95dcd2b 100644 --- a/packages/devextreme/js/__internal/core/m_renderer.ts +++ b/packages/devextreme/js/__internal/core/m_renderer.ts @@ -1,2 +1,5 @@ -import rendererBase from './renderer_base'; -export default rendererBase.get(); +import rendererBase from '@js/core/renderer_base'; + +const renderer = rendererBase.get(); +export { renderer }; +export default renderer; diff --git a/packages/devextreme/js/__internal/core/m_renderer_base.ts b/packages/devextreme/js/__internal/core/m_renderer_base.ts index 5dc579970585..84326229ba67 100644 --- a/packages/devextreme/js/__internal/core/m_renderer_base.ts +++ b/packages/devextreme/js/__internal/core/m_renderer_base.ts @@ -1,810 +1,824 @@ -import { cleanDataRecursive, removeData, data as elementData } from './element_data'; -import domAdapter from './dom_adapter'; -import { getWindow } from './utils/window'; -import { isObject, isWindow, isPlainObject, isString, isNumeric, isDefined, isFunction, type } from './utils/type'; -import { styleProp, normalizeStyleProp } from './utils/style'; -import { getOffset, getWindowByElement } from './utils/size'; -import { parseHTML, isTablePart } from './utils/html_parser'; +/* eslint-disable guard-for-in */ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable prefer-arrow-callback */ +/* eslint-disable object-shorthand */ +import domAdapter from '@js/core/dom_adapter'; +import { cleanDataRecursive, data as elementData, removeData } from '@js/core/element_data'; +import { isTablePart, parseHTML } from '@js/core/utils/html_parser'; +import { getOffset, getWindowByElement } from '@js/core/utils/size'; +import { normalizeStyleProp, styleProp } from '@js/core/utils/style'; +import { + isDefined, isFunction, isNumeric, isObject, isPlainObject, isString, isWindow, type, +} from '@js/core/utils/type'; +import { getWindow } from '@js/core/utils/window'; const window = getWindow(); let renderer; -const initRender = function(selector, context) { - if(!selector) { - this.length = 0; - return this; - } - - if(typeof selector === 'string') { - if(selector === 'body') { - this[0] = context ? context.body : domAdapter.getBody(); - this.length = 1; - return this; - } +const initRender = function (selector, context) { + if (!selector) { + this.length = 0; + return this; + } - context = context || domAdapter.getDocument(); - if(selector[0] === '<') { - this[0] = domAdapter.createElement(selector.slice(1, -1), context); - this.length = 1; - return this; - } + if (typeof selector === 'string') { + if (selector === 'body') { + this[0] = context ? context.body : domAdapter.getBody(); + this.length = 1; + return this; + } - [].push.apply(this, domAdapter.querySelectorAll(context, selector)); - return this; - } else if(domAdapter.isNode(selector) || isWindow(selector)) { - this[0] = selector; - this.length = 1; - return this; - } else if(Array.isArray(selector)) { - [].push.apply(this, selector); - return this; + context = context || domAdapter.getDocument(); + if (selector.startsWith('<')) { + this[0] = domAdapter.createElement(selector.slice(1, -1), context); + this.length = 1; + return this; } - return renderer(selector.toArray ? selector.toArray() : [selector]); + [].push.apply(this, domAdapter.querySelectorAll(context, selector)); + return this; + } if (domAdapter.isNode(selector) || isWindow(selector)) { + this[0] = selector; + this.length = 1; + return this; + } if (Array.isArray(selector)) { + // @ts-expect-error + [].push.apply(this, selector); + return this; + } + + return renderer(selector.toArray ? selector.toArray() : [selector]); }; -renderer = function(selector, context) { - return new initRender(selector, context); +renderer = function (selector, context) { + // @ts-expect-error void constructor + // eslint-disable-next-line new-cap + return new initRender(selector, context); }; renderer.fn = { dxRenderer: true }; initRender.prototype = renderer.fn; -const repeatMethod = function(methodName, args) { - for(let i = 0; i < this.length; i++) { - const item = renderer(this[i]); - item[methodName].apply(item, args); - } - return this; +const repeatMethod = function (methodName, args) { + for (let i = 0; i < this.length; i++) { + const item = renderer(this[i]); + item[methodName].apply(item, args); + } + return this; }; -const setAttributeValue = function(element, attrName, value) { - if(value !== undefined && value !== null && value !== false) { - domAdapter.setAttribute(element, attrName, value); - } else { - domAdapter.removeAttribute(element, attrName); - } +const setAttributeValue = function (element, attrName, value) { + if (value !== undefined && value !== null && value !== false) { + domAdapter.setAttribute(element, attrName, value); + } else { + domAdapter.removeAttribute(element, attrName); + } }; -initRender.prototype.show = function() { - return this.toggle(true); +initRender.prototype.show = function () { + return this.toggle(true); }; -initRender.prototype.hide = function() { - return this.toggle(false); +initRender.prototype.hide = function () { + return this.toggle(false); }; -initRender.prototype.toggle = function(value) { - if(this[0]) { - this.toggleClass('dx-state-invisible', !value); - } +initRender.prototype.toggle = function (value) { + if (this[0]) { + this.toggleClass('dx-state-invisible', !value); + } - return this; + return this; }; -initRender.prototype.attr = function(attrName, value) { - if(this.length > 1 && arguments.length > 1) return repeatMethod.call(this, 'attr', arguments); - if(!this[0]) { - if(isObject(attrName) || value !== undefined) { - return this; - } else { - return undefined; - } - } - if(!this[0].getAttribute) { - return this.prop(attrName, value); +initRender.prototype.attr = function (attrName, value) { + if (this.length > 1 && arguments.length > 1) return repeatMethod.call(this, 'attr', arguments); + if (!this[0]) { + if (isObject(attrName) || value !== undefined) { + return this; } - if(typeof attrName === 'string' && arguments.length === 1) { - const result = this[0].getAttribute(attrName); - return result == null ? undefined : result; - } else if(isPlainObject(attrName)) { - for(const key in attrName) { - this.attr(key, attrName[key]); - } - } else { - setAttributeValue(this[0], attrName, value); + return undefined; + } + if (!this[0].getAttribute) { + return this.prop(attrName, value); + } + if (typeof attrName === 'string' && arguments.length === 1) { + const result = this[0].getAttribute(attrName); + return result == null ? undefined : result; + } if (isPlainObject(attrName)) { + for (const key in attrName) { + this.attr(key, attrName[key]); } - return this; + } else { + setAttributeValue(this[0], attrName, value); + } + return this; }; -initRender.prototype.removeAttr = function(attrName) { - this[0] && domAdapter.removeAttribute(this[0], attrName); - return this; +initRender.prototype.removeAttr = function (attrName) { + this[0] && domAdapter.removeAttribute(this[0], attrName); + return this; }; -initRender.prototype.prop = function(propName, value) { - if(!this[0]) return this; - if(typeof propName === 'string' && arguments.length === 1) { - return this[0][propName]; - } else if(isPlainObject(propName)) { - for(const key in propName) { - this.prop(key, propName[key]); - } - } else { - domAdapter.setProperty(this[0], propName, value); +initRender.prototype.prop = function (propName, value) { + if (!this[0]) return this; + if (typeof propName === 'string' && arguments.length === 1) { + return this[0][propName]; + } if (isPlainObject(propName)) { + for (const key in propName) { + this.prop(key, propName[key]); } + } else { + domAdapter.setProperty(this[0], propName, value); + } - return this; + return this; }; -initRender.prototype.addClass = function(className) { - return this.toggleClass(className, true); +initRender.prototype.addClass = function (className) { + return this.toggleClass(className, true); }; -initRender.prototype.removeClass = function(className) { - return this.toggleClass(className, false); +initRender.prototype.removeClass = function (className) { + return this.toggleClass(className, false); }; -initRender.prototype.hasClass = function(className) { - if(!this[0] || this[0].className === undefined) return false; +initRender.prototype.hasClass = function (className) { + if (!this[0] || this[0].className === undefined) return false; - const classNames = className.split(' '); - for(let i = 0; i < classNames.length; i++) { - if(this[0].classList) { - if(this[0].classList.contains(classNames[i])) return true; - } else { // IE9 - const className = isString(this[0].className) ? this[0].className : domAdapter.getAttribute(this[0], 'class'); - if((className || '').split(' ').indexOf(classNames[i]) >= 0) return true; - } + const classNames = className.split(' '); + for (let i = 0; i < classNames.length; i++) { + if (this[0].classList) { + if (this[0].classList.contains(classNames[i])) return true; + } else { // IE9 + const className = isString(this[0].className) ? this[0].className : domAdapter.getAttribute(this[0], 'class'); + if ((className || '').split(' ').indexOf(classNames[i]) >= 0) return true; } - return false; + } + return false; }; -initRender.prototype.toggleClass = function(className, value) { - if(this.length > 1) { - return repeatMethod.call(this, 'toggleClass', arguments); - } +initRender.prototype.toggleClass = function (className, value) { + if (this.length > 1) { + return repeatMethod.call(this, 'toggleClass', arguments); + } - if(!this[0] || !className) return this; - value = value === undefined ? !this.hasClass(className) : value; + if (!this[0] || !className) return this; + value = value === undefined ? !this.hasClass(className) : value; - const classNames = className.split(' '); - for(let i = 0; i < classNames.length; i++) { - domAdapter.setClass(this[0], classNames[i], value); - } - return this; + const classNames = className.split(' '); + for (let i = 0; i < classNames.length; i++) { + domAdapter.setClass(this[0], classNames[i], value); + } + return this; }; -initRender.prototype.html = function(value) { - if(!arguments.length) { - return this[0].innerHTML; - } +initRender.prototype.html = function (value) { + if (!arguments.length) { + return this[0].innerHTML; + } - this.empty(); + this.empty(); - if(typeof value === 'string' && !isTablePart(value) || typeof value === 'number') { - this[0].innerHTML = value; + if (typeof value === 'string' && !isTablePart(value) || typeof value === 'number') { + this[0].innerHTML = value; - return this; - } + return this; + } - return this.append(parseHTML(value)); + return this.append(parseHTML(value)); }; -const appendElements = function(element, nextSibling) { - if(!this[0] || !element) return; +const appendElements = function (element, nextSibling) { + if (!this[0] || !element) return; - if(typeof element === 'string') { - element = parseHTML(element); - } else if(element.nodeType) { - element = [element]; - } else if(isNumeric(element)) { - element = [domAdapter.createTextNode(element)]; - } + if (typeof element === 'string') { + element = parseHTML(element); + } else if (element.nodeType) { + element = [element]; + } else if (isNumeric(element)) { + element = [domAdapter.createTextNode(element)]; + } - for(let i = 0; i < element.length; i++) { - const item = element[i]; - let container = this[0]; - const wrapTR = container.tagName === 'TABLE' && item.tagName === 'TR'; + for (let i = 0; i < element.length; i++) { + const item = element[i]; + let container = this[0]; + const wrapTR = container.tagName === 'TABLE' && item.tagName === 'TR'; - if(wrapTR && container.tBodies && container.tBodies.length) { - container = container.tBodies[0]; - } - domAdapter.insertElement(container, item.nodeType ? item : item[0], nextSibling); + if (wrapTR && container.tBodies && container.tBodies.length) { + // HTML collection, not an array + // eslint-disable-next-line prefer-destructuring + container = container.tBodies[0]; } + domAdapter.insertElement(container, item.nodeType ? item : item[0], nextSibling); + } }; -const setCss = function(name, value) { - if(!this[0] || !this[0].style) return; +const setCss = function (name, value) { + if (!this[0] || !this[0].style) return; - if(value === null || (typeof value === 'number' && isNaN(value))) { - return; - } + if (value === null || (typeof value === 'number' && isNaN(value))) { + return; + } - name = styleProp(name); - for(let i = 0; i < this.length; i++) { - this[i].style[name] = normalizeStyleProp(name, value); - } + name = styleProp(name); + for (let i = 0; i < this.length; i++) { + this[i].style[name] = normalizeStyleProp(name, value); + } }; -initRender.prototype.css = function(name, value) { - if(isString(name)) { - if(arguments.length === 2) { - setCss.call(this, name, value); - } else { - if(!this[0]) return; +initRender.prototype.css = function (name, value) { + if (isString(name)) { + if (arguments.length === 2) { + setCss.call(this, name, value); + } else { + if (!this[0]) return; - name = styleProp(name); + name = styleProp(name); - const result = window.getComputedStyle(this[0])[name] || this[0].style[name]; - return isNumeric(result) ? result.toString() : result; - } - } else if(isPlainObject(name)) { - for(const key in name) { - setCss.call(this, key, name[key]); - } + const result = window.getComputedStyle(this[0])[name] || this[0].style[name]; + return isNumeric(result) ? result.toString() : result; + } + } else if (isPlainObject(name)) { + for (const key in name) { + setCss.call(this, key, name[key]); } + } - return this; + return this; }; -initRender.prototype.prepend = function(element) { - if(arguments.length > 1) { - for(let i = 0; i < arguments.length; i++) { - this.prepend(arguments[i]); - } - return this; +initRender.prototype.prepend = function (element) { + if (arguments.length > 1) { + for (let i = 0; i < arguments.length; i++) { + this.prepend(arguments[i]); } - appendElements.apply(this, [element, this[0].firstChild]); return this; + } + appendElements.apply(this, [element, this[0].firstChild]); + return this; }; -initRender.prototype.append = function(element) { - if(arguments.length > 1) { - for(let i = 0; i < arguments.length; i++) { - this.append(arguments[i]); - } - return this; +initRender.prototype.append = function (element) { + if (arguments.length > 1) { + for (let i = 0; i < arguments.length; i++) { + this.append(arguments[i]); } - appendElements.apply(this, [element]); return this; + } + // @ts-expect-error + appendElements.apply(this, [element]); + return this; }; -initRender.prototype.prependTo = function(element) { - if(this.length > 1) { - for(let i = this.length - 1; i >= 0; i--) { - renderer(this[i]).prependTo(element); - } - return this; +initRender.prototype.prependTo = function (element) { + if (this.length > 1) { + for (let i = this.length - 1; i >= 0; i--) { + renderer(this[i]).prependTo(element); } + return this; + } - element = renderer(element); - if(element[0]) { - domAdapter.insertElement(element[0], this[0], element[0].firstChild); - } + element = renderer(element); + if (element[0]) { + domAdapter.insertElement(element[0], this[0], element[0].firstChild); + } - return this; + return this; }; -initRender.prototype.appendTo = function(element) { - if(this.length > 1) { - return repeatMethod.call(this, 'appendTo', arguments); - } +initRender.prototype.appendTo = function (element) { + if (this.length > 1) { + return repeatMethod.call(this, 'appendTo', arguments); + } - domAdapter.insertElement(renderer(element)[0], this[0]); - return this; + domAdapter.insertElement(renderer(element)[0], this[0]); + return this; }; -initRender.prototype.insertBefore = function(element) { - if(element && element[0]) { - domAdapter.insertElement(element[0].parentNode, this[0], element[0]); - } - return this; +initRender.prototype.insertBefore = function (element) { + if (element && element[0]) { + domAdapter.insertElement(element[0].parentNode, this[0], element[0]); + } + return this; }; -initRender.prototype.insertAfter = function(element) { - if(element && element[0]) { - domAdapter.insertElement(element[0].parentNode, this[0], element[0].nextSibling); - } - return this; +initRender.prototype.insertAfter = function (element) { + if (element && element[0]) { + domAdapter.insertElement(element[0].parentNode, this[0], element[0].nextSibling); + } + return this; }; -initRender.prototype.before = function(element) { - if(this[0]) { - domAdapter.insertElement(this[0].parentNode, element[0], this[0]); - } - return this; +initRender.prototype.before = function (element) { + if (this[0]) { + domAdapter.insertElement(this[0].parentNode, element[0], this[0]); + } + return this; }; -initRender.prototype.after = function(element) { - if(this[0]) { - domAdapter.insertElement(this[0].parentNode, element[0], this[0].nextSibling); - } - return this; +initRender.prototype.after = function (element) { + if (this[0]) { + domAdapter.insertElement(this[0].parentNode, element[0], this[0].nextSibling); + } + return this; }; -initRender.prototype.wrap = function(wrapper) { - if(this[0]) { - const wrap = renderer(wrapper); +initRender.prototype.wrap = function (wrapper) { + if (this[0]) { + const wrap = renderer(wrapper); - wrap.insertBefore(this); - wrap.append(this); - } + wrap.insertBefore(this); + wrap.append(this); + } - return this; + return this; }; -initRender.prototype.wrapInner = function(wrapper) { - const contents = this.contents(); +initRender.prototype.wrapInner = function (wrapper) { + const contents = this.contents(); - if(contents.length) { - contents.wrap(wrapper); - } else { - this.append(wrapper); - } + if (contents.length) { + contents.wrap(wrapper); + } else { + this.append(wrapper); + } - return this; + return this; }; -initRender.prototype.replaceWith = function(element) { - if(!(element && element[0])) return; - if(element.is(this)) return this; +initRender.prototype.replaceWith = function (element) { + if (!(element && element[0])) return; + if (element.is(this)) return this; - element.insertBefore(this); - this.remove(); + element.insertBefore(this); + this.remove(); - return element; + return element; }; -initRender.prototype.remove = function() { - if(this.length > 1) { - return repeatMethod.call(this, 'remove', arguments); - } +initRender.prototype.remove = function () { + if (this.length > 1) { + return repeatMethod.call(this, 'remove', arguments); + } - cleanDataRecursive(this[0], true); - domAdapter.removeElement(this[0]); + cleanDataRecursive(this[0], true); + domAdapter.removeElement(this[0]); - return this; + return this; }; -initRender.prototype.detach = function() { - if(this.length > 1) { - return repeatMethod.call(this, 'detach', arguments); - } +initRender.prototype.detach = function () { + if (this.length > 1) { + return repeatMethod.call(this, 'detach', arguments); + } - domAdapter.removeElement(this[0]); + domAdapter.removeElement(this[0]); - return this; + return this; }; -initRender.prototype.empty = function() { - if(this.length > 1) { - return repeatMethod.call(this, 'empty', arguments); - } +initRender.prototype.empty = function () { + if (this.length > 1) { + return repeatMethod.call(this, 'empty', arguments); + } - cleanDataRecursive(this[0]); - domAdapter.setText(this[0], ''); + cleanDataRecursive(this[0]); + domAdapter.setText(this[0], ''); - return this; + return this; }; -initRender.prototype.clone = function() { - const result = []; - for(let i = 0; i < this.length; i++) { - result.push(this[i].cloneNode(true)); - } - return renderer(result); +initRender.prototype.clone = function () { + const result: any[] = []; + for (let i = 0; i < this.length; i++) { + result.push(this[i].cloneNode(true)); + } + return renderer(result); }; -initRender.prototype.text = function(value) { - if(!arguments.length) { - let result = ''; +initRender.prototype.text = function (value) { + if (!arguments.length) { + let result = ''; - for(let i = 0; i < this.length; i++) { - result += this[i] && this[i].textContent || ''; - } - return result; + for (let i = 0; i < this.length; i++) { + result += this[i] && this[i].textContent || ''; } + return result; + } - const text = isFunction(value) ? value() : value; - - cleanDataRecursive(this[0], false); - domAdapter.setText(this[0], isDefined(text) ? text : ''); - - return this; -}; + const text = isFunction(value) ? value() : value; -initRender.prototype.val = function(value) { - if(arguments.length === 1) { - return this.prop('value', isDefined(value) ? value : ''); - } + cleanDataRecursive(this[0], false); + domAdapter.setText(this[0], isDefined(text) ? text : ''); - return this.prop('value'); + return this; }; -initRender.prototype.contents = function() { - if(!this[0]) return renderer(); +initRender.prototype.val = function (value) { + if (arguments.length === 1) { + return this.prop('value', isDefined(value) ? value : ''); + } - const result = []; - result.push.apply(result, this[0].childNodes); - return renderer(result); + return this.prop('value'); }; -initRender.prototype.find = function(selector) { - const result = renderer(); - if(!selector) { - return result; - } - - const nodes = []; - let i; - - if(typeof selector === 'string') { - selector = selector.trim(); - - for(i = 0; i < this.length; i++) { - const element = this[i]; - if(domAdapter.isElementNode(element)) { - const elementId = element.getAttribute('id'); - let queryId = elementId || 'dx-query-children'; - - if(!elementId) { - setAttributeValue(element, 'id', queryId); - } - queryId = '[id=\'' + queryId + '\'] '; - - const querySelector = queryId + selector.replace(/([^\\])(,)/g, '$1, ' + queryId); - nodes.push.apply(nodes, domAdapter.querySelectorAll(element, querySelector)); - setAttributeValue(element, 'id', elementId); - } else if(domAdapter.isDocument(element) || domAdapter.isDocumentFragment(element)) { - nodes.push.apply(nodes, domAdapter.querySelectorAll(element, selector)); - } - } - } else { - for(i = 0; i < this.length; i++) { - selector = domAdapter.isNode(selector) ? selector : selector[0]; - if(this[i] !== selector && this[i].contains(selector)) { - nodes.push(selector); - } - } - } +initRender.prototype.contents = function () { + if (!this[0]) return renderer(); - return result.add(nodes); + const result = []; + result.push.apply(result, this[0].childNodes); + return renderer(result); }; -const isVisible = function(_, element) { - element = element.host ?? element; +initRender.prototype.find = function (selector) { + const result = renderer(); + if (!selector) { + return result; + } - if(!element.nodeType) return true; - return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length); -}; + const nodes: any = []; + let i; -initRender.prototype.filter = function(selector) { - if(!selector) return renderer(); + if (typeof selector === 'string') { + selector = selector.trim(); - if(selector === ':visible') { - return this.filter(isVisible); - } else if(selector === ':hidden') { - return this.filter(function(_, element) { - return !isVisible(_, element); - }); - } + for (i = 0; i < this.length; i++) { + const element = this[i]; + if (domAdapter.isElementNode(element)) { + const elementId = element.getAttribute('id'); + let queryId = elementId || 'dx-query-children'; - const result = []; - for(let i = 0; i < this.length; i++) { - const item = this[i]; - if(domAdapter.isElementNode(item) && type(selector) === 'string') { - domAdapter.elementMatches(item, selector) && result.push(item); - } else if(domAdapter.isNode(selector) || isWindow(selector)) { - selector === item && result.push(item); - } else if(isFunction(selector)) { - selector.call(item, i, item) && result.push(item); - } else { - for(let j = 0; j < selector.length; j++) { - selector[j] === item && result.push(item); - } + if (!elementId) { + setAttributeValue(element, 'id', queryId); } + queryId = `[id='${queryId}'] `; + + const querySelector = queryId + selector.replace(/([^\\])(,)/g, `$1, ${queryId}`); + nodes.push.apply(nodes, domAdapter.querySelectorAll(element, querySelector)); + setAttributeValue(element, 'id', elementId); + } else if (domAdapter.isDocument(element) || domAdapter.isDocumentFragment(element)) { + nodes.push.apply(nodes, domAdapter.querySelectorAll(element, selector)); + } + } + } else { + for (i = 0; i < this.length; i++) { + selector = domAdapter.isNode(selector) ? selector : selector[0]; + if (this[i] !== selector && this[i].contains(selector)) { + nodes.push(selector); + } + } + } + + return result.add(nodes); +}; + +const isVisible = function (_, element) { + element = element.host ?? element; + + if (!element.nodeType) return true; + return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length); +}; + +initRender.prototype.filter = function (selector) { + if (!selector) return renderer(); + + if (selector === ':visible') { + return this.filter(isVisible); + } if (selector === ':hidden') { + return this.filter(function (_, element) { + return !isVisible(_, element); + }); + } + + const result: any[] = []; + for (let i = 0; i < this.length; i++) { + const item = this[i]; + if (domAdapter.isElementNode(item) && type(selector) === 'string') { + domAdapter.elementMatches(item, selector) && result.push(item); + } else if (domAdapter.isNode(selector) || isWindow(selector)) { + selector === item && result.push(item); + } else if (isFunction(selector)) { + selector.call(item, i, item) && result.push(item); + } else { + for (let j = 0; j < selector.length; j++) { + selector[j] === item && result.push(item); + } } + } - return renderer(result); + return renderer(result); }; -initRender.prototype.not = function(selector) { - const result = []; - const nodes = this.filter(selector).toArray(); +initRender.prototype.not = function (selector) { + const result: any[] = []; + const nodes = this.filter(selector).toArray(); - for(let i = 0; i < this.length; i++) { - if(nodes.indexOf(this[i]) === -1) { - result.push(this[i]); - } + for (let i = 0; i < this.length; i++) { + if (nodes.indexOf(this[i]) === -1) { + result.push(this[i]); } + } - return renderer(result); + return renderer(result); }; -initRender.prototype.is = function(selector) { - return !!this.filter(selector).length; +initRender.prototype.is = function (selector) { + return !!this.filter(selector).length; }; -initRender.prototype.children = function(selector) { - let result = []; - for(let i = 0; i < this.length; i++) { - const nodes = this[i] ? this[i].childNodes : []; - for(let j = 0; j < nodes.length; j++) { - if(domAdapter.isElementNode(nodes[j])) { - result.push(nodes[j]); - } - } +initRender.prototype.children = function (selector) { + let result: any[] = []; + for (let i = 0; i < this.length; i++) { + const nodes = this[i] ? this[i].childNodes : []; + for (let j = 0; j < nodes.length; j++) { + if (domAdapter.isElementNode(nodes[j])) { + result.push(nodes[j]); + } } + } - result = renderer(result); + result = renderer(result); - return selector ? result.filter(selector) : result; + return selector ? result.filter(selector) : result; }; -initRender.prototype.siblings = function() { - const element = this[0]; - if(!element || !element.parentNode) { - return renderer(); - } +initRender.prototype.siblings = function () { + const element = this[0]; + if (!element || !element.parentNode) { + return renderer(); + } - const result = []; - const parentChildNodes = element.parentNode.childNodes || []; + const result: any[] = []; + const parentChildNodes = element.parentNode.childNodes || []; - for(let i = 0; i < parentChildNodes.length; i++) { - const node = parentChildNodes[i]; - if(domAdapter.isElementNode(node) && node !== element) { - result.push(node); - } + for (let i = 0; i < parentChildNodes.length; i++) { + const node = parentChildNodes[i]; + if (domAdapter.isElementNode(node) && node !== element) { + result.push(node); } + } - return renderer(result); + return renderer(result); }; -initRender.prototype.each = function(callback) { - for(let i = 0; i < this.length; i++) { - if(callback.call(this[i], i, this[i]) === false) { - break; - } +initRender.prototype.each = function (callback) { + for (let i = 0; i < this.length; i++) { + if (callback.call(this[i], i, this[i]) === false) { + break; } + } }; -initRender.prototype.index = function(element) { - if(!element) { - return this.parent().children().index(this); - } +initRender.prototype.index = function (element) { + if (!element) { + return this.parent().children().index(this); + } - element = renderer(element); - return this.toArray().indexOf(element[0]); + element = renderer(element); + return this.toArray().indexOf(element[0]); }; -initRender.prototype.get = function(index) { - return this[index < 0 ? this.length + index : index]; +initRender.prototype.get = function (index) { + return this[index < 0 ? this.length + index : index]; }; -initRender.prototype.eq = function(index) { - index = index < 0 ? this.length + index : index; - return renderer(this[index]); +initRender.prototype.eq = function (index) { + index = index < 0 ? this.length + index : index; + return renderer(this[index]); }; -initRender.prototype.first = function() { - return this.eq(0); +initRender.prototype.first = function () { + return this.eq(0); }; -initRender.prototype.last = function() { - return this.eq(-1); +initRender.prototype.last = function () { + return this.eq(-1); }; -initRender.prototype.select = function() { - for(let i = 0; i < this.length; i += 1) { - this[i].select && this[i].select(); - } +initRender.prototype.select = function () { + for (let i = 0; i < this.length; i += 1) { + this[i].select && this[i].select(); + } - return this; + return this; }; -initRender.prototype.parent = function(selector) { - if(!this[0]) return renderer(); - const result = renderer(this[0].parentNode); - return !selector || result.is(selector) ? result : renderer(); +initRender.prototype.parent = function (selector) { + if (!this[0]) return renderer(); + const result = renderer(this[0].parentNode); + return !selector || result.is(selector) ? result : renderer(); }; -initRender.prototype.parents = function(selector) { - const result = []; - let parent = this.parent(); +initRender.prototype.parents = function (selector) { + const result: any[] = []; + let parent = this.parent(); - while(parent && parent[0] && !domAdapter.isDocument(parent[0])) { - if(domAdapter.isElementNode(parent[0])) { - if(!selector || parent.is(selector)) { - result.push(parent.get(0)); - } - } - parent = parent.parent(); + while (parent && parent[0] && !domAdapter.isDocument(parent[0])) { + if (domAdapter.isElementNode(parent[0])) { + if (!selector || parent.is(selector)) { + result.push(parent.get(0)); + } } - return renderer(result); + parent = parent.parent(); + } + return renderer(result); }; -initRender.prototype.closest = function(selector) { - if(this.is(selector)) { - return this; - } +initRender.prototype.closest = function (selector) { + if (this.is(selector)) { + return this; + } - let parent = this.parent(); - while(parent && parent.length) { - if(parent.is(selector)) { - return parent; - } - parent = parent.parent(); + let parent = this.parent(); + while (parent && parent.length) { + if (parent.is(selector)) { + return parent; } + parent = parent.parent(); + } - return renderer(); + return renderer(); }; -initRender.prototype.next = function(selector) { - if(!this[0]) return renderer(); - let next = renderer(this[0].nextSibling); - if(!arguments.length) { - return next; - } - while(next && next.length) { - if(next.is(selector)) return next; - next = next.next(); - } - return renderer(); +initRender.prototype.next = function (selector) { + if (!this[0]) return renderer(); + let next = renderer(this[0].nextSibling); + if (!arguments.length) { + return next; + } + while (next && next.length) { + if (next.is(selector)) return next; + next = next.next(); + } + return renderer(); }; -initRender.prototype.prev = function() { - if(!this[0]) return renderer(); - return renderer(this[0].previousSibling); +initRender.prototype.prev = function () { + if (!this[0]) return renderer(); + return renderer(this[0].previousSibling); }; -initRender.prototype.add = function(selector) { - const targets = renderer(selector); - const result = this.toArray(); +initRender.prototype.add = function (selector) { + const targets = renderer(selector); + const result = this.toArray(); - for(let i = 0; i < targets.length; i++) { - const target = targets[i]; - if(result.indexOf(target) === -1) { - result.push(target); - } + for (let i = 0; i < targets.length; i++) { + const target = targets[i]; + if (result.indexOf(target) === -1) { + result.push(target); } + } - return renderer(result); + return renderer(result); }; -const emptyArray = []; -initRender.prototype.splice = function() { - return renderer(emptyArray.splice.apply(this, arguments)); +const emptyArray: any[] = []; +initRender.prototype.splice = function () { + // @ts-expect-error get rid of arguments + // eslint-disable-next-line prefer-rest-params + return renderer(emptyArray.splice.apply(this, arguments)); }; -initRender.prototype.slice = function() { - return renderer(emptyArray.slice.apply(this, arguments)); +initRender.prototype.slice = function () { + // @ts-expect-error get rid of arguments + // eslint-disable-next-line prefer-rest-params + return renderer(emptyArray.slice.apply(this, arguments)); }; -initRender.prototype.toArray = function() { - return emptyArray.slice.call(this); +initRender.prototype.toArray = function () { + return emptyArray.slice.call(this); }; -initRender.prototype.offset = function() { - if(!this[0]) return; +initRender.prototype.offset = function () { + if (!this[0]) return; - return getOffset(this[0]); + return getOffset(this[0]); }; -initRender.prototype.offsetParent = function() { - if(!this[0]) return renderer(); +initRender.prototype.offsetParent = function () { + if (!this[0]) return renderer(); - let offsetParent = renderer(this[0].offsetParent); + let offsetParent = renderer(this[0].offsetParent); - while(offsetParent[0] && offsetParent.css('position') === 'static') { - offsetParent = renderer(offsetParent[0].offsetParent); - } + while (offsetParent[0] && offsetParent.css('position') === 'static') { + offsetParent = renderer(offsetParent[0].offsetParent); + } - offsetParent = offsetParent[0] ? offsetParent : renderer(domAdapter.getDocumentElement()); + offsetParent = offsetParent[0] ? offsetParent : renderer(domAdapter.getDocumentElement()); - return offsetParent; + return offsetParent; }; -initRender.prototype.position = function() { - if(!this[0]) return; +initRender.prototype.position = function () { + if (!this[0]) return; - let offset; - const marginTop = parseFloat(this.css('marginTop')); - const marginLeft = parseFloat(this.css('marginLeft')); + let offset; + const marginTop = parseFloat(this.css('marginTop')); + const marginLeft = parseFloat(this.css('marginLeft')); - if(this.css('position') === 'fixed') { - offset = this[0].getBoundingClientRect(); + if (this.css('position') === 'fixed') { + offset = this[0].getBoundingClientRect(); - return { - top: offset.top - marginTop, - left: offset.left - marginLeft - }; - } + return { + top: offset.top - marginTop, + left: offset.left - marginLeft, + }; + } - offset = this.offset(); + offset = this.offset(); - const offsetParent = this.offsetParent(); - let parentOffset = { - top: 0, - left: 0 - }; + const offsetParent = this.offsetParent(); + let parentOffset = { + top: 0, + left: 0, + }; - if(offsetParent[0].nodeName !== 'HTML') { - parentOffset = offsetParent.offset(); - } + if (offsetParent[0].nodeName !== 'HTML') { + parentOffset = offsetParent.offset(); + } - parentOffset = { - top: parentOffset.top + parseFloat(offsetParent.css('borderTopWidth')), - left: parentOffset.left + parseFloat(offsetParent.css('borderLeftWidth')) - }; + parentOffset = { + top: parentOffset.top + parseFloat(offsetParent.css('borderTopWidth')), + left: parentOffset.left + parseFloat(offsetParent.css('borderLeftWidth')), + }; - return { - top: offset.top - parentOffset.top - marginTop, - left: offset.left - parentOffset.left - marginLeft - }; + return { + top: offset.top - parentOffset.top - marginTop, + left: offset.left - parentOffset.left - marginLeft, + }; }; [{ - name: 'scrollLeft', - offsetProp: 'pageXOffset', - scrollWindow: function(win, value) { - win.scrollTo(value, win.pageYOffset); - } + name: 'scrollLeft', + offsetProp: 'pageXOffset', + scrollWindow: function (win, value) { + win.scrollTo(value, win.pageYOffset); + }, }, { - name: 'scrollTop', - offsetProp: 'pageYOffset', - scrollWindow: function(win, value) { - win.scrollTo(win.pageXOffset, value); - } -}].forEach(function(directionStrategy) { - const propName = directionStrategy.name; + name: 'scrollTop', + offsetProp: 'pageYOffset', + scrollWindow: function (win, value) { + win.scrollTo(win.pageXOffset, value); + }, +}].forEach(function (directionStrategy) { + const propName = directionStrategy.name; - initRender.prototype[propName] = function(value) { - if(!this[0]) { - return; - } + initRender.prototype[propName] = function (value) { + if (!this[0]) { + return; + } - const window = getWindowByElement(this[0]); + const window = getWindowByElement(this[0]); - if(value === undefined) { - return window ? window[directionStrategy.offsetProp] : this[0][propName]; - } + if (value === undefined) { + return window ? window[directionStrategy.offsetProp] : this[0][propName]; + } - if(window) { - directionStrategy.scrollWindow(window, value); - } else { - this[0][propName] = value; - } - return this; - }; + if (window) { + directionStrategy.scrollWindow(window, value); + } else { + this[0][propName] = value; + } + return this; + }; }); -initRender.prototype.data = function(key, value) { - if(!this[0]) return; - - if(arguments.length < 2) { - return elementData.call(renderer, this[0], key); - } +initRender.prototype.data = function (key, value) { + if (!this[0]) return; - elementData.call(renderer, this[0], key, value); - return this; + if (arguments.length < 2) { + return elementData.call(renderer, this[0], key); + } + elementData.call(renderer, this[0], key, value); + return this; }; -initRender.prototype.removeData = function(key) { - this[0] && removeData(this[0], key); +initRender.prototype.removeData = function (key) { + this[0] && removeData(this[0], key); - return this; + return this; }; -const rendererWrapper = function() { - return renderer.apply(this, arguments); +const rendererWrapper = function () { + return renderer.apply(this, arguments); }; Object.defineProperty(rendererWrapper, 'fn', { - enumerable: true, - configurable: true, + enumerable: true, + configurable: true, - get: function() { - return renderer.fn; - }, + get: function () { + return renderer.fn; + }, - set: function(value) { - renderer.fn = value; - } + set: function (value) { + renderer.fn = value; + }, }); export default { - set: function(strategy) { - renderer = strategy; - }, - get: function() { - return rendererWrapper; - } + set: function (strategy) { + renderer = strategy; + }, + get: function () { + return rendererWrapper; + }, }; diff --git a/packages/devextreme/js/__internal/core/m_resize_observer.ts b/packages/devextreme/js/__internal/core/m_resize_observer.ts index b7babb33da1f..91a694b2b2a2 100644 --- a/packages/devextreme/js/__internal/core/m_resize_observer.ts +++ b/packages/devextreme/js/__internal/core/m_resize_observer.ts @@ -1,47 +1,56 @@ -import { noop } from './utils/common'; -import { getWindow, hasWindow } from './utils/window'; -const window = getWindow(); +import { noop } from '@js/core/utils/common'; + +import windowUtils from './utils/m_window'; + +const window = windowUtils.getWindow(); const ResizeObserverMock = { - observe: noop, - unobserve: noop, - disconnect: noop + observe: noop, + unobserve: noop, + disconnect: noop, }; class ResizeObserverSingleton { - constructor() { - if(!hasWindow() || !window.ResizeObserver) { - return ResizeObserverMock; - } - - this._callbacksMap = new Map(); - this._observer = new window.ResizeObserver((entries) => { - entries.forEach(entry => { - this._callbacksMap.get(entry.target)?.(entry); - }); - }); - } + _callbacksMap?: any; - observe(element, callback) { - this._callbacksMap.set(element, callback); - this._observer.observe(element); - } + _observer?: any; - unobserve(element) { - this._callbacksMap.delete(element); - this._observer.unobserve(element); + constructor() { + // we need to make our own for extensions like this + if (!windowUtils.hasWindow() || !window.ResizeObserver) { + // eslint-disable-next-line no-constructor-return + return ResizeObserverMock; } - disconnect() { - this._callbacksMap.clear(); - this._observer.disconnect(); - } + this._callbacksMap = new Map(); + this._observer = new window.ResizeObserver((entries) => { + entries.forEach((entry) => { + this._callbacksMap.get(entry.target)?.(entry); + }); + }); + } + + observe(element, callback) { + this._callbacksMap.set(element, callback); + this._observer.observe(element); + } + + unobserve(element) { + this._callbacksMap.delete(element); + this._observer.unobserve(element); + } + + disconnect() { + this._callbacksMap.clear(); + this._observer.disconnect(); + } } const resizeObserverSingleton = new ResizeObserverSingleton(); -///#DEBUG +/// #DEBUG +// @ts-expect-error singleton typing issue resizeObserverSingleton.ResizeObserverSingleton = ResizeObserverSingleton; -///#ENDDEBUG +/// #ENDDEBUG -export default resizeObserverSingleton; +export { resizeObserverSingleton }; diff --git a/packages/devextreme/js/__internal/core/m_set_template_engine.ts b/packages/devextreme/js/__internal/core/m_set_template_engine.ts index 66317828997b..934e587bd3af 100644 --- a/packages/devextreme/js/__internal/core/m_set_template_engine.ts +++ b/packages/devextreme/js/__internal/core/m_set_template_engine.ts @@ -1 +1 @@ -export { setTemplateEngine as default } from './templates/template_engine_registry'; +export { setTemplateEngine } from '@js/core/templates/template_engine_registry'; diff --git a/packages/devextreme/js/__internal/core/m_template_manager.ts b/packages/devextreme/js/__internal/core/m_template_manager.ts index 22d81ac18dbf..5a6403054784 100644 --- a/packages/devextreme/js/__internal/core/m_template_manager.ts +++ b/packages/devextreme/js/__internal/core/m_template_manager.ts @@ -1,161 +1,167 @@ -import $ from './renderer'; -import { isDefined, isFunction, isRenderer } from './utils/type'; -import { noop } from './utils/common'; -import { extend } from './utils/extend'; -import { FunctionTemplate } from './templates/function_template'; -import { EmptyTemplate } from './templates/empty_template'; +import $ from '@js/core/renderer'; +import { EmptyTemplate } from '@js/core/templates/empty_template'; +import { FunctionTemplate } from '@js/core/templates/function_template'; +import { noop } from '@js/core/utils/common'; +import { extend } from '@js/core/utils/extend'; import { - findTemplates, - suitableTemplatesByName, - templateKey, - getNormalizedTemplateArgs, - validateTemplateSource, - defaultCreateElement, - acquireTemplate, -} from './utils/template_manager'; + acquireTemplate, + defaultCreateElement, + findTemplates, + getNormalizedTemplateArgs, + suitableTemplatesByName, + templateKey, + validateTemplateSource, +} from '@js/core/utils/template_manager'; +import { isDefined, isFunction, isRenderer } from '@js/core/utils/type'; const TEXT_NODE = 3; const ANONYMOUS_TEMPLATE_NAME = 'template'; const TEMPLATE_OPTIONS_NAME = 'dxTemplate'; const TEMPLATE_WRAPPER_CLASS = 'dx-template-wrapper'; +// @ts-expect-error need to add overloaded constructor type to templates const DX_POLYMORPH_WIDGET_TEMPLATE = new FunctionTemplate(({ model, parent }) => { - const widgetName = model.widget; - if(!widgetName) return $(); + const widgetName = model.widget; + if (!widgetName) return $(); - const widgetElement = $('
'); - const widgetOptions = model.options || {}; + const widgetElement = $('
'); + const widgetOptions = model.options || {}; - if(parent) { - parent._createComponent(widgetElement, widgetName, widgetOptions); - } else { - widgetElement[widgetName](widgetOptions); - } + if (parent) { + parent._createComponent(widgetElement, widgetName, widgetOptions); + } else { + widgetElement[widgetName](widgetOptions); + } - return widgetElement; + return widgetElement; }); export class TemplateManager { - constructor(createElement, anonymousTemplateName) { - this._tempTemplates = []; - this._defaultTemplates = {}; - this._anonymousTemplateName = anonymousTemplateName || ANONYMOUS_TEMPLATE_NAME; - - this._createElement = createElement || defaultCreateElement; - this._createTemplateIfNeeded = this._createTemplateIfNeeded.bind(this); - } - - static createDefaultOptions() { - return { - integrationOptions: { - watchMethod: (fn, callback, options = {}) => { - if(!options.skipImmediate) { - callback(fn()); - } - return noop; - }, - templates: { 'dx-polymorph-widget': DX_POLYMORPH_WIDGET_TEMPLATE }, - useDeferUpdateForTemplates: true - } - }; - } - - get anonymousTemplateName() { - return this._anonymousTemplateName; - } - - addDefaultTemplates(templates) { - this._defaultTemplates = extend({}, this._defaultTemplates, templates); - } - - dispose() { - this._tempTemplates.forEach(tempTemplate => { - tempTemplate.template.dispose && tempTemplate.template.dispose(); - }); - this._tempTemplates = []; - } - - extractTemplates($el) { - const templates = this._extractTemplates($el); - const anonymousTemplateMeta = this._extractAnonymousTemplate($el); - return { templates, anonymousTemplateMeta }; - } - - _extractTemplates($el) { - const templates = findTemplates($el, TEMPLATE_OPTIONS_NAME); - const suitableTemplates = suitableTemplatesByName(templates); - - templates.forEach(({ element, options: { name } }) => { - if(element === suitableTemplates[name]) { - $(element).addClass(TEMPLATE_WRAPPER_CLASS).detach(); - } else { - $(element).remove(); - } - }); - - return Object.keys(suitableTemplates).map((name) => { - return { - name, - template: this._createTemplate(suitableTemplates[name]), - }; - }); + _tempTemplates: any[]; + + _defaultTemplates: any; + + _anonymousTemplateName: any; + + _createElement: any; + + constructor(createElement, anonymousTemplateName) { + this._tempTemplates = []; + this._defaultTemplates = {}; + this._anonymousTemplateName = anonymousTemplateName || ANONYMOUS_TEMPLATE_NAME; + + this._createElement = createElement || defaultCreateElement; + this._createTemplateIfNeeded = this._createTemplateIfNeeded.bind(this); + } + + static createDefaultOptions() { + return { + integrationOptions: { + watchMethod: (fn, callback, options: any = {}) => { + if (!options.skipImmediate) { + callback(fn()); + } + return noop; + }, + templates: { 'dx-polymorph-widget': DX_POLYMORPH_WIDGET_TEMPLATE }, + useDeferUpdateForTemplates: true, + }, + }; + } + + get anonymousTemplateName() { + return this._anonymousTemplateName; + } + + addDefaultTemplates(templates) { + this._defaultTemplates = extend({}, this._defaultTemplates, templates); + } + + dispose() { + this._tempTemplates.forEach((tempTemplate: any) => { + tempTemplate.template.dispose && tempTemplate.template.dispose(); + }); + this._tempTemplates = []; + } + + extractTemplates($el) { + const templates = this._extractTemplates($el); + const anonymousTemplateMeta = this._extractAnonymousTemplate($el); + return { templates, anonymousTemplateMeta }; + } + + _extractTemplates($el) { + const templates = findTemplates($el, TEMPLATE_OPTIONS_NAME); + const suitableTemplates = suitableTemplatesByName(templates); + + templates.forEach(({ element, options: { name } }) => { + if (element === suitableTemplates[name]) { + $(element).addClass(TEMPLATE_WRAPPER_CLASS).detach(); + } else { + $(element).remove(); + } + }); + + return Object.keys(suitableTemplates).map((name) => ({ + name, + template: this._createTemplate(suitableTemplates[name]), + })); + } + + _extractAnonymousTemplate($el) { + const $anonymousTemplate = $el.contents().detach(); + + const $notJunkTemplateContent = $anonymousTemplate.filter((_, element) => { + const isTextNode = element.nodeType === TEXT_NODE; + const isEmptyText = $(element).text().trim().length < 1; + + return !(isTextNode && isEmptyText); + }); + + return $notJunkTemplateContent.length > 0 + ? { template: this._createTemplate($anonymousTemplate), name: this._anonymousTemplateName } + : {}; + } + + _createTemplateIfNeeded(templateSource) { + const cachedTemplate: any = this._tempTemplates.filter((tempTemplate: any) => tempTemplate.source === templateKey(templateSource))[0]; + if (cachedTemplate) return cachedTemplate.template; + + const template = this._createTemplate(templateSource); + this._tempTemplates.push({ template, source: templateKey(templateSource) }); + return template; + } + + _createTemplate(templateSource) { + return this._createElement(validateTemplateSource(templateSource)); + } + + getTemplate(templateSource, templates, { isAsyncTemplate, skipTemplates }, context) { + if (!isFunction(templateSource)) { + return acquireTemplate(templateSource, this._createTemplateIfNeeded, templates, isAsyncTemplate, skipTemplates, this._defaultTemplates); } - - _extractAnonymousTemplate($el) { - const $anonymousTemplate = $el.contents().detach(); - - const $notJunkTemplateContent = $anonymousTemplate.filter((_, element) => { - const isTextNode = element.nodeType === TEXT_NODE; - const isEmptyText = $(element).text().trim().length < 1; - - return !(isTextNode && isEmptyText); - }); - - return $notJunkTemplateContent.length > 0 - ? { template: this._createTemplate($anonymousTemplate), name: this._anonymousTemplateName } - : {}; - } - - _createTemplateIfNeeded(templateSource) { - const cachedTemplate = this._tempTemplates.filter(tempTemplate => - tempTemplate.source === templateKey(templateSource) - )[0]; - if(cachedTemplate) return cachedTemplate.template; - - const template = this._createTemplate(templateSource); - this._tempTemplates.push({ template, source: templateKey(templateSource) }); - return template; - } - - _createTemplate(templateSource) { - return this._createElement(validateTemplateSource(templateSource)); - } - - getTemplate(templateSource, templates, { isAsyncTemplate, skipTemplates }, context) { - if(!isFunction(templateSource)) { - return acquireTemplate( - templateSource, this._createTemplateIfNeeded, templates, isAsyncTemplate, skipTemplates, this._defaultTemplates - ); + // @ts-expect-error need to add overloaded constructor type to templates + return new FunctionTemplate((options) => { + const templateSourceResult = templateSource.apply(context, getNormalizedTemplateArgs(options)); + + if (!isDefined(templateSourceResult)) { + return new EmptyTemplate(); + } + + let dispose = false; + const template = acquireTemplate(templateSourceResult, (templateSource) => { + if (templateSource.nodeType || isRenderer(templateSource) && !$(templateSource).is('script')) { + // @ts-expect-error need to add overloaded constructor type to templates + return new FunctionTemplate(() => templateSource); } - - return new FunctionTemplate((options) => { - const templateSourceResult = templateSource.apply(context, getNormalizedTemplateArgs(options)); - - if(!isDefined(templateSourceResult)) { - return new EmptyTemplate(); - } - - let dispose = false; - const template = acquireTemplate(templateSourceResult, (templateSource) => { - if(templateSource.nodeType || isRenderer(templateSource) && !$(templateSource).is('script')) { - return new FunctionTemplate(() => templateSource); - } - dispose = true; - return this._createTemplate(templateSource); - }, templates, isAsyncTemplate, skipTemplates, this._defaultTemplates); - - const result = template.render(options); - dispose && template.dispose && template.dispose(); - return result; - }); - } + dispose = true; + return this._createTemplate(templateSource); + }, templates, isAsyncTemplate, skipTemplates, this._defaultTemplates); + + const result = template.render(options); + dispose && template.dispose && template.dispose(); + return result; + }); + } } + +export default { TemplateManager }; diff --git a/packages/devextreme/js/__internal/core/options/m_index.ts b/packages/devextreme/js/__internal/core/options/m_index.ts index 1ad78b9f1d06..bc81f61a5194 100644 --- a/packages/devextreme/js/__internal/core/options/m_index.ts +++ b/packages/devextreme/js/__internal/core/options/m_index.ts @@ -1,233 +1,256 @@ -import { isFunction, isObject, type } from '../utils/type'; -import { equalByValue, noop } from '../utils/common'; -import { OptionManager } from './option_manager'; -import { getPathParts } from '../utils/data'; -import { getFieldName, getParentName, convertRulesToOptions, getNestedOptionValue } from './utils'; -import { extend } from '../utils/extend'; +import { OptionManager } from '@js/core/options/option_manager'; +import { + convertRulesToOptions, getFieldName, getNestedOptionValue, getParentName, +} from '@js/core/options/utils'; +import { equalByValue, noop } from '@js/core/utils/common'; +import { getPathParts } from '@js/core/utils/data'; +import { extend } from '@js/core/utils/extend'; +import { isFunction, isObject, type } from '@js/core/utils/type'; export class Options { - constructor(options, defaultOptions, optionsByReference, deprecatedOptions) { - this._deprecatedCallback; - this._startChangeCallback; - this._endChangeCallback; - this._validateOptionsCallback; - - this._default = defaultOptions; - this._deprecated = deprecatedOptions; - - this._deprecatedNames = []; - this._initDeprecatedNames(); - - this._optionManager = new OptionManager( - options, - optionsByReference - ); - this._optionManager.onRelevantNamesPrepared((options, name, value, silent) => this._setRelevantNames(options, name, value, silent)); - this._cachedOptions = {}; - - this._rules = []; - } + _deprecatedCallback: any; - set _initial(value) { - this._initialOptions = value; - } + _startChangeCallback: any; - get _initial() { - if(!this._initialOptions) { - const rulesOptions = this._getByRules(this.silent('defaultOptionsRules')); + _endChangeCallback: any; - this._initialOptions = this._default; - this._optionManager._setByReference(this._initialOptions, rulesOptions); - } + _validateOptionsCallback: any; - return this._initialOptions; - } + _default: any; - _initDeprecatedNames() { - for(const optionName in this._deprecated) { - this._deprecatedNames.push(optionName); - } - } + _deprecated: any; - _getByRules(rules) { - rules = Array.isArray(rules) ? this._rules.concat(rules) : this._rules; + _deprecatedNames: any[]; - return convertRulesToOptions(rules); - } + _optionManager: OptionManager; - _notifyDeprecated(option) { - const info = this._deprecated[option]; + _cachedOptions: Record; - if(info) { - this._deprecatedCallback(option, info); - } + _rules: any[]; + + _initialOptions: any; + + constructor(options, defaultOptions, optionsByReference, deprecatedOptions) { + this._deprecatedCallback; + this._startChangeCallback; + this._endChangeCallback; + this._validateOptionsCallback; + + this._default = defaultOptions; + this._deprecated = deprecatedOptions; + + this._deprecatedNames = []; + this._initDeprecatedNames(); + + this._optionManager = new OptionManager( + options, + optionsByReference, + ); + this._optionManager.onRelevantNamesPrepared((options, name, value, silent) => this._setRelevantNames(options, name, value, silent)); + this._cachedOptions = {}; + + this._rules = []; + } + + set _initial(value) { + this._initialOptions = value; + } + + get _initial() { + if (!this._initialOptions) { + const rulesOptions = this._getByRules(this.silent('defaultOptionsRules')); + + this._initialOptions = this._default; + this._optionManager._setByReference(this._initialOptions, rulesOptions); } - _setRelevantNames(options, name, value, silent) { - if(name) { - const normalizedName = this._normalizeName(name, silent); + return this._initialOptions; + } - if(normalizedName && normalizedName !== name) { - this._setField(options, normalizedName, value); - this._clearField(options, name); - } - } + _initDeprecatedNames() { + for (const optionName in this._deprecated) { + this._deprecatedNames.push(optionName); } + } + + _getByRules(rules) { + rules = Array.isArray(rules) ? this._rules.concat(rules) : this._rules; + + return convertRulesToOptions(rules); + } + + _notifyDeprecated(option) { + const info = this._deprecated[option]; - _setField(options, fullName, value) { - let fieldName = ''; - let fieldObject = null; + if (info) { + this._deprecatedCallback(option, info); + } + } - do { - fieldName = fieldName ? `.${fieldName}` : ''; - fieldName = getFieldName(fullName) + fieldName; - fullName = getParentName(fullName); - fieldObject = fullName ? this._optionManager.get(options, fullName, false) : options; - } while(!fieldObject); + _setRelevantNames(options, name, value, silent) { + if (name) { + const normalizedName = this._normalizeName(name, silent); - fieldObject[fieldName] = value; + if (normalizedName && normalizedName !== name) { + this._setField(options, normalizedName, value); + this._clearField(options, name); + } + } + } + + _setField(options, fullName, value) { + let fieldName = ''; + let fieldObject: any = null; + + do { + fieldName = fieldName ? `.${fieldName}` : ''; + fieldName = getFieldName(fullName) + fieldName; + fullName = getParentName(fullName); + fieldObject = fullName ? this._optionManager.get(options, fullName, false) : options; + } while (!fieldObject); + + fieldObject[fieldName] = value; + } + + _clearField(options, name) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete options[name]; + + const previousFieldName = getParentName(name); + const fieldObject = previousFieldName + ? this._optionManager.get(options, previousFieldName, false) + : options; + + if (fieldObject) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete fieldObject[getFieldName(name)]; } + } - _clearField(options, name) { - delete options[name]; + _normalizeName(name, silent?: boolean) { + if (this._deprecatedNames.length && name) { + for (let i = 0; i < this._deprecatedNames.length; i++) { + if (this._deprecatedNames[i] === name) { + const deprecate = this._deprecated[name]; - const previousFieldName = getParentName(name); - const fieldObject = previousFieldName ? - this._optionManager.get(options, previousFieldName, false) : - options; + if (deprecate) { + !silent && this._notifyDeprecated(name); - if(fieldObject) { - delete fieldObject[getFieldName(name)]; + return deprecate.alias || name; + } } + } } - _normalizeName(name, silent) { - if(this._deprecatedNames.length && name) { - for(let i = 0; i < this._deprecatedNames.length; i++) { - if(this._deprecatedNames[i] === name) { - const deprecate = this._deprecated[name]; + return name; + } - if(deprecate) { - !silent && this._notifyDeprecated(name); + addRules(rules) { + this._rules = rules.concat(this._rules); + } - return deprecate.alias || name; - } - } - } - } + applyRules(rules) { + const options = this._getByRules(rules); - return name; - } + this.silent(options); + } - addRules(rules) { - this._rules = rules.concat(this._rules); - } + dispose() { + this._deprecatedCallback = noop; + this._startChangeCallback = noop; + this._endChangeCallback = noop; + this._optionManager.dispose(); + } - applyRules(rules) { - const options = this._getByRules(rules); + onChanging(callBack) { + this._optionManager.onChanging(callBack); + } - this.silent(options); - } + onChanged(callBack) { + this._optionManager.onChanged(callBack); + } - dispose() { - this._deprecatedCallback = noop; - this._startChangeCallback = noop; - this._endChangeCallback = noop; - this._optionManager.dispose(); - } + validateOptions(callBack) { + this._optionManager.onValidateOptions(callBack); + } - onChanging(callBack) { - this._optionManager.onChanging(callBack); - } + onDeprecated(callBack) { + this._deprecatedCallback = callBack; + } - onChanged(callBack) { - this._optionManager.onChanged(callBack); - } - validateOptions(callBack) { - this._optionManager.onValidateOptions(callBack); - } + onStartChange(callBack) { + this._startChangeCallback = callBack; + } - onDeprecated(callBack) { - this._deprecatedCallback = callBack; - } + onEndChange(callBack) { + this._endChangeCallback = callBack; + } - onStartChange(callBack) { - this._startChangeCallback = callBack; - } + isInitial(name) { + const value = this.silent(name); + const initialValue = this.initial(name); + const areFunctions = isFunction(value) && isFunction(initialValue); - onEndChange(callBack) { - this._endChangeCallback = callBack; - } + return areFunctions + ? value.toString() === initialValue.toString() + : equalByValue(value, initialValue); + } - isInitial(name) { - const value = this.silent(name); - const initialValue = this.initial(name); - const areFunctions = isFunction(value) && isFunction(initialValue); + initial(name): any { + return getNestedOptionValue(this._initial, name); + } - return areFunctions ? - value.toString() === initialValue.toString() : - equalByValue(value, initialValue); - } + option(options, value) { + const isGetter = arguments.length < 2 && type(options) !== 'object'; - initial(name) { - return getNestedOptionValue(this._initial, name); + if (isGetter) { + return this._optionManager.get(undefined, this._normalizeName(options)); } - - option(options, value) { - const isGetter = arguments.length < 2 && type(options) !== 'object'; - - if(isGetter) { - return this._optionManager.get(undefined, this._normalizeName(options)); - } else { - this._startChangeCallback(); - try { - this._optionManager.set(options, value); - } finally { - this._endChangeCallback(); - } - } + this._startChangeCallback(); + try { + this._optionManager.set(options, value); + } finally { + this._endChangeCallback(); } + } - silent(options, value) { - const isGetter = arguments.length < 2 && type(options) !== 'object'; + silent(options, value?: unknown) { + const isGetter = arguments.length < 2 && type(options) !== 'object'; - if(isGetter) { - return this._optionManager.get(undefined, options, undefined, true); - } else { - this._optionManager.set(options, value, undefined, true); - } + if (isGetter) { + // @ts-expect-error more args than needed + return this._optionManager.get(undefined, options, undefined, true); } + this._optionManager.set(options, value, undefined, true); + } - reset(name) { - if(name) { - const fullPath = getPathParts(name); - const value = fullPath.reduce( - (value, field) => value ? value[field] : this.initial(field), null - ); + reset(name) { + if (name) { + const fullPath = getPathParts(name); + const value = fullPath.reduce((value: any, field) => (value ? value[field] : this.initial(field)), null); - const defaultValue = isObject(value) ? { ...value } : value; + const defaultValue = isObject(value) ? { ...value } : value; - this._optionManager.set(name, defaultValue, false); - } + this._optionManager.set(name, defaultValue, false); } + } - getAliasesByName(name) { - return Object.keys(this._deprecated).filter( - aliasName => name === this._deprecated[aliasName].alias - ); - } + getAliasesByName(name) { + return Object.keys(this._deprecated).filter( + (aliasName) => name === this._deprecated[aliasName].alias, + ); + } - isDeprecated(name) { - return Object.prototype.hasOwnProperty.call(this._deprecated, name); - } + isDeprecated(name) { + return Object.prototype.hasOwnProperty.call(this._deprecated, name); + } - cache(name, options) { - const isGetter = arguments.length < 2; + cache(name, options) { + const isGetter = arguments.length < 2; - if(isGetter) { - return this._cachedOptions[name]; - } else { - this._cachedOptions[name] = extend(this._cachedOptions[name], options); - } + if (isGetter) { + return this._cachedOptions[name]; } + this._cachedOptions[name] = extend(this._cachedOptions[name], options); + } } diff --git a/packages/devextreme/js/__internal/core/options/m_option_manager.ts b/packages/devextreme/js/__internal/core/options/m_option_manager.ts index 69c5f1b297b9..76007ada960d 100644 --- a/packages/devextreme/js/__internal/core/options/m_option_manager.ts +++ b/packages/devextreme/js/__internal/core/options/m_option_manager.ts @@ -1,101 +1,116 @@ -import { compileGetter, compileSetter, getPathParts } from '../utils/data'; -import { noop } from '../utils/common'; -import { equals } from '../utils/comparator'; -import { extend } from '../utils/extend'; -import { isDefined, isPlainObject } from '../utils/type'; -import { normalizeOptions } from './utils'; +/* eslint-disable guard-for-in */ +/* eslint-disable no-restricted-syntax */ +import { normalizeOptions } from '@js/core/options/utils'; +import { noop } from '@js/core/utils/common'; +import { equals } from '@js/core/utils/comparator'; +import { compileGetter, compileSetter, getPathParts } from '@js/core/utils/data'; +import { extend } from '@js/core/utils/extend'; +import { isDefined, isPlainObject } from '@js/core/utils/type'; const cachedGetters = {}; const cachedSetters = {}; export class OptionManager { - constructor(options, optionsByReference) { - this._options = options; - this._optionsByReference = optionsByReference; - - this._changingCallback; - this._changedCallback; - this._namePreparedCallbacks; - this._validateOptionsCallback; - } + _options: any; - _setByReference(options, rulesOptions) { - extend(true, options, rulesOptions); + _optionsByReference: any; - for(const fieldName in this._optionsByReference) { - if(Object.prototype.hasOwnProperty.call(rulesOptions, fieldName)) { - options[fieldName] = rulesOptions[fieldName]; - } - } - } + _changingCallback: any; - _setPreparedValue(name, value, merge, silent) { - const previousValue = this.get(this._options, name, false); - - if(!equals(previousValue, value)) { - const path = getPathParts(name); - - !silent && this._changingCallback(name, previousValue, value); - cachedSetters[name] = cachedSetters[name] || compileSetter(name); - cachedSetters[name](this._options, value, { - functionsAsIs: true, - merge: isDefined(merge) ? merge : !this._optionsByReference[name], - unwrapObservables: path.length > 1 && !!this._optionsByReference[path[0]] - }); - !silent && this._changedCallback(name, value, previousValue); - } - } + _changedCallback: any; - _prepareRelevantNames(options, name, value, silent) { - if(isPlainObject(value)) { - for(const valueName in value) { - this._prepareRelevantNames(options, `${name}.${valueName}`, value[valueName]); - } - } + _namePreparedCallbacks: any; - this._namePreparedCallbacks(options, name, value, silent); - } + _validateOptionsCallback: any; - get(options = this._options, name, unwrapObservables) { - cachedGetters[name] = cachedGetters[name] || compileGetter(name); + constructor(options, optionsByReference) { + this._options = options; + this._optionsByReference = optionsByReference; - return cachedGetters[name](options, { functionsAsIs: true, unwrapObservables }); + this._changingCallback; + this._changedCallback; + this._namePreparedCallbacks; + this._validateOptionsCallback; + } + + _setByReference(options, rulesOptions) { + extend(true, options, rulesOptions); + + for (const fieldName in this._optionsByReference) { + if (Object.prototype.hasOwnProperty.call(rulesOptions, fieldName)) { + options[fieldName] = rulesOptions[fieldName]; + } } + } + + _setPreparedValue(name, value, merge?: any, silent?: boolean) { + const previousValue = this.get(this._options, name, false); + + if (!equals(previousValue, value)) { + const path = getPathParts(name); + + !silent && this._changingCallback(name, previousValue, value); + cachedSetters[name] = cachedSetters[name] || compileSetter(name); + cachedSetters[name](this._options, value, { + functionsAsIs: true, + merge: isDefined(merge) ? merge : !this._optionsByReference[name], + unwrapObservables: path.length > 1 && !!this._optionsByReference[path[0]], + }); + !silent && this._changedCallback(name, value, previousValue); + } + } - set(options, value, merge, silent) { - options = normalizeOptions(options, value); + _prepareRelevantNames(options, name, value, silent?: boolean) { + if (isPlainObject(value)) { + for (const valueName in value) { + this._prepareRelevantNames(options, `${name}.${valueName}`, value[valueName]); + } + } - for(const name in options) { - this._prepareRelevantNames(options, name, options[name], silent); - } + this._namePreparedCallbacks(options, name, value, silent); + } - if(this._validateOptionsCallback) { - options = this._validateOptionsCallback(options); - } + // eslint-disable-next-line @typescript-eslint/default-param-last + get(options = this._options, name, unwrapObservables?: boolean) { + cachedGetters[name] = cachedGetters[name] || compileGetter(name); - for(const name in options) { - this._setPreparedValue(name, options[name], merge, silent); - } - } + return cachedGetters[name](options, { functionsAsIs: true, unwrapObservables }); + } - onRelevantNamesPrepared(callBack) { - this._namePreparedCallbacks = callBack; - } + set(options, value, merge?: any, silent?: boolean) { + options = normalizeOptions(options, value); - onChanging(callBack) { - this._changingCallback = callBack; + for (const name in options) { + this._prepareRelevantNames(options, name, options[name], silent); } - onChanged(callBack) { - this._changedCallback = callBack; + if (this._validateOptionsCallback) { + options = this._validateOptionsCallback(options); } - onValidateOptions(callback) { - this._validateOptionsCallback = callback; + for (const name in options) { + this._setPreparedValue(name, options[name], merge, silent); } + } - dispose() { - this._changingCallback = noop; - this._changedCallback = noop; - } + onRelevantNamesPrepared(callBack) { + this._namePreparedCallbacks = callBack; + } + + onChanging(callBack) { + this._changingCallback = callBack; + } + + onChanged(callBack) { + this._changedCallback = callBack; + } + + onValidateOptions(callback) { + this._validateOptionsCallback = callback; + } + + dispose() { + this._changingCallback = noop; + this._changedCallback = noop; + } } diff --git a/packages/devextreme/js/__internal/core/options/m_utils.ts b/packages/devextreme/js/__internal/core/options/m_utils.ts index 08be167a4175..59f2bd821c7c 100644 --- a/packages/devextreme/js/__internal/core/options/m_utils.ts +++ b/packages/devextreme/js/__internal/core/options/m_utils.ts @@ -1,39 +1,37 @@ -import devices from '../devices'; -import { isEmptyObject, isFunction } from '../utils/type'; -import { findBestMatches } from '../utils/common'; -import { extend } from '../utils/extend'; -import { compileGetter } from '../utils/data'; +import devices from '@js/core/devices'; +import { findBestMatches } from '@js/core/utils/common'; +import { compileGetter } from '@js/core/utils/data'; +import { extend } from '@js/core/utils/extend'; +import { isEmptyObject, isFunction } from '@js/core/utils/type'; const cachedGetters = {}; export const convertRulesToOptions = (rules) => { - const currentDevice = devices.current(); - return rules.reduce((options, { device, options: ruleOptions }) => { - const deviceFilter = device || {}; - const match = isFunction(deviceFilter) ? - deviceFilter(currentDevice) : - deviceMatch(currentDevice, deviceFilter); - - if(match) { - extend(true, options, ruleOptions); - } - return options; - }, {}); + const currentDevice = devices.current(); + return rules.reduce((options, { device, options: ruleOptions }) => { + const deviceFilter = device || {}; + const match = isFunction(deviceFilter) + ? deviceFilter(currentDevice) + : deviceMatch(currentDevice, deviceFilter); + + if (match) { + extend(true, options, ruleOptions); + } + return options; + }, {}); }; -export const normalizeOptions = (options, value) => { - return typeof options !== 'string' ? options : { [options]: value }; -}; +export const normalizeOptions = (options, value) => (typeof options !== 'string' ? options : { [options]: value }); export const deviceMatch = (device, filter) => isEmptyObject(filter) || findBestMatches(device, [filter]).length > 0; -export const getFieldName = fullName => fullName.substr(fullName.lastIndexOf('.') + 1); +export const getFieldName = (fullName) => fullName.substr(fullName.lastIndexOf('.') + 1); -export const getParentName = fullName => fullName.substr(0, fullName.lastIndexOf('.')); +export const getParentName = (fullName) => fullName.substr(0, fullName.lastIndexOf('.')); -export const getNestedOptionValue = function(optionsObject, name) { - cachedGetters[name] = cachedGetters[name] || compileGetter(name); - return cachedGetters[name](optionsObject, { functionsAsIs: true }); +export const getNestedOptionValue = function (optionsObject, name) { + cachedGetters[name] = cachedGetters[name] || compileGetter(name); + return cachedGetters[name](optionsObject, { functionsAsIs: true }); }; export const createDefaultOptionRules = (options = []) => options; diff --git a/packages/devextreme/js/__internal/core/templates/m_bindable_template.ts b/packages/devextreme/js/__internal/core/templates/m_bindable_template.ts index f666ae2d1130..b3239ee92178 100644 --- a/packages/devextreme/js/__internal/core/templates/m_bindable_template.ts +++ b/packages/devextreme/js/__internal/core/templates/m_bindable_template.ts @@ -1,83 +1,91 @@ -import $ from '../renderer'; -import { TemplateBase } from './template_base'; -import eventsEngine from '../../events/core/events_engine'; -import { removeEvent } from '../../events/remove'; -import { isPrimitive } from '../utils/type'; - -const watchChanges = (function() { - const globalWatch = (data, watchMethod, callback) => watchMethod(() => data, callback); - - const fieldsWatch = function(data, watchMethod, fields, fieldsMap, callback) { - const resolvedData = {}; - const missedFields = fields.slice(); - - const watchHandlers = fields.map(function(name) { - const fieldGetter = fieldsMap[name]; - - return watchMethod( - fieldGetter ? () => fieldGetter(data) : () => data[name], - function(value) { - resolvedData[name] = value; - - if(missedFields.length) { - const index = missedFields.indexOf(name); - if(index >= 0) { - missedFields.splice(index, 1); - } - } - - if(!missedFields.length) { - callback(resolvedData); - } - } - ); - }); - - return function() { - watchHandlers.forEach(dispose => dispose()); - }; +import $ from '@js/core/renderer'; +import { TemplateBase } from '@js/core/templates/template_base'; +import { isPrimitive } from '@js/core/utils/type'; +import eventsEngine from '@js/events/core/events_engine'; +import { removeEvent } from '@js/events/remove'; + +const watchChanges = (function () { + const globalWatch = (data, watchMethod, callback) => watchMethod(() => data, callback); + + const fieldsWatch = function (data, watchMethod, fields, fieldsMap, callback) { + const resolvedData = {}; + const missedFields = fields.slice(); + + const watchHandlers = fields.map((name) => { + const fieldGetter = fieldsMap[name]; + + return watchMethod( + fieldGetter ? () => fieldGetter(data) : () => data[name], + (value) => { + resolvedData[name] = value; + + if (missedFields.length) { + const index = missedFields.indexOf(name); + if (index >= 0) { + missedFields.splice(index, 1); + } + } + + if (!missedFields.length) { + callback(resolvedData); + } + }, + ); + }); + + return function () { + watchHandlers.forEach((dispose) => dispose()); }; + }; - return function(rawData, watchMethod, fields, fieldsMap, callback) { - let fieldsDispose; + return function (rawData, watchMethod, fields, fieldsMap, callback) { + let fieldsDispose; - const globalDispose = globalWatch(rawData, watchMethod, function(dataWithRawFields) { - fieldsDispose && fieldsDispose(); + const globalDispose = globalWatch(rawData, watchMethod, (dataWithRawFields) => { + fieldsDispose && fieldsDispose(); - if(isPrimitive(dataWithRawFields)) { - callback(dataWithRawFields); - return; - } + if (isPrimitive(dataWithRawFields)) { + callback(dataWithRawFields); + return; + } - fieldsDispose = fieldsWatch(dataWithRawFields, watchMethod, fields, fieldsMap, callback); - }); + fieldsDispose = fieldsWatch(dataWithRawFields, watchMethod, fields, fieldsMap, callback); + }); - return function() { - fieldsDispose && fieldsDispose(); - globalDispose && globalDispose(); - }; + return function () { + fieldsDispose && fieldsDispose(); + globalDispose && globalDispose(); }; - -})(); + }; +}()); export class BindableTemplate extends TemplateBase { - constructor(render, fields, watchMethod, fieldsMap) { - super(); - this._render = render; - this._fields = fields; - this._fieldsMap = fieldsMap || {}; - this._watchMethod = watchMethod; - } - - _renderCore(options) { - const $container = $(options.container); - - const dispose = watchChanges(options.model, this._watchMethod, this._fields, this._fieldsMap, data => { - $container.empty(); - this._render($container, data, options.model); - }); - eventsEngine.on($container, removeEvent, dispose); - - return $container.contents(); - } + _render: any; + + _fields: any; + + _fieldsMap: any; + + _watchMethod: any; + + constructor(render, fields, watchMethod, fieldsMap?) { + super(); + this._render = render; + this._fields = fields; + this._fieldsMap = fieldsMap || {}; + this._watchMethod = watchMethod; + } + + // @ts-expect-error renderCore differs from baseTemplate + _renderCore(options) { + const $container = $(options.container); + + const dispose = watchChanges(options.model, this._watchMethod, this._fields, this._fieldsMap, (data) => { + $container.empty(); + this._render($container, data, options.model); + }); + eventsEngine.on($container, removeEvent, dispose); + + return $container.contents(); + } } diff --git a/packages/devextreme/js/__internal/core/templates/m_child_default_template.ts b/packages/devextreme/js/__internal/core/templates/m_child_default_template.ts index 6a3d558302db..79a5a08c800c 100644 --- a/packages/devextreme/js/__internal/core/templates/m_child_default_template.ts +++ b/packages/devextreme/js/__internal/core/templates/m_child_default_template.ts @@ -1,8 +1,10 @@ -import { TemplateBase } from './template_base'; +import { TemplateBase } from '@js/core/templates/template_base'; export class ChildDefaultTemplate extends TemplateBase { - constructor(name) { - super(); - this.name = name; - } + name: any; + + constructor(name) { + super(); + this.name = name; + } } diff --git a/packages/devextreme/js/__internal/core/templates/m_empty_template.ts b/packages/devextreme/js/__internal/core/templates/m_empty_template.ts index 99c27225ae7d..324cd5e7854a 100644 --- a/packages/devextreme/js/__internal/core/templates/m_empty_template.ts +++ b/packages/devextreme/js/__internal/core/templates/m_empty_template.ts @@ -1,8 +1,8 @@ -import $ from '../renderer'; -import { TemplateBase } from './template_base'; +import $ from '@js/core/renderer'; +import { TemplateBase } from '@js/core/templates/template_base'; export class EmptyTemplate extends TemplateBase { - _renderCore() { - return $(); - } + _renderCore() { + return $(); + } } diff --git a/packages/devextreme/js/__internal/core/templates/m_function_template.ts b/packages/devextreme/js/__internal/core/templates/m_function_template.ts index 6a59e3e3704a..6825ba76287f 100644 --- a/packages/devextreme/js/__internal/core/templates/m_function_template.ts +++ b/packages/devextreme/js/__internal/core/templates/m_function_template.ts @@ -1,13 +1,16 @@ -import { TemplateBase } from './template_base'; -import { normalizeTemplateElement } from '../utils/dom'; +import { TemplateBase } from '@js/core/templates/template_base'; +import { normalizeTemplateElement } from '@js/core/utils/dom'; export class FunctionTemplate extends TemplateBase { - constructor(render) { - super(); - this._render = render; - } + _render: any; - _renderCore(options) { - return normalizeTemplateElement(this._render(options)); - } + constructor(render) { + super(); + this._render = render; + } + + // @ts-expect-error need type overload + _renderCore(options) { + return normalizeTemplateElement(this._render(options)); + } } diff --git a/packages/devextreme/js/__internal/core/templates/m_template.ts b/packages/devextreme/js/__internal/core/templates/m_template.ts index 68ec8c895638..95cfac5e4aa5 100644 --- a/packages/devextreme/js/__internal/core/templates/m_template.ts +++ b/packages/devextreme/js/__internal/core/templates/m_template.ts @@ -1,33 +1,37 @@ -import $ from '../renderer'; -import { TemplateBase } from './template_base'; -import { normalizeTemplateElement } from '../utils/dom'; -import { getCurrentTemplateEngine, registerTemplateEngine, setTemplateEngine } from './template_engine_registry'; +import $ from '@js/core/renderer'; +import { TemplateBase } from '@js/core/templates/template_base'; +import { getCurrentTemplateEngine, registerTemplateEngine, setTemplateEngine } from '@js/core/templates/template_engine_registry'; +import { normalizeTemplateElement } from '@js/core/utils/dom'; registerTemplateEngine('default', { - compile: (element) => normalizeTemplateElement(element), - render: (template, model, index) => template.clone() + compile: (element) => normalizeTemplateElement(element), + // eslint-disable-next-line @typescript-eslint/no-unused-vars + render: (template, model, index) => template.clone(), }); setTemplateEngine('default'); export class Template extends TemplateBase { - constructor(element) { - super(); - this._element = element; - } + _compiledTemplate: any; - _renderCore(options) { - const transclude = options.transclude; - if(!transclude && !this._compiledTemplate) { - this._compiledTemplate = getCurrentTemplateEngine().compile(this._element); - } + constructor(element) { + super(); + this._element = element; + } - return $('
').append( - transclude ? this._element : getCurrentTemplateEngine().render(this._compiledTemplate, options.model, options.index) - ).contents(); + // @ts-expect-error need type overload + _renderCore(options) { + const { transclude } = options; + if (!transclude && !this._compiledTemplate) { + this._compiledTemplate = getCurrentTemplateEngine().compile(this._element); } - source() { - return $(this._element).clone(); - } + return $('
').append( + transclude ? this._element : getCurrentTemplateEngine().render(this._compiledTemplate, options.model, options.index), + ).contents(); + } + + source() { + return $(this._element).clone(); + } } diff --git a/packages/devextreme/js/__internal/core/templates/m_template_base.ts b/packages/devextreme/js/__internal/core/templates/m_template_base.ts index e4d2ab378e90..e3f84627b56e 100644 --- a/packages/devextreme/js/__internal/core/templates/m_template_base.ts +++ b/packages/devextreme/js/__internal/core/templates/m_template_base.ts @@ -1,54 +1,57 @@ -import $ from '../renderer'; -import domAdapter from '../dom_adapter'; -import Callbacks from '../utils/callbacks'; -import { contains } from '../utils/dom'; -import { triggerShownEvent } from '../../events/visibility_change'; -import errors from '../errors'; +import domAdapter from '@js/core/dom_adapter'; +import errors from '@js/core/errors'; +import $ from '@js/core/renderer'; +import Callbacks from '@js/core/utils/callbacks'; +import { contains } from '@js/core/utils/dom'; +import { triggerShownEvent } from '@js/events/visibility_change'; export const renderedCallbacks = Callbacks({ syncStrategy: true }); export class TemplateBase { - render(options) { - options = options || {}; + _element: any; - const onRendered = options.onRendered; - delete options.onRendered; + render(options) { + options = options || {}; - let $result; - if(options.renovated && options.transclude && this._element) { - $result = $('
').append(this._element).contents(); - } else { - $result = this._renderCore(options); - } + const { onRendered } = options; + delete options.onRendered; - this._ensureResultInContainer($result, options.container); - renderedCallbacks.fire($result, options.container); - - onRendered && onRendered(); - return $result; + let $result; + if (options.renovated && options.transclude && this._element) { + $result = $('
').append(this._element).contents(); + } else { + // @ts-expect-error need type overload + $result = this._renderCore(options); } - _ensureResultInContainer($result, container) { - if(!container) { - return; - } + this._ensureResultInContainer($result, options.container); + renderedCallbacks.fire($result, options.container); - const $container = $(container); - const resultInContainer = contains($container.get(0), $result.get(0)); - $container.append($result); - if(resultInContainer) { - return; - } + onRendered && onRendered(); + return $result; + } - const resultInBody = contains(domAdapter.getBody(), $container.get(0)); - if(!resultInBody) { - return; - } + _ensureResultInContainer($result, container) { + if (!container) { + return; + } - triggerShownEvent($result); + const $container = $(container); + const resultInContainer = contains($container.get(0), $result.get(0)); + $container.append($result); + if (resultInContainer) { + return; } - _renderCore() { - throw errors.Error('E0001'); + const resultInBody = contains(domAdapter.getBody(), $container.get(0)); + if (!resultInBody) { + return; } + + triggerShownEvent($result); + } + + _renderCore() { + throw errors.Error('E0001'); + } } diff --git a/packages/devextreme/js/__internal/core/templates/m_template_engine_registry.ts b/packages/devextreme/js/__internal/core/templates/m_template_engine_registry.ts index 9fb63dcafcf4..1500c021436e 100644 --- a/packages/devextreme/js/__internal/core/templates/m_template_engine_registry.ts +++ b/packages/devextreme/js/__internal/core/templates/m_template_engine_registry.ts @@ -1,23 +1,22 @@ -import { isString } from '../utils/type'; -import errors from '../errors'; +import errors from '@js/core/errors'; +import { isString } from '@js/core/utils/type'; const templateEngines = {}; let currentTemplateEngine; export function registerTemplateEngine(name, templateEngine) { - templateEngines[name] = templateEngine; + templateEngines[name] = templateEngine; } - export function setTemplateEngine(templateEngine) { - if(isString(templateEngine)) { - currentTemplateEngine = templateEngines[templateEngine]; - if(!currentTemplateEngine) { - throw errors.Error('E0020', templateEngine); - } - } else { - currentTemplateEngine = templateEngine; + if (isString(templateEngine)) { + currentTemplateEngine = templateEngines[templateEngine]; + if (!currentTemplateEngine) { + throw errors.Error('E0020', templateEngine); } + } else { + currentTemplateEngine = templateEngine; + } } export function getCurrentTemplateEngine() { return currentTemplateEngine; } diff --git a/packages/devextreme/js/__internal/core/utils/m_ajax.ts b/packages/devextreme/js/__internal/core/utils/m_ajax.ts index 3db05f2e8110..6e9d9deca4d7 100644 --- a/packages/devextreme/js/__internal/core/utils/m_ajax.ts +++ b/packages/devextreme/js/__internal/core/utils/m_ajax.ts @@ -1,18 +1,19 @@ -import { Deferred } from './deferred'; -import httpRequest from '../../core/http_request'; -import { getWindow } from '../../core/utils/window'; -const window = getWindow(); -import { isDefined } from './type'; -import injector from './dependency_injector'; +import httpRequest from '@js/core/http_request'; import { - isCrossDomain, - getJsonpCallbackName as getJsonpOptions, - getRequestHeaders, - getRequestOptions, - evalScript, - evalCrossDomainScript, - getMethod, -} from './ajax_utils'; + evalCrossDomainScript, + evalScript, + getJsonpCallbackName as getJsonpOptions, + getMethod, + getRequestHeaders, + getRequestOptions, + isCrossDomain, +} from '@js/core/utils/ajax_utils'; +import { Deferred } from '@js/core/utils/deferred'; +import injector from '@js/core/utils/dependency_injector'; +import { isDefined } from '@js/core/utils/type'; +import { getWindow } from '@js/core/utils/window'; + +const window = getWindow(); const SUCCESS = 'success'; const ERROR = 'error'; @@ -20,160 +21,164 @@ const TIMEOUT = 'timeout'; const NO_CONTENT = 'nocontent'; const PARSER_ERROR = 'parsererror'; -const isStatusSuccess = function(status) { - return 200 <= status && status < 300; +const isStatusSuccess = function (status) { + return status >= 200 && status < 300; }; -const hasContent = function(status) { - return status !== 204; +const hasContent = function (status) { + return status !== 204; }; -const getDataFromResponse = function(xhr) { - return xhr.responseType && xhr.responseType !== 'text' || typeof xhr.responseText !== 'string' - ? xhr.response - : xhr.responseText; +const getDataFromResponse = function (xhr) { + return xhr.responseType && xhr.responseType !== 'text' || typeof xhr.responseText !== 'string' + ? xhr.response + : xhr.responseText; }; -const postProcess = function(deferred, xhr, dataType) { - - const data = getDataFromResponse(xhr); - - switch(dataType) { - case 'jsonp': - evalScript(data); - break; - - case 'script': - evalScript(data); - deferred.resolve(data, SUCCESS, xhr); - break; - - case 'json': - try { - deferred.resolve(JSON.parse(data), SUCCESS, xhr); - } catch(e) { - deferred.reject(xhr, PARSER_ERROR, e); - } - break; - - default: - deferred.resolve(data, SUCCESS, xhr); - } +const postProcess = function (deferred, xhr, dataType) { + const data = getDataFromResponse(xhr); + + switch (dataType) { + case 'jsonp': + evalScript(data); + break; + + case 'script': + evalScript(data); + deferred.resolve(data, SUCCESS, xhr); + break; + + case 'json': + try { + deferred.resolve(JSON.parse(data), SUCCESS, xhr); + } catch (e) { + deferred.reject(xhr, PARSER_ERROR, e); + } + break; + + default: + deferred.resolve(data, SUCCESS, xhr); + } }; -const setHttpTimeout = function(timeout, xhr) { - return timeout && setTimeout(function() { - xhr.customStatus = TIMEOUT; - xhr.abort(); - }, timeout); +const setHttpTimeout = function (timeout, xhr) { + return timeout && setTimeout(function () { + xhr.customStatus = TIMEOUT; + xhr.abort(); + }, timeout); }; -const sendRequest = function(options) { - const xhr = httpRequest.getXhr(); - const d = new Deferred(); - const result = d.promise(); - const async = isDefined(options.async) ? options.async : true; - const dataType = options.dataType; - const timeout = options.timeout || 0; - let timeoutId; - - options.crossDomain = isCrossDomain(options.url); - const needScriptEvaluation = dataType === 'jsonp' || dataType === 'script'; - - if(options.cache === undefined) { - options.cache = !needScriptEvaluation; - } - - const callbackName = getJsonpOptions(options); - const headers = getRequestHeaders(options); - const requestOptions = getRequestOptions(options, headers); - const url = requestOptions.url; - const parameters = requestOptions.parameters; - - if(callbackName) { - window[callbackName] = function(data) { - d.resolve(data, SUCCESS, xhr); - }; - } - - if(options.crossDomain && needScriptEvaluation) { - const reject = function() { - d.reject(xhr, ERROR); - }; - const resolve = function() { - if(dataType === 'jsonp') return; - d.resolve(null, SUCCESS, xhr); - }; - - evalCrossDomainScript(url).then(resolve, reject); - return result; - } - - if(options.crossDomain && !('withCredentials' in xhr)) { - d.reject(xhr, ERROR); - return result; - } - - xhr.open( - getMethod(options), - url, - async, - options.username, - options.password); - - if(async) { - xhr.timeout = timeout; - timeoutId = setHttpTimeout(timeout, xhr); - } +const sendRequest = function (options) { + const xhr = httpRequest.getXhr(); + // @ts-expect-error only void function can be called with new + const d = new Deferred(); + const result = d.promise(); + const async = isDefined(options.async) ? options.async : true; + const { dataType } = options; + const timeout = options.timeout || 0; + let timeoutId; + + options.crossDomain = isCrossDomain(options.url); + const needScriptEvaluation = dataType === 'jsonp' || dataType === 'script'; + + if (options.cache === undefined) { + options.cache = !needScriptEvaluation; + } + + const callbackName = getJsonpOptions(options); + const headers = getRequestHeaders(options); + const requestOptions = getRequestOptions(options, headers); + const { url } = requestOptions; + const { parameters } = requestOptions; + + if (callbackName) { + // @ts-expect-error window[callback] is window type + window[callbackName] = function (data) { + d.resolve(data, SUCCESS, xhr); + }; + } - xhr['onreadystatechange'] = function(e) { - if(xhr.readyState === 4) { - clearTimeout(timeoutId); - if(isStatusSuccess(xhr.status)) { - if(hasContent(xhr.status)) { - postProcess(d, xhr, dataType); - } else { - d.resolve(null, NO_CONTENT, xhr); - } - } else { - d.reject(xhr, xhr.customStatus || ERROR); - } - } + if (options.crossDomain && needScriptEvaluation) { + const reject = function () { + d.reject(xhr, ERROR); + }; + const resolve = function () { + if (dataType === 'jsonp') return; + d.resolve(null, SUCCESS, xhr); }; - if(options.upload) { - xhr.upload['onprogress'] = options.upload['onprogress']; - xhr.upload['onloadstart'] = options.upload['onloadstart']; - xhr.upload['onabort'] = options.upload['onabort']; - } + evalCrossDomainScript(url).then(resolve, reject); + return result; + } - if(options.xhrFields) { - for(const field in options.xhrFields) { - xhr[field] = options.xhrFields[field]; + if (options.crossDomain && !('withCredentials' in xhr)) { + d.reject(xhr, ERROR); + return result; + } + + xhr.open( + getMethod(options), + url, + async, + options.username, + options.password, + ); + + if (async) { + xhr.timeout = timeout; + timeoutId = setHttpTimeout(timeout, xhr); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + xhr.onreadystatechange = function (e) { + if (xhr.readyState === 4) { + clearTimeout(timeoutId); + if (isStatusSuccess(xhr.status)) { + if (hasContent(xhr.status)) { + postProcess(d, xhr, dataType); + } else { + d.resolve(null, NO_CONTENT, xhr); } + } else { + d.reject(xhr, xhr.customStatus || ERROR); + } } + }; - if(options.responseType === 'arraybuffer') { - xhr.responseType = options.responseType; - } + if (options.upload) { + xhr.upload.onprogress = options.upload.onprogress; + xhr.upload.onloadstart = options.upload.onloadstart; + xhr.upload.onabort = options.upload.onabort; + } - for(const name in headers) { - if(Object.prototype.hasOwnProperty.call(headers, name) && isDefined(headers[name])) { - xhr.setRequestHeader(name, headers[name]); - } + if (options.xhrFields) { + for (const field in options.xhrFields) { + xhr[field] = options.xhrFields[field]; } + } - if(options.beforeSend) { - options.beforeSend(xhr); + if (options.responseType === 'arraybuffer') { + xhr.responseType = options.responseType; + } + + for (const name in headers) { + if (Object.prototype.hasOwnProperty.call(headers, name) && isDefined(headers[name])) { + xhr.setRequestHeader(name, headers[name]); } + } - xhr.send(parameters); + if (options.beforeSend) { + options.beforeSend(xhr); + } - result.abort = function() { - xhr.abort(); - }; + xhr.send(parameters); - return result; + result.abort = function () { + xhr.abort(); + }; + + return result; }; -export default injector({ sendRequest: sendRequest }); +const Ajax = injector({ sendRequest }); +export { Ajax }; diff --git a/packages/devextreme/js/__internal/core/utils/m_ajax_utils.ts b/packages/devextreme/js/__internal/core/utils/m_ajax_utils.ts index 3d385bb5753c..671d1e7c461e 100644 --- a/packages/devextreme/js/__internal/core/utils/m_ajax_utils.ts +++ b/packages/devextreme/js/__internal/core/utils/m_ajax_utils.ts @@ -1,200 +1,202 @@ -import { extendFromObject } from './extend'; -import { getWindow, hasWindow } from './window'; -import domAdapter from '../dom_adapter'; +/* eslint-disable guard-for-in */ +/* eslint-disable no-restricted-syntax */ +import domAdapter from '@js/core/dom_adapter'; +import { extendFromObject } from '@js/core/utils/extend'; +import { getWindow, hasWindow } from '@js/core/utils/window'; const window = getWindow(); -const createScript = function(options) { - const script = domAdapter.createElement('script'); - for(const name in options) { - script[name] = options[name]; - } - return script; +const createScript = function (options) { + const script = domAdapter.createElement('script'); + for (const name in options) { + script[name] = options[name]; + } + return script; }; -const appendToHead = function(element) { - return domAdapter.getHead().appendChild(element); +const appendToHead = function (element) { + return domAdapter.getHead().appendChild(element); }; -const removeScript = function(scriptNode) { - scriptNode.parentNode.removeChild(scriptNode); +const removeScript = function (scriptNode) { + scriptNode.parentNode.removeChild(scriptNode); }; -const evalScript = function(code) { - const script = createScript({ text: code }); - appendToHead(script); - removeScript(script); +const evalScript = function (code) { + const script = createScript({ text: code }); + appendToHead(script); + removeScript(script); }; -const evalCrossDomainScript = function(url) { - const script = createScript({ src: url }); +const evalCrossDomainScript = function (url) { + const script = createScript({ src: url }); - return new Promise(function(resolve, reject) { - const events = { - 'load': resolve, - 'error': reject - }; + return new Promise((resolve, reject) => { + const events = { + load: resolve, + error: reject, + }; - const loadHandler = function(e) { - events[e.type](); - removeScript(script); - }; + const loadHandler = function (e) { + events[e.type](); + removeScript(script); + }; - for(const event in events) { - domAdapter.listen(script, event, loadHandler); - } + for (const event in events) { + domAdapter.listen(script, event, loadHandler); + } - appendToHead(script); - }); + appendToHead(script); + }); }; function getMethod(options) { - return (options.method || 'GET').toUpperCase(); + return (options.method || 'GET').toUpperCase(); } -const paramsConvert = function(params) { - const result = []; - - for(const name in params) { - let value = params[name]; - - if(value === undefined) { - continue; - } +const paramsConvert = function (params) { + const result: string[] = []; - if(value === null) { - value = ''; - } + for (const name in params) { + let value = params[name]; - if(typeof value === 'function') { - value = value(); - } - - result.push(encodeURIComponent(name) + '=' + encodeURIComponent(value)); + if (value === undefined) { + continue; } - return result.join('&'); -}; + if (value === null) { + value = ''; + } -const getContentTypeHeader = function(options) { - let defaultContentType; - if(options.data && !options.upload && getMethod(options) !== 'GET') { - defaultContentType = 'application/x-www-form-urlencoded;charset=utf-8'; + if (typeof value === 'function') { + value = value(); } - return options.contentType || - defaultContentType; + result.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`); + } + + return result.join('&'); }; -const getAcceptHeader = function(options) { - const dataType = options.dataType || '*'; - const scriptAccept = 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript'; - const accepts = { - '*': '*/*', - text: 'text/plain', - html: 'text/html', - xml: 'application/xml, text/xml', - json: 'application/json, text/javascript', - jsonp: scriptAccept, - script: scriptAccept - }; +const getContentTypeHeader = function (options) { + let defaultContentType; + if (options.data && !options.upload && getMethod(options) !== 'GET') { + defaultContentType = 'application/x-www-form-urlencoded;charset=utf-8'; + } - extendFromObject(accepts, options.accepts, true); + return options.contentType + || defaultContentType; +}; - return accepts[dataType] ? - accepts[dataType] + (dataType !== '*' ? ', */*; q=0.01' : '') : - accepts['*']; +const getAcceptHeader = function (options) { + const dataType = options.dataType || '*'; + const scriptAccept = 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript'; + const accepts = { + '*': '*/*', + text: 'text/plain', + html: 'text/html', + xml: 'application/xml, text/xml', + json: 'application/json, text/javascript', + jsonp: scriptAccept, + script: scriptAccept, + }; + + extendFromObject(accepts, options.accepts, true); + + return accepts[dataType] + ? accepts[dataType] + (dataType !== '*' ? ', */*; q=0.01' : '') + : accepts['*']; }; -const getRequestHeaders = function(options) { - const headers = options.headers || {}; +const getRequestHeaders = function (options) { + const headers = options.headers || {}; - headers['Content-Type'] = headers['Content-Type'] || getContentTypeHeader(options); - headers['Accept'] = headers['Accept'] || getAcceptHeader(options); + headers['Content-Type'] = headers['Content-Type'] || getContentTypeHeader(options); + headers.Accept = headers.Accept || getAcceptHeader(options); - if(!options.crossDomain && !headers['X-Requested-With']) { - headers['X-Requested-With'] = 'XMLHttpRequest'; - } - return headers; + if (!options.crossDomain && !headers['X-Requested-With']) { + headers['X-Requested-With'] = 'XMLHttpRequest'; + } + return headers; }; -const getJsonpOptions = function(options) { - if(options.dataType === 'jsonp') { - const random = Math.random().toString().replace(/\D/g, ''); - const callbackName = options.jsonpCallback || 'dxCallback' + Date.now() + '_' + random; - const callbackParameter = options.jsonp || 'callback'; +const getJsonpOptions = function (options) { + if (options.dataType === 'jsonp') { + const random = Math.random().toString().replace(/\D/g, ''); + const callbackName = options.jsonpCallback || `dxCallback${Date.now()}_${random}`; + const callbackParameter = options.jsonp || 'callback'; - options.data = options.data || {}; - options.data[callbackParameter] = callbackName; + options.data = options.data || {}; + options.data[callbackParameter] = callbackName; - return callbackName; - } + return callbackName; + } }; -const getRequestOptions = function(options, headers) { - let params = options.data; - const paramsAlreadyString = typeof params === 'string'; - let url = options.url || window.location.href; +const getRequestOptions = function (options, headers) { + let params = options.data; + const paramsAlreadyString = typeof params === 'string'; + let url = options.url || window.location.href; + + if (!paramsAlreadyString && !options.cache) { + params = params || {}; + params._ = Date.now(); + } - if(!paramsAlreadyString && !options.cache) { - params = params || {}; - params['_'] = Date.now(); + if (params && !options.upload) { + if (!paramsAlreadyString) { + params = paramsConvert(params); } - if(params && !options.upload) { - if(!paramsAlreadyString) { - params = paramsConvert(params); - } - - if(getMethod(options) === 'GET') { - if(params !== '') { - url += (url.indexOf('?') > -1 ? '&' : '?') + params; - } - params = null; - } else if(headers['Content-Type'] && headers['Content-Type'].indexOf('application/x-www-form-urlencoded') > -1) { - params = params.replace(/%20/g, '+'); - } + if (getMethod(options) === 'GET') { + if (params !== '') { + url += (url.indexOf('?') > -1 ? '&' : '?') + params; + } + params = null; + } else if (headers['Content-Type'] && headers['Content-Type'].indexOf('application/x-www-form-urlencoded') > -1) { + params = params.replace(/%20/g, '+'); } + } - return { - url: url, - parameters: params - }; + return { + url, + parameters: params, + }; }; -const isCrossDomain = function(url) { - if(!hasWindow()) { - return true; - } +const isCrossDomain = function (url) { + if (!hasWindow()) { + return true; + } - let crossDomain = false; - const originAnchor = domAdapter.createElement('a'); - const urlAnchor = domAdapter.createElement('a'); + let crossDomain = false; + const originAnchor = domAdapter.createElement('a') as HTMLAnchorElement; + const urlAnchor = domAdapter.createElement('a') as HTMLAnchorElement; - originAnchor.href = window.location.href; + originAnchor.href = window.location.href; - try { - urlAnchor.href = url; + try { + urlAnchor.href = url; - // NOTE: IE11 - // eslint-disable-next-line no-self-assign - urlAnchor.href = urlAnchor.href; + // NOTE: IE11 + // eslint-disable-next-line no-self-assign + urlAnchor.href = urlAnchor.href; - crossDomain = originAnchor.protocol + '//' + originAnchor.host !== - urlAnchor.protocol + '//' + urlAnchor.host; - } catch(e) { - crossDomain = true; - } - return crossDomain; + crossDomain = `${originAnchor.protocol}//${originAnchor.host}` + !== `${urlAnchor.protocol}//${urlAnchor.host}`; + } catch (e) { + crossDomain = true; + } + return crossDomain; }; export { - isCrossDomain, - getJsonpOptions as getJsonpCallbackName, - getRequestHeaders, - getRequestOptions, - getAcceptHeader, - evalScript, - evalCrossDomainScript, - getMethod, + evalCrossDomainScript, + evalScript, + getAcceptHeader, + getJsonpOptions as getJsonpCallbackName, + getMethod, + getRequestHeaders, + getRequestOptions, + isCrossDomain, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_array.ts b/packages/devextreme/js/__internal/core/utils/m_array.ts index 139bd930937c..5048cdd27d4e 100644 --- a/packages/devextreme/js/__internal/core/utils/m_array.ts +++ b/packages/devextreme/js/__internal/core/utils/m_array.ts @@ -1,101 +1,99 @@ -import { isDefined } from './type'; -import { orderEach } from './object'; -import config from '../config'; +import config from '@js/core/config'; +import { orderEach } from '@js/core/utils/object'; +import { isDefined } from '@js/core/utils/type'; function createOccurrenceMap(array) { - return array.reduce((map, value) => { - const count = (map.get(value) ?? 0) + 1; - map.set(value, count); - return map; - }, new Map()); + return array.reduce((map, value) => { + const count = (map.get(value) ?? 0) + 1; + map.set(value, count); + return map; + }, new Map()); } -export const wrapToArray = function(item) { - return Array.isArray(item) ? item : [item]; +export const wrapToArray = function (item) { + return Array.isArray(item) ? item : [item]; }; -export const getUniqueValues = function(values) { - return [...new Set(values)]; +export const getUniqueValues = function (values) { + return [...new Set(values)]; }; -export const getIntersection = function(firstArray, secondArray) { - const toRemoveMap = createOccurrenceMap(secondArray); - return firstArray.filter(value => { - const occurrencesCount = toRemoveMap.get(value); - occurrencesCount && toRemoveMap.set(value, occurrencesCount - 1); - return occurrencesCount; - }); +export const getIntersection = function (firstArray, secondArray) { + const toRemoveMap = createOccurrenceMap(secondArray); + return firstArray.filter((value) => { + const occurrencesCount = toRemoveMap.get(value); + occurrencesCount && toRemoveMap.set(value, occurrencesCount - 1); + return occurrencesCount; + }); }; -export const removeDuplicates = function(from = [], toRemove = []) { - const toRemoveMap = createOccurrenceMap(toRemove); - return from.filter(value => { - const occurrencesCount = toRemoveMap.get(value); - occurrencesCount && toRemoveMap.set(value, occurrencesCount - 1); - return !occurrencesCount; - }); +export const removeDuplicates = function (from = [], toRemove = []) { + const toRemoveMap = createOccurrenceMap(toRemove); + return from.filter((value) => { + const occurrencesCount = toRemoveMap.get(value); + occurrencesCount && toRemoveMap.set(value, occurrencesCount - 1); + return !occurrencesCount; + }); }; -export const normalizeIndexes = function(items, indexPropName, currentItem, needIndexCallback) { - const indexedItems = {}; - const { useLegacyVisibleIndex } = config(); - let currentIndex = 0; +export const normalizeIndexes = function (items, indexPropName, currentItem?, needIndexCallback?) { + const indexedItems = {}; + const { useLegacyVisibleIndex } = config(); + let currentIndex = 0; - const shouldUpdateIndex = (item) => !isDefined(item[indexPropName]) - && (!needIndexCallback || needIndexCallback(item)); + const shouldUpdateIndex = (item) => !isDefined(item[indexPropName]) + && (!needIndexCallback || needIndexCallback(item)); - items.forEach((item) => { - const index = item[indexPropName]; - if(index >= 0) { - indexedItems[index] = indexedItems[index] || []; + items.forEach((item) => { + const index = item[indexPropName]; + if (index >= 0) { + indexedItems[index] = indexedItems[index] || []; - if(item === currentItem) { - indexedItems[index].unshift(item); - } else { - indexedItems[index].push(item); - } - } else { - item[indexPropName] = undefined; + if (item === currentItem) { + indexedItems[index].unshift(item); + } else { + indexedItems[index].push(item); + } + } else { + item[indexPropName] = undefined; + } + }); + + if (!useLegacyVisibleIndex) { + items.forEach((item) => { + if (shouldUpdateIndex(item)) { + while (indexedItems[currentIndex]) { + currentIndex++; } + indexedItems[currentIndex] = [item]; + currentIndex++; + } }); + } - if(!useLegacyVisibleIndex) { - items.forEach(item => { - if(shouldUpdateIndex(item)) { - while(indexedItems[currentIndex]) { - currentIndex++; - } - indexedItems[currentIndex] = [item]; - currentIndex++; - } - }); - } + currentIndex = 0; - currentIndex = 0; - - orderEach(indexedItems, function(index, items) { - items.forEach(item => { - if(index >= 0) { - item[indexPropName] = currentIndex++; - } - }); + orderEach(indexedItems, function (index, items) { + items.forEach((item) => { + if (index >= 0) { + item[indexPropName] = currentIndex++; + } }); + }); - if(useLegacyVisibleIndex) { - items.forEach(item => { - if(shouldUpdateIndex(item)) { - item[indexPropName] = currentIndex++; - } - }); - } + if (useLegacyVisibleIndex) { + items.forEach((item) => { + if (shouldUpdateIndex(item)) { + item[indexPropName] = currentIndex++; + } + }); + } }; -export const groupBy = (array, getGroupName) => { - return array.reduce((groupedResult, item) => { - const groupName = getGroupName(item); - groupedResult[groupName] = groupedResult[groupName] ?? []; - groupedResult[groupName].push(item); +export const groupBy = (array, getGroupName) => array.reduce((groupedResult, item) => { + const groupName = getGroupName(item); + groupedResult[groupName] = groupedResult[groupName] ?? []; + groupedResult[groupName].push(item); - return groupedResult; - }, {}); -}; + return groupedResult; +}, {}); diff --git a/packages/devextreme/js/__internal/core/utils/m_array_compare.ts b/packages/devextreme/js/__internal/core/utils/m_array_compare.ts index 0821bbfdb4b7..31e83dada542 100644 --- a/packages/devextreme/js/__internal/core/utils/m_array_compare.ts +++ b/packages/devextreme/js/__internal/core/utils/m_array_compare.ts @@ -1,98 +1,97 @@ -import { isObject } from './type'; +import { isObject } from '@js/core/utils/type'; -const getKeyWrapper = function(item, getKey) { - const key = getKey(item); - if(isObject(key)) { - try { - return JSON.stringify(key); - } catch(e) { - return key; - } +const getKeyWrapper = function (item, getKey) { + const key = getKey(item); + if (isObject(key)) { + try { + return JSON.stringify(key); + } catch (e) { + return key; } - return key; + } + return key; }; -const getSameNewByOld = function(oldItem, newItems, newIndexByKey, getKey) { - const key = getKeyWrapper(oldItem, getKey); - return newItems[newIndexByKey[key]]; +const getSameNewByOld = function (oldItem, newItems, newIndexByKey, getKey) { + const key = getKeyWrapper(oldItem, getKey); + return newItems[newIndexByKey[key]]; }; -export const isKeysEqual = function(oldKeys, newKeys) { - if(oldKeys.length !== newKeys.length) { - return false; - } +export const isKeysEqual = function (oldKeys, newKeys) { + if (oldKeys.length !== newKeys.length) { + return false; + } - for(let i = 0; i < newKeys.length; i++) { - if(oldKeys[i] !== newKeys[i]) { - return false; - } + for (let i = 0; i < newKeys.length; i++) { + if (oldKeys[i] !== newKeys[i]) { + return false; } + } - return true; + return true; }; -export const findChanges = function(oldItems, newItems, getKey, isItemEquals) { - const oldIndexByKey = {}; - const newIndexByKey = {}; - let addedCount = 0; - let removeCount = 0; - const result = []; +export const findChanges = function (oldItems, newItems, getKey, isItemEquals) { + const oldIndexByKey = {}; + const newIndexByKey = {}; + let addedCount = 0; + let removeCount = 0; + const result: any[] = []; - oldItems.forEach(function(item, index) { - const key = getKeyWrapper(item, getKey); - oldIndexByKey[key] = index; - }); + oldItems.forEach(function (item, index) { + const key = getKeyWrapper(item, getKey); + oldIndexByKey[key] = index; + }); - newItems.forEach(function(item, index) { - const key = getKeyWrapper(item, getKey); - newIndexByKey[key] = index; - }); + newItems.forEach(function (item, index) { + const key = getKeyWrapper(item, getKey); + newIndexByKey[key] = index; + }); - const itemCount = Math.max(oldItems.length, newItems.length); - for(let index = 0; index < itemCount + addedCount; index++) { - const newItem = newItems[index]; - const oldNextIndex = index - addedCount + removeCount; - const nextOldItem = oldItems[oldNextIndex]; - const isRemoved = !newItem || (nextOldItem && !getSameNewByOld(nextOldItem, newItems, newIndexByKey, getKey)); + const itemCount = Math.max(oldItems.length, newItems.length); + for (let index = 0; index < itemCount + addedCount; index++) { + const newItem = newItems[index]; + const oldNextIndex = index - addedCount + removeCount; + const nextOldItem = oldItems[oldNextIndex]; + const isRemoved = !newItem || (nextOldItem && !getSameNewByOld(nextOldItem, newItems, newIndexByKey, getKey)); - if(isRemoved) { - if(nextOldItem) { - result.push({ - type: 'remove', - key: getKey(nextOldItem), - index: index, - oldItem: nextOldItem - }); - removeCount++; - index--; - } - } else { - const key = getKeyWrapper(newItem, getKey); - const oldIndex = oldIndexByKey[key]; - const oldItem = oldItems[oldIndex]; - if(!oldItem) { - addedCount++; - result.push({ - type: 'insert', - data: newItem, - index: index - }); - } else if(oldIndex === oldNextIndex) { - if(!isItemEquals(oldItem, newItem)) { - result.push({ - type: 'update', - data: newItem, - key: getKey(newItem), - index: index, - oldItem: oldItem - }); - } - } else { - return; - } + if (isRemoved) { + if (nextOldItem) { + result.push({ + type: 'remove', + key: getKey(nextOldItem), + index, + oldItem: nextOldItem, + }); + removeCount++; + index--; + } + } else { + const key = getKeyWrapper(newItem, getKey); + const oldIndex = oldIndexByKey[key]; + const oldItem = oldItems[oldIndex]; + if (!oldItem) { + addedCount++; + result.push({ + type: 'insert', + data: newItem, + index, + }); + } else if (oldIndex === oldNextIndex) { + if (!isItemEquals(oldItem, newItem)) { + result.push({ + type: 'update', + data: newItem, + key: getKey(newItem), + index, + oldItem, + }); } + } else { + return; + } } + } - return result; + return result; }; - diff --git a/packages/devextreme/js/__internal/core/utils/m_browser.ts b/packages/devextreme/js/__internal/core/utils/m_browser.ts index 658f4f95b55f..2420a5b4d70e 100644 --- a/packages/devextreme/js/__internal/core/utils/m_browser.ts +++ b/packages/devextreme/js/__internal/core/utils/m_browser.ts @@ -1,48 +1,49 @@ -import { extend } from './extend'; -import { getNavigator } from './window'; +import { extend } from '@js/core/utils/extend'; +import { getNavigator } from '@js/core/utils/window'; + const navigator = getNavigator(); const webkitRegExp = /(webkit)[ /]([\w.]+)/; const mozillaRegExp = /(mozilla)(?:.*? rv:([\w.]+))/; const browserFromUA = (ua) => { - ua = ua.toLowerCase(); - - const result = {}; - const matches = - webkitRegExp.exec(ua) || - ua.indexOf('compatible') < 0 && mozillaRegExp.exec(ua) || - []; - let browserName = matches[1]; - let browserVersion = matches[2]; - - if(browserName === 'webkit') { - result['webkit'] = true; - - if(ua.indexOf('chrome') >= 0 || ua.indexOf('crios') >= 0) { - browserName = 'chrome'; - browserVersion = /(?:chrome|crios)\/(\d+\.\d+)/.exec(ua); - browserVersion = browserVersion && browserVersion[1]; - } else if(ua.indexOf('fxios') >= 0) { - browserName = 'mozilla'; - browserVersion = /fxios\/(\d+\.\d+)/.exec(ua); - browserVersion = browserVersion && browserVersion[1]; - } else if(ua.indexOf('safari') >= 0 && /version|phantomjs/.test(ua)) { - browserName = 'safari'; - browserVersion = /(?:version|phantomjs)\/([0-9.]+)/.exec(ua); - browserVersion = browserVersion && browserVersion[1]; - } else { - browserName = 'unknown'; - browserVersion = /applewebkit\/([0-9.]+)/.exec(ua); - browserVersion = browserVersion && browserVersion[1]; - } - } + ua = ua.toLowerCase(); + + const result: any = {}; + const matches = webkitRegExp.exec(ua) + || ua.indexOf('compatible') < 0 && mozillaRegExp.exec(ua) + || []; + let browserName = matches[1]; + let browserVersion: any = matches[2]; - if(browserName) { - result[browserName] = true; - result.version = browserVersion; + if (browserName === 'webkit') { + result.webkit = true; + + if (ua.indexOf('chrome') >= 0 || ua.indexOf('crios') >= 0) { + browserName = 'chrome'; + browserVersion = /(?:chrome|crios)\/(\d+\.\d+)/.exec(ua); + browserVersion = browserVersion && browserVersion[1]; + } else if (ua.indexOf('fxios') >= 0) { + browserName = 'mozilla'; + browserVersion = /fxios\/(\d+\.\d+)/.exec(ua); + browserVersion = browserVersion && browserVersion[1]; + } else if (ua.indexOf('safari') >= 0 && /version|phantomjs/.test(ua)) { + browserName = 'safari'; + browserVersion = /(?:version|phantomjs)\/([0-9.]+)/.exec(ua); + browserVersion = browserVersion && browserVersion[1]; + } else { + browserName = 'unknown'; + browserVersion = /applewebkit\/([0-9.]+)/.exec(ua); + browserVersion = browserVersion && browserVersion[1]; } + } + + if (browserName) { + result[browserName] = true; + result.version = browserVersion; + } - return result; + return result; }; -export default extend({ _fromUA: browserFromUA }, browserFromUA(navigator.userAgent)); +const browser = extend({ _fromUA: browserFromUA }, browserFromUA(navigator.userAgent)); +export { browser }; diff --git a/packages/devextreme/js/__internal/core/utils/m_call_once.ts b/packages/devextreme/js/__internal/core/utils/m_call_once.ts index 1771ea8fac42..ca68b5648b5d 100644 --- a/packages/devextreme/js/__internal/core/utils/m_call_once.ts +++ b/packages/devextreme/js/__internal/core/utils/m_call_once.ts @@ -1,17 +1,18 @@ -const callOnce = function(handler) { - let result; +const callOnce = function (handler) { + let result; - let wrappedHandler = function() { - result = handler.apply(this, arguments); - wrappedHandler = function() { - return result; - }; - return result; + let wrappedHandler = function () { + result = handler.apply(this, arguments); + wrappedHandler = function () { + return result; }; + return result; + }; - return function() { - return wrappedHandler.apply(this, arguments); - }; + return function () { + // @ts-expect-error Iarguments not assignable to [] + return wrappedHandler.apply(this, arguments); + }; }; -export default callOnce; +export { callOnce }; diff --git a/packages/devextreme/js/__internal/core/utils/m_callbacks.ts b/packages/devextreme/js/__internal/core/utils/m_callbacks.ts index 9f9b82cc343d..f404ffb73616 100644 --- a/packages/devextreme/js/__internal/core/utils/m_callbacks.ts +++ b/packages/devextreme/js/__internal/core/utils/m_callbacks.ts @@ -1,109 +1,130 @@ -const Callback = function(options) { - this._options = options || {}; - this._list = []; - this._queue = []; - this._firing = false; - this._fired = false; - this._firingIndexes = []; -}; +type CallbackType + = ((this: TContext, ...args: TArgs) => boolean) + | ((this: TContext, ...args: TArgs) => void); -Callback.prototype._fireCore = function(context, args) { - const firingIndexes = this._firingIndexes; - const list = this._list; - const stopOnFalse = this._options.stopOnFalse; - const step = firingIndexes.length; +export interface CallbackInterface { + add: (fn: CallbackType) => this; - for(firingIndexes[step] = 0; firingIndexes[step] < list.length; firingIndexes[step]++) { - const result = list[firingIndexes[step]].apply(context, args); + remove: (fn: CallbackType) => this; - if(result === false && stopOnFalse) { - break; - } - } + has: (fn: CallbackType) => this; + + empty: () => this; + + fireWith: (context: TContext, args: TArgs) => this; + + fire: (...args: TArgs) => this; + + fired: () => boolean; +} - firingIndexes.pop(); +const Callback = function (options) { + this._options = options || {}; + this._list = []; + this._queue = []; + this._firing = false; + this._fired = false; + this._firingIndexes = []; }; +Callback.prototype._fireCore = function (context, args) { + const firingIndexes = this._firingIndexes; + const list = this._list; + const { stopOnFalse } = this._options; + const step = firingIndexes.length; -Callback.prototype.add = function(fn) { - if(typeof fn === 'function' && (!this._options.unique || !this.has(fn))) { - this._list.push(fn); + for (firingIndexes[step] = 0; firingIndexes[step] < list.length; firingIndexes[step]++) { + const result = list[firingIndexes[step]].apply(context, args); + + if (result === false && stopOnFalse) { + break; } - return this; + } + + firingIndexes.pop(); +}; + +Callback.prototype.add = function (fn) { + if (typeof fn === 'function' && (!this._options.unique || !this.has(fn))) { + this._list.push(fn); + } + return this; }; -Callback.prototype.remove = function(fn) { - const list = this._list; - const firingIndexes = this._firingIndexes; - const index = list.indexOf(fn); +Callback.prototype.remove = function (fn) { + const list = this._list; + const firingIndexes = this._firingIndexes; + const index = list.indexOf(fn); - if(index > -1) { - list.splice(index, 1); + if (index > -1) { + list.splice(index, 1); - if(this._firing && firingIndexes.length) { - for(let step = 0; step < firingIndexes.length; step++) { - if(index <= firingIndexes[step]) { - firingIndexes[step]--; - } - } + if (this._firing && firingIndexes.length) { + for (let step = 0; step < firingIndexes.length; step++) { + if (index <= firingIndexes[step]) { + firingIndexes[step]--; } + } } + } - return this; + return this; }; -Callback.prototype.has = function(fn) { - const list = this._list; +Callback.prototype.has = function (fn) { + const list = this._list; - return fn ? list.indexOf(fn) > -1 : !!list.length; + return fn ? list.indexOf(fn) > -1 : !!list.length; }; -Callback.prototype.empty = function(fn) { - this._list = []; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +Callback.prototype.empty = function (fn) { + this._list = []; - return this; + return this; }; -Callback.prototype.fireWith = function(context, args) { - const queue = this._queue; +Callback.prototype.fireWith = function (context, args) { + const queue = this._queue; - args = args || []; - args = args.slice ? args.slice() : args; + args = args || []; + args = args.slice ? args.slice() : args; - if(this._options.syncStrategy) { - this._firing = true; - this._fireCore(context, args); - } else { - queue.push([context, args]); - if(this._firing) { - return; - } + if (this._options.syncStrategy) { + this._firing = true; + this._fireCore(context, args); + } else { + queue.push([context, args]); + if (this._firing) { + return; + } - this._firing = true; + this._firing = true; - while(queue.length) { - const memory = queue.shift(); + while (queue.length) { + const memory = queue.shift(); - this._fireCore(memory[0], memory[1]); - } + this._fireCore(memory[0], memory[1]); } + } - this._firing = false; - this._fired = true; + this._firing = false; + this._fired = true; - return this; + return this; }; -Callback.prototype.fire = function() { - this.fireWith(this, arguments); +Callback.prototype.fire = function () { + this.fireWith(this, arguments); }; -Callback.prototype.fired = function() { - return this._fired; +Callback.prototype.fired = function () { + return this._fired; }; -const Callbacks = function(options) { - return new Callback(options); +const Callbacks = function (options?) { + return new Callback(options); }; +export { Callbacks }; export default Callbacks; diff --git a/packages/devextreme/js/__internal/core/utils/m_common.ts b/packages/devextreme/js/__internal/core/utils/m_common.ts index 34520f56b5e4..2517eb6c4e4a 100644 --- a/packages/devextreme/js/__internal/core/utils/m_common.ts +++ b/packages/devextreme/js/__internal/core/utils/m_common.ts @@ -1,320 +1,348 @@ -import config from '../config'; -import Guid from '../guid'; -import { when, Deferred } from '../utils/deferred'; -import { toComparable } from './data'; -import { each } from './iterator'; -import { isDefined, isFunction, isString, isObject, type } from './type'; - -export const ensureDefined = function(value, defaultValue) { - return isDefined(value) ? value : defaultValue; +import config from '@js/core/config'; +import Guid from '@js/core/guid'; +import { toComparable } from '@js/core/utils/data'; +import { Deferred, when } from '@js/core/utils/deferred'; +import { each } from '@js/core/utils/iterator'; +import { + isDefined, isFunction, isObject, isString, type, +} from '@js/core/utils/type'; + +export const ensureDefined = function (value, defaultValue) { + return isDefined(value) ? value : defaultValue; }; -export const executeAsync = function(action, context/* , internal */) { - const deferred = new Deferred(); - const normalizedContext = context || this; - const task = { - promise: deferred.promise(), - abort: function() { - clearTimeout(timerId); - deferred.rejectWith(normalizedContext); - } - }; - - const callback = function() { - const result = action.call(normalizedContext); - - if(result && result.done && isFunction(result.done)) { - result.done(function() { - deferred.resolveWith(normalizedContext); - }); - } else { - deferred.resolveWith(normalizedContext); - } - }; - - const timerId = (arguments[2] || setTimeout)(callback, typeof context === 'number' ? context : 0); - - return task; +export const executeAsync = function (action, context?/* , internal */) { + // @ts-expect-error only void function can be called with new + const deferred = new Deferred(); + const normalizedContext = context || this; + const task = { + promise: deferred.promise(), + abort() { + clearTimeout(timerId); + deferred.rejectWith(normalizedContext); + }, + }; + + const callback = function () { + const result = action.call(normalizedContext); + + if (result && result.done && isFunction(result.done)) { + result.done(function () { + deferred.resolveWith(normalizedContext); + }); + } else { + deferred.resolveWith(normalizedContext); + } + }; + + const timerId = (arguments[2] || setTimeout)(callback, typeof context === 'number' ? context : 0); + + return task; }; -const delayedFuncs = []; -const delayedNames = []; -const delayedDeferreds = []; +const delayedFuncs: any[] = []; +const delayedNames: any[] = []; +const delayedDeferreds: any[] = []; let executingName; -const deferExecute = function(name, func, deferred) { - if(executingName && executingName !== name) { - delayedFuncs.push(func); - delayedNames.push(name); - deferred = deferred || new Deferred(); - delayedDeferreds.push(deferred); - return deferred; - } else { - const oldExecutingName = executingName; - const currentDelayedCount = delayedDeferreds.length; - - executingName = name; - let result = func(); - - if(!result) { - if(delayedDeferreds.length > currentDelayedCount) { - result = when.apply(this, delayedDeferreds.slice(currentDelayedCount)); - } else if(deferred) { - deferred.resolve(); - } - } - - executingName = oldExecutingName; - - if(deferred && result && result.done) { - result.done(deferred.resolve).fail(deferred.reject); - } - - if(!executingName && delayedFuncs.length) { - (delayedNames.shift() === 'render' ? deferRender : deferUpdate)(delayedFuncs.shift(), delayedDeferreds.shift()); - } - return result || when(); +const deferExecute = function (name, func, deferred?) { + if (executingName && executingName !== name) { + delayedFuncs.push(func); + delayedNames.push(name); + // @ts-expect-error only void function can be called with new + deferred = deferred || new Deferred(); + delayedDeferreds.push(deferred); + return deferred; + } + const oldExecutingName = executingName; + const currentDelayedCount = delayedDeferreds.length; + + executingName = name; + let result = func(); + + if (!result) { + if (delayedDeferreds.length > currentDelayedCount) { + result = when.apply(this, delayedDeferreds.slice(currentDelayedCount)); + } else if (deferred) { + deferred.resolve(); } + } + + executingName = oldExecutingName; + + if (deferred && result && result.done) { + result.done(deferred.resolve).fail(deferred.reject); + } + + if (!executingName && delayedFuncs.length) { + (delayedNames.shift() === 'render' ? deferRender : deferUpdate)(delayedFuncs.shift(), delayedDeferreds.shift()); + } + return result || when(); }; -export const deferRender = function(func, deferred) { - return deferExecute('render', func, deferred); +export const deferRender = function (func, deferred) { + return deferExecute('render', func, deferred); }; -export const deferUpdate = function(func, deferred) { - return deferExecute('update', func, deferred); +export const deferUpdate = function (func, deferred) { + return deferExecute('update', func, deferred); }; -export const deferRenderer = function(func) { - return function() { - const that = this; - return deferExecute('render', function() { - return func.call(that); - }); - }; +export const deferRenderer = function (func) { + return function () { + const that = this; + return deferExecute('render', function () { + return func.call(that); + }); + }; }; -export const deferUpdater = function(func) { - return function() { - const that = this; - return deferExecute('update', function() { - return func.call(that); - }); - }; +export const deferUpdater = function (func) { + return function () { + const that = this; + return deferExecute('update', function () { + return func.call(that); + }); + }; }; -export const findBestMatches = function(targetFilter, items, mapFn) { - const bestMatches = []; - let maxMatchCount = 0; - - each(items, (index, itemSrc) => { - let matchCount = 0; - const item = mapFn ? mapFn(itemSrc) : itemSrc; - - each(targetFilter, (paramName, targetValue) => { - const value = item[paramName]; - - if(value === undefined) { - return; - } - - if(match(value, targetValue)) { - matchCount++; - return; - } - matchCount = -1; - return false; - }); - - if(matchCount < maxMatchCount) { - return; - } - if(matchCount > maxMatchCount) { - bestMatches.length = 0; - maxMatchCount = matchCount; - } - bestMatches.push(itemSrc); +export const findBestMatches = ( + targetFilter: unknown, + items: unknown[], + mapFn?: (item: unknown) => unknown, +): unknown[] => { + const bestMatches: unknown[] = []; + let maxMatchCount = 0; + + each(items, (index, itemSrc) => { + let matchCount = 0; + const item = mapFn ? mapFn(itemSrc) : itemSrc; + + each(targetFilter, (paramName, targetValue) => { + const value = item[paramName]; + + if (value === undefined) { + return; + } + + if (match(value, targetValue)) { + matchCount++; + return; + } + matchCount = -1; + return false; }); - return bestMatches; -}; + if (matchCount < maxMatchCount) { + return; + } + if (matchCount > maxMatchCount) { + bestMatches.length = 0; + maxMatchCount = matchCount; + } + bestMatches.push(itemSrc); + }); -const match = function(value, targetValue) { - if(Array.isArray(value) && Array.isArray(targetValue)) { - let mismatch = false; + return bestMatches; +}; - each(value, (index, valueItem) => { - if(valueItem !== targetValue[index]) { - mismatch = true; - return false; - } - }); +const match = function (value, targetValue) { + if (Array.isArray(value) && Array.isArray(targetValue)) { + let mismatch = false; - if(mismatch) { - return false; - } + // @ts-expect-error not all code paths return value + each(value, (index, valueItem) => { + if (valueItem !== targetValue[index]) { + mismatch = true; + return false; + } + }); - return true; + if (mismatch) { + return false; } - if(value === targetValue) { - return true; - } + return true; + } - return false; + if (value === targetValue) { + return true; + } + + return false; }; -export const splitPair = function(raw) { - switch(type(raw)) { - case 'string': - return raw.split(/\s+/, 2); - case 'object': - return [raw.x ?? raw.h, raw.y ?? raw.v]; - case 'number': - return [raw]; - case 'array': - return raw; - default: - return null; - } +export const splitPair = function (raw) { + switch (type(raw)) { + case 'string': + return raw.split(/\s+/, 2); + case 'object': + return [raw.x ?? raw.h, raw.y ?? raw.v]; + case 'number': + return [raw]; + case 'array': + return raw; + default: + return null; + } }; -export const normalizeKey = function(id) { - let key = isString(id) ? id : id.toString(); - const arr = key.match(/[^a-zA-Z0-9_]/g); +export const normalizeKey = function (id) { + let key = isString(id) ? id : id.toString(); + const arr = key.match(/[^a-zA-Z0-9_]/g); - arr && each(arr, (_, sign) => { - key = key.replace(sign, '__' + sign.charCodeAt() + '__'); - }); - return key; + arr && each(arr, (_, sign) => { + key = key.replace(sign, `__${sign.charCodeAt()}__`); + }); + return key; }; -export const denormalizeKey = function(key) { - const arr = key.match(/__\d+__/g); +export const denormalizeKey = function (key) { + const arr = key.match(/__\d+__/g); - arr && arr.forEach((char) => { - const charCode = parseInt(char.replace('__', '')); + arr && arr.forEach((char) => { + const charCode = parseInt(char.replace('__', '')); - key = key.replace(char, String.fromCharCode(charCode)); - }); + key = key.replace(char, String.fromCharCode(charCode)); + }); - return key; + return key; }; -export const pairToObject = function(raw, preventRound) { - const pair = splitPair(raw); - let h = preventRound ? parseFloat(pair && pair[0]) : parseInt(pair && pair[0], 10); - let v = preventRound ? parseFloat(pair && pair[1]) : parseInt(pair && pair[1], 10); +export const pairToObject = function (raw, preventRound) { + const pair = splitPair(raw); + let h = preventRound ? parseFloat(pair && pair[0]) : parseInt(pair && pair[0], 10); + let v = preventRound ? parseFloat(pair && pair[1]) : parseInt(pair && pair[1], 10); - if(!isFinite(h)) { - h = 0; - } - if(!isFinite(v)) { - v = h; - } + if (!isFinite(h)) { + h = 0; + } + if (!isFinite(v)) { + v = h; + } - return { h, v }; + return { h, v }; }; -export const getKeyHash = function(key) { - if(key instanceof Guid) { - return key.toString(); - } else if(isObject(key) || Array.isArray(key)) { - try { - const keyHash = JSON.stringify(key); - return keyHash === '{}' ? key : keyHash; - } catch(e) { - return key; - } +export const getKeyHash = function (key) { + if (key instanceof Guid) { + return key.toString(); + } if (isObject(key) || Array.isArray(key)) { + try { + const keyHash = JSON.stringify(key); + return keyHash === '{}' ? key : keyHash; + } catch (e) { + return key; } + } - return key; + return key; }; -export const escapeRegExp = function(string) { - return string.replace(/[[\]{}\-()*+?.\\^$|\s]/g, '\\$&'); +export const escapeRegExp = function (string) { + return string.replace(/[[\]{}\-()*+?.\\^$|\s]/g, '\\$&'); }; -export const applyServerDecimalSeparator = function(value) { - const separator = config().serverDecimalSeparator; - if(isDefined(value)) { - value = value.toString().replace('.', separator); - } - return value; +export const applyServerDecimalSeparator = function (value) { + const separator = config().serverDecimalSeparator; + if (isDefined(value)) { + value = value.toString().replace('.', separator); + } + return value; }; -export const noop = function() {}; -export const asyncNoop = function() { return new Deferred().resolve().promise(); }; +export const noop = function () {}; +// @ts-expect-error only void function can be called with new +export const asyncNoop = function () { return new Deferred().resolve().promise(); }; -export const grep = function(elements, checkFunction, invert) { - const result = []; - let check; - const expectedCheck = !invert; +export const grep = function (elements, checkFunction, invert) { + const result: any[] = []; + let check; + const expectedCheck = !invert; - for(let i = 0; i < elements.length; i++) { - check = !!checkFunction(elements[i], i); + for (let i = 0; i < elements.length; i++) { + check = !!checkFunction(elements[i], i); - if(check === expectedCheck) { - result.push(elements[i]); - } + if (check === expectedCheck) { + result.push(elements[i]); } + } - return result; + return result; }; const compareArrays = (array1, array2, depth, options) => { - if(array1.length !== array2.length) { - return false; - } + if (array1.length !== array2.length) { + return false; + } - return !array1.some((item, idx) => !compareByValue(item, array2[idx], depth + 1, { - ...options, - strict: true, - })); + return !array1.some((item, idx) => !compareByValue(item, array2[idx], depth + 1, { + ...options, + strict: true, + })); }; const compareObjects = (object1, object2, depth, options) => { - const keys1 = Object.keys(object1); - const keys2 = Object.keys(object2); + const keys1 = Object.keys(object1); + const keys2 = Object.keys(object2); - if(keys1.length !== keys2.length) { - return false; - } + if (keys1.length !== keys2.length) { + return false; + } - const keys2Set = new Set(keys2); - return !keys1.some((key) => - !keys2Set.has(key) || !compareByValue(object1[key], object2[key], depth + 1, options) - ); + const keys2Set = new Set(keys2); + return !keys1.some((key) => !keys2Set.has(key) || !compareByValue(object1[key], object2[key], depth + 1, options)); }; const DEFAULT_EQUAL_BY_VALUE_OPTS = { - maxDepth: 3, - strict: true, + maxDepth: 3, + strict: true, }; const compareByValue = (value1, value2, depth, options) => { - const { strict, maxDepth } = options; - const comparable1 = toComparable(value1, true); - const comparable2 = toComparable(value2, true); - - const comparisonResult = strict - ? comparable1 === comparable2 - // eslint-disable-next-line eqeqeq - : comparable1 == comparable2; - - switch(true) { - case comparisonResult: - case depth >= maxDepth: - return true; - case isObject(comparable1) && isObject(comparable2): - return compareObjects(comparable1, comparable2, depth, options); - case Array.isArray(comparable1) && Array.isArray(comparable2): - return compareArrays(comparable1, comparable2, depth, options); - default: - return false; - } + const { strict, maxDepth } = options; + const comparable1 = toComparable(value1, true); + const comparable2 = toComparable(value2, true); + + const comparisonResult = strict + ? comparable1 === comparable2 + // eslint-disable-next-line eqeqeq + : comparable1 == comparable2; + + switch (true) { + case comparisonResult: + case depth >= maxDepth: + return true; + case isObject(comparable1) && isObject(comparable2): + return compareObjects(comparable1, comparable2, depth, options); + case Array.isArray(comparable1) && Array.isArray(comparable2): + return compareArrays(comparable1, comparable2, depth, options); + default: + return false; + } }; export const equalByValue = (value1, value2, options = DEFAULT_EQUAL_BY_VALUE_OPTS) => { - const compareOptions = { ...DEFAULT_EQUAL_BY_VALUE_OPTS, ...options }; - return compareByValue(value1, value2, 0, compareOptions); + const compareOptions = { ...DEFAULT_EQUAL_BY_VALUE_OPTS, ...options }; + return compareByValue(value1, value2, 0, compareOptions); +}; + +export default { + ensureDefined, + executeAsync, + deferRender, + deferUpdate, + deferRenderer, + deferUpdater, + findBestMatches, + splitPair, + normalizeKey, + denormalizeKey, + pairToObject, + getKeyHash, + escapeRegExp, + applyServerDecimalSeparator, + noop, + asyncNoop, + grep, + equalByValue, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_comparator.ts b/packages/devextreme/js/__internal/core/utils/m_comparator.ts index 36ba408364ea..0a4fd974984f 100644 --- a/packages/devextreme/js/__internal/core/utils/m_comparator.ts +++ b/packages/devextreme/js/__internal/core/utils/m_comparator.ts @@ -1,32 +1,32 @@ -import domAdapter from '../dom_adapter'; -import { toComparable } from './data'; -import { isRenderer } from './type'; +import domAdapter from '@js/core/dom_adapter'; +import { toComparable } from '@js/core/utils/data'; +import { isRenderer } from '@js/core/utils/type'; -const hasNegation = function(oldValue, newValue) { - return (1 / oldValue) === (1 / newValue); +const hasNegation = function (oldValue, newValue) { + return (1 / oldValue) === (1 / newValue); }; -export const equals = function(oldValue, newValue) { - oldValue = toComparable(oldValue, true); - newValue = toComparable(newValue, true); +export const equals = function (oldValue, newValue) { + oldValue = toComparable(oldValue, true); + newValue = toComparable(newValue, true); - if(oldValue && newValue && isRenderer(oldValue) && isRenderer(newValue)) { - return newValue.is(oldValue); - } + if (oldValue && newValue && isRenderer(oldValue) && isRenderer(newValue)) { + return newValue.is(oldValue); + } - const oldValueIsNaN = oldValue !== oldValue; - const newValueIsNaN = newValue !== newValue; - if(oldValueIsNaN && newValueIsNaN) { - return true; - } + const oldValueIsNaN = oldValue !== oldValue; + const newValueIsNaN = newValue !== newValue; + if (oldValueIsNaN && newValueIsNaN) { + return true; + } - if(oldValue === 0 && newValue === 0) { - return hasNegation(oldValue, newValue); - } + if (oldValue === 0 && newValue === 0) { + return hasNegation(oldValue, newValue); + } - if(oldValue === null || typeof oldValue !== 'object' || domAdapter.isElementNode(oldValue)) { - return oldValue === newValue; - } + if (oldValue === null || typeof oldValue !== 'object' || domAdapter.isElementNode(oldValue)) { + return oldValue === newValue; + } - return false; + return false; }; diff --git a/packages/devextreme/js/__internal/core/utils/m_console.ts b/packages/devextreme/js/__internal/core/utils/m_console.ts index ed1181b5c92a..0cba72576449 100644 --- a/packages/devextreme/js/__internal/core/utils/m_console.ts +++ b/packages/devextreme/js/__internal/core/utils/m_console.ts @@ -1,34 +1,36 @@ /* global console */ /* eslint no-console: off */ -import { isFunction } from './type'; +import { isFunction } from '@js/core/utils/type'; -const noop = function() {}; -const getConsoleMethod = function(method) { - if(typeof console === 'undefined' || !isFunction(console[method])) { - return noop; - } - return console[method].bind(console); +const noop = function () {}; +const getConsoleMethod = function (method) { + if (typeof console === 'undefined' || !isFunction(console[method])) { + return noop; + } + return console[method].bind(console); }; export const logger = { - log: getConsoleMethod('log'), - info: getConsoleMethod('info'), - warn: getConsoleMethod('warn'), - error: getConsoleMethod('error') + log: getConsoleMethod('log'), + info: getConsoleMethod('info'), + warn: getConsoleMethod('warn'), + error: getConsoleMethod('error'), }; -export const debug = (function() { - function assert(condition, message) { - if(!condition) { - throw new Error(message); - } - } - function assertParam(parameter, message) { - assert(parameter !== null && parameter !== undefined, message); +export const debug = (function () { + function assert(condition, message) { + if (!condition) { + throw new Error(message); } - return { - assert: assert, - assertParam: assertParam - }; + } + function assertParam(parameter, message) { + assert(parameter !== null && parameter !== undefined, message); + } + return { + assert, + assertParam, + }; }()); + +export default { logger, debug }; diff --git a/packages/devextreme/js/__internal/core/utils/m_data.ts b/packages/devextreme/js/__internal/core/utils/m_data.ts index 0daeed1c41e4..52a70b038e39 100644 --- a/packages/devextreme/js/__internal/core/utils/m_data.ts +++ b/packages/devextreme/js/__internal/core/utils/m_data.ts @@ -1,221 +1,225 @@ -import errors from '../errors'; -import Class from '../class'; -import { deepExtendArraySafe } from './object'; -import { isObject, isPlainObject, isFunction, isDefined } from './type'; -import { each } from './iterator'; -import variableWrapper from './variable_wrapper'; +import Class from '@js/core/class'; +import errors from '@js/core/errors'; +import { each } from '@js/core/utils/iterator'; +import { deepExtendArraySafe } from '@js/core/utils/object'; +import { + isDefined, isFunction, isObject, isPlainObject, +} from '@js/core/utils/type'; +import variableWrapper from '@js/core/utils/variable_wrapper'; + const unwrapVariable = variableWrapper.unwrap; -const isWrapped = variableWrapper.isWrapped; -const assign = variableWrapper.assign; +const { isWrapped } = variableWrapper; +const { assign } = variableWrapper; -const bracketsToDots = function(expr) { - return expr - .replace(/\[/g, '.') - .replace(/\]/g, ''); +const bracketsToDots = function (expr) { + return expr + .replace(/\[/g, '.') + .replace(/\]/g, ''); }; -export const getPathParts = function(name) { - return bracketsToDots(name).split('.'); +export const getPathParts = function (name) { + return bracketsToDots(name).split('.'); }; -const readPropValue = function(obj, propName, options) { - options = options || { }; - if(propName === 'this') { - return unwrap(obj, options); - } - return unwrap(obj[propName], options); +const readPropValue = function (obj, propName, options) { + options = options || { }; + if (propName === 'this') { + return unwrap(obj, options); + } + return unwrap(obj[propName], options); }; -const assignPropValue = function(obj, propName, value, options) { - if(propName === 'this') { - throw new errors.Error('E4016'); - } - - const propValue = obj[propName]; - if(options.unwrapObservables && isWrapped(propValue)) { - assign(propValue, value); - } else { - obj[propName] = value; - } +const assignPropValue = function (obj, propName, value, options) { + if (propName === 'this') { + // @ts-expect-error only void function can be called with new + throw new errors.Error('E4016'); + } + + const propValue = obj[propName]; + if (options.unwrapObservables && isWrapped(propValue)) { + assign(propValue, value); + } else { + obj[propName] = value; + } }; -const prepareOptions = function(options) { - options = options || {}; - options.unwrapObservables = options.unwrapObservables !== undefined ? options.unwrapObservables : true; - return options; +const prepareOptions = function (options) { + options = options || {}; + options.unwrapObservables = options.unwrapObservables !== undefined ? options.unwrapObservables : true; + return options; }; function unwrap(value, options) { - return options.unwrapObservables ? unwrapVariable(value) : value; + return options.unwrapObservables ? unwrapVariable(value) : value; } -export const compileGetter = function(expr) { - if(arguments.length > 1) { - expr = [].slice.call(arguments); - } - - if(!expr || expr === 'this') { - return function(obj) { return obj; }; - } - - if(typeof expr === 'string') { - const path = getPathParts(expr); - - return function(obj, options) { - options = prepareOptions(options); - const functionAsIs = options.functionsAsIs; - const hasDefaultValue = 'defaultValue' in options; - let current = unwrap(obj, options); - - for(let i = 0; i < path.length; i++) { - if(!current) { - if(current == null && hasDefaultValue) { - return options.defaultValue; - } - break; - } +export const compileGetter = function (expr) { + if (arguments.length > 1) { + expr = [].slice.call(arguments); + } + + if (!expr || expr === 'this') { + return function (obj) { return obj; }; + } + + if (typeof expr === 'string') { + const path = getPathParts(expr); + + return function (obj, options) { + options = prepareOptions(options); + const functionAsIs = options.functionsAsIs; + const hasDefaultValue = 'defaultValue' in options; + let current = unwrap(obj, options); + + for (let i = 0; i < path.length; i++) { + if (!current) { + if (current == null && hasDefaultValue) { + return options.defaultValue; + } + break; + } - const pathPart = path[i]; + const pathPart = path[i]; - if(hasDefaultValue && isObject(current) && !(pathPart in current)) { - return options.defaultValue; - } + if (hasDefaultValue && isObject(current) && !(pathPart in current)) { + return options.defaultValue; + } - let next = unwrap(current[pathPart], options); + let next = unwrap(current[pathPart], options); - if(!functionAsIs && isFunction(next)) { - next = next.call(current); - } + if (!functionAsIs && isFunction(next)) { + next = next.call(current); + } - current = next; - } + current = next; + } - return current; - }; - } + return current; + }; + } - if(Array.isArray(expr)) { - return combineGetters(expr); - } + if (Array.isArray(expr)) { + return combineGetters(expr); + } - if(isFunction(expr)) { - return expr; - } + if (isFunction(expr)) { + return expr; + } }; function combineGetters(getters) { - const compiledGetters = {}; - for(let i = 0, l = getters.length; i < l; i++) { - const getter = getters[i]; - compiledGetters[getter] = compileGetter(getter); - } - - return function(obj, options) { - let result; - - each(compiledGetters, function(name) { - const value = this(obj, options); - - if(value === undefined) { - return; - } - - let current = (result || (result = {})); - const path = name.split('.'); - const last = path.length - 1; - - for(let i = 0; i < last; i++) { - const pathItem = path[i]; - if(!(pathItem in current)) { - current[pathItem] = { }; - } - current = current[pathItem]; - } + const compiledGetters = {}; + for (let i = 0, l = getters.length; i < l; i++) { + const getter = getters[i]; + compiledGetters[getter] = compileGetter(getter); + } + + return function (obj, options) { + let result; + + each(compiledGetters, function (name) { + const value = this(obj, options); + + if (value === undefined) { + return; + } + + let current = result || (result = {}); + const path = name.split('.'); + const last = path.length - 1; + + for (let i = 0; i < last; i++) { + const pathItem = path[i]; + if (!(pathItem in current)) { + current[pathItem] = { }; + } + current = current[pathItem]; + } - current[path[last]] = value; - }); - return result; - }; + current[path[last]] = value; + }); + return result; + }; } function toLowerCase(value, options) { - return options?.locale ? value.toLocaleLowerCase(options.locale) : value.toLowerCase(); + return options?.locale ? value.toLocaleLowerCase(options.locale) : value.toLowerCase(); } function toUpperCase(value, options) { - return options?.locale ? value.toLocaleUpperCase(options.locale) : value.toUpperCase(); + return options?.locale ? value.toLocaleUpperCase(options.locale) : value.toUpperCase(); } -const ensurePropValueDefined = function(obj, propName, value, options) { - if(isDefined(value)) { - return value; - } +const ensurePropValueDefined = function (obj, propName, value, options) { + if (isDefined(value)) { + return value; + } - const newValue = {}; - assignPropValue(obj, propName, newValue, options); + const newValue = {}; + assignPropValue(obj, propName, newValue, options); - return newValue; + return newValue; }; -export const compileSetter = function(expr) { - expr = getPathParts(expr || 'this'); - const lastLevelIndex = expr.length - 1; - - return function(obj, value, options) { - options = prepareOptions(options); - let currentValue = unwrap(obj, options); - - expr.forEach(function(propertyName, levelIndex) { - let propertyValue = readPropValue(currentValue, propertyName, options); - const isPropertyFunc = !options.functionsAsIs && isFunction(propertyValue) && !isWrapped(propertyValue); - - if(levelIndex === lastLevelIndex) { - if(options.merge && isPlainObject(value) && (!isDefined(propertyValue) || isPlainObject(propertyValue))) { - propertyValue = ensurePropValueDefined(currentValue, propertyName, propertyValue, options); - deepExtendArraySafe(propertyValue, value, false, true); - } else if(isPropertyFunc) { - currentValue[propertyName](value); - } else { - assignPropValue(currentValue, propertyName, value, options); - } - } else { - propertyValue = ensurePropValueDefined(currentValue, propertyName, propertyValue, options); - if(isPropertyFunc) { - propertyValue = propertyValue.call(currentValue); - } - currentValue = propertyValue; - } - }); - }; +export const compileSetter = function (expr) { + expr = getPathParts(expr || 'this'); + const lastLevelIndex = expr.length - 1; + + return function (obj, value, options) { + options = prepareOptions(options); + let currentValue = unwrap(obj, options); + + expr.forEach(function (propertyName, levelIndex) { + let propertyValue = readPropValue(currentValue, propertyName, options); + const isPropertyFunc = !options.functionsAsIs && isFunction(propertyValue) && !isWrapped(propertyValue); + + if (levelIndex === lastLevelIndex) { + if (options.merge && isPlainObject(value) && (!isDefined(propertyValue) || isPlainObject(propertyValue))) { + propertyValue = ensurePropValueDefined(currentValue, propertyName, propertyValue, options); + deepExtendArraySafe(propertyValue, value, false, true); + } else if (isPropertyFunc) { + currentValue[propertyName](value); + } else { + assignPropValue(currentValue, propertyName, value, options); + } + } else { + propertyValue = ensurePropValueDefined(currentValue, propertyName, propertyValue, options); + if (isPropertyFunc) { + propertyValue = propertyValue.call(currentValue); + } + currentValue = propertyValue; + } + }); + }; }; -export const toComparable = function(value, caseSensitive, options = {}) { - if(value instanceof Date) { - return value.getTime(); - } +export const toComparable = function (value, caseSensitive?, options: any = {}) { + if (value instanceof Date) { + return value.getTime(); + } - const collatorSensitivity = options?.collatorOptions?.sensitivity; + const collatorSensitivity = options?.collatorOptions?.sensitivity; - if(value && value instanceof Class && value.valueOf) { - value = value.valueOf(); - } else if(typeof value === 'string' && (collatorSensitivity === 'base' || collatorSensitivity === 'case')) { - const REMOVE_DIACRITICAL_MARKS_REGEXP = /[\u0300-\u036f]/g; + if (value && value instanceof Class && value.valueOf) { + value = value.valueOf(); + } else if (typeof value === 'string' && (collatorSensitivity === 'base' || collatorSensitivity === 'case')) { + const REMOVE_DIACRITICAL_MARKS_REGEXP = /[\u0300-\u036f]/g; - if(collatorSensitivity === 'base') { - value = toLowerCase(value, options); - } - - value = value.normalize('NFD').replace(REMOVE_DIACRITICAL_MARKS_REGEXP, ''); + if (collatorSensitivity === 'base') { + value = toLowerCase(value, options); } - const isCaseSensitive = caseSensitive || collatorSensitivity === 'case' || collatorSensitivity === 'variant'; + value = value.normalize('NFD').replace(REMOVE_DIACRITICAL_MARKS_REGEXP, ''); + } - if(typeof value === 'string' && !isCaseSensitive) { - const locale = options?.locale?.toLowerCase(); - const useUpperCase = locale && !!['hy', 'el'].find((code) => locale === code || locale.startsWith(`${code}-`)); + const isCaseSensitive = caseSensitive || collatorSensitivity === 'case' || collatorSensitivity === 'variant'; - return (useUpperCase ? toUpperCase : toLowerCase)(value, options); - } + if (typeof value === 'string' && !isCaseSensitive) { + const locale = options?.locale?.toLowerCase(); + const useUpperCase = locale && !!['hy', 'el'].find((code) => locale === code || locale.startsWith(`${code}-`)); - return value; + return (useUpperCase ? toUpperCase : toLowerCase)(value, options); + } + + return value; }; diff --git a/packages/devextreme/js/__internal/core/utils/m_date.ts b/packages/devextreme/js/__internal/core/utils/m_date.ts index 7c9dde7451c4..ed5f11487ef6 100644 --- a/packages/devextreme/js/__internal/core/utils/m_date.ts +++ b/packages/devextreme/js/__internal/core/utils/m_date.ts @@ -1,11 +1,14 @@ /* globals Intl */ // TODO refactoring: Review all date utils functions and move useful to __internal/core/utils/date.ts -import { isObject, isString, isDate, isDefined, isNumeric } from './type'; -import { adjust } from './math'; -import { each } from './iterator'; -import { camelize } from './inflector'; -import { toMilliseconds } from '../../renovation/ui/common/utils/date/index'; -import dateSerialization from './date_serialization'; +import dateSerialization from '@js/core/utils/date_serialization'; +import { camelize } from '@js/core/utils/inflector'; +import { each } from '@js/core/utils/iterator'; +import { adjust } from '@js/core/utils/math'; +import { + isDate, isDefined, isNumeric, isObject, isString, +} from '@js/core/utils/type'; + +import { toMilliseconds } from '../../../renovation/ui/common/utils/date/index'; const DAYS_IN_WEEK = 7; const THURSDAY_WEEK_NUMBER = 4; @@ -14,782 +17,787 @@ const USUAL_WEEK_COUNT_IN_YEAR = 52; const dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year']; -const getDatesInterval = function(startDate, endDate, intervalUnit) { - const delta = endDate.getTime() - startDate.getTime(); - const millisecondCount = toMilliseconds(intervalUnit) || 1; - - return Math.floor(delta / millisecondCount); -}; - -const getNextDateUnit = function(unit, withWeeks) { - const interval = getDateUnitInterval(unit); - - switch(interval) { - case 'millisecond': - return 'second'; - case 'second': - return 'minute'; - case 'minute': - return 'hour'; - case 'hour': - return 'day'; - case 'day': - return withWeeks ? 'week' : 'month'; - case 'week': - return 'month'; - case 'month': - return 'quarter'; - case 'quarter': - return 'year'; - case 'year': - return 'year'; - default: - return 0; - } -}; - -const convertMillisecondsToDateUnits = function(value) { - let i; - let dateUnitCount; - let dateUnitInterval; - const dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'month', 'year']; - const result = {}; - - for(i = dateUnitIntervals.length - 1; i >= 0; i--) { - dateUnitInterval = dateUnitIntervals[i]; - dateUnitCount = Math.floor(value / toMilliseconds(dateUnitInterval)); - if(dateUnitCount > 0) { - result[dateUnitInterval + 's'] = dateUnitCount; - value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount); - } - } - return result; -}; - -const dateToMilliseconds = function(tickInterval) { - let milliseconds = 0; - if(isObject(tickInterval)) { - each(tickInterval, function(key, value) { - milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value); - }); - } - if(isString(tickInterval)) { - milliseconds = convertDateUnitToMilliseconds(tickInterval, 1); - } - return milliseconds; +const getDatesInterval = function (startDate, endDate, intervalUnit) { + const delta = endDate.getTime() - startDate.getTime(); + const millisecondCount = toMilliseconds(intervalUnit) || 1; + + return Math.floor(delta / millisecondCount); +}; + +const getNextDateUnit = function (unit, withWeeks) { + const interval = getDateUnitInterval(unit); + + switch (interval) { + case 'millisecond': + return 'second'; + case 'second': + return 'minute'; + case 'minute': + return 'hour'; + case 'hour': + return 'day'; + case 'day': + return withWeeks ? 'week' : 'month'; + case 'week': + return 'month'; + case 'month': + return 'quarter'; + case 'quarter': + return 'year'; + case 'year': + return 'year'; + default: + return 0; + } +}; + +const convertMillisecondsToDateUnits = function (value) { + let i; + let dateUnitCount; + let dateUnitInterval; + const dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'month', 'year']; + const result = {}; + + for (i = dateUnitIntervals.length - 1; i >= 0; i--) { + dateUnitInterval = dateUnitIntervals[i]; + dateUnitCount = Math.floor(value / toMilliseconds(dateUnitInterval)); + if (dateUnitCount > 0) { + result[`${dateUnitInterval}s`] = dateUnitCount; + value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount); + } + } + return result; +}; + +const dateToMilliseconds = function (tickInterval) { + let milliseconds = 0; + if (isObject(tickInterval)) { + each(tickInterval, function (key, value) { + milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value); + }); + } + if (isString(tickInterval)) { + milliseconds = convertDateUnitToMilliseconds(tickInterval, 1); + } + return milliseconds; }; function convertDateUnitToMilliseconds(dateUnit, count) { - return toMilliseconds(dateUnit) * count; + return toMilliseconds(dateUnit) * count; } // refactor for performance function getDateUnitInterval(tickInterval) { - let maxInterval = -1; - let i; - - if(isString(tickInterval)) { - return tickInterval; - } - - if(isObject(tickInterval)) { - each(tickInterval, function(key, value) { - for(i = 0; i < dateUnitIntervals.length; i++) { - if(value && (key === dateUnitIntervals[i] + 's' || key === dateUnitIntervals[i]) && maxInterval < i) { - maxInterval = i; - } - } - }); + let maxInterval = -1; + let i; + + if (isString(tickInterval)) { + return tickInterval; + } + + if (isObject(tickInterval)) { + each(tickInterval, function (key, value) { + for (i = 0; i < dateUnitIntervals.length; i++) { + if (value && (key === `${dateUnitIntervals[i]}s` || key === dateUnitIntervals[i]) && maxInterval < i) { + maxInterval = i; + } + } + }); - return dateUnitIntervals[maxInterval]; - } - return ''; + return dateUnitIntervals[maxInterval]; + } + return ''; } // T375972 const tickIntervalToFormatMap = { - millisecond: 'millisecond', - second: 'longtime', - minute: 'shorttime', - hour: 'shorttime', - day: 'day', - week: 'day', - month: 'month', - quarter: 'quarter', - year: 'year' + millisecond: 'millisecond', + second: 'longtime', + minute: 'shorttime', + hour: 'shorttime', + day: 'day', + week: 'day', + month: 'month', + quarter: 'quarter', + year: 'year', }; // Because of changes in formatting (Globalize has been updated) common date formatting has been changed. // The purpose of the following method is to preserve original dates formatting in axes and range selector slider markers. function getDateFormatByTickInterval(tickInterval) { - return tickIntervalToFormatMap[getDateUnitInterval(tickInterval)] || ''; + return tickIntervalToFormatMap[getDateUnitInterval(tickInterval)] || ''; } -const getQuarter = function(month) { - return Math.floor(month / 3); -}; - -const getFirstQuarterMonth = function(month) { - return getQuarter(month) * 3; -}; - -function correctDateWithUnitBeginning(date, dateInterval, withCorrection, firstDayOfWeek) { - date = new Date(date.getTime()); - const oldDate = new Date(date.getTime()); - let firstQuarterMonth; - let month; - const dateUnitInterval = getDateUnitInterval(dateInterval); - - switch(dateUnitInterval) { - case 'second': - date = new Date(Math.floor(oldDate.getTime() / 1000) * 1000); - break; - case 'minute': - date = new Date(Math.floor(oldDate.getTime() / 60000) * 60000); - break; - case 'hour': - date = new Date(Math.floor(oldDate.getTime() / 3600000) * 3600000); - break; - case 'year': - date.setMonth(0); - /* falls through */ - case 'month': - date.setDate(1); - /* falls through */ - case 'day': - date.setHours(0, 0, 0, 0); - break; - case 'week': - date = getFirstWeekDate(date, firstDayOfWeek || 0); - date.setHours(0, 0, 0, 0); - break; - case 'quarter': - firstQuarterMonth = getFirstQuarterMonth(date.getMonth()); - month = date.getMonth(); - - date.setDate(1); - date.setHours(0, 0, 0, 0); - if(month !== firstQuarterMonth) { - date.setMonth(firstQuarterMonth); - } - break; - } - - if(withCorrection && dateUnitInterval !== 'hour' && dateUnitInterval !== 'minute' && dateUnitInterval !== 'second') { - fixTimezoneGap(oldDate, date); - } - return date; +const getQuarter = function (month) { + return Math.floor(month / 3); +}; + +const getFirstQuarterMonth = function (month) { + return getQuarter(month) * 3; +}; + +function correctDateWithUnitBeginning(date, dateInterval, withCorrection?, firstDayOfWeek?) { + date = new Date(date.getTime()); + const oldDate = new Date(date.getTime()); + let firstQuarterMonth; + let month; + const dateUnitInterval = getDateUnitInterval(dateInterval); + + // eslint-disable-next-line default-case + switch (dateUnitInterval) { + case 'second': + date = new Date(Math.floor(oldDate.getTime() / 1000) * 1000); + break; + case 'minute': + date = new Date(Math.floor(oldDate.getTime() / 60000) * 60000); + break; + case 'hour': + date = new Date(Math.floor(oldDate.getTime() / 3600000) * 3600000); + break; + case 'year': + date.setMonth(0); + /* falls through */ + case 'month': + date.setDate(1); + /* falls through */ + case 'day': + date.setHours(0, 0, 0, 0); + break; + case 'week': + date = getFirstWeekDate(date, firstDayOfWeek || 0); + date.setHours(0, 0, 0, 0); + break; + case 'quarter': + firstQuarterMonth = getFirstQuarterMonth(date.getMonth()); + month = date.getMonth(); + + date.setDate(1); + date.setHours(0, 0, 0, 0); + if (month !== firstQuarterMonth) { + date.setMonth(firstQuarterMonth); + } + break; + } + + if (withCorrection && dateUnitInterval !== 'hour' && dateUnitInterval !== 'minute' && dateUnitInterval !== 'second') { + fixTimezoneGap(oldDate, date); + } + return date; } function trimTime(date) { - return correctDateWithUnitBeginning(date, 'day'); + return correctDateWithUnitBeginning(date, 'day'); } -const setToDayEnd = function(date) { - const result = trimTime(date); +const setToDayEnd = function (date) { + const result = trimTime(date); - result.setDate(result.getDate() + 1); - return new Date(result.getTime() - 1); + result.setDate(result.getDate() + 1); + return new Date(result.getTime() - 1); }; +const getDatesDifferences = function (date1, date2) { + let counter = 0; -const getDatesDifferences = function(date1, date2) { - let counter = 0; + const differences: any = { + year: date1.getFullYear() !== date2.getFullYear(), + month: date1.getMonth() !== date2.getMonth(), + day: date1.getDate() !== date2.getDate(), + hour: date1.getHours() !== date2.getHours(), + minute: date1.getMinutes() !== date2.getMinutes(), + second: date1.getSeconds() !== date2.getSeconds(), + millisecond: date1.getMilliseconds() !== date2.getMilliseconds(), + }; - const differences = { - year: date1.getFullYear() !== date2.getFullYear(), - month: date1.getMonth() !== date2.getMonth(), - day: date1.getDate() !== date2.getDate(), - hour: date1.getHours() !== date2.getHours(), - minute: date1.getMinutes() !== date2.getMinutes(), - second: date1.getSeconds() !== date2.getSeconds(), - millisecond: date1.getMilliseconds() !== date2.getMilliseconds() - }; - - each(differences, function(key, value) { - if(value) { - counter++; - } - }); - if(counter === 0 && getTimezonesDifference(date1, date2) !== 0) { - differences.hour = true; - counter++; + each(differences, function (key, value) { + if (value) { + counter++; } + }); + if (counter === 0 && getTimezonesDifference(date1, date2) !== 0) { + differences.hour = true; + counter++; + } - differences.count = counter; - return differences; + differences.count = counter; + return differences; }; function addDateInterval(value, interval, dir) { - const result = new Date(value.getTime()); - const intervalObject = isString(interval) ? getDateIntervalByString(interval.toLowerCase()) - : isNumeric(interval) ? convertMillisecondsToDateUnits(interval) - : interval; - if(intervalObject.years) { - result.setFullYear(result.getFullYear() + intervalObject.years * dir); - } - if(intervalObject.quarters) { - result.setMonth(result.getMonth() + 3 * intervalObject.quarters * dir); - } - if(intervalObject.months) { - result.setMonth(result.getMonth() + intervalObject.months * dir); - } - if(intervalObject.weeks) { - result.setDate(result.getDate() + 7 * intervalObject.weeks * dir); - } - if(intervalObject.days) { - result.setDate(result.getDate() + intervalObject.days * dir); - } - if(intervalObject.hours) { - result.setTime(result.getTime() + intervalObject.hours * 3600000 * dir); - } - if(intervalObject.minutes) { - result.setTime(result.getTime() + intervalObject.minutes * 60000 * dir); - } - if(intervalObject.seconds) { - result.setTime(result.getTime() + intervalObject.seconds * 1000 * dir); - } - if(intervalObject.milliseconds) { - result.setTime(result.getTime() + intervalObject.milliseconds * dir); - } - return result; + const result = new Date(value.getTime()); + const intervalObject = isString(interval) ? getDateIntervalByString(interval.toLowerCase()) + : isNumeric(interval) ? convertMillisecondsToDateUnits(interval) + : interval; + if (intervalObject.years) { + result.setFullYear(result.getFullYear() + intervalObject.years * dir); + } + if (intervalObject.quarters) { + result.setMonth(result.getMonth() + 3 * intervalObject.quarters * dir); + } + if (intervalObject.months) { + result.setMonth(result.getMonth() + intervalObject.months * dir); + } + if (intervalObject.weeks) { + result.setDate(result.getDate() + 7 * intervalObject.weeks * dir); + } + if (intervalObject.days) { + result.setDate(result.getDate() + intervalObject.days * dir); + } + if (intervalObject.hours) { + result.setTime(result.getTime() + intervalObject.hours * 3600000 * dir); + } + if (intervalObject.minutes) { + result.setTime(result.getTime() + intervalObject.minutes * 60000 * dir); + } + if (intervalObject.seconds) { + result.setTime(result.getTime() + intervalObject.seconds * 1000 * dir); + } + if (intervalObject.milliseconds) { + result.setTime(result.getTime() + intervalObject.milliseconds * dir); + } + return result; } -const addInterval = function(value, interval, isNegative) { - const dir = isNegative ? -1 : +1; - return isDate(value) ? addDateInterval(value, interval, dir) : adjust(value + interval * dir, interval); +const addInterval = function (value, interval, isNegative?: boolean) { + const dir = isNegative ? -1 : +1; + return isDate(value) ? addDateInterval(value, interval, dir) : adjust(value + interval * dir, interval); }; -const getSequenceByInterval = function(min, max, interval) { - const intervals = []; - let cur; +const getSequenceByInterval = function (min, max, interval) { + const intervals: any[] = []; + let cur; - intervals.push(isDate(min) ? new Date(min.getTime()) : min); - cur = min; - while(cur < max) { - cur = addInterval(cur, interval); - intervals.push(cur); - } - return intervals; + intervals.push(isDate(min) ? new Date(min.getTime()) : min); + cur = min; + while (cur < max) { + cur = addInterval(cur, interval); + intervals.push(cur); + } + return intervals; }; -const getViewFirstCellDate = function(viewType, date) { - if(viewType === 'month') { return createDateWithFullYear(date.getFullYear(), date.getMonth(), 1); } - if(viewType === 'year') { return createDateWithFullYear(date.getFullYear(), 0, date.getDate()); } - if(viewType === 'decade') { return createDateWithFullYear(getFirstYearInDecade(date), date.getMonth(), date.getDate()); } - if(viewType === 'century') { return createDateWithFullYear(getFirstDecadeInCentury(date), date.getMonth(), date.getDate()); } +// @ts-expect-error not all code paths return value +const getViewFirstCellDate = function (viewType, date) { + if (viewType === 'month') { return createDateWithFullYear(date.getFullYear(), date.getMonth(), 1); } + if (viewType === 'year') { return createDateWithFullYear(date.getFullYear(), 0, date.getDate()); } + if (viewType === 'decade') { return createDateWithFullYear(getFirstYearInDecade(date), date.getMonth(), date.getDate()); } + if (viewType === 'century') { return createDateWithFullYear(getFirstDecadeInCentury(date), date.getMonth(), date.getDate()); } }; -const getViewLastCellDate = function(viewType, date) { - if(viewType === 'month') { return createDateWithFullYear(date.getFullYear(), date.getMonth(), getLastMonthDay(date)); } - if(viewType === 'year') { return createDateWithFullYear(date.getFullYear(), 11, date.getDate()); } - if(viewType === 'decade') { return createDateWithFullYear(getFirstYearInDecade(date) + 9, date.getMonth(), date.getDate()); } - if(viewType === 'century') { return createDateWithFullYear(getFirstDecadeInCentury(date) + 90, date.getMonth(), date.getDate()); } +// @ts-expect-error not all code paths return value +const getViewLastCellDate = function (viewType, date) { + if (viewType === 'month') { return createDateWithFullYear(date.getFullYear(), date.getMonth(), getLastMonthDay(date)); } + if (viewType === 'year') { return createDateWithFullYear(date.getFullYear(), 11, date.getDate()); } + if (viewType === 'decade') { return createDateWithFullYear(getFirstYearInDecade(date) + 9, date.getMonth(), date.getDate()); } + if (viewType === 'century') { return createDateWithFullYear(getFirstDecadeInCentury(date) + 90, date.getMonth(), date.getDate()); } }; -const getViewMinBoundaryDate = function(viewType, date) { - const resultDate = createDateWithFullYear(date.getFullYear(), date.getMonth(), 1); +const getViewMinBoundaryDate = function (viewType, date) { + const resultDate = createDateWithFullYear(date.getFullYear(), date.getMonth(), 1); - if(viewType === 'month') { - return resultDate; - } + if (viewType === 'month') { + return resultDate; + } - resultDate.setMonth(0); + resultDate.setMonth(0); - if(viewType === 'year') { - return resultDate; - } + if (viewType === 'year') { + return resultDate; + } - if(viewType === 'decade') { - resultDate.setFullYear(getFirstYearInDecade(date)); - } + if (viewType === 'decade') { + resultDate.setFullYear(getFirstYearInDecade(date)); + } - if(viewType === 'century') { - resultDate.setFullYear(getFirstDecadeInCentury(date)); - } + if (viewType === 'century') { + resultDate.setFullYear(getFirstDecadeInCentury(date)); + } - return resultDate; + return resultDate; }; -const getViewMaxBoundaryDate = function(viewType, date) { - const resultDate = new Date(date); - resultDate.setDate(getLastMonthDay(date)); +const getViewMaxBoundaryDate = function (viewType, date) { + const resultDate = new Date(date); + resultDate.setDate(getLastMonthDay(date)); - if(viewType === 'month') { - return resultDate; - } + if (viewType === 'month') { + return resultDate; + } - resultDate.setMonth(11); - resultDate.setDate(getLastMonthDay(resultDate)); + resultDate.setMonth(11); + resultDate.setDate(getLastMonthDay(resultDate)); - if(viewType === 'year') { - return resultDate; - } + if (viewType === 'year') { + return resultDate; + } - if(viewType === 'decade') { - resultDate.setFullYear(getFirstYearInDecade(date) + 9); - } + if (viewType === 'decade') { + resultDate.setFullYear(getFirstYearInDecade(date) + 9); + } - if(viewType === 'century') { - resultDate.setFullYear(getFirstDecadeInCentury(date) + 99); - } + if (viewType === 'century') { + resultDate.setFullYear(getFirstDecadeInCentury(date) + 99); + } - return resultDate; + return resultDate; }; function getLastMonthDay(date) { - const resultDate = createDateWithFullYear(date.getFullYear(), date.getMonth() + 1, 0); - return resultDate.getDate(); + const resultDate = createDateWithFullYear(date.getFullYear(), date.getMonth() + 1, 0); + return resultDate.getDate(); } - -const getViewUp = function(typeView) { - switch(typeView) { - case 'month': - return 'year'; - case 'year': - return 'decade'; - case 'decade': - return 'century'; - default: - break; - } +// @ts-expect-error not all code paths return value +const getViewUp = function (typeView) { + switch (typeView) { + case 'month': + return 'year'; + case 'year': + return 'decade'; + case 'decade': + return 'century'; + default: + break; + } }; - -const getViewDown = function(typeView) { - switch(typeView) { - case 'century': - return 'decade'; - case 'decade': - return 'year'; - case 'year': - return 'month'; - default: - break; - } +// @ts-expect-error not all code paths return value +const getViewDown = function (typeView) { + switch (typeView) { + case 'century': + return 'decade'; + case 'decade': + return 'year'; + case 'year': + return 'month'; + default: + break; + } }; -const getDifferenceInMonth = function(typeView) { - let difference = 1; +const getDifferenceInMonth = function (typeView) { + let difference = 1; - if(typeView === 'year') { difference = 12; } - if(typeView === 'decade') { difference = 12 * 10; } - if(typeView === 'century') { difference = 12 * 100; } + if (typeView === 'year') { difference = 12; } + if (typeView === 'decade') { difference = 12 * 10; } + if (typeView === 'century') { difference = 12 * 100; } - return difference; + return difference; }; -const getDifferenceInMonthForCells = function(typeView) { - let difference = 1; +const getDifferenceInMonthForCells = function (typeView) { + let difference = 1; - if(typeView === 'decade') { difference = 12; } - if(typeView === 'century') { difference = 12 * 10; } + if (typeView === 'decade') { difference = 12; } + if (typeView === 'century') { difference = 12 * 10; } - return difference; + return difference; }; function getDateIntervalByString(intervalString) { - const result = {}; - switch(intervalString) { - case 'year': - result.years = 1; - break; - case 'month': - result.months = 1; - break; - case 'quarter': - result.months = 3; - break; - case 'week': - result.weeks = 1; - break; - case 'day': - result.days = 1; - break; - case 'hour': - result.hours = 1; - break; - case 'minute': - result.minutes = 1; - break; - case 'second': - result.seconds = 1; - break; - case 'millisecond': - result.milliseconds = 1; - break; - } - return result; + const result: any = {}; + // eslint-disable-next-line default-case + switch (intervalString) { + case 'year': + result.years = 1; + break; + case 'month': + result.months = 1; + break; + case 'quarter': + result.months = 3; + break; + case 'week': + result.weeks = 1; + break; + case 'day': + result.days = 1; + break; + case 'hour': + result.hours = 1; + break; + case 'minute': + result.minutes = 1; + break; + case 'second': + result.seconds = 1; + break; + case 'millisecond': + result.milliseconds = 1; + break; + } + return result; } function sameDate(date1, date2) { - return sameMonthAndYear(date1, date2) && date1.getDate() === date2.getDate(); + return sameMonthAndYear(date1, date2) && date1.getDate() === date2.getDate(); } function sameMonthAndYear(date1, date2) { - return sameYear(date1, date2) && date1.getMonth() === date2.getMonth(); + return sameYear(date1, date2) && date1.getMonth() === date2.getMonth(); } function sameYear(date1, date2) { - return date1 && date2 && date1.getFullYear() === date2.getFullYear(); + return date1 && date2 && date1.getFullYear() === date2.getFullYear(); } function sameHoursAndMinutes(date1, date2) { - return date1 && date2 && date1.getHours() === date2.getHours() && date1.getMinutes() === date2.getMinutes(); + return date1 && date2 && date1.getHours() === date2.getHours() && date1.getMinutes() === date2.getMinutes(); } -const sameDecade = function(date1, date2) { - if(!isDefined(date1) || !isDefined(date2)) return; +const sameDecade = function (date1, date2) { + if (!isDefined(date1) || !isDefined(date2)) return; - const startDecadeDate1 = date1.getFullYear() - date1.getFullYear() % 10; - const startDecadeDate2 = date2.getFullYear() - date2.getFullYear() % 10; + const startDecadeDate1 = date1.getFullYear() - date1.getFullYear() % 10; + const startDecadeDate2 = date2.getFullYear() - date2.getFullYear() % 10; - return date1 && date2 && startDecadeDate1 === startDecadeDate2; + return date1 && date2 && startDecadeDate1 === startDecadeDate2; }; -const sameCentury = function(date1, date2) { - if(!isDefined(date1) || !isDefined(date2)) return; +const sameCentury = function (date1, date2) { + if (!isDefined(date1) || !isDefined(date2)) return; - const startCenturyDate1 = date1.getFullYear() - date1.getFullYear() % 100; - const startCenturyDate2 = date2.getFullYear() - date2.getFullYear() % 100; + const startCenturyDate1 = date1.getFullYear() - date1.getFullYear() % 100; + const startCenturyDate2 = date2.getFullYear() - date2.getFullYear() % 100; - return date1 && date2 && startCenturyDate1 === startCenturyDate2; + return date1 && date2 && startCenturyDate1 === startCenturyDate2; }; function getFirstDecadeInCentury(date) { - return date && date.getFullYear() - date.getFullYear() % 100; + return date && date.getFullYear() - date.getFullYear() % 100; } function getFirstYearInDecade(date) { - return date && date.getFullYear() - date.getFullYear() % 10; + return date && date.getFullYear() - date.getFullYear() % 10; } -const getShortDateFormat = function() { - return 'yyyy/MM/dd'; +const getShortDateFormat = function () { + return 'yyyy/MM/dd'; }; -const getFirstMonthDate = function(date) { - if(!isDefined(date)) return; - return createDateWithFullYear(date.getFullYear(), date.getMonth(), 1); +const getFirstMonthDate = function (date) { + if (!isDefined(date)) return; + return createDateWithFullYear(date.getFullYear(), date.getMonth(), 1); }; -const getLastMonthDate = function(date) { - if(!isDefined(date)) return; - return createDateWithFullYear(date.getFullYear(), date.getMonth() + 1, 0); +const getLastMonthDate = function (date) { + if (!isDefined(date)) return; + return createDateWithFullYear(date.getFullYear(), date.getMonth() + 1, 0); }; function getFirstWeekDate(date, firstDayOfWeek) { - const delta = (date.getDay() - firstDayOfWeek + DAYS_IN_WEEK) % DAYS_IN_WEEK; + const delta = (date.getDay() - firstDayOfWeek + DAYS_IN_WEEK) % DAYS_IN_WEEK; - const result = new Date(date); - result.setDate(date.getDate() - delta); + const result = new Date(date); + result.setDate(date.getDate() - delta); - return result; + return result; } function getUTCTime(date) { - return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()); + return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()); } function getDayNumber(date) { - const ms = getUTCTime(date) - getUTCTime(getFirstDateInYear(date.getFullYear())); + const ms = getUTCTime(date) - getUTCTime(getFirstDateInYear(date.getFullYear())); - return 1 + Math.floor(ms / toMilliseconds('day')); + return 1 + Math.floor(ms / toMilliseconds('day')); } function getFirstDateInYear(year) { - return new Date(year, 0, 1); + return new Date(year, 0, 1); } function getLastDateInYear(year) { - return new Date(year, 11, 31); + return new Date(year, 11, 31); } function getDayWeekNumber(date, firstDayOfWeek) { - let day = date.getDay() - firstDayOfWeek + 1; - if(day <= 0) { day += DAYS_IN_WEEK; } + let day = date.getDay() - firstDayOfWeek + 1; + if (day <= 0) { day += DAYS_IN_WEEK; } - return day; + return day; } function getWeekNumber(date, firstDayOfWeek, rule) { - const firstWeekDayInYear = getDayWeekNumber(getFirstDateInYear(date.getFullYear()), firstDayOfWeek); - const lastWeekDayInYear = getDayWeekNumber(getLastDateInYear(date.getFullYear()), firstDayOfWeek); - const daysInFirstWeek = DAYS_IN_WEEK - firstWeekDayInYear + 1; - - let weekNumber = Math.ceil((getDayNumber(date) - daysInFirstWeek) / 7); - switch(rule) { - case 'fullWeek': { - if(daysInFirstWeek === DAYS_IN_WEEK) { weekNumber++; } - if(weekNumber === 0) { - const lastDateInPreviousYear = getLastDateInYear(date.getFullYear() - 1); - return getWeekNumber(lastDateInPreviousYear, firstDayOfWeek, rule); - } - return weekNumber; - } - case 'firstDay': { - if(daysInFirstWeek > 0) { weekNumber++; } - - const isSunday = firstWeekDayInYear === SUNDAY_WEEK_NUMBER + const firstWeekDayInYear = getDayWeekNumber(getFirstDateInYear(date.getFullYear()), firstDayOfWeek); + const lastWeekDayInYear = getDayWeekNumber(getLastDateInYear(date.getFullYear()), firstDayOfWeek); + const daysInFirstWeek = DAYS_IN_WEEK - firstWeekDayInYear + 1; + + let weekNumber = Math.ceil((getDayNumber(date) - daysInFirstWeek) / 7); + switch (rule) { + case 'fullWeek': { + if (daysInFirstWeek === DAYS_IN_WEEK) { weekNumber++; } + if (weekNumber === 0) { + const lastDateInPreviousYear = getLastDateInYear(date.getFullYear() - 1); + return getWeekNumber(lastDateInPreviousYear, firstDayOfWeek, rule); + } + return weekNumber; + } + case 'firstDay': { + if (daysInFirstWeek > 0) { weekNumber++; } + + const isSunday = firstWeekDayInYear === SUNDAY_WEEK_NUMBER || lastWeekDayInYear === SUNDAY_WEEK_NUMBER; - if((weekNumber > USUAL_WEEK_COUNT_IN_YEAR && !isSunday) || weekNumber === 54) { weekNumber = 1; } + if ((weekNumber > USUAL_WEEK_COUNT_IN_YEAR && !isSunday) || weekNumber === 54) { weekNumber = 1; } - return weekNumber; - } - case 'firstFourDays': { - if(daysInFirstWeek > 3) { weekNumber++; } + return weekNumber; + } + case 'firstFourDays': { + if (daysInFirstWeek > 3) { weekNumber++; } - const isThursday = firstWeekDayInYear === THURSDAY_WEEK_NUMBER + const isThursday = firstWeekDayInYear === THURSDAY_WEEK_NUMBER || lastWeekDayInYear === THURSDAY_WEEK_NUMBER; - if(weekNumber > USUAL_WEEK_COUNT_IN_YEAR && !isThursday) { weekNumber = 1; } + if (weekNumber > USUAL_WEEK_COUNT_IN_YEAR && !isThursday) { weekNumber = 1; } - if(weekNumber === 0) { - const lastDateInPreviousYear = getLastDateInYear(date.getFullYear() - 1); - return getWeekNumber(lastDateInPreviousYear, firstDayOfWeek, rule); - } - return weekNumber; - } - default: - break; + if (weekNumber === 0) { + const lastDateInPreviousYear = getLastDateInYear(date.getFullYear() - 1); + return getWeekNumber(lastDateInPreviousYear, firstDayOfWeek, rule); + } + return weekNumber; } + default: + break; + } } -const normalizeDateByWeek = function(date, currentDate) { - const differenceInDays = dateUtils.getDatesInterval(date, currentDate, 'day'); - let resultDate = new Date(date); +const normalizeDateByWeek = function (date, currentDate) { + const differenceInDays = dateUtils.getDatesInterval(date, currentDate, 'day'); + let resultDate = new Date(date); - if(differenceInDays >= 6) { - resultDate = new Date(resultDate.setDate(resultDate.getDate() + 7)); - } + if (differenceInDays >= 6) { + resultDate = new Date(resultDate.setDate(resultDate.getDate() + 7)); + } - return resultDate; + return resultDate; }; -const dateInRange = function(date, min, max, format) { - if(format === 'date') { - min = min && dateUtils.correctDateWithUnitBeginning(min, 'day'); - max = max && dateUtils.correctDateWithUnitBeginning(max, 'day'); - date = date && dateUtils.correctDateWithUnitBeginning(date, 'day'); - } +const dateInRange = function (date, min, max, format?) { + if (format === 'date') { + min = min && dateUtils.correctDateWithUnitBeginning(min, 'day'); + max = max && dateUtils.correctDateWithUnitBeginning(max, 'day'); + date = date && dateUtils.correctDateWithUnitBeginning(date, 'day'); + } - return normalizeDate(date, min, max) === date; + return normalizeDate(date, min, max) === date; }; -const intervalsOverlap = function(options) { - const { - firstMin, - firstMax, - secondMin, - secondMax - } = options; +const intervalsOverlap = function (options) { + const { + firstMin, + firstMax, + secondMin, + secondMax, + } = options; - return (firstMin <= secondMin && secondMin <= firstMax) || - (firstMin > secondMin && firstMin < secondMax) || - (firstMin < secondMax && firstMax > secondMax); + return (firstMin <= secondMin && secondMin <= firstMax) + || (firstMin > secondMin && firstMin < secondMax) + || (firstMin < secondMax && firstMax > secondMax); }; -const dateTimeFromDecimal = function(number) { - const hours = Math.floor(number); - const minutes = (number % 1) * 60; +const dateTimeFromDecimal = function (number) { + const hours = Math.floor(number); + const minutes = (number % 1) * 60; - return { - hours: hours, - minutes: minutes - }; + return { + hours, + minutes, + }; }; -const roundDateByStartDayHour = function(date, startDayHour) { - const startTime = this.dateTimeFromDecimal(startDayHour); - const result = new Date(date); +const roundDateByStartDayHour = function (date, startDayHour) { + const startTime = this.dateTimeFromDecimal(startDayHour); + const result = new Date(date); - if(date.getHours() === startTime.hours && date.getMinutes() < startTime.minutes || date.getHours() < startTime.hours) { - result.setHours(startTime.hours, startTime.minutes, 0, 0); - } + if (date.getHours() === startTime.hours && date.getMinutes() < startTime.minutes || date.getHours() < startTime.hours) { + result.setHours(startTime.hours, startTime.minutes, 0, 0); + } - return result; + return result; }; -function normalizeDate(date, min, max) { - let normalizedDate = date; +function normalizeDate(date, min?, max?) { + let normalizedDate = date; - if(!isDefined(date)) { - return date; - } + if (!isDefined(date)) { + return date; + } - if(isDefined(min) && date < min) { - normalizedDate = min; - } + if (isDefined(min) && date < min) { + normalizedDate = min; + } - if(isDefined(max) && date > max) { - normalizedDate = max; - } + if (isDefined(max) && date > max) { + normalizedDate = max; + } - return normalizedDate; + return normalizedDate; } function fixTimezoneGap(oldDate, newDate) { - // NOTE: T182866 - if(!isDefined(oldDate)) { - return; - } + // NOTE: T182866 + if (!isDefined(oldDate)) { + return; + } - const diff = newDate.getHours() - oldDate.getHours(); + const diff = newDate.getHours() - oldDate.getHours(); - if(diff === 0) { - return; - } + if (diff === 0) { + return; + } - const sign = (diff === 1 || diff === -23) ? -1 : 1; - const trial = new Date(newDate.getTime() + sign * 3600000); + const sign = diff === 1 || diff === -23 ? -1 : 1; + const trial = new Date(newDate.getTime() + sign * 3600000); - if(sign > 0 || trial.getDate() === newDate.getDate()) { - newDate.setTime(trial.getTime()); - } + if (sign > 0 || trial.getDate() === newDate.getDate()) { + newDate.setTime(trial.getTime()); + } } -const roundToHour = function(date) { - const result = new Date(date.getTime()); +const roundToHour = function (date) { + const result = new Date(date.getTime()); - result.setHours(result.getHours() + 1); - result.setMinutes(0); + result.setHours(result.getHours() + 1); + result.setMinutes(0); - return result; + return result; }; function getTimezonesDifference(min, max) { - return (max.getTimezoneOffset() - min.getTimezoneOffset()) * 60 * 1000; + return (max.getTimezoneOffset() - min.getTimezoneOffset()) * 60 * 1000; } -const makeDate = function(date) { - // TODO: will be useful later for work with different timezones - return new Date(date); +const makeDate = function (date) { + // TODO: will be useful later for work with different timezones + return new Date(date); }; -const getDatesOfInterval = function(startDate, endDate, step) { - const result = []; - let currentDate = new Date(startDate.getTime()); +const getDatesOfInterval = function (startDate, endDate, step) { + const result: any[] = []; + let currentDate = new Date(startDate.getTime()); - while(currentDate < endDate) { - result.push(new Date(currentDate.getTime())); + while (currentDate < endDate) { + result.push(new Date(currentDate.getTime())); - currentDate = this.addInterval(currentDate, step); - } + currentDate = this.addInterval(currentDate, step); + } - return result; + return result; }; -const createDateWithFullYear = function(year) { - const result = new Date(...arguments); - result.setFullYear(year); - return result; +const createDateWithFullYear = function (year, ...args) { + // @ts-expect-error spread should have tuple type + const result = new Date(year, ...args); + result.setFullYear(year); + return result; }; const getMachineTimezoneName = () => { - const hasIntl = typeof Intl !== 'undefined'; - return hasIntl - ? Intl.DateTimeFormat().resolvedOptions().timeZone - : null; + const hasIntl = typeof Intl !== 'undefined'; + return hasIntl + ? Intl.DateTimeFormat().resolvedOptions().timeZone + : null; }; const getRangesByDates = (dates) => { - const datesInMilliseconds = dates.map((value) => correctDateWithUnitBeginning(value, 'day').getTime()); - const sortedDates = datesInMilliseconds.sort((a, b) => a - b); + const datesInMilliseconds = dates.map((value) => correctDateWithUnitBeginning(value, 'day').getTime()); + const sortedDates = datesInMilliseconds.sort((a, b) => a - b); - const msInDay = toMilliseconds('day'); - const ranges = []; + const msInDay = toMilliseconds('day'); + const ranges: any[] = []; - let startDate = sortedDates[0]; + let startDate = sortedDates[0]; - for(let i = 1; i <= sortedDates.length; ++i) { - const nextDate = sortedDates[i]; - const currentDate = sortedDates[i - 1]; + for (let i = 1; i <= sortedDates.length; ++i) { + const nextDate = sortedDates[i]; + const currentDate = sortedDates[i - 1]; - const isNewRange = nextDate - currentDate > msInDay; + const isNewRange = nextDate - currentDate > msInDay; - if(isNewRange || i === sortedDates.length) { - const range = startDate === sortedDates[i - 1] - ? [startDate] - : [startDate, sortedDates[i - 1]]; + if (isNewRange || i === sortedDates.length) { + const range = startDate === sortedDates[i - 1] + ? [startDate] + : [startDate, sortedDates[i - 1]]; - const serializedRange = range.map((value) => dateSerialization.deserializeDate(value)); + const serializedRange = range.map((value) => dateSerialization.deserializeDate(value)); - ranges.push(serializedRange); + ranges.push(serializedRange); - startDate = nextDate; - } + startDate = nextDate; } + } + + return ranges; +}; - return ranges; +const sameView = function (view, date1, date2) { + return dateUtils[camelize(`same ${view}`)](date1, date2); }; const dateUtils = { - dateUnitIntervals: dateUnitIntervals, - - convertMillisecondsToDateUnits: convertMillisecondsToDateUnits, - dateToMilliseconds: dateToMilliseconds, - getNextDateUnit: getNextDateUnit, - convertDateUnitToMilliseconds: convertDateUnitToMilliseconds, - getDateUnitInterval: getDateUnitInterval, - getDateFormatByTickInterval: getDateFormatByTickInterval, // T375972 - getDatesDifferences: getDatesDifferences, - correctDateWithUnitBeginning: correctDateWithUnitBeginning, - trimTime: trimTime, - setToDayEnd: setToDayEnd, - roundDateByStartDayHour: roundDateByStartDayHour, - dateTimeFromDecimal: dateTimeFromDecimal, - - addDateInterval: addDateInterval, - addInterval: addInterval, - getSequenceByInterval: getSequenceByInterval, - getDateIntervalByString: getDateIntervalByString, - sameHoursAndMinutes: sameHoursAndMinutes, - sameDate: sameDate, - sameMonthAndYear: sameMonthAndYear, - sameMonth: sameMonthAndYear, - sameYear: sameYear, - sameDecade: sameDecade, - sameCentury: sameCentury, - getDifferenceInMonth: getDifferenceInMonth, - getDifferenceInMonthForCells: getDifferenceInMonthForCells, - getFirstYearInDecade: getFirstYearInDecade, - getFirstDecadeInCentury: getFirstDecadeInCentury, - getShortDateFormat: getShortDateFormat, - getViewFirstCellDate: getViewFirstCellDate, - getViewLastCellDate: getViewLastCellDate, - getViewDown: getViewDown, - getViewUp: getViewUp, - getLastMonthDay: getLastMonthDay, - getLastMonthDate: getLastMonthDate, - getFirstMonthDate: getFirstMonthDate, - getFirstWeekDate: getFirstWeekDate, - getWeekNumber: getWeekNumber, - normalizeDateByWeek: normalizeDateByWeek, - getQuarter: getQuarter, - getFirstQuarterMonth: getFirstQuarterMonth, - dateInRange: dateInRange, - intervalsOverlap: intervalsOverlap, - roundToHour: roundToHour, - normalizeDate: normalizeDate, - getViewMinBoundaryDate: getViewMinBoundaryDate, - getViewMaxBoundaryDate: getViewMaxBoundaryDate, - - fixTimezoneGap: fixTimezoneGap, - getTimezonesDifference: getTimezonesDifference, - - makeDate: makeDate, - - getDatesInterval: getDatesInterval, - - getDatesOfInterval: getDatesOfInterval, - - createDateWithFullYear: createDateWithFullYear, - - getMachineTimezoneName: getMachineTimezoneName, - - getRangesByDates: getRangesByDates, -}; - -dateUtils.sameView = function(view, date1, date2) { - return dateUtils[camelize('same ' + view)](date1, date2); -}; - -export default dateUtils; + dateUnitIntervals, + + convertMillisecondsToDateUnits, + dateToMilliseconds, + getNextDateUnit, + convertDateUnitToMilliseconds, + getDateUnitInterval, + getDateFormatByTickInterval, // T375972 + getDatesDifferences, + correctDateWithUnitBeginning, + trimTime, + setToDayEnd, + roundDateByStartDayHour, + dateTimeFromDecimal, + + addDateInterval, + addInterval, + getSequenceByInterval, + getDateIntervalByString, + sameHoursAndMinutes, + sameDate, + sameMonthAndYear, + sameMonth: sameMonthAndYear, + sameYear, + sameDecade, + sameCentury, + sameView, + getDifferenceInMonth, + getDifferenceInMonthForCells, + getFirstYearInDecade, + getFirstDecadeInCentury, + getShortDateFormat, + getViewFirstCellDate, + getViewLastCellDate, + getViewDown, + getViewUp, + getLastMonthDay, + getLastMonthDate, + getFirstMonthDate, + getFirstWeekDate, + getWeekNumber, + normalizeDateByWeek, + getQuarter, + getFirstQuarterMonth, + dateInRange, + intervalsOverlap, + roundToHour, + normalizeDate, + getViewMinBoundaryDate, + getViewMaxBoundaryDate, + + fixTimezoneGap, + getTimezonesDifference, + + makeDate, + + getDatesInterval, + + getDatesOfInterval, + + createDateWithFullYear, + + getMachineTimezoneName, + + getRangesByDates, +}; + +export { dateUtils }; diff --git a/packages/devextreme/js/__internal/core/utils/m_date_serialization.ts b/packages/devextreme/js/__internal/core/utils/m_date_serialization.ts index 0b87f7bee468..09ffd2877370 100644 --- a/packages/devextreme/js/__internal/core/utils/m_date_serialization.ts +++ b/packages/devextreme/js/__internal/core/utils/m_date_serialization.ts @@ -1,7 +1,7 @@ -import config from '../config'; -import { getFormatter as getLDMLFormatter } from '../../localization/ldml/date.formatter'; -import defaultDateNames from '../../localization/default_date_names'; -import { isString, isDate, isNumeric as isNumber } from './type'; +import config from '@js/core/config'; +import { isDate, isNumeric as isNumber, isString } from '@js/core/utils/type'; +import defaultDateNames from '@js/localization/default_date_names'; +import { getFormatter as getLDMLFormatter } from '@js/localization/ldml/date.formatter'; const NUMBER_SERIALIZATION_FORMAT = 'number'; const DATE_SERIALIZATION_FORMAT = 'yyyy/MM/dd'; @@ -15,167 +15,168 @@ const DATE_SERIALIZATION_PATTERN = /^(\d{4})\/(\d{2})\/(\d{2})$/; const MILLISECOND_LENGHT = 3; -const dateParser = function(text, skipISO8601Parsing) { - let result; +const dateParser = function (text, skipISO8601Parsing?: boolean) { + let result; - if(isString(text) && !skipISO8601Parsing) { - result = parseISO8601String(text); - } + if (isString(text) && !skipISO8601Parsing) { + result = parseISO8601String(text); + } - return result || parseDate(text); + return result || parseDate(text); }; function getTimePart(part) { - return +part || 0; + return +part || 0; } function parseDate(text) { - const isDefaultSerializationFormat = getDateSerializationFormat(text) === DATE_SERIALIZATION_FORMAT; - const parsedValue = !isDate(text) && Date.parse(text); - if(!parsedValue && isDefaultSerializationFormat) { - const parts = text.match(DATE_SERIALIZATION_PATTERN); - if(parts) { - const newDate = new Date(getTimePart(parts[1]), getTimePart(parts[2]), getTimePart(parts[3])); - newDate.setFullYear(getTimePart(parts[1])); - newDate.setMonth(getTimePart(parts[2]) - 1); - newDate.setDate(getTimePart(parts[3])); - return newDate; - } + const isDefaultSerializationFormat = getDateSerializationFormat(text) === DATE_SERIALIZATION_FORMAT; + const parsedValue = !isDate(text) && Date.parse(text); + if (!parsedValue && isDefaultSerializationFormat) { + const parts = text.match(DATE_SERIALIZATION_PATTERN); + if (parts) { + const newDate = new Date(getTimePart(parts[1]), getTimePart(parts[2]), getTimePart(parts[3])); + newDate.setFullYear(getTimePart(parts[1])); + newDate.setMonth(getTimePart(parts[2]) - 1); + newDate.setDate(getTimePart(parts[3])); + return newDate; } + } - return isNumber(parsedValue) ? new Date(parsedValue) : text; + return isNumber(parsedValue) ? new Date(parsedValue) : text; } function parseISO8601String(text) { - let parts = text.match(ISO8601_PATTERN); - - if(!parts) { - parts = text.match(ISO8601_TIME_PATTERN); - if(parts) { - return new Date(0, 0, 0, getTimePart(parts[1]), getTimePart(parts[2]), getTimePart(parts[4])); - } + let parts = text.match(ISO8601_PATTERN); - return; + if (!parts) { + parts = text.match(ISO8601_TIME_PATTERN); + if (parts) { + return new Date(0, 0, 0, getTimePart(parts[1]), getTimePart(parts[2]), getTimePart(parts[4])); } - const year = getTimePart(parts[1]); - const month = --parts[3]; - const day = parts[5]; - let timeZoneHour = 0; - let timeZoneMinute = 0; - const correctYear = (d) => { - year < 100 && d.setFullYear(year); - return d; - }; - - timeZoneHour = getTimePart(parts[14]); - timeZoneMinute = getTimePart(parts[16]); - - if(parts[13] === '-') { - timeZoneHour = -timeZoneHour; - timeZoneMinute = -timeZoneMinute; - } - - const hour = getTimePart(parts[6]) - timeZoneHour; - const minute = getTimePart(parts[8]) - timeZoneMinute; - const second = getTimePart(parts[10]); - const parseMilliseconds = function(part) { - part = part || ''; - return getTimePart(part) * Math.pow(10, MILLISECOND_LENGHT - part.length); - }; - const millisecond = parseMilliseconds(parts[11]); - - if(parts[12]) { - return correctYear(new Date(Date.UTC(year, month, day, hour, minute, second, millisecond))); - } - - return correctYear(new Date(year, month, day, hour, minute, second, millisecond)); + return; + } + + const year = getTimePart(parts[1]); + const month = --parts[3]; + const day = parts[5]; + let timeZoneHour = 0; + let timeZoneMinute = 0; + const correctYear = (d) => { + year < 100 && d.setFullYear(year); + return d; + }; + + timeZoneHour = getTimePart(parts[14]); + timeZoneMinute = getTimePart(parts[16]); + + if (parts[13] === '-') { + timeZoneHour = -timeZoneHour; + timeZoneMinute = -timeZoneMinute; + } + + const hour = getTimePart(parts[6]) - timeZoneHour; + const minute = getTimePart(parts[8]) - timeZoneMinute; + const second = getTimePart(parts[10]); + const parseMilliseconds = function (part) { + part = part || ''; + return getTimePart(part) * 10 ** (MILLISECOND_LENGHT - part.length); + }; + const millisecond = parseMilliseconds(parts[11]); + + if (parts[12]) { + return correctYear(new Date(Date.UTC(year, month, day, hour, minute, second, millisecond))); + } + + return correctYear(new Date(year, month, day, hour, minute, second, millisecond)); } -const getIso8601Format = function(text, useUtc) { - let parts = text.match(ISO8601_PATTERN); - let result = ''; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const getIso8601Format = function (text, useUtc?) { + let parts = text.match(ISO8601_PATTERN); + let result = ''; - if(!parts) { - parts = text.match(ISO8601_TIME_PATTERN); - if(parts) { - return parts[3] ? 'HH:mm:ss' : 'HH:mm'; - } - return; + if (!parts) { + parts = text.match(ISO8601_TIME_PATTERN); + if (parts) { + return parts[3] ? 'HH:mm:ss' : 'HH:mm'; } + return; + } - - for(let i = 1; i < ISO8601_PATTERN_PARTS.length; i++) { - if(parts[i]) { - result += ISO8601_PATTERN_PARTS[i] || parts[i]; - } + for (let i = 1; i < ISO8601_PATTERN_PARTS.length; i++) { + if (parts[i]) { + result += ISO8601_PATTERN_PARTS[i] || parts[i]; } - - if(parts[12] === 'Z') { - result += '\'Z\''; + } + + if (parts[12] === 'Z') { + result += '\'Z\''; + } + + if (parts[14]) { + if (parts[15]) { + result += 'xxx'; + } else if (parts[16]) { + result += 'xx'; + } else { + result += 'x'; } + } - if(parts[14]) { - if(parts[15]) { - result += 'xxx'; - } else if(parts[16]) { - result += 'xx'; - } else { - result += 'x'; - } - } - - return result; + return result; }; -const deserializeDate = function(value) { - if(typeof value === 'number') { - return new Date(value); - } +const deserializeDate = function (value) { + if (typeof value === 'number') { + return new Date(value); + } - return dateParser(value, !config().forceIsoDateParsing); + return dateParser(value, !config().forceIsoDateParsing); }; -const serializeDate = function(value, serializationFormat) { - if(!serializationFormat) { - return value; - } +const serializeDate = function (value, serializationFormat) { + if (!serializationFormat) { + return value; + } - if(!isDate(value)) { - return null; - } + if (!isDate(value)) { + return null; + } - if(serializationFormat === NUMBER_SERIALIZATION_FORMAT) { - return value && value.valueOf ? value.valueOf() : null; - } + if (serializationFormat === NUMBER_SERIALIZATION_FORMAT) { + return value && value.valueOf ? value.valueOf() : null; + } - return getLDMLFormatter(serializationFormat, defaultDateNames)(value); + return getLDMLFormatter(serializationFormat, defaultDateNames)(value); }; -const getDateSerializationFormat = function(value) { - if(typeof value === 'number') { - return NUMBER_SERIALIZATION_FORMAT; - } else if(isString(value)) { - let format; - - if(config().forceIsoDateParsing) { - format = getIso8601Format(value); - } - if(format) { - return format; - } else if(value.indexOf(':') >= 0) { - return DATETIME_SERIALIZATION_FORMAT; - } else { - return DATE_SERIALIZATION_FORMAT; - } - } else if(value) { - return null; +const getDateSerializationFormat = function (value) { + if (typeof value === 'number') { + return NUMBER_SERIALIZATION_FORMAT; + } if (isString(value)) { + let format; + + if (config().forceIsoDateParsing) { + format = getIso8601Format(value); } + if (format) { + return format; + } if (value.includes(':')) { + return DATETIME_SERIALIZATION_FORMAT; + } + return DATE_SERIALIZATION_FORMAT; + } if (value) { + return null; + } }; -export default { - dateParser: dateParser, - deserializeDate: deserializeDate, - serializeDate: serializeDate, - getDateSerializationFormat: getDateSerializationFormat +const dateSerialization = { + dateParser, + deserializeDate, + serializeDate, + getDateSerializationFormat, }; + +export { dateSerialization }; diff --git a/packages/devextreme/js/__internal/core/utils/m_deferred.ts b/packages/devextreme/js/__internal/core/utils/m_deferred.ts index 381f9b72ab15..ca4bcb249a84 100644 --- a/packages/devextreme/js/__internal/core/utils/m_deferred.ts +++ b/packages/devextreme/js/__internal/core/utils/m_deferred.ts @@ -1,179 +1,179 @@ -import { isDeferred, isDefined, isPromise } from '../utils/type'; -import { extend } from '../utils/extend'; -import Callbacks from '../utils/callbacks'; +import Callbacks from '@js/core/utils/callbacks'; +import { extend } from '@js/core/utils/extend'; +import { isDeferred, isDefined, isPromise } from '@js/core/utils/type'; const deferredConfig = [{ - method: 'resolve', - handler: 'done', - state: 'resolved' + method: 'resolve', + handler: 'done', + state: 'resolved', }, { - method: 'reject', - handler: 'fail', - state: 'rejected' + method: 'reject', + handler: 'fail', + state: 'rejected', }, { - method: 'notify', - handler: 'progress' + method: 'notify', + handler: 'progress', }]; -let DeferredObj = function() { - const that = this; - this._state = 'pending'; - this._promise = {}; - - deferredConfig.forEach(function(config) { - const methodName = config.method; - this[methodName + 'Callbacks'] = Callbacks(); - - this[methodName] = function() { - return this[methodName + 'With'](this._promise, arguments); - }.bind(this); - - this._promise[config.handler] = function(handler) { - if(!handler) return this; - - const callbacks = that[methodName + 'Callbacks']; - if(callbacks.fired()) { - handler.apply(that[methodName + 'Context'], that[methodName + 'Args']); - } else { - callbacks.add(function(context, args) { - handler.apply(context, args); - }.bind(this)); - } - return this; - }; - }.bind(this)); +let DeferredObj = function () { + const that = this; + this._state = 'pending'; + this._promise = {}; - this._promise.always = function(handler) { - return this.done(handler).fail(handler); - }; + deferredConfig.forEach(function (config) { + const methodName = config.method; + this[`${methodName}Callbacks`] = Callbacks(); - this._promise.catch = function(handler) { - return this.then(null, handler); - }; + this[methodName] = function () { + return this[`${methodName}With`](this._promise, arguments); + }.bind(this); - this._promise.then = function(resolve, reject) { - const result = new DeferredObj(); - - ['done', 'fail'].forEach(function(method) { - const callback = method === 'done' ? resolve : reject; - - this[method](function() { - if(!callback) { - result[method === 'done' ? 'resolve' : 'reject'].apply(this, arguments); - return; - } - - const callbackResult = callback && callback.apply(this, arguments); - if(isDeferred(callbackResult)) { - callbackResult.done(result.resolve).fail(result.reject); - } else if(isPromise(callbackResult)) { - callbackResult.then(result.resolve, result.reject); - } else { - result.resolve.apply(this, isDefined(callbackResult) ? [callbackResult] : arguments); - } - }); - }.bind(this)); - - return result.promise(); - }; + this._promise[config.handler] = function (handler) { + if (!handler) return this; - this._promise.state = function() { - return that._state; + const callbacks = that[`${methodName}Callbacks`]; + if (callbacks.fired()) { + handler.apply(that[`${methodName}Context`], that[`${methodName}Args`]); + } else { + callbacks.add(function (context, args) { + handler.apply(context, args); + }); + } + return this; }; + }.bind(this)); - this._promise.promise = function(args) { - return args ? extend(args, that._promise) : that._promise; - }; + this._promise.always = function (handler) { + return this.done(handler).fail(handler); + }; - this._promise.promise(this); -}; + this._promise.catch = function (handler) { + return this.then(null, handler); + }; -deferredConfig.forEach(function(config) { - const methodName = config.method; - const state = config.state; - - DeferredObj.prototype[methodName + 'With'] = function(context, args) { - const callbacks = this[methodName + 'Callbacks']; - - if(this.state() === 'pending') { - this[methodName + 'Args'] = args; - this[methodName + 'Context'] = context; - if(state) this._state = state; - callbacks.fire(context, args); - if(state !== 'pending') { - this.resolveCallbacks.empty(); - this.rejectCallbacks.empty(); - } + this._promise.then = function (resolve, reject) { + const result = new DeferredObj(); + + ['done', 'fail'].forEach(function (method) { + const callback = method === 'done' ? resolve : reject; + + this[method](function () { + if (!callback) { + result[method === 'done' ? 'resolve' : 'reject'].apply(this, arguments); + return; } - return this; - }; -}); + const callbackResult = callback && callback.apply(this, arguments); + if (isDeferred(callbackResult)) { + callbackResult.done(result.resolve).fail(result.reject); + } else if (isPromise(callbackResult)) { + callbackResult.then(result.resolve, result.reject); + } else { + result.resolve.apply(this, isDefined(callbackResult) ? [callbackResult] : arguments); + } + }); + }.bind(this)); -export function fromPromise(promise, context) { - if(isDeferred(promise)) { - return promise; - } else if(isPromise(promise)) { - const d = new DeferredObj(); - promise.then(function() { - d.resolveWith.apply(d, [context].concat([[].slice.call(arguments)])); - }, function() { - d.rejectWith.apply(d, [context].concat([[].slice.call(arguments)])); - }); - return d; - } + return result.promise(); + }; - return new DeferredObj().resolveWith(context, [promise]); -} + this._promise.state = function () { + return that._state; + }; -let whenFunc = function() { - if(arguments.length === 1) { - return fromPromise(arguments[0]); - } + this._promise.promise = function (args) { + return args ? extend(args, that._promise) : that._promise; + }; - const values = [].slice.call(arguments); - const contexts = []; - let resolvedCount = 0; - const deferred = new DeferredObj(); - - const updateState = function(i) { - return function(value) { - contexts[i] = this; - values[i] = arguments.length > 1 ? [].slice.call(arguments) : value; - resolvedCount++; - if(resolvedCount === values.length) { - deferred.resolveWith(contexts, values); - } - }; - }; + this._promise.promise(this); +}; - for(let i = 0; i < values.length; i++) { - if(isDeferred(values[i])) { - values[i].promise() - .done(updateState(i)) - .fail(deferred.reject); - } else { - resolvedCount++; - } +deferredConfig.forEach(function (config) { + const methodName = config.method; + const { state } = config; + + DeferredObj.prototype[`${methodName}With`] = function (context, args) { + const callbacks = this[`${methodName}Callbacks`]; + + if (this.state() === 'pending') { + this[`${methodName}Args`] = args; + this[`${methodName}Context`] = context; + if (state) this._state = state; + callbacks.fire(context, args); + if (state !== 'pending') { + this.resolveCallbacks.empty(); + this.rejectCallbacks.empty(); + } } - if(resolvedCount === values.length) { + return this; + }; +}); + +export function fromPromise(promise, context?: any) { + if (isDeferred(promise)) { + return promise; + } if (isPromise(promise)) { + const d = new DeferredObj(); + promise.then(function () { + d.resolveWith.apply(d, [context].concat([[].slice.call(arguments)])); + }, function () { + d.rejectWith.apply(d, [context].concat([[].slice.call(arguments)])); + }); + return d; + } + + return new DeferredObj().resolveWith(context, [promise]); +} + +let whenFunc = function () { + if (arguments.length === 1) { + return fromPromise(arguments[0]); + } + + const values: any[] = [].slice.call(arguments); + const contexts: any[] = []; + let resolvedCount = 0; + const deferred = new DeferredObj(); + + const updateState = function (i) { + return function (value) { + contexts[i] = this; + values[i] = arguments.length > 1 ? [].slice.call(arguments) : value; + resolvedCount++; + if (resolvedCount === values.length) { deferred.resolveWith(contexts, values); + } + }; + }; + + for (let i = 0; i < values.length; i++) { + if (isDeferred(values[i])) { + values[i].promise() + .done(updateState(i)) + .fail(deferred.reject); + } else { + resolvedCount++; } + } + + if (resolvedCount === values.length) { + deferred.resolveWith(contexts, values); + } - return deferred.promise(); + return deferred.promise(); }; export function setStrategy(value) { - DeferredObj = value.Deferred; - whenFunc = value.when; + DeferredObj = value.Deferred; + whenFunc = value.when; } export function Deferred() { - return new DeferredObj(); + return new DeferredObj(); } export function when() { - return whenFunc.apply(this, arguments); + // @ts-expect-error + return whenFunc.apply(this, arguments); } - diff --git a/packages/devextreme/js/__internal/core/utils/m_dependency_injector.ts b/packages/devextreme/js/__internal/core/utils/m_dependency_injector.ts index 6b7da1a67e62..acda838cd10d 100644 --- a/packages/devextreme/js/__internal/core/utils/m_dependency_injector.ts +++ b/packages/devextreme/js/__internal/core/utils/m_dependency_injector.ts @@ -1,44 +1,48 @@ -import { extend } from './extend'; -import { isFunction } from './type'; -import { each } from './iterator'; -import Class from '../class'; +/* eslint-disable prefer-arrow-callback */ +/* eslint-disable func-names */ +import Class from '@js/core/class'; +import { extend } from '@js/core/utils/extend'; +import { each } from '@js/core/utils/iterator'; +import { isFunction } from '@js/core/utils/type'; -export default function(object) { - const BaseClass = Class.inherit(object); - let InjectedClass = BaseClass; - let instance = new InjectedClass(object); - const initialFields = {}; +function injector(object) { + const BaseClass = Class.inherit(object); + let InjectedClass = BaseClass; + let instance = new InjectedClass(object); + const initialFields = {}; - const injectFields = function(injectionObject, initial) { - each(injectionObject, function(key) { - if(isFunction(instance[key])) { - if(initial || !object[key]) { - object[key] = function() { - return instance[key].apply(object, arguments); - }; - } - } else { - if(initial) { - initialFields[key] = object[key]; - } - object[key] = instance[key]; - } - }); - }; + const injectFields = function (injectionObject, initial?) { + each(injectionObject, function (key) { + if (isFunction(instance[key])) { + if (initial || !object[key]) { + object[key] = function () { + return instance[key].apply(object, arguments); + }; + } + } else { + if (initial) { + initialFields[key] = object[key]; + } + object[key] = instance[key]; + } + }); + }; - injectFields(object, true); + injectFields(object, true); - object.inject = function(injectionObject) { - InjectedClass = InjectedClass.inherit(injectionObject); - instance = new InjectedClass(); - injectFields(injectionObject); - }; + object.inject = function (injectionObject) { + InjectedClass = InjectedClass.inherit(injectionObject); + instance = new InjectedClass(); + injectFields(injectionObject); + }; - object.resetInjection = function() { - extend(object, initialFields); - InjectedClass = BaseClass; - instance = new BaseClass(); - }; + object.resetInjection = function () { + extend(object, initialFields); + InjectedClass = BaseClass; + instance = new BaseClass(); + }; - return object; + return object; } + +export { injector }; diff --git a/packages/devextreme/js/__internal/core/utils/m_dom.ts b/packages/devextreme/js/__internal/core/utils/m_dom.ts index 195466856316..1a36392a4b9e 100644 --- a/packages/devextreme/js/__internal/core/utils/m_dom.ts +++ b/packages/devextreme/js/__internal/core/utils/m_dom.ts @@ -1,164 +1,181 @@ -import domAdapter from '../../core/dom_adapter'; -import $ from '../../core/renderer'; -import { each } from './iterator'; -import { isDefined, isRenderer, isWindow, isString } from './type'; -import { getWindow } from './window'; +import domAdapter from '@js/core/dom_adapter'; +import $ from '@js/core/renderer'; +import { each } from '@js/core/utils/iterator'; +import { + isDefined, isRenderer, isString, isWindow, +} from '@js/core/utils/type'; +import { getWindow } from '@js/core/utils/window'; const window = getWindow(); const getRootNodeHost = (element) => { - if(!element.getRootNode) { - return undefined; - } + if (!element.getRootNode) { + return undefined; + } - const host = element.getRootNode().host; + const { host } = element.getRootNode(); - // NOTE: getRootNode().host can return a string if element is detached "a" element - if(isString(host)) { - return undefined; - } + // NOTE: getRootNode().host can return a string if element is detached "a" element + if (isString(host)) { + return undefined; + } - return host; + return host; }; export const resetActiveElement = () => { - const activeElement = domAdapter.getActiveElement(); + const activeElement = domAdapter.getActiveElement(); - if(activeElement && activeElement !== domAdapter.getBody()) { - activeElement.blur?.(); - } + if (activeElement && activeElement !== domAdapter.getBody()) { + activeElement.blur?.(); + } }; export const clearSelection = () => { - const selection = window.getSelection(); - if(!selection) return; - if(selection.type === 'Caret') return; - - if(selection.empty) { - selection.empty(); - } else if(selection.removeAllRanges) { - // T522811 - try { - selection.removeAllRanges(); - } catch(e) {} - } + const selection = window.getSelection(); + if (!selection) return; + if (selection.type === 'Caret') return; + + if (selection.empty) { + selection.empty(); + } else if (selection.removeAllRanges) { + // T522811 + try { + selection.removeAllRanges(); + } catch (e) { /* empty */ } + } }; export const closestCommonParent = (startTarget, endTarget) => { - const $startTarget = $(startTarget); - const $endTarget = $(endTarget); + const $startTarget = $(startTarget); + const $endTarget = $(endTarget); - if($startTarget[0] === $endTarget[0]) { - return $startTarget[0]; - } + if ($startTarget[0] === $endTarget[0]) { + return $startTarget[0]; + } - const $startParents = $startTarget.parents(); - const $endParents = $endTarget.parents(); - const startingParent = Math.min($startParents.length, $endParents.length); + const $startParents = $startTarget.parents(); + const $endParents = $endTarget.parents(); + const startingParent = Math.min($startParents.length, $endParents.length); - for(let i = -startingParent; i < 0; i++) { - if($startParents.get(i) === $endParents.get(i)) { - return $startParents.get(i); - } + for (let i = -startingParent; i < 0; i++) { + if ($startParents.get(i) === $endParents.get(i)) { + return $startParents.get(i); } + } }; export const extractTemplateMarkup = (element) => { - element = $(element); - - const templateTag = element.length && element.filter(function isNotExecutableScript() { - const $node = $(this); - return $node.is('script[type]') && ($node.attr('type').indexOf('script') < 0); - }); - - if(templateTag.length) { - return templateTag.eq(0).html(); - } else { - element = $('
').append(element); - return element.html(); - } + element = $(element); + + const templateTag = element.length && element.filter(function isNotExecutableScript() { + const $node = $(this); + // @ts-expect-error + return $node.is('script[type]') && !$node.attr('type').includes('script'); + }); + + if (templateTag.length) { + return templateTag.eq(0).html(); + } + element = $('
').append(element); + return element.html(); }; export const normalizeTemplateElement = (element) => { - let $element = isDefined(element) && (element.nodeType || isRenderer(element)) - ? $(element) - : $('
').html(element).contents(); - - if($element.length === 1) { - if($element.is('script')) { - $element = normalizeTemplateElement($element.html().trim()); - } else if($element.is('table')) { - $element = $element.children('tbody').contents(); - } + let $element = isDefined(element) && (element.nodeType || isRenderer(element)) + ? $(element) + : $('
').html(element).contents(); + + if ($element.length === 1) { + if ($element.is('script')) { + $element = normalizeTemplateElement($element.html().trim()); + } else if ($element.is('table')) { + $element = $element.children('tbody').contents(); } + } - return $element; + return $element; }; -export const clipboardText = (event, text) => { - const clipboard = (event.originalEvent && event.originalEvent.clipboardData) || window.clipboardData; - if(!text) { - return clipboard && clipboard.getData('Text'); - } +export const clipboardText = (event, text?) => { + // @ts-expect-error clipboardData doesn't exist in window type + const clipboard = (event.originalEvent && event.originalEvent.clipboardData) || window.clipboardData; + if (!text) { + return clipboard && clipboard.getData('Text'); + } - clipboard && clipboard.setData('Text', text); + clipboard && clipboard.setData('Text', text); }; export const contains = (container, element) => { - if(!element) { - return false; - } - if(isWindow(container)) { - return contains(container.document, element); - } - return container.contains(element) || contains(container, getRootNodeHost(element)); + if (!element) { + return false; + } + if (isWindow(container)) { + return contains(container.document, element); + } + return container.contains(element) || contains(container, getRootNodeHost(element)); }; -export const createTextElementHiddenCopy = (element, text, options) => { - const elementStyles = window.getComputedStyle($(element).get(0)); - const includePaddings = options && options.includePaddings; - - return $('
').text(text).css({ - 'fontStyle': elementStyles.fontStyle, - 'fontVariant': elementStyles.fontVariant, - 'fontWeight': elementStyles.fontWeight, - 'fontSize': elementStyles.fontSize, - 'fontFamily': elementStyles.fontFamily, - 'letterSpacing': elementStyles.letterSpacing, - 'border': elementStyles.border, - 'paddingTop': includePaddings ? elementStyles.paddingTop : '', - 'paddingRight': includePaddings ? elementStyles.paddingRight : '', - 'paddingBottom': includePaddings ? elementStyles.paddingBottom : '', - 'paddingLeft': includePaddings ? elementStyles.paddingLeft : '', - 'visibility': 'hidden', - 'whiteSpace': 'pre', - 'position': 'absolute', - 'float': 'left' - }); +export const createTextElementHiddenCopy = (element, text, options?) => { + const elementStyles = window.getComputedStyle($(element).get(0)); + const includePaddings = options && options.includePaddings; + + return $('
').text(text).css({ + fontStyle: elementStyles.fontStyle, + fontVariant: elementStyles.fontVariant, + fontWeight: elementStyles.fontWeight, + fontSize: elementStyles.fontSize, + fontFamily: elementStyles.fontFamily, + letterSpacing: elementStyles.letterSpacing, + border: elementStyles.border, + paddingTop: includePaddings ? elementStyles.paddingTop : '', + paddingRight: includePaddings ? elementStyles.paddingRight : '', + paddingBottom: includePaddings ? elementStyles.paddingBottom : '', + paddingLeft: includePaddings ? elementStyles.paddingLeft : '', + visibility: 'hidden', + whiteSpace: 'pre', + position: 'absolute', + float: 'left', + }); }; export const insertBefore = (element, newElement) => { - if(newElement) { - domAdapter.insertElement(element.parentNode, newElement, element); - } - return element; + if (newElement) { + domAdapter.insertElement(element.parentNode, newElement, element); + } + return element; }; export const replaceWith = (element, newElement) => { - if(!(newElement && newElement[0])) return; - if(newElement.is(element)) return element; + if (!(newElement && newElement[0])) return; + if (newElement.is(element)) return element; - each(newElement, (_, currentElement) => { - insertBefore(element[0], currentElement); - }); - element.remove(); + each(newElement, (_, currentElement) => { + insertBefore(element[0], currentElement); + }); + element.remove(); - return newElement; + return newElement; }; -export const isElementInDom = $element => { - const element = $element?.get(0); - const shadowHost = element?.getRootNode().host; +export const isElementInDom = ($element) => { + const element = $element?.get(0); + const shadowHost = element?.getRootNode().host; + + return !!$(shadowHost || element).closest(getWindow().document).length; +}; - return !!$(shadowHost || element).closest(getWindow().document).length; +export default { + resetActiveElement, + clearSelection, + closestCommonParent, + extractTemplateMarkup, + normalizeTemplateElement, + clipboardText, + contains, + createTextElementHiddenCopy, + insertBefore, + replaceWith, + isElementInDom, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_error.ts b/packages/devextreme/js/__internal/core/utils/m_error.ts index 7759cbcce27d..ff5fc27fc9f4 100644 --- a/packages/devextreme/js/__internal/core/utils/m_error.ts +++ b/packages/devextreme/js/__internal/core/utils/m_error.ts @@ -1,68 +1,71 @@ /* eslint-disable import/no-commonjs */ -import { extend } from './extend'; -import { logger } from './console'; -import { format } from './string'; -import { version } from '../version'; - -const ERROR_URL = 'https://js.devexpress.com/error/' + version.split('.').slice(0, 2).join('_') + '/'; - -export default function(baseErrors, errors) { - - const exports = { - - ERROR_MESSAGES: extend(errors, baseErrors), - - Error: function() { - return makeError([].slice.call(arguments)); - }, - - log: function(id) { - let method = 'log'; - - if(/^E\d+$/.test(id)) { - method = 'error'; - } else if(/^W\d+$/.test(id)) { - method = 'warn'; - } - - logger[method](method === 'log' ? id : combineMessage([].slice.call(arguments))); - } - }; - - function combineMessage(args) { - const id = args[0]; - args = args.slice(1); - return formatMessage(id, formatDetails(id, args)); - } - - function formatDetails(id, args) { - args = [exports.ERROR_MESSAGES[id]].concat(args); - return format.apply(this, args).replace(/\.*\s*?$/, ''); - } - - function formatMessage(id, details) { - const kind = id?.startsWith('W') ? 'warning' : 'error'; - return format.apply(this, ['{0} - {1}.\n\nFor additional information on this {2} message, see: {3}', id, details, kind, getErrorUrl(id)]); - } - - function makeError(args) { - const id = args[0]; - args = args.slice(1); - const details = formatDetails(id, args); - const url = getErrorUrl(id); - const message = formatMessage(id, details); - - return extend(new Error(message), { - __id: id, - __details: details, - url: url - }); - } - - function getErrorUrl(id) { - return ERROR_URL + id; - } - - return exports; - +import { extend } from '@js/core/utils/extend'; +import { format } from '@js/core/utils/string'; +import { version } from '@js/core/version'; + +import consoleUtils from './m_console'; + +const ERROR_URL = `https://js.devexpress.com/error/${version.split('.').slice(0, 2).join('_')}/`; + +function error(baseErrors, errors?) { + const exports = { + + ERROR_MESSAGES: extend(errors, baseErrors), + + // eslint-disable-next-line object-shorthand + Error: function (...args) { + return makeError(args); + }, + + log(...args) { + const id = args[0]; + let method = 'log'; + + if (/^E\d+$/.test(id)) { + method = 'error'; + } else if (/^W\d+$/.test(id)) { + method = 'warn'; + } + + consoleUtils.logger[method](method === 'log' ? id : combineMessage(args)); + }, + }; + + function combineMessage(args) { + const id = args[0]; + args = args.slice(1); + return formatMessage(id, formatDetails(id, args)); + } + + function formatDetails(id, args) { + args = [exports.ERROR_MESSAGES[id]].concat(args); + return format.apply(this, args).replace(/\.*\s*?$/, ''); + } + + function formatMessage(id, details) { + const kind = id?.startsWith('W') ? 'warning' : 'error'; + return format.apply(this, ['{0} - {1}.\n\nFor additional information on this {2} message, see: {3}', id, details, kind, getErrorUrl(id)]); + } + + function makeError(args) { + const id = args[0]; + args = args.slice(1); + const details = formatDetails(id, args); + const url = getErrorUrl(id); + const message = formatMessage(id, details); + + return extend(new Error(message), { + __id: id, + __details: details, + url, + }); + } + + function getErrorUrl(id) { + return ERROR_URL + id; + } + + return exports; } +export { error }; +export default error; diff --git a/packages/devextreme/js/__internal/core/utils/m_extend.ts b/packages/devextreme/js/__internal/core/utils/m_extend.ts index 77a64ea64e5e..cfbfe04debc7 100644 --- a/packages/devextreme/js/__internal/core/utils/m_extend.ts +++ b/packages/devextreme/js/__internal/core/utils/m_extend.ts @@ -1,62 +1,61 @@ -import { isPlainObject } from './type'; - -export const extendFromObject = function(target, source, overrideExistingValues) { - target = target || {}; - for(const prop in source) { - if(Object.prototype.hasOwnProperty.call(source, prop)) { - const value = source[prop]; - if(!(prop in target) || overrideExistingValues) { - target[prop] = value; - } - } +import { isPlainObject } from '@js/core/utils/type'; + +export const extendFromObject = function (target, source, overrideExistingValues) { + target = target || {}; + for (const prop in source) { + if (Object.prototype.hasOwnProperty.call(source, prop)) { + const value = source[prop]; + if (!(prop in target) || overrideExistingValues) { + target[prop] = value; + } } - return target; + } + return target; }; -export const extend = function(target) { - target = target || {}; +export const extend: any = function (target) { + target = target || {}; + + let i = 1; + let deep = false; - let i = 1; - let deep = false; + if (typeof target === 'boolean') { + deep = target; + target = arguments[1] || {}; + i++; + } - if(typeof target === 'boolean') { - deep = target; - target = arguments[1] || {}; - i++; + for (; i < arguments.length; i++) { + const source = arguments[i]; + if (source == null) { + continue; } - for(; i < arguments.length; i++) { - const source = arguments[i]; - if(source == null) { - continue; + for (const key in source) { + const targetValue = target[key]; + const sourceValue = source[key]; + let sourceValueIsArray = false; + let clone; + + if (key === '__proto__' || key === 'constructor' || target === sourceValue) { + continue; + } + + if (deep && sourceValue && (isPlainObject(sourceValue) + // eslint-disable-next-line no-cond-assign + || (sourceValueIsArray = Array.isArray(sourceValue)))) { + if (sourceValueIsArray) { + clone = targetValue && Array.isArray(targetValue) ? targetValue : []; + } else { + clone = targetValue && isPlainObject(targetValue) ? targetValue : {}; } - for(const key in source) { - const targetValue = target[key]; - const sourceValue = source[key]; - let sourceValueIsArray = false; - let clone; - - if(key === '__proto__' || key === 'constructor' || target === sourceValue) { - continue; - } - - if(deep && sourceValue && (isPlainObject(sourceValue) || - (sourceValueIsArray = Array.isArray(sourceValue)))) { - - if(sourceValueIsArray) { - clone = targetValue && Array.isArray(targetValue) ? targetValue : []; - } else { - clone = targetValue && isPlainObject(targetValue) ? targetValue : {}; - } - - target[key] = extend(deep, clone, sourceValue); - - } else if(sourceValue !== undefined) { - target[key] = sourceValue; - } - } + target[key] = extend(deep, clone, sourceValue); + } else if (sourceValue !== undefined) { + target[key] = sourceValue; + } } + } - return target; + return target; }; diff --git a/packages/devextreme/js/__internal/core/utils/m_html_parser.ts b/packages/devextreme/js/__internal/core/utils/m_html_parser.ts index 21426cc4b4ff..a8b4b6be967a 100644 --- a/packages/devextreme/js/__internal/core/utils/m_html_parser.ts +++ b/packages/devextreme/js/__internal/core/utils/m_html_parser.ts @@ -1,59 +1,59 @@ -import domAdapter from '../dom_adapter'; +import domAdapter from '@js/core/dom_adapter'; const isTagName = (/<([a-z][^/\0>\x20\t\r\n\f]+)/i); -const tagWrappers = { - default: { - tagsCount: 0, - startTags: '', - endTags: '' - }, - thead: { - tagsCount: 1, - startTags: '', - endTags: '
' - }, - td: { - tagsCount: 3, - startTags: '', - endTags: '
' - }, - col: { - tagsCount: 2, - startTags: '', - endTags: '
' - }, - tr: { - tagsCount: 2, - startTags: '', - endTags: '
' - }, +const tagWrappers: any = { + default: { + tagsCount: 0, + startTags: '', + endTags: '', + }, + thead: { + tagsCount: 1, + startTags: '', + endTags: '
', + }, + td: { + tagsCount: 3, + startTags: '', + endTags: '
', + }, + col: { + tagsCount: 2, + startTags: '', + endTags: '
', + }, + tr: { + tagsCount: 2, + startTags: '', + endTags: '
', + }, }; tagWrappers.tbody = tagWrappers.colgroup = tagWrappers.caption = tagWrappers.tfoot = tagWrappers.thead; tagWrappers.th = tagWrappers.td; -export const parseHTML = function(html) { - if(typeof html !== 'string') { - return null; - } +export const parseHTML = function (html) { + if (typeof html !== 'string') { + return null; + } - const fragment = domAdapter.createDocumentFragment(); - let container = fragment.appendChild(domAdapter.createElement('div')); - const tags = isTagName.exec(html); - const firstRootTag = tags && tags[1].toLowerCase(); - const tagWrapper = tagWrappers[firstRootTag] || tagWrappers.default; + const fragment = domAdapter.createDocumentFragment(); + let container: HTMLElement | ChildNode = fragment.appendChild(domAdapter.createElement('div')); + const tags = isTagName.exec(html); + const firstRootTag = tags?.[1].toLowerCase(); + const tagWrapper = tagWrappers[firstRootTag!] || tagWrappers.default; - container.innerHTML = tagWrapper.startTags + html + tagWrapper.endTags; + (container as HTMLElement).innerHTML = tagWrapper.startTags + html + tagWrapper.endTags; - for(let i = 0; i < tagWrapper.tagsCount; i++) { - container = container.lastChild; - } + for (let i = 0; i < tagWrapper.tagsCount; i++) { + container = container.lastChild!; + } - return [...container.childNodes]; + return [...container.childNodes]; }; -export const isTablePart = function(html) { - const tags = isTagName.exec(html); - return tags && tags[1] in tagWrappers; +export const isTablePart = function (html) { + const tags = isTagName.exec(html); + return tags && tags[1] in tagWrappers; }; diff --git a/packages/devextreme/js/__internal/core/utils/m_icon.ts b/packages/devextreme/js/__internal/core/utils/m_icon.ts index f5adfea791cc..2525500340f1 100644 --- a/packages/devextreme/js/__internal/core/utils/m_icon.ts +++ b/packages/devextreme/js/__internal/core/utils/m_icon.ts @@ -1,43 +1,43 @@ -import $ from '../../core/renderer'; +import $ from '@js/core/renderer'; const ICON_CLASS = 'dx-icon'; const SVG_ICON_CLASS = 'dx-svg-icon'; export const getImageSourceType = (source) => { - if(!source || typeof source !== 'string') { - return false; - } + if (!source || typeof source !== 'string') { + return false; + } - if(/^\s*]*>(.|\r?\n)*?<\/svg>\s*$/i.test(source)) { - return 'svg'; - } + if (/^\s*]*>(.|\r?\n)*?<\/svg>\s*$/i.test(source)) { + return 'svg'; + } - if(/data:.*base64|\.|[^<\s]\/{1,1}/.test(source)) { - return 'image'; - } + if (/data:.*base64|\.|[^<\s]\/{1,1}/.test(source)) { + return 'image'; + } - if(/^[\w-_]+$/.test(source)) { - return 'dxIcon'; - } + if (/^[\w-_]+$/.test(source)) { + return 'dxIcon'; + } - if(/^\s?([\w-_:]\s?)+$/.test(source)) { - return 'fontIcon'; - } + if (/^\s?([\w-_:]\s?)+$/.test(source)) { + return 'fontIcon'; + } - return false; + return false; }; export const getImageContainer = (source) => { - switch(getImageSourceType(source)) { - case 'image': - return $('').attr('src', source).addClass(ICON_CLASS); - case 'fontIcon': - return $('').addClass(`${ICON_CLASS} ${source}`); - case 'dxIcon': - return $('').addClass(`${ICON_CLASS} ${ICON_CLASS}-${source}`); - case 'svg': - return $('').addClass(`${ICON_CLASS} ${SVG_ICON_CLASS}`).append(source); - default: - return null; - } + switch (getImageSourceType(source)) { + case 'image': + return $('').attr('src', source).addClass(ICON_CLASS); + case 'fontIcon': + return $('').addClass(`${ICON_CLASS} ${source}`); + case 'dxIcon': + return $('').addClass(`${ICON_CLASS} ${ICON_CLASS}-${source}`); + case 'svg': + return $('').addClass(`${ICON_CLASS} ${SVG_ICON_CLASS}`).append(source); + default: + return null; + } }; diff --git a/packages/devextreme/js/__internal/core/utils/m_inflector.ts b/packages/devextreme/js/__internal/core/utils/m_inflector.ts index eff346cdf3c4..2780edcad369 100644 --- a/packages/devextreme/js/__internal/core/utils/m_inflector.ts +++ b/packages/devextreme/js/__internal/core/utils/m_inflector.ts @@ -1,75 +1,85 @@ -import { map } from './iterator'; +/* eslint-disable @typescript-eslint/naming-convention */ +import { map } from '@js/core/utils/iterator'; -const _normalize = function(text) { - if(text === undefined || text === null) { - return ''; - } - return String(text); +const _normalize = function (text) { + if (text === undefined || text === null) { + return ''; + } + return String(text); }; -const _upperCaseFirst = function(text) { - return _normalize(text).charAt(0).toUpperCase() + text.substr(1); +const _upperCaseFirst = function (text) { + return _normalize(text).charAt(0).toUpperCase() + text.substr(1); }; -const _chop = function(text) { - return _normalize(text) - .replace(/([a-z\d])([A-Z])/g, '$1 $2') - .split(/[\s_-]+/); +const _chop = function (text) { + return _normalize(text) + .replace(/([a-z\d])([A-Z])/g, '$1 $2') + .split(/[\s_-]+/); }; -export const dasherize = function(text) { - return map(_chop(text), function(p) { return p.toLowerCase(); }).join('-'); +export const dasherize = function (text) { + return map(_chop(text), function (p) { return p.toLowerCase(); }).join('-'); }; -export const underscore = function(text) { - return dasherize(text).replace(/-/g, '_'); +export const underscore = function (text) { + return dasherize(text).replace(/-/g, '_'); }; -export const camelize = function(text, upperFirst) { - return map(_chop(text), function(p, i) { - p = p.toLowerCase(); - if(upperFirst || i > 0) { - p = _upperCaseFirst(p); - } - return p; - }).join(''); +export const camelize = function (text, upperFirst?) { + return map(_chop(text), function (p, i) { + p = p.toLowerCase(); + if (upperFirst || i > 0) { + p = _upperCaseFirst(p); + } + return p; + }).join(''); }; -export const humanize = function(text) { - return _upperCaseFirst(dasherize(text).replace(/-/g, ' ')); +export const humanize = function (text) { + return _upperCaseFirst(dasherize(text).replace(/-/g, ' ')); }; -export const titleize = function(text) { - return map(_chop(text), function(p) { - return _upperCaseFirst(p.toLowerCase()); - }).join(' '); +export const titleize = function (text) { + return map(_chop(text), function (p) { + return _upperCaseFirst(p.toLowerCase()); + }).join(' '); }; const DIGIT_CHARS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; -export const captionize = function(name) { - const captionList = []; - let i; - let char; - let isPrevCharNewWord = false; - let isNewWord = false; +export const captionize = function (name) { + const captionList: any[] = []; + let i; + let char; + let isPrevCharNewWord = false; + let isNewWord = false; - for(i = 0; i < name.length; i++) { - char = name.charAt(i); - isNewWord = (char === char.toUpperCase() && char !== '-' && char !== ')' && char !== '/') || (char in DIGIT_CHARS); - if(char === '_' || char === '.') { - char = ' '; - isNewWord = true; - } else if(i === 0) { - char = char.toUpperCase(); - isNewWord = true; - } else if(!isPrevCharNewWord && isNewWord) { - if(captionList.length > 0) { - captionList.push(' '); - } - } - captionList.push(char); - isPrevCharNewWord = isNewWord; + for (i = 0; i < name.length; i++) { + char = name.charAt(i); + isNewWord = (char === char.toUpperCase() && char !== '-' && char !== ')' && char !== '/') || (char in DIGIT_CHARS); + if (char === '_' || char === '.') { + char = ' '; + isNewWord = true; + } else if (i === 0) { + char = char.toUpperCase(); + isNewWord = true; + } else if (!isPrevCharNewWord && isNewWord) { + if (captionList.length > 0) { + captionList.push(' '); + } } - return captionList.join(''); + captionList.push(char); + isPrevCharNewWord = isNewWord; + } + return captionList.join(''); +}; + +export default { + dasherize, + underscore, + camelize, + humanize, + titleize, + captionize, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_iterator.ts b/packages/devextreme/js/__internal/core/utils/m_iterator.ts index 344650e17143..6b6b17d5e989 100644 --- a/packages/devextreme/js/__internal/core/utils/m_iterator.ts +++ b/packages/devextreme/js/__internal/core/utils/m_iterator.ts @@ -1,15 +1,15 @@ -const map = (values, callback) => { - if(Array.isArray(values)) { - return values.map(callback); - } +const map = (values, callback): any[] => { + if (Array.isArray(values)) { + return values.map(callback); + } - const result = []; + const result: unknown[] = []; - for(const key in values) { - result.push(callback(values[key], key)); - } + for (const key in values) { + result.push(callback(values[key], key)); + } - return result; + return result; }; /** @@ -19,37 +19,38 @@ const map = (values, callback) => { * }} */ const each = (values, callback) => { - if(!values) return; - - if('length' in values) { - for(let i = 0; i < values.length; i++) { - if(callback.call(values[i], i, values[i]) === false) { - break; - } - } - } else { - for(const key in values) { - if(callback.call(values[key], key, values[key]) === false) { - break; - } - } + if (!values) return; + + if ('length' in values) { + for (let i = 0; i < values.length; i++) { + if (callback.call(values[i], i, values[i]) === false) { + break; + } + } + } else { + // eslint-disable-next-line no-restricted-syntax + for (const key in values) { + if (callback.call(values[key], key, values[key]) === false) { + break; + } } + } - return values; + return values; }; const reverseEach = (array, callback) => { - if(!array || !('length' in array) || array.length === 0) return; + if (!array || !('length' in array) || array.length === 0) return; - for(let i = array.length - 1; i >= 0; i--) { - if(callback.call(array[i], i, array[i]) === false) { - break; - } + for (let i = array.length - 1; i >= 0; i--) { + if (callback.call(array[i], i, array[i]) === false) { + break; } + } }; export { - map, - each, - reverseEach + each, + map, + reverseEach, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_locker.ts b/packages/devextreme/js/__internal/core/utils/m_locker.ts index a9ca993d7d44..8aa46cce1440 100644 --- a/packages/devextreme/js/__internal/core/utils/m_locker.ts +++ b/packages/devextreme/js/__internal/core/utils/m_locker.ts @@ -1,35 +1,36 @@ -import errors from '../errors'; - -const Locker = function() { - const info = {}; - - const currentCount = function(lockName) { - return info[lockName] || 0; - }; - - return { - obtain: function(lockName) { - info[lockName] = currentCount(lockName) + 1; - }, - - release: function(lockName) { - const count = currentCount(lockName); - - if(count < 1) { - throw errors.Error('E0014'); - } - - if(count === 1) { - delete info[lockName]; - } else { - info[lockName] = count - 1; - } - }, - - locked: function(lockName) { - return currentCount(lockName) > 0; - } - }; +import errors from '@js/core/errors'; + +const Locker = function () { + const info = {}; + + const currentCount = function (lockName) { + return info[lockName] || 0; + }; + + return { + obtain(lockName) { + info[lockName] = currentCount(lockName) + 1; + }, + + release(lockName) { + const count = currentCount(lockName); + + if (count < 1) { + throw errors.Error('E0014'); + } + + if (count === 1) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete info[lockName]; + } else { + info[lockName] = count - 1; + } + }, + + locked(lockName) { + return currentCount(lockName) > 0; + }, + }; }; -export default Locker; +export { Locker }; diff --git a/packages/devextreme/js/__internal/core/utils/m_math.ts b/packages/devextreme/js/__internal/core/utils/m_math.ts index b24e643923fd..f4745378b13e 100644 --- a/packages/devextreme/js/__internal/core/utils/m_math.ts +++ b/packages/devextreme/js/__internal/core/utils/m_math.ts @@ -1,200 +1,201 @@ -import { isExponential } from './type'; +import { isExponential } from '@js/core/utils/type'; -const sign = function(value) { - if(value === 0) { - return 0; - } +const sign = function (value) { + if (value === 0) { + return 0; + } - return value / Math.abs(value); + return value / Math.abs(value); }; -const fitIntoRange = function(value, minValue, maxValue) { - const isMinValueUndefined = !minValue && minValue !== 0; - const isMaxValueUndefined = !maxValue && maxValue !== 0; +const fitIntoRange = function (value, minValue, maxValue) { + const isMinValueUndefined = !minValue && minValue !== 0; + const isMaxValueUndefined = !maxValue && maxValue !== 0; - isMinValueUndefined && (minValue = !isMaxValueUndefined ? Math.min(value, maxValue) : value); - isMaxValueUndefined && (maxValue = !isMinValueUndefined ? Math.max(value, minValue) : value); + isMinValueUndefined && (minValue = !isMaxValueUndefined ? Math.min(value, maxValue) : value); + isMaxValueUndefined && (maxValue = !isMinValueUndefined ? Math.max(value, minValue) : value); - return Math.min(Math.max(value, minValue), maxValue); + return Math.min(Math.max(value, minValue), maxValue); }; -const inRange = function(value, minValue, maxValue) { - return value >= minValue && value <= maxValue; +const inRange = function (value, minValue, maxValue) { + return value >= minValue && value <= maxValue; }; function getExponent(value) { - return Math.abs(parseInt(value.toExponential().split('e')[1])); + return Math.abs(parseInt(value.toExponential().split('e')[1], 10)); } function getExponentialNotation(value) { - const parts = value.toExponential().split('e'); + const parts = value.toExponential().split('e'); - const mantissa = parseFloat(parts[0]); - const exponent = parseInt(parts[1]); + const mantissa = parseFloat(parts[0]); + const exponent = parseInt(parts[1], 10); - return { - exponent, - mantissa, - }; + return { + exponent, + mantissa, + }; } function multiplyInExponentialForm(value, exponentShift) { - const exponentialNotation = getExponentialNotation(value); + const exponentialNotation = getExponentialNotation(value); - return parseFloat(`${exponentialNotation.mantissa}e${exponentialNotation.exponent + exponentShift}`); + return parseFloat(`${exponentialNotation.mantissa}e${exponentialNotation.exponent + exponentShift}`); } // T570217 -function _isEdgeBug() { - const value = 0.0003; - const correctValue = '0.000300'; - const precisionValue = 3; - return correctValue !== value.toPrecision(precisionValue); +function isEdgeBug() { + const value = 0.0003; + const correctValue = '0.000300'; + const precisionValue = 3; + return correctValue !== value.toPrecision(precisionValue); } function adjust(value, interval) { - let precision = getPrecision(interval || 0) + 2; - const separatedValue = value.toString().split('.'); - const sourceValue = value; - const absValue = Math.abs(value); - let separatedAdjustedValue; - const isExponentValue = isExponential(value); - const integerPart = absValue > 1 ? 10 : 0; - - if(separatedValue.length === 1) { - return value; - } - - if(!isExponentValue) { - if(isExponential(interval)) { - precision = separatedValue[0].length + getExponent(interval); - } - value = absValue; - value = value - Math.floor(value) + integerPart; + let precision = getPrecision(interval || 0) + 2; + const separatedValue = value.toString().split('.'); + const sourceValue = value; + const absValue = Math.abs(value); + let separatedAdjustedValue; + const isExponentValue = isExponential(value); + const integerPart = absValue > 1 ? 10 : 0; + + if (separatedValue.length === 1) { + return value; + } + + if (!isExponentValue) { + if (isExponential(interval)) { + precision = separatedValue[0].length + getExponent(interval); } + value = absValue; + value = value - Math.floor(value) + integerPart; + } - precision = ((_isEdgeBug() && (getExponent(value) > 6)) || precision > 7) ? 15 : 7; // fix toPrecision() bug in Edge (T570217) + precision = (isEdgeBug() && (getExponent(value) > 6)) || precision > 7 ? 15 : 7; // fix toPrecision() bug in Edge (T570217) - if(!isExponentValue) { - separatedAdjustedValue = parseFloat(value.toPrecision(precision)).toString().split('.'); - if(separatedAdjustedValue[0] === integerPart.toString()) { - return parseFloat(separatedValue[0] + '.' + separatedAdjustedValue[1]); - } + if (!isExponentValue) { + separatedAdjustedValue = parseFloat(value.toPrecision(precision)).toString().split('.'); + if (separatedAdjustedValue[0] === integerPart.toString()) { + return parseFloat(`${separatedValue[0]}.${separatedAdjustedValue[1]}`); } - return parseFloat(sourceValue.toPrecision(precision)); + } + return parseFloat(sourceValue.toPrecision(precision)); } function getPrecision(value) { - const str = value.toString(); + const str = value.toString(); - if(str.indexOf('.') < 0) { - return 0; - } + if (str.indexOf('.') < 0) { + return 0; + } - const mantissa = str.split('.'); - const positionOfDelimiter = mantissa[1].indexOf('e'); + const mantissa = str.split('.'); + const positionOfDelimiter = mantissa[1].indexOf('e'); - return positionOfDelimiter >= 0 ? positionOfDelimiter : mantissa[1].length; + return positionOfDelimiter >= 0 ? positionOfDelimiter : mantissa[1].length; } function getRoot(x, n) { - if(x < 0 && n % 2 !== 1) { - return NaN; - } + if (x < 0 && n % 2 !== 1) { + return NaN; + } - const y = Math.pow(Math.abs(x), 1 / n); - return n % 2 === 1 && x < 0 ? -y : y; + const y = Math.abs(x) ** (1 / n); + return n % 2 === 1 && x < 0 ? -y : y; } function solveCubicEquation(a, b, c, d) { - const min = 1e-8; - if(Math.abs(a) < min) { - a = b; b = c; c = d; - if(Math.abs(a) < min) { - a = b; b = c; - if(Math.abs(a) < min) { - return []; - } - return [-b / a]; - } - - const D2 = b * b - 4 * a * c; - if(Math.abs(D2) < min) { - return [-b / (2 * a)]; - } else if(D2 > 0) { - return [(-b + Math.sqrt(D2)) / (2 * a), (-b - Math.sqrt(D2)) / (2 * a)]; - } + const min = 1e-8; + if (Math.abs(a) < min) { + a = b; b = c; c = d; + if (Math.abs(a) < min) { + a = b; b = c; + if (Math.abs(a) < min) { return []; + } + return [-b / a]; } - const p = (3 * a * c - b * b) / (3 * a * a); - const q = (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) / (27 * a * a * a); - let roots; - let u; - - if(Math.abs(p) < min) { - roots = [getRoot(-q, 3)]; - } else if(Math.abs(q) < min) { - roots = [0].concat(p < 0 ? [Math.sqrt(-p), -Math.sqrt(-p)] : []); + const D2 = b * b - 4 * a * c; + if (Math.abs(D2) < min) { + return [-b / (2 * a)]; + } if (D2 > 0) { + return [(-b + Math.sqrt(D2)) / (2 * a), (-b - Math.sqrt(D2)) / (2 * a)]; + } + return []; + } + + const p = (3 * a * c - b * b) / (3 * a * a); + const q = (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) / (27 * a * a * a); + let roots; + let u; + + if (Math.abs(p) < min) { + roots = [getRoot(-q, 3)]; + } else if (Math.abs(q) < min) { + roots = [0].concat(p < 0 ? [Math.sqrt(-p), -Math.sqrt(-p)] : []); + } else { + const D3 = q * q / 4 + p * p * p / 27; + if (Math.abs(D3) < min) { + roots = [-1.5 * q / p, 3 * q / p]; + } else if (D3 > 0) { + u = getRoot(-q / 2 - Math.sqrt(D3), 3); + roots = [u - p / (3 * u)]; } else { - const D3 = q * q / 4 + p * p * p / 27; - if(Math.abs(D3) < min) { - roots = [-1.5 * q / p, 3 * q / p]; - } else if(D3 > 0) { - u = getRoot(-q / 2 - Math.sqrt(D3), 3); - roots = [u - p / (3 * u)]; - } else { - u = 2 * Math.sqrt(-p / 3); - const t = Math.acos(3 * q / p / u) / 3; - const k = 2 * Math.PI / 3; - roots = [u * Math.cos(t), u * Math.cos(t - k), u * Math.cos(t - 2 * k)]; - } + u = 2 * Math.sqrt(-p / 3); + const t = Math.acos(3 * q / p / u) / 3; + const k = 2 * Math.PI / 3; + roots = [u * Math.cos(t), u * Math.cos(t - k), u * Math.cos(t - 2 * k)]; } + } - for(let i = 0; i < roots.length; i++) { - roots[i] -= b / (3 * a); - } + for (let i = 0; i < roots.length; i++) { + roots[i] -= b / (3 * a); + } - return roots; + return roots; } function trunc(value) { - return Math.trunc ? Math.trunc(value) : (value > 0 ? Math.floor(value) : Math.ceil(value)); + return Math.trunc ? Math.trunc(value) : value > 0 ? Math.floor(value) : Math.ceil(value); } function getRemainderByDivision(dividend, divider, digitsCount) { - if(divider === parseInt(divider)) { - return dividend % divider; - } + if (divider === parseInt(divider, 10)) { + return dividend % divider; + } - const quotient = roundFloatPart(dividend / divider, digitsCount); - return (quotient - parseInt(quotient)) * divider; + const quotient = roundFloatPart(dividend / divider, digitsCount); + // @ts-expect-error probably remove parseInt here + return (quotient - parseInt(quotient, 10)) * divider; } function getExponentLength(value) { - const valueString = value.toString(); + const valueString = value.toString(); - return valueString.split('.')[1]?.length - || parseInt(valueString.split('e-')[1]) + return valueString.split('.')[1]?.length + || parseInt(valueString.split('e-')[1], 10) || 0; } function roundFloatPart(value, digitsCount = 0) { - return parseFloat(value.toFixed(digitsCount)); + return parseFloat(value.toFixed(digitsCount)); } export { - sign, - fitIntoRange, - inRange, - adjust, - getPrecision, - getExponent, - getRoot, - solveCubicEquation, - trunc, - roundFloatPart, - getExponentLength, - getRemainderByDivision, - multiplyInExponentialForm, + adjust, + fitIntoRange, + getExponent, + getExponentLength, + getPrecision, + getRemainderByDivision, + getRoot, + inRange, + multiplyInExponentialForm, + roundFloatPart, + sign, + solveCubicEquation, + trunc, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_object.ts b/packages/devextreme/js/__internal/core/utils/m_object.ts index f851747d0bc9..d2d3aa009244 100644 --- a/packages/devextreme/js/__internal/core/utils/m_object.ts +++ b/packages/devextreme/js/__internal/core/utils/m_object.ts @@ -1,120 +1,121 @@ -import { isNumeric, isPlainObject, isObject } from './type'; -import variableWrapper from './variable_wrapper'; +import { isNumeric, isObject, isPlainObject } from '@js/core/utils/type'; +import variableWrapper from '@js/core/utils/variable_wrapper'; -const clone = (function() { - function Clone() { } +const clone = (function () { + function Clone() { } - return function(obj) { - Clone.prototype = obj; - return new Clone(); - }; + return function (obj) { + Clone.prototype = obj; + return new Clone(); + }; })(); -const orderEach = function(map, func) { - const keys = []; - let key; - let i; +const orderEach = function (map, func) { + const keys: string[] = []; + let key; + let i; - for(key in map) { - if(Object.prototype.hasOwnProperty.call(map, key)) { - keys.push(key); - } - } - - keys.sort(function(x, y) { - const isNumberX = isNumeric(x); - const isNumberY = isNumeric(y); - - if(isNumberX && isNumberY) return x - y; - if(isNumberX && !isNumberY) return -1; - if(!isNumberX && isNumberY) return 1; - if(x < y) return -1; - if(x > y) return 1; - return 0; - }); - - for(i = 0; i < keys.length; i++) { - key = keys[i]; - func(key, map[key]); + for (key in map) { + if (Object.prototype.hasOwnProperty.call(map, key)) { + keys.push(key); } + } + + keys.sort(function (x, y) { + const isNumberX = isNumeric(x); + const isNumberY = isNumeric(y); + + if (isNumberX && isNumberY) return x - y; + if (isNumberX && !isNumberY) return -1; + if (!isNumberX && isNumberY) return 1; + if (x < y) return -1; + if (x > y) return 1; + return 0; + }); + + for (i = 0; i < keys.length; i++) { + key = keys[i]; + func(key, map[key]); + } }; const getDeepCopyTarget = (item) => { - if(isObject(item)) { - return Array.isArray(item) ? [] : {}; - } - return item; + if (isObject(item)) { + return Array.isArray(item) ? [] : {}; + } + return item; }; -const legacyAssign = function(target, property, value, extendComplexObject, assignByReference, shouldCopyUndefined) { - if(!assignByReference && variableWrapper.isWrapped(target[property])) { - variableWrapper.assign(target[property], value); - } else { - target[property] = value; - } +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const legacyAssign = function (target, property, value, extendComplexObject, assignByReference, shouldCopyUndefined) { + if (!assignByReference && variableWrapper.isWrapped(target[property])) { + variableWrapper.assign(target[property], value); + } else { + target[property] = value; + } }; -const newAssign = function(target, property, value, extendComplexObject, assignByReference, shouldCopyUndefined) { - const goDeeper = extendComplexObject ? isObject(target) : isPlainObject(target); - if(!assignByReference && variableWrapper.isWrapped(target[property])) { - variableWrapper.assign(target[property], value); - } else if(!assignByReference && Array.isArray(value)) { - target[property] = value.map(item => deepExtendArraySafe( - getDeepCopyTarget(item), - item, - extendComplexObject, - assignByReference, - shouldCopyUndefined - )); - } else if(!assignByReference && goDeeper) { - target[property] = deepExtendArraySafe( - getDeepCopyTarget(value), - value, - extendComplexObject, - assignByReference, - shouldCopyUndefined, - newAssign - ); - } else { - target[property] = value; - } +const newAssign = function (target, property, value, extendComplexObject, assignByReference, shouldCopyUndefined) { + const goDeeper = extendComplexObject ? isObject(target) : isPlainObject(target); + if (!assignByReference && variableWrapper.isWrapped(target[property])) { + variableWrapper.assign(target[property], value); + } else if (!assignByReference && Array.isArray(value)) { + target[property] = value.map((item) => deepExtendArraySafe( + getDeepCopyTarget(item), + item, + extendComplexObject, + assignByReference, + shouldCopyUndefined, + )); + } else if (!assignByReference && goDeeper) { + target[property] = deepExtendArraySafe( + getDeepCopyTarget(value), + value, + extendComplexObject, + assignByReference, + shouldCopyUndefined, + newAssign, + ); + } else { + target[property] = value; + } }; // B239679, http://bugs.jquery.com/ticket/9477 -const deepExtendArraySafe = function(target, changes, extendComplexObject, assignByReference, shouldCopyUndefined, useNewAssign) { - let prevValue; - let newValue; - const assignFunc = useNewAssign ? newAssign : legacyAssign; - - for(const name in changes) { - prevValue = target[name]; - newValue = changes[name]; - - if(name === '__proto__' || name === 'constructor' || target === newValue) { - continue; - } - - if(isPlainObject(newValue)) { - const goDeeper = extendComplexObject ? isObject(prevValue) : isPlainObject(prevValue); - newValue = deepExtendArraySafe(goDeeper ? prevValue : {}, newValue, extendComplexObject, assignByReference, shouldCopyUndefined); - } - - const isDeepCopyArray = Array.isArray(newValue) && !assignByReference; - const hasDifferentNewValue = (shouldCopyUndefined || newValue !== undefined) && prevValue !== newValue || - shouldCopyUndefined && prevValue === undefined; - - if(isDeepCopyArray || hasDifferentNewValue) { - assignFunc(target, name, newValue, extendComplexObject, assignByReference, shouldCopyUndefined); - } +const deepExtendArraySafe = function (target, changes, extendComplexObject?, assignByReference?, shouldCopyUndefined?, useNewAssign?) { + let prevValue; + let newValue; + const assignFunc = useNewAssign ? newAssign : legacyAssign; + + for (const name in changes) { + prevValue = target[name]; + newValue = changes[name]; + + if (name === '__proto__' || name === 'constructor' || target === newValue) { + continue; + } + + if (isPlainObject(newValue)) { + const goDeeper = extendComplexObject ? isObject(prevValue) : isPlainObject(prevValue); + newValue = deepExtendArraySafe(goDeeper ? prevValue : {}, newValue, extendComplexObject, assignByReference, shouldCopyUndefined); + } + + const isDeepCopyArray = Array.isArray(newValue) && !assignByReference; + const hasDifferentNewValue = (shouldCopyUndefined || newValue !== undefined) && prevValue !== newValue + || shouldCopyUndefined && prevValue === undefined; + + if (isDeepCopyArray || hasDifferentNewValue) { + assignFunc(target, name, newValue, extendComplexObject, assignByReference, shouldCopyUndefined); } + } - return target; + return target; }; export { - clone, - orderEach, - deepExtendArraySafe, - legacyAssign, - newAssign + clone, + deepExtendArraySafe, + legacyAssign, + newAssign, + orderEach, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_position.ts b/packages/devextreme/js/__internal/core/utils/m_position.ts index 4a8adffcb46d..a8cf17cbb8c4 100644 --- a/packages/devextreme/js/__internal/core/utils/m_position.ts +++ b/packages/devextreme/js/__internal/core/utils/m_position.ts @@ -1,24 +1,24 @@ -import config from '../config'; -import { isWindow } from '../utils/type'; +import config from '@js/core/config'; +import { isWindow } from '@js/core/utils/type'; const getDefaultAlignment = (isRtlEnabled) => { - const rtlEnabled = isRtlEnabled ?? config().rtlEnabled; + const rtlEnabled = isRtlEnabled ?? config().rtlEnabled; - return rtlEnabled ? 'right' : 'left'; + return rtlEnabled ? 'right' : 'left'; }; const getBoundingRect = (element) => { - if(isWindow(element)) { - return { - width: element.outerWidth, - height: element.outerHeight - }; - } + if (isWindow(element)) { + return { + width: element.outerWidth, + height: element.outerHeight, + }; + } - return element.getBoundingClientRect(); + return element.getBoundingClientRect(); }; export { - getBoundingRect, - getDefaultAlignment + getBoundingRect, + getDefaultAlignment, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_public_component.ts b/packages/devextreme/js/__internal/core/utils/m_public_component.ts index facd902a0283..be3be2f12cd1 100644 --- a/packages/devextreme/js/__internal/core/utils/m_public_component.ts +++ b/packages/devextreme/js/__internal/core/utils/m_public_component.ts @@ -1,7 +1,7 @@ -import { data as elementData } from '../../core/element_data'; -import eventsEngine from '../../events/core/events_engine'; -import { isDefined } from './type'; -import { removeEvent } from '../../events/remove'; +import { data as elementData } from '@js/core/element_data'; +import { isDefined } from '@js/core/utils/type'; +import eventsEngine from '@js/events/core/events_engine'; +import { removeEvent } from '@js/events/remove'; const COMPONENT_NAMES_DATA_KEY = 'dxComponents'; const ANONYMOUS_COMPONENT_DATA_KEY = 'dxPrivateComponent'; @@ -9,44 +9,45 @@ const ANONYMOUS_COMPONENT_DATA_KEY = 'dxPrivateComponent'; const componentNames = new WeakMap(); let nextAnonymousComponent = 0; -const getName = function(componentClass, newName) { - if(isDefined(newName)) { - componentNames.set(componentClass, newName); - return; - } +const getName = function (componentClass, newName?) { + if (isDefined(newName)) { + componentNames.set(componentClass, newName); + return; + } - if(!componentNames.has(componentClass)) { - const generatedName = ANONYMOUS_COMPONENT_DATA_KEY + nextAnonymousComponent++; - componentNames.set(componentClass, generatedName); - return generatedName; - } + if (!componentNames.has(componentClass)) { + const generatedName = ANONYMOUS_COMPONENT_DATA_KEY + nextAnonymousComponent++; + componentNames.set(componentClass, generatedName); + return generatedName; + } - return componentNames.get(componentClass); + return componentNames.get(componentClass); }; export function attachInstanceToElement($element, componentInstance, disposeFn) { - const data = elementData($element.get(0)); - const name = getName(componentInstance.constructor); + const data = elementData($element.get(0)); + const name = getName(componentInstance.constructor); - data[name] = componentInstance; + data[name] = componentInstance; - if(disposeFn) { - eventsEngine.one($element, removeEvent, function() { - disposeFn.call(componentInstance); - }); - } + if (disposeFn) { + eventsEngine.one($element, removeEvent, function () { + disposeFn.call(componentInstance); + }); + } - if(!data[COMPONENT_NAMES_DATA_KEY]) { - data[COMPONENT_NAMES_DATA_KEY] = []; - } + if (!data[COMPONENT_NAMES_DATA_KEY]) { + data[COMPONENT_NAMES_DATA_KEY] = []; + } - data[COMPONENT_NAMES_DATA_KEY].push(name); + data[COMPONENT_NAMES_DATA_KEY].push(name); } export function getInstanceByElement($element, componentClass) { - const name = getName(componentClass); + const name = getName(componentClass); - return elementData($element.get(0), name); + return elementData($element.get(0), name); } export { getName as name }; +export default { name: getName }; diff --git a/packages/devextreme/js/__internal/core/utils/m_queue.ts b/packages/devextreme/js/__internal/core/utils/m_queue.ts index 70338e1a75a8..024ab5dd64ab 100644 --- a/packages/devextreme/js/__internal/core/utils/m_queue.ts +++ b/packages/devextreme/js/__internal/core/utils/m_queue.ts @@ -1,57 +1,58 @@ -import errors from '../errors'; -import { when } from '../../core/utils/deferred'; +import errors from '@js/core/errors'; +import { when } from '@js/core/utils/deferred'; -function createQueue(discardPendingTasks) { - let _tasks = []; - let _busy = false; +function createQueue(discardPendingTasks?: boolean) { + // eslint-disable-next-line @typescript-eslint/naming-convention + let _tasks: any[] = []; + // eslint-disable-next-line @typescript-eslint/naming-convention + let _busy = false; - function exec() { - while(_tasks.length) { - _busy = true; + function exec() { + while (_tasks.length) { + _busy = true; - const task = _tasks.shift(); - const result = task(); + const task = _tasks.shift(); + const result = task(); - if(result === undefined) { - continue; - } + if (result === undefined) { + continue; + } - if(result.then) { - // NOTE: immediate "then" on the next line can reset it back to false - when(result).always(exec); - return; - } + if (result.then) { + // NOTE: immediate "then" on the next line can reset it back to false + when(result).always(exec); + return; + } - throw errors.Error('E0015'); - } - - _busy = false; + throw errors.Error('E0015'); } - function add(task, removeTaskCallback) { - if(!discardPendingTasks) { - _tasks.push(task); - } else { - if(_tasks[0] && removeTaskCallback) { - removeTaskCallback(_tasks[0]); - } - _tasks = [task]; - } - if(!_busy) { - exec(); - } + _busy = false; + } + + function add(task, removeTaskCallback) { + if (!discardPendingTasks) { + _tasks.push(task); + } else { + if (_tasks[0] && removeTaskCallback) { + removeTaskCallback(_tasks[0]); + } + _tasks = [task]; } - - function busy() { - return _busy; + if (!_busy) { + exec(); } + } - return { - add: add, - busy: busy - }; -} + function busy() { + return _busy; + } + return { + add, + busy, + }; +} export { createQueue as create }; export const enqueue = createQueue().add; // Default global queue for UI sync, consider renaming diff --git a/packages/devextreme/js/__internal/core/utils/m_ready_callbacks.ts b/packages/devextreme/js/__internal/core/utils/m_ready_callbacks.ts index faceec92ea2e..843112015ba1 100644 --- a/packages/devextreme/js/__internal/core/utils/m_ready_callbacks.ts +++ b/packages/devextreme/js/__internal/core/utils/m_ready_callbacks.ts @@ -1,30 +1,34 @@ -import domAdapter from '../dom_adapter'; -import injector from './dependency_injector'; -import { hasWindow } from './window'; -import callOnce from './call_once'; -let callbacks = []; +import domAdapter from '@js/core/dom_adapter'; +import callOnce from '@js/core/utils/call_once'; +import injector from '@js/core/utils/dependency_injector'; +import { hasWindow } from '@js/core/utils/window'; + +let callbacks: any[] = []; const subscribeReady = callOnce(() => { - const removeListener = domAdapter.listen(domAdapter.getDocument(), 'DOMContentLoaded', () => { - readyCallbacks.fire(); - removeListener(); - }); + const removeListener = domAdapter.listen(domAdapter.getDocument(), 'DOMContentLoaded', () => { + readyCallbacks.fire(); + removeListener(); + }); }); const readyCallbacks = { - add: callback => { - const windowExists = hasWindow(); - if(windowExists && domAdapter.getReadyState() !== 'loading') { - callback(); - } else { - callbacks.push(callback); - windowExists && subscribeReady(); - } - }, - fire: () => { - callbacks.forEach(callback => callback()); - callbacks = []; + add: (callback) => { + const windowExists = hasWindow(); + if (windowExists && domAdapter.getReadyState() !== 'loading') { + callback(); + } else { + callbacks.push(callback); + windowExists && subscribeReady(); } + }, + fire: () => { + callbacks.forEach((callback) => callback()); + callbacks = []; + }, }; -export default injector(readyCallbacks); +const readyCallbacksModule = injector(readyCallbacks); + +export { readyCallbacksModule }; +export default readyCallbacksModule; diff --git a/packages/devextreme/js/__internal/core/utils/m_resize_callbacks.ts b/packages/devextreme/js/__internal/core/utils/m_resize_callbacks.ts index b5c96e3effb5..c69c32e2077d 100644 --- a/packages/devextreme/js/__internal/core/utils/m_resize_callbacks.ts +++ b/packages/devextreme/js/__internal/core/utils/m_resize_callbacks.ts @@ -1,77 +1,79 @@ -import { hasWindow, getWindow } from './window'; -import domAdapter from '../dom_adapter'; -import Callbacks from './callbacks'; -import readyCallbacks from './ready_callbacks'; -import callOnce from './call_once'; - -const resizeCallbacks = (function() { - let prevSize; - const callbacks = Callbacks(); - const originalCallbacksAdd = callbacks.add; - const originalCallbacksRemove = callbacks.remove; - - if(!hasWindow()) { - return callbacks; - } - - const formatSize = function() { - const window = getWindow(); - return { - width: window.innerWidth, - height: window.innerHeight, - }; - }; +import domAdapter from '@js/core/dom_adapter'; +import callOnce from '@js/core/utils/call_once'; - const handleResize = function() { - const now = formatSize(); - if(now.width === prevSize.width && now.height === prevSize.height) { - return; - } +// eslint-disable-next-line import/no-named-as-default +import Callbacks from './m_callbacks'; +import readyCallbacks from './m_ready_callbacks'; +import windowModule from './m_window'; - let changedDimension; - if(now.width === prevSize.width) { - changedDimension = 'height'; - } - if(now.height === prevSize.height) { - changedDimension = 'width'; - } +const resizeCallbacks = (function () { + let prevSize; + const callbacks = Callbacks(); + const originalCallbacksAdd = callbacks.add; + const originalCallbacksRemove = callbacks.remove; - prevSize = now; + if (!windowModule.hasWindow()) { + return callbacks; + } - callbacks.fire(changedDimension); + const formatSize = function () { + const window = windowModule.getWindow(); + return { + width: window.innerWidth, + height: window.innerHeight, }; + }; - const setPrevSize = callOnce(function() { - prevSize = formatSize(); - }); + const handleResize = function () { + const now = formatSize(); + if (now.width === prevSize.width && now.height === prevSize.height) { + return; + } + + let changedDimension; + if (now.width === prevSize.width) { + changedDimension = 'height'; + } + if (now.height === prevSize.height) { + changedDimension = 'width'; + } - let removeListener; + prevSize = now; - callbacks.add = function() { - const result = originalCallbacksAdd.apply(callbacks, arguments); + callbacks.fire(changedDimension); + }; - setPrevSize(); + const setPrevSize = callOnce(function () { + prevSize = formatSize(); + }); - readyCallbacks.add(function() { - if(!removeListener && callbacks.has()) { - removeListener = domAdapter.listen(getWindow(), 'resize', handleResize); - } - }); + let removeListener; - return result; - }; + callbacks.add = function () { + const result = originalCallbacksAdd.apply(callbacks, arguments); - callbacks.remove = function() { - const result = originalCallbacksRemove.apply(callbacks, arguments); + setPrevSize(); - if(!callbacks.has() && removeListener) { - removeListener(); - removeListener = undefined; - } - return result; - }; + readyCallbacks.add(function () { + if (!removeListener && callbacks.has()) { + removeListener = domAdapter.listen(windowModule.getWindow(), 'resize', handleResize); + } + }); - return callbacks; + return result; + }; + + callbacks.remove = function () { + const result = originalCallbacksRemove.apply(callbacks, arguments); + if (!callbacks.has() && removeListener) { + removeListener(); + removeListener = undefined; + } + return result; + }; + + return callbacks; })(); +export { resizeCallbacks }; export default resizeCallbacks; diff --git a/packages/devextreme/js/__internal/core/utils/m_selection_filter.ts b/packages/devextreme/js/__internal/core/utils/m_selection_filter.ts index 904feb3e54c2..70c6d35627cd 100644 --- a/packages/devextreme/js/__internal/core/utils/m_selection_filter.ts +++ b/packages/devextreme/js/__internal/core/utils/m_selection_filter.ts @@ -1,131 +1,132 @@ -import { getKeyHash, equalByValue } from './common'; -import { isString, isObject } from './type'; -import { compileGetter } from './data'; - -export const SelectionFilterCreator = function(selectedItemKeys, isSelectAll) { - - this.getLocalFilter = function(keyGetter, equalKeys, equalByReference, keyExpr) { - equalKeys = equalKeys === undefined ? equalByValue : equalKeys; - return functionFilter.bind(this, equalKeys, keyGetter, equalByReference, keyExpr); - }; - - this.getExpr = function(keyExpr) { - if(!keyExpr) { - return; - } - - let filterExpr; +import { equalByValue, getKeyHash } from '@js/core/utils/common'; +import { compileGetter } from '@js/core/utils/data'; +import { isObject, isString } from '@js/core/utils/type'; + +export const SelectionFilterCreator = function (selectedItemKeys, isSelectAll?: boolean) { + this.getLocalFilter = function (keyGetter, equalKeys, equalByReference, keyExpr) { + equalKeys = equalKeys === undefined ? equalByValue : equalKeys; + return functionFilter.bind(this, equalKeys, keyGetter, equalByReference, keyExpr); + }; + + this.getExpr = function (keyExpr) { + if (!keyExpr) { + return; + } - selectedItemKeys.forEach(function(key, index) { - filterExpr = filterExpr || []; + let filterExpr; - let filterExprPart; + selectedItemKeys.forEach(function (key, index) { + filterExpr = filterExpr || []; - if(index > 0) { - filterExpr.push(isSelectAll ? 'and' : 'or'); - } + let filterExprPart; - if(isString(keyExpr)) { - filterExprPart = getFilterForPlainKey(keyExpr, key); - } else { - filterExprPart = getFilterForCompositeKey(keyExpr, key); - } + if (index > 0) { + filterExpr.push(isSelectAll ? 'and' : 'or'); + } - filterExpr.push(filterExprPart); - }); + if (isString(keyExpr)) { + filterExprPart = getFilterForPlainKey(keyExpr, key); + } else { + filterExprPart = getFilterForCompositeKey(keyExpr, key); + } - if(filterExpr && filterExpr.length === 1) { - filterExpr = filterExpr[0]; - } + filterExpr.push(filterExprPart); + }); - return filterExpr; - }; - - this.getCombinedFilter = function(keyExpr, dataSourceFilter, forceCombinedFilter = false) { - const filterExpr = this.getExpr(keyExpr); - let combinedFilter = filterExpr; - - if((forceCombinedFilter || isSelectAll) && dataSourceFilter) { - if(filterExpr) { - combinedFilter = []; - combinedFilter.push(filterExpr); - combinedFilter.push(dataSourceFilter); - } else { - combinedFilter = dataSourceFilter; - } - } + if (filterExpr && filterExpr.length === 1) { + // eslint-disable-next-line prefer-destructuring + filterExpr = filterExpr[0]; + } - return combinedFilter; - }; + return filterExpr; + }; + + this.getCombinedFilter = function (keyExpr, dataSourceFilter, forceCombinedFilter = false) { + const filterExpr = this.getExpr(keyExpr); + let combinedFilter = filterExpr; + + if ((forceCombinedFilter || isSelectAll) && dataSourceFilter) { + if (filterExpr) { + combinedFilter = []; + combinedFilter.push(filterExpr); + combinedFilter.push(dataSourceFilter); + } else { + combinedFilter = dataSourceFilter; + } + } - let selectedItemKeyHashesMap; + return combinedFilter; + }; - const getSelectedItemKeyHashesMap = function(keyOf, keyExpr) { - if(!selectedItemKeyHashesMap) { - selectedItemKeyHashesMap = {}; - const normalizedKeys = normalizeKeys(selectedItemKeys, keyOf, keyExpr); - for(let i = 0; i < normalizedKeys.length; i++) { - selectedItemKeyHashesMap[getKeyHash(normalizedKeys[i])] = true; - } - } - return selectedItemKeyHashesMap; - }; - - const normalizeKeys = function(keys, keyOf, keyExpr) { - return Array.isArray(keyExpr) ? keys.map(key => keyOf(key)) : keys; - }; - - function functionFilter(equalKeys, keyOf, equalByReference, keyExpr, item) { - const key = keyOf(item); - let keyHash; - let i; - - if(!equalByReference) { - keyHash = getKeyHash(key); - if(!isObject(keyHash)) { - const selectedKeyHashesMap = getSelectedItemKeyHashesMap(keyOf, keyExpr); - if(selectedKeyHashesMap[keyHash]) { - return !isSelectAll; - } - return !!isSelectAll; - } - } + let selectedItemKeyHashesMap; - for(i = 0; i < selectedItemKeys.length; i++) { - if(equalKeys(selectedItemKeys[i], key)) { - return !isSelectAll; - } + const getSelectedItemKeyHashesMap = function (keyOf, keyExpr) { + if (!selectedItemKeyHashesMap) { + selectedItemKeyHashesMap = {}; + const normalizedKeys = normalizeKeys(selectedItemKeys, keyOf, keyExpr); + for (let i = 0; i < normalizedKeys.length; i++) { + selectedItemKeyHashesMap[getKeyHash(normalizedKeys[i])] = true; + } + } + return selectedItemKeyHashesMap; + }; + + const normalizeKeys = function (keys, keyOf, keyExpr) { + return Array.isArray(keyExpr) ? keys.map((key) => keyOf(key)) : keys; + }; + + function functionFilter(equalKeys, keyOf, equalByReference, keyExpr, item) { + const key = keyOf(item); + let keyHash; + let i; + + if (!equalByReference) { + keyHash = getKeyHash(key); + if (!isObject(keyHash)) { + const selectedKeyHashesMap = getSelectedItemKeyHashesMap(keyOf, keyExpr); + if (selectedKeyHashesMap[keyHash]) { + return !isSelectAll; } return !!isSelectAll; + } } - function getFilterForPlainKey(keyExpr, keyValue) { - if(keyValue === undefined) { - return; - } - return [keyExpr, isSelectAll ? '<>' : '=', keyValue]; + for (i = 0; i < selectedItemKeys.length; i++) { + if (equalKeys(selectedItemKeys[i], key)) { + return !isSelectAll; + } } + return !!isSelectAll; + } - function getFilterForCompositeKey(keyExpr, itemKeyValue) { - const filterExpr = []; + function getFilterForPlainKey(keyExpr, keyValue) { + if (keyValue === undefined) { + return; + } + return [keyExpr, isSelectAll ? '<>' : '=', keyValue]; + } - for(let i = 0, length = keyExpr.length; i < length; i++) { - const currentKeyExpr = keyExpr[i]; - const keyValueGetter = compileGetter(currentKeyExpr); - const currentKeyValue = itemKeyValue && keyValueGetter(itemKeyValue); - const filterExprPart = getFilterForPlainKey(currentKeyExpr, currentKeyValue); + function getFilterForCompositeKey(keyExpr, itemKeyValue) { + const filterExpr: any[] = []; - if(!filterExprPart) { - break; - } + for (let i = 0, { length } = keyExpr; i < length; i++) { + const currentKeyExpr = keyExpr[i]; + const keyValueGetter = compileGetter(currentKeyExpr); + // @ts-expect-error keyValueGetter is unknown + const currentKeyValue = itemKeyValue && keyValueGetter(itemKeyValue); + const filterExprPart = getFilterForPlainKey(currentKeyExpr, currentKeyValue); - if(i > 0) { - filterExpr.push(isSelectAll ? 'or' : 'and'); - } + if (!filterExprPart) { + break; + } - filterExpr.push(filterExprPart); - } + if (i > 0) { + filterExpr.push(isSelectAll ? 'or' : 'and'); + } - return filterExpr; + filterExpr.push(filterExprPart); } + + return filterExpr; + } }; diff --git a/packages/devextreme/js/__internal/core/utils/m_shadow_dom.ts b/packages/devextreme/js/__internal/core/utils/m_shadow_dom.ts index f1d9a3e7e05b..b712a4315fcd 100644 --- a/packages/devextreme/js/__internal/core/utils/m_shadow_dom.ts +++ b/packages/devextreme/js/__internal/core/utils/m_shadow_dom.ts @@ -3,121 +3,121 @@ const DX_RULE_PREFIX = 'dx-'; let ownerDocumentStyleSheet = null; function createConstructedStyleSheet(rootNode) { - try { - // eslint-disable-next-line no-undef - return new CSSStyleSheet(); - } catch(err) { - const styleElement = rootNode.ownerDocument.createElement('style'); + try { + // eslint-disable-next-line no-undef + return new CSSStyleSheet(); + } catch (err) { + const styleElement = rootNode.ownerDocument.createElement('style'); - rootNode.appendChild(styleElement); + rootNode.appendChild(styleElement); - return styleElement.sheet; - } + return styleElement.sheet; + } } function processRules(targetStyleSheet, styleSheets, needApplyAllStyles) { - for(let i = 0; i < styleSheets.length; i++) { - const sheet = styleSheets[i]; - try { - for(let j = 0; j < sheet.cssRules.length; j++) { - insertRule(targetStyleSheet, sheet.cssRules[j], needApplyAllStyles); - } - } catch(err) { - // NOTE: need try/catch block for not-supported cross-domain css - } + for (let i = 0; i < styleSheets.length; i++) { + const sheet = styleSheets[i]; + try { + for (let j = 0; j < sheet.cssRules.length; j++) { + insertRule(targetStyleSheet, sheet.cssRules[j], needApplyAllStyles); + } + } catch (err) { + // NOTE: need try/catch block for not-supported cross-domain css } + } } function insertRule(targetStyleSheet, rule, needApplyAllStyles) { - const isDxRule = needApplyAllStyles || - rule.selectorText?.includes(DX_RULE_PREFIX) || - rule.cssRules?.[0]?.selectorText?.includes(DX_RULE_PREFIX) || - rule.name?.startsWith(DX_RULE_PREFIX) || - rule.style?.fontFamily === 'DXIcons'; - - if(isDxRule) { - targetStyleSheet.insertRule( - rule.cssText, - targetStyleSheet.cssRules.length - ); - } + const isDxRule = needApplyAllStyles + || rule.selectorText?.includes(DX_RULE_PREFIX) + || rule.cssRules?.[0]?.selectorText?.includes(DX_RULE_PREFIX) + || rule.name?.startsWith(DX_RULE_PREFIX) + || rule.style?.fontFamily === 'DXIcons'; + + if (isDxRule) { + targetStyleSheet.insertRule( + rule.cssText, + targetStyleSheet.cssRules.length, + ); + } } export function addShadowDomStyles($element) { - const el = $element.get(0); - const root = el.getRootNode?.(); + const el = $element.get(0); + const root = el.getRootNode?.(); - if(!root?.host) { - return; - } + if (!root?.host) { + return; + } - if(!ownerDocumentStyleSheet) { - ownerDocumentStyleSheet = createConstructedStyleSheet(root); + if (!ownerDocumentStyleSheet) { + ownerDocumentStyleSheet = createConstructedStyleSheet(root); - processRules(ownerDocumentStyleSheet, el.ownerDocument.styleSheets, false); - } + processRules(ownerDocumentStyleSheet, el.ownerDocument.styleSheets, false); + } - const currentShadowDomStyleSheet = createConstructedStyleSheet(root); + const currentShadowDomStyleSheet = createConstructedStyleSheet(root); - processRules(currentShadowDomStyleSheet, root.styleSheets, true); + processRules(currentShadowDomStyleSheet, root.styleSheets, true); - root.adoptedStyleSheets = [ownerDocumentStyleSheet, currentShadowDomStyleSheet]; + root.adoptedStyleSheets = [ownerDocumentStyleSheet, currentShadowDomStyleSheet]; } function isPositionInElementRectangle(element, x, y) { - const rect = element.getBoundingClientRect(); + const rect = element.getBoundingClientRect(); - return rect && x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom; + return rect && x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom; } function createQueue() { - let shiftIndex = 0; - const items = []; - - return { - push(item) { - items.push(item); - return this; - }, - - shift() { - shiftIndex++; - return items[shiftIndex - 1]; - }, - - get length() { - return items.length - shiftIndex; - }, - - get items() { - return items; - } - }; + let shiftIndex = 0; + const items: any[] = []; + + return { + push(item) { + items.push(item); + return this; + }, + + shift() { + shiftIndex++; + return items[shiftIndex - 1]; + }, + + get length() { + return items.length - shiftIndex; + }, + + get items() { + return items; + }, + }; } export function getShadowElementsFromPoint(x, y, root) { - const elementQueue = createQueue().push(root); + const elementQueue = createQueue().push(root); - while(elementQueue.length) { - const el = elementQueue.shift(); + while (elementQueue.length) { + const el = elementQueue.shift(); - for(let i = 0; i < el.childNodes.length; i++) { - const childNode = el.childNodes[i]; + for (let i = 0; i < el.childNodes.length; i++) { + const childNode = el.childNodes[i]; - // eslint-disable-next-line no-undef - if(childNode.nodeType === Node.ELEMENT_NODE && - isPositionInElementRectangle(childNode, x, y) && + // eslint-disable-next-line no-undef + if (childNode.nodeType === Node.ELEMENT_NODE + && isPositionInElementRectangle(childNode, x, y) // eslint-disable-next-line no-undef - getComputedStyle(childNode).pointerEvents !== 'none' - ) { - elementQueue.push(childNode); - } - } + && getComputedStyle(childNode).pointerEvents !== 'none' + ) { + elementQueue.push(childNode); + } } + } - const result = elementQueue.items.reverse(); + const result = elementQueue.items.reverse(); - result.pop(); + result.pop(); - return result; + return result; } diff --git a/packages/devextreme/js/__internal/core/utils/m_size.ts b/packages/devextreme/js/__internal/core/utils/m_size.ts index e2a49b1e40e6..5ce50c0fd751 100644 --- a/packages/devextreme/js/__internal/core/utils/m_size.ts +++ b/packages/devextreme/js/__internal/core/utils/m_size.ts @@ -1,322 +1,321 @@ -import { getWindow } from '../../core/utils/window'; -import domAdapter from '../../core/dom_adapter'; -import { isWindow, isString, isNumeric, isRenderer } from '../utils/type'; +import domAdapter from '@js/core/dom_adapter'; +import { + isNumeric, isRenderer, isString, isWindow, +} from '@js/core/utils/type'; +import { getWindow } from '@js/core/utils/window'; const window = getWindow(); const SPECIAL_HEIGHT_VALUES = ['auto', 'none', 'inherit', 'initial']; -const getSizeByStyles = function(elementStyles, styles) { - let result = 0; +const getSizeByStyles = function (elementStyles, styles) { + let result = 0; - styles.forEach(function(style) { - result += (parseFloat(elementStyles[style]) || 0); - }); + styles.forEach(function (style) { + result += parseFloat(elementStyles[style]) || 0; + }); - return result; + return result; }; -export const getElementBoxParams = function(name, elementStyles) { - const beforeName = name === 'width' ? 'Left' : 'Top'; - const afterName = name === 'width' ? 'Right' : 'Bottom'; +export const getElementBoxParams = function (name, elementStyles) { + const beforeName = name === 'width' ? 'Left' : 'Top'; + const afterName = name === 'width' ? 'Right' : 'Bottom'; - return { - padding: getSizeByStyles(elementStyles, ['padding' + beforeName, 'padding' + afterName]), - border: getSizeByStyles(elementStyles, ['border' + beforeName + 'Width', 'border' + afterName + 'Width']), - margin: getSizeByStyles(elementStyles, ['margin' + beforeName, 'margin' + afterName]), - }; + return { + padding: getSizeByStyles(elementStyles, [`padding${beforeName}`, `padding${afterName}`]), + border: getSizeByStyles(elementStyles, [`border${beforeName}Width`, `border${afterName}Width`]), + margin: getSizeByStyles(elementStyles, [`margin${beforeName}`, `margin${afterName}`]), + }; }; -const getElementComputedStyle = function(element) { - const view = element?.ownerDocument?.defaultView || window; - return view.getComputedStyle && view.getComputedStyle(element); +const getElementComputedStyle = function (element) { + const view = element?.ownerDocument?.defaultView || window; + return view.getComputedStyle && view.getComputedStyle(element); }; -const getCSSProperty = function(element, styles, name, defaultValue) { - return styles?.[name] || element.style?.[name] || defaultValue; +const getCSSProperty = function (element, styles, name, defaultValue?) { + return styles?.[name] || element.style?.[name] || defaultValue; }; - const boxIndices = { - content: 0, - padding: 1, - border: 2, - margin: 3, - 'content-box': 0, - 'border-box': 2, + content: 0, + padding: 1, + border: 2, + margin: 3, + 'content-box': 0, + 'border-box': 2, }; const dimensionComponents = { - width: ['left', 'right'], - height: ['top', 'bottom'] + width: ['left', 'right'], + height: ['top', 'bottom'], }; function getComponentThickness(elem, dimension, component, styles) { - const get = (elem, styles, field) => parseFloat(getCSSProperty(elem, styles, field, '0')) || 0; - const suffix = component === 'border' ? '-width' : ''; - return get(elem, styles, `${component}-${dimensionComponents[dimension][0]}${suffix}`) + const get = (elem, styles, field) => parseFloat(getCSSProperty(elem, styles, field, '0')) || 0; + const suffix = component === 'border' ? '-width' : ''; + return get(elem, styles, `${component}-${dimensionComponents[dimension][0]}${suffix}`) + get(elem, styles, `${component}-${dimensionComponents[dimension][1]}${suffix}`); } -export const getSize = function(element, dimension, box) { - const offsetFieldName = dimension === 'width' ? 'offsetWidth' : 'offsetHeight'; +export const getSize = function (element, dimension, box) { + const offsetFieldName = dimension === 'width' ? 'offsetWidth' : 'offsetHeight'; - const styles = getElementComputedStyle(element); - let result = getCSSProperty(element, styles, dimension); - if(result === '' || result === 'auto') { - result = element[offsetFieldName]; - } - result = parseFloat(result) || 0; - - const currentBox = getCSSProperty(element, styles, 'boxSizing', 'content-box'); - const targetBox = box || currentBox; - - let targetBoxIndex = boxIndices[targetBox]; - let currentBoxIndex = boxIndices[currentBox]; - - if(targetBoxIndex === undefined || currentBoxIndex === undefined) { - throw new Error(); - } + const styles = getElementComputedStyle(element); + let result = getCSSProperty(element, styles, dimension); + if (result === '' || result === 'auto') { + result = element[offsetFieldName]; + } + result = parseFloat(result) || 0; - if(currentBoxIndex === targetBoxIndex) { - return result; - } + const currentBox = getCSSProperty(element, styles, 'boxSizing', 'content-box'); + const targetBox = box || currentBox; - const coeff = Math.sign(targetBoxIndex - currentBoxIndex); - let padding = false; - let border = false; - let margin = false; - let scrollThickness = false; + let targetBoxIndex = boxIndices[targetBox]; + let currentBoxIndex = boxIndices[currentBox]; - if(coeff === 1) { - targetBoxIndex += 1; - currentBoxIndex += 1; - } + if (targetBoxIndex === undefined || currentBoxIndex === undefined) { + throw new Error(); + } - for(let boxPart = currentBoxIndex; boxPart !== targetBoxIndex; boxPart += coeff) { - - switch(boxPart) { - case boxIndices.content: - break; - case boxIndices.padding: - padding = coeff * getComponentThickness(element, dimension, 'padding', styles); - break; - case boxIndices.border: - border = coeff * getComponentThickness(element, dimension, 'border', styles); - break; - case boxIndices.margin: - margin = coeff * getComponentThickness(element, dimension, 'margin', styles); - break; - } + if (currentBoxIndex === targetBoxIndex) { + return result; + } + + const coeff = Math.sign(targetBoxIndex - currentBoxIndex); + let padding: number | boolean = false; + let border: number | boolean = false; + let margin: number | boolean = false; + let scrollThickness: number | boolean = false; + + if (coeff === 1) { + targetBoxIndex += 1; + currentBoxIndex += 1; + } + + for (let boxPart = currentBoxIndex; boxPart !== targetBoxIndex; boxPart += coeff) { + // eslint-disable-next-line default-case + switch (boxPart) { + case boxIndices.content: + break; + case boxIndices.padding: + padding = coeff * getComponentThickness(element, dimension, 'padding', styles); + break; + case boxIndices.border: + border = coeff * getComponentThickness(element, dimension, 'border', styles); + break; + case boxIndices.margin: + margin = coeff * getComponentThickness(element, dimension, 'margin', styles); + break; } + } - if(padding || border) { - const paddingAndBorder = - (padding === false ? coeff * getComponentThickness(element, dimension, 'padding', styles) : padding) + if (padding || border) { + const paddingAndBorder = (padding === false ? coeff * getComponentThickness(element, dimension, 'padding', styles) : padding) + (border === false ? coeff * getComponentThickness(element, dimension, 'border', styles) : border); - scrollThickness = coeff * Math.max(0, Math.floor( - element[offsetFieldName] - - result - - (coeff * paddingAndBorder) - )) || 0; - } + scrollThickness = coeff * Math.max(0, Math.floor( + element[offsetFieldName] + - result + - (coeff * paddingAndBorder), + )) || 0; + } - return result + margin + padding + border + scrollThickness; + return result + margin + padding + border + scrollThickness; }; -const getContainerHeight = function(container) { - return isWindow(container) ? container.innerHeight : container.offsetHeight; +const getContainerHeight = function (container) { + return isWindow(container) ? container.innerHeight : container.offsetHeight; }; -export const parseHeight = function(value, container, element) { - if(value.indexOf('px') > 0) { - value = parseInt(value.replace('px', '')); - } else if(value.indexOf('%') > 0) { - value = parseInt(value.replace('%', '')) * getContainerHeight(container) / 100; - } else if(!isNaN(value)) { - value = parseInt(value); - } else if(value.indexOf('vh') > 0) { - value = window.innerHeight / 100 * parseInt(value.replace('vh', '')); - } else if(element && value.indexOf('em') > 0) { - value = parseFloat(value.replace('em', '')) * parseFloat(window.getComputedStyle(element).fontSize); - } - - return value; +export const parseHeight = function (value, container, element?) { + if (value.indexOf('px') > 0) { + value = parseInt(value.replace('px', '')); + } else if (value.indexOf('%') > 0) { + value = parseInt(value.replace('%', '')) * getContainerHeight(container) / 100; + } else if (!isNaN(value)) { + value = parseInt(value); + } else if (value.indexOf('vh') > 0) { + value = window.innerHeight / 100 * parseInt(value.replace('vh', '')); + } else if (element && value.indexOf('em') > 0) { + value = parseFloat(value.replace('em', '')) * parseFloat(window.getComputedStyle(element).fontSize); + } + + return value; }; -const getHeightWithOffset = function(value, offset, container) { - if(!value) { - return null; - } +const getHeightWithOffset = function (value, offset, container) { + if (!value) { + return null; + } - if(SPECIAL_HEIGHT_VALUES.indexOf(value) > -1) { - return offset ? null : value; - } + if (SPECIAL_HEIGHT_VALUES.includes(value)) { + return offset ? null : value; + } - if(isString(value)) { - value = parseHeight(value, container); - } + if (isString(value)) { + value = parseHeight(value, container); + } - if(isNumeric(value)) { - return Math.max(0, value + offset); - } + if (isNumeric(value)) { + return Math.max(0, value + offset); + } - const operationString = offset < 0 ? ' - ' : ' '; + const operationString = offset < 0 ? ' - ' : ' '; - return 'calc(' + value + operationString + Math.abs(offset) + 'px)'; + return `calc(${value}${operationString}${Math.abs(offset)}px)`; }; -export const addOffsetToMaxHeight = function(value, offset, container) { - const maxHeight = getHeightWithOffset(value, offset, container); - return maxHeight !== null ? maxHeight : 'none'; +export const addOffsetToMaxHeight = function (value, offset, container) { + const maxHeight = getHeightWithOffset(value, offset, container); + return maxHeight !== null ? maxHeight : 'none'; }; -export const addOffsetToMinHeight = function(value, offset, container) { - const minHeight = getHeightWithOffset(value, offset, container); - return minHeight !== null ? minHeight : 0; +export const addOffsetToMinHeight = function (value, offset, container) { + const minHeight = getHeightWithOffset(value, offset, container); + return minHeight !== null ? minHeight : 0; }; -export const getVerticalOffsets = function(element, withMargins) { - if(!element) { - return 0; - } +export const getVerticalOffsets = function (element, withMargins) { + if (!element) { + return 0; + } - const boxParams = getElementBoxParams('height', window.getComputedStyle(element)); + const boxParams = getElementBoxParams('height', window.getComputedStyle(element)); - return boxParams.padding + return boxParams.padding + boxParams.border + (withMargins ? boxParams.margin : 0); }; -export const getVisibleHeight = function(element) { - if(element) { - const boundingClientRect = element.getBoundingClientRect(); +export const getVisibleHeight = function (element) { + if (element) { + const boundingClientRect = element.getBoundingClientRect(); - if(boundingClientRect.height) { - return boundingClientRect.height; - } + if (boundingClientRect.height) { + return boundingClientRect.height; } + } - return 0; + return 0; }; // TODO: remove when we'll start mocking named exports export const implementationsMap = { - getWidth: (...args) => elementSizeHelper('width', ...args), - setWidth: (...args) => elementSizeHelper('width', ...args), - getHeight: (...args) => elementSizeHelper('height', ...args), - setHeight: (...args) => elementSizeHelper('height', ...args), - getOuterWidth: (...args) => elementSizeHelper('outerWidth', ...args), - setOuterWidth: (...args) => elementSizeHelper('outerWidth', ...args), - getOuterHeight: (...args) => elementSizeHelper('outerHeight', ...args), - setOuterHeight: (...args) => elementSizeHelper('outerHeight', ...args), - getInnerWidth: (...args) => elementSizeHelper('innerWidth', ...args), - setInnerWidth: (...args) => elementSizeHelper('innerWidth', ...args), - getInnerHeight: (...args) => elementSizeHelper('innerHeight', ...args), - setInnerHeight: (...args) => elementSizeHelper('innerHeight', ...args), + getWidth: (...args) => elementSizeHelper('width', ...args as [any, any]), + setWidth: (...args) => elementSizeHelper('width', ...args as [any, any]), + getHeight: (...args) => elementSizeHelper('height', ...args as [any, any]), + setHeight: (...args) => elementSizeHelper('height', ...args as [any, any]), + getOuterWidth: (...args) => elementSizeHelper('outerWidth', ...args as [any, any]), + setOuterWidth: (...args) => elementSizeHelper('outerWidth', ...args as [any, any]), + getOuterHeight: (...args) => elementSizeHelper('outerHeight', ...args as [any, any]), + setOuterHeight: (...args) => elementSizeHelper('outerHeight', ...args as [any, any]), + getInnerWidth: (...args) => elementSizeHelper('innerWidth', ...args as [any, any]), + setInnerWidth: (...args) => elementSizeHelper('innerWidth', ...args as [any, any]), + getInnerHeight: (...args) => elementSizeHelper('innerHeight', ...args as [any, any]), + setInnerHeight: (...args) => elementSizeHelper('innerHeight', ...args as [any, any]), }; function elementSizeHelper(sizeProperty, el, value) { - return arguments.length === 2 ? elementSize(el, sizeProperty) : elementSize(el, sizeProperty, value); + return arguments.length === 2 ? elementSize(el, sizeProperty) : elementSize(el, sizeProperty, value); } export const getWidth = (el) => implementationsMap.getWidth(el); export const setWidth = (el, value) => implementationsMap.setWidth(el, value); export const getHeight = (el) => implementationsMap.getHeight(el); export const setHeight = (el, value) => implementationsMap.setHeight(el, value); -export const getOuterWidth = (el, includeMargin) => implementationsMap.getOuterWidth(el, includeMargin || false); +export const getOuterWidth = (el, includeMargin?) => implementationsMap.getOuterWidth(el, includeMargin || false); export const setOuterWidth = (el, value) => implementationsMap.setOuterWidth(el, value); -export const getOuterHeight = (el, includeMargin) => implementationsMap.getOuterHeight(el, includeMargin || false); +export const getOuterHeight = (el, includeMargin?) => implementationsMap.getOuterHeight(el, includeMargin || false); export const setOuterHeight = (el, value) => implementationsMap.setOuterHeight(el, value); export const getInnerWidth = (el) => implementationsMap.getInnerWidth(el); export const setInnerWidth = (el, value) => implementationsMap.setInnerWidth(el, value); export const getInnerHeight = (el) => implementationsMap.getInnerHeight(el); export const setInnerHeight = (el, value) => implementationsMap.setInnerHeight(el, value); -const elementSize = function(el, sizeProperty, value) { - const partialName = sizeProperty.toLowerCase().indexOf('width') >= 0 ? 'Width' : 'Height'; - const propName = partialName.toLowerCase(); - const isOuter = sizeProperty.indexOf('outer') === 0; - const isInner = sizeProperty.indexOf('inner') === 0; - const isGetter = arguments.length === 2 || typeof value === 'boolean'; - - if(isRenderer(el)) { - if(el.length > 1 && !isGetter) { - for(let i = 0; i < el.length; i++) { - elementSize(el[i], sizeProperty, value); - } - return; - } - el = el[0]; +const elementSize = function (el, sizeProperty, value?) { + const partialName = sizeProperty.toLowerCase().indexOf('width') >= 0 ? 'Width' : 'Height'; + const propName = partialName.toLowerCase(); + const isOuter = sizeProperty.indexOf('outer') === 0; + const isInner = sizeProperty.indexOf('inner') === 0; + const isGetter = arguments.length === 2 || typeof value === 'boolean'; + + if (isRenderer(el)) { + if (el.length > 1 && !isGetter) { + for (let i = 0; i < el.length; i++) { + elementSize(el[i], sizeProperty, value); + } + return; } - - if(!el) return; - - if(isWindow(el)) { - return isOuter ? el['inner' + partialName] : domAdapter.getDocumentElement()['client' + partialName]; - } - - if(domAdapter.isDocument(el)) { - const documentElement = domAdapter.getDocumentElement(); - const body = domAdapter.getBody(); - - return Math.max( - body['scroll' + partialName], - body['offset' + partialName], - documentElement['scroll' + partialName], - documentElement['offset' + partialName], - documentElement['client' + partialName] - ); + // eslint-disable-next-line prefer-destructuring + el = el[0]; + } + + if (!el) return; + + if (isWindow(el)) { + return isOuter ? el[`inner${partialName}`] : domAdapter.getDocumentElement()[`client${partialName}`]; + } + + if (domAdapter.isDocument(el)) { + const documentElement = domAdapter.getDocumentElement(); + const body = domAdapter.getBody(); + + return Math.max( + body[`scroll${partialName}`], + body[`offset${partialName}`], + documentElement[`scroll${partialName}`], + documentElement[`offset${partialName}`], + documentElement[`client${partialName}`], + ); + } + + if (isGetter) { + let box = 'content'; + if (isOuter) { + box = value ? 'margin' : 'border'; } - - if(isGetter) { - let box = 'content'; - if(isOuter) { - box = value ? 'margin' : 'border'; - } - if(isInner) { - box = 'padding'; - } - - return getSize(el, propName, box); + if (isInner) { + box = 'padding'; } - if(isNumeric(value)) { - const elementStyles = getElementComputedStyle(el); - const sizeAdjustment = getElementBoxParams(propName, elementStyles); - const isBorderBox = elementStyles.boxSizing === 'border-box'; - value = Number(value); - - if(isOuter) { - value -= isBorderBox ? 0 : (sizeAdjustment.border + sizeAdjustment.padding); - } else if(isInner) { - value += isBorderBox ? sizeAdjustment.border : -sizeAdjustment.padding; - } else if(isBorderBox) { - value += sizeAdjustment.border + sizeAdjustment.padding; - } + return getSize(el, propName, box); + } + + if (isNumeric(value)) { + const elementStyles = getElementComputedStyle(el); + const sizeAdjustment = getElementBoxParams(propName, elementStyles); + const isBorderBox = elementStyles.boxSizing === 'border-box'; + value = Number(value); + + if (isOuter) { + value -= isBorderBox ? 0 : sizeAdjustment.border + sizeAdjustment.padding; + } else if (isInner) { + value += isBorderBox ? sizeAdjustment.border : -sizeAdjustment.padding; + } else if (isBorderBox) { + value += sizeAdjustment.border + sizeAdjustment.padding; } - value += isNumeric(value) ? 'px' : ''; + } + value += isNumeric(value) ? 'px' : ''; - domAdapter.setStyle(el, propName, value); + domAdapter.setStyle(el, propName, value); - return null; + return null; }; -export const getWindowByElement = (el) => { - return isWindow(el) ? el : el.defaultView; -}; +export const getWindowByElement = (el) => (isWindow(el) ? el : el.defaultView); export const getOffset = (el) => { - if(!el.getClientRects().length) { - return { - top: 0, - left: 0 - }; - } - - const rect = el.getBoundingClientRect(); - const win = getWindowByElement(el.ownerDocument); - const docElem = el.ownerDocument.documentElement; - + if (!el.getClientRects().length) { return { - top: rect.top + win.pageYOffset - docElem.clientTop, - left: rect.left + win.pageXOffset - docElem.clientLeft + top: 0, + left: 0, }; + } + + const rect = el.getBoundingClientRect(); + const win = getWindowByElement(el.ownerDocument); + const docElem = el.ownerDocument.documentElement; + + return { + top: rect.top + win.pageYOffset - docElem.clientTop, + left: rect.left + win.pageXOffset - docElem.clientLeft, + }; }; diff --git a/packages/devextreme/js/__internal/core/utils/m_storage.ts b/packages/devextreme/js/__internal/core/utils/m_storage.ts index d8cc55cd8942..2a775524398f 100644 --- a/packages/devextreme/js/__internal/core/utils/m_storage.ts +++ b/packages/devextreme/js/__internal/core/utils/m_storage.ts @@ -1,14 +1,15 @@ -import { getWindow } from '../../core/utils/window'; +import { getWindow } from '@js/core/utils/window'; + const window = getWindow(); -const getSessionStorage = function() { - let sessionStorage; +const getSessionStorage = function () { + let sessionStorage; - try { - sessionStorage = window.sessionStorage; - } catch(e) { } + try { + sessionStorage = window.sessionStorage; + } catch (e) { /* empty */ } - return sessionStorage; + return sessionStorage; }; export { getSessionStorage as sessionStorage }; diff --git a/packages/devextreme/js/__internal/core/utils/m_string.ts b/packages/devextreme/js/__internal/core/utils/m_string.ts index 3dfce66f32b3..fd14b5795637 100644 --- a/packages/devextreme/js/__internal/core/utils/m_string.ts +++ b/packages/devextreme/js/__internal/core/utils/m_string.ts @@ -1,81 +1,81 @@ -import { isFunction, isString } from './type'; +import { isFunction, isString } from '@js/core/utils/type'; -export const encodeHtml = (function() { - const encodeRegExp = [new RegExp('&', 'g'), new RegExp('"', 'g'), new RegExp('\'', 'g'), new RegExp('<', 'g'), new RegExp('>', 'g')]; +export const encodeHtml = (function () { + const encodeRegExp = [new RegExp('&', 'g'), new RegExp('"', 'g'), new RegExp('\'', 'g'), new RegExp('<', 'g'), new RegExp('>', 'g')]; - return function(str) { - return String(str) - .replace(encodeRegExp[0], '&') - .replace(encodeRegExp[1], '"') - .replace(encodeRegExp[2], ''') - .replace(encodeRegExp[3], '<') - .replace(encodeRegExp[4], '>'); - }; + return function (str) { + return String(str) + .replace(encodeRegExp[0], '&') + .replace(encodeRegExp[1], '"') + .replace(encodeRegExp[2], ''') + .replace(encodeRegExp[3], '<') + .replace(encodeRegExp[4], '>'); + }; })(); - -const splitQuad = function(raw) { - switch(typeof raw) { - case 'string': - return raw.split(/\s+/, 4); - case 'object': - return [ - raw.x || raw.h || raw.left, - raw.y || raw.v || raw.top, - raw.x || raw.h || raw.right, - raw.y || raw.v || raw.bottom]; - case 'number': - return [raw]; - default: - return raw; - } +const splitQuad = function (raw) { + switch (typeof raw) { + case 'string': + return raw.split(/\s+/, 4); + case 'object': + return [ + raw.x || raw.h || raw.left, + raw.y || raw.v || raw.top, + raw.x || raw.h || raw.right, + raw.y || raw.v || raw.bottom]; + case 'number': + return [raw]; + default: + return raw; + } }; -export const quadToObject = function(raw) { - const quad = splitQuad(raw); - let left = parseInt(quad && quad[0], 10); - let top = parseInt(quad && quad[1], 10); - let right = parseInt(quad && quad[2], 10); - let bottom = parseInt(quad && quad[3], 10); +export const quadToObject = function (raw) { + const quad = splitQuad(raw); + let left = parseInt(quad && quad[0], 10); + let top = parseInt(quad && quad[1], 10); + let right = parseInt(quad && quad[2], 10); + let bottom = parseInt(quad && quad[3], 10); - if(!isFinite(left)) { - left = 0; - } - if(!isFinite(top)) { - top = left; - } - if(!isFinite(right)) { - right = left; - } - if(!isFinite(bottom)) { - bottom = top; - } + if (!isFinite(left)) { + left = 0; + } + if (!isFinite(top)) { + top = left; + } + if (!isFinite(right)) { + right = left; + } + if (!isFinite(bottom)) { + bottom = top; + } - return { top: top, right: right, bottom: bottom, left: left }; + return { + top, right, bottom, left, + }; }; export function format(template, ...values) { - if(isFunction(template)) { - return template(...values); - } + if (isFunction(template)) { + return template(...values); + } - values.forEach((value, index) => { - if(isString(value)) { - value = value.replace(/\$/g, '$$$$'); - } + values.forEach((value, index) => { + if (isString(value)) { + value = value.replace(/\$/g, '$$$$'); + } - const placeholderReg = new RegExp('\\{' + index + '\\}', 'gm'); - template = template.replace(placeholderReg, value); - }); + const placeholderReg = new RegExp(`\\{${index}\\}`, 'gm'); + template = template.replace(placeholderReg, value); + }); - return template; + return template; } -export const isEmpty = (function() { - const SPACE_REGEXP = /\s/g; +export const isEmpty = (function () { + const SPACE_REGEXP = /\s/g; - return function(text) { - return !text || !text.replace(SPACE_REGEXP, ''); - }; + return function (text) { + return !text || !text.replace(SPACE_REGEXP, ''); + }; })(); - diff --git a/packages/devextreme/js/__internal/core/utils/m_stubs.ts b/packages/devextreme/js/__internal/core/utils/m_stubs.ts index 780fd01108c3..85e206739c42 100644 --- a/packages/devextreme/js/__internal/core/utils/m_stubs.ts +++ b/packages/devextreme/js/__internal/core/utils/m_stubs.ts @@ -1,10 +1,11 @@ export function stubComponent(componentName) { - return class NoComponent { - constructor() { - // TODO: make correct exceptions here and in decorators - throw new Error(`Module '${componentName}' not found`); - } + // eslint-disable-next-line @typescript-eslint/no-extraneous-class + return class NoComponent { + constructor() { + // TODO: make correct exceptions here and in decorators + throw new Error(`Module '${componentName}' not found`); + } - static getInstance() {} - }; + static getInstance() {} + }; } diff --git a/packages/devextreme/js/__internal/core/utils/m_style.ts b/packages/devextreme/js/__internal/core/utils/m_style.ts index 5a396e2f16e7..42b46c59eac9 100644 --- a/packages/devextreme/js/__internal/core/utils/m_style.ts +++ b/packages/devextreme/js/__internal/core/utils/m_style.ts @@ -1,138 +1,139 @@ -import { camelize } from './inflector'; -import callOnce from './call_once'; -import { isNumeric, isString } from './type'; -import domAdapter from '../dom_adapter'; +import domAdapter from '@js/core/dom_adapter'; +import callOnce from '@js/core/utils/call_once'; +import { camelize } from '@js/core/utils/inflector'; +import { isNumeric, isString } from '@js/core/utils/type'; const jsPrefixes = ['', 'Webkit', 'Moz', 'O', 'Ms']; const cssPrefixes = { - '': '', - 'Webkit': '-webkit-', - 'Moz': '-moz-', - 'O': '-o-', - 'ms': '-ms-' + '': '', + Webkit: '-webkit-', + Moz: '-moz-', + O: '-o-', + ms: '-ms-', }; -const getStyles = callOnce(function() { - return domAdapter.createElement('dx').style; +const getStyles = callOnce(function () { + return domAdapter.createElement('dx').style; }); -const forEachPrefixes = function(prop, callBack) { - prop = camelize(prop, true); +const forEachPrefixes = function (prop, callBack) { + prop = camelize(prop, true); - let result; + let result; - for(let i = 0, cssPrefixesCount = jsPrefixes.length; i < cssPrefixesCount; i++) { - const jsPrefix = jsPrefixes[i]; - const prefixedProp = jsPrefix + prop; - const lowerPrefixedProp = camelize(prefixedProp); + for (let i = 0, cssPrefixesCount = jsPrefixes.length; i < cssPrefixesCount; i++) { + const jsPrefix = jsPrefixes[i]; + const prefixedProp = jsPrefix + prop; + const lowerPrefixedProp = camelize(prefixedProp); - result = callBack(lowerPrefixedProp, jsPrefix); + result = callBack(lowerPrefixedProp, jsPrefix); - if(result === undefined) { - result = callBack(prefixedProp, jsPrefix); - } + if (result === undefined) { + result = callBack(prefixedProp, jsPrefix); + } - if(result !== undefined) { - break; - } + if (result !== undefined) { + break; } + } - return result || ''; + return result || ''; }; -const styleProp = function(name) { - if(name in getStyles()) { - return name; - } - - const originalName = name; - name = name.charAt(0).toUpperCase() + name.substr(1); - for(let i = 1; i < jsPrefixes.length; i++) { - const prefixedProp = jsPrefixes[i].toLowerCase() + name; - if(prefixedProp in getStyles()) { - return prefixedProp; - } +const styleProp = function (name) { + if (name in getStyles()) { + return name; + } + + const originalName = name; + name = name.charAt(0).toUpperCase() + name.substr(1); + for (let i = 1; i < jsPrefixes.length; i++) { + const prefixedProp = jsPrefixes[i].toLowerCase() + name; + if (prefixedProp in getStyles()) { + return prefixedProp; } + } - return originalName; + return originalName; }; -const stylePropPrefix = function(prop) { - return forEachPrefixes(prop, function(specific, jsPrefix) { - if(specific in getStyles()) { - return cssPrefixes[jsPrefix]; - } - }); +const stylePropPrefix = function (prop) { + return forEachPrefixes(prop, function (specific, jsPrefix) { + if (specific in getStyles()) { + return cssPrefixes[jsPrefix]; + } + }); }; - const pxExceptions = [ - 'fillOpacity', - 'columnCount', - 'flexGrow', - 'flexShrink', - 'fontWeight', - 'lineHeight', - 'opacity', - 'zIndex', - 'zoom' + 'fillOpacity', + 'columnCount', + 'flexGrow', + 'flexShrink', + 'fontWeight', + 'lineHeight', + 'opacity', + 'zIndex', + 'zoom', ]; -const parsePixelValue = function(value) { - if(isNumeric(value)) { - return value; - } else if(isString(value)) { - return Number(value.replace('px', '')); - } - return NaN; +const parsePixelValue = function (value) { + if (isNumeric(value)) { + return value; + } if (isString(value)) { + return Number(value.replace('px', '')); + } + return NaN; }; -const normalizeStyleProp = function(prop, value) { - if(isNumeric(value) && pxExceptions.indexOf(prop) === -1) { - value += 'px'; - } +const normalizeStyleProp = function (prop, value) { + if (isNumeric(value) && !pxExceptions.includes(prop)) { + // @ts-expect-error number + string + value += 'px'; + } - return value; + return value; }; -const setDimensionProperty = function(elements, propertyName, value) { - if(elements) { - value = isNumeric(value) ? value += 'px' : value; - for(let i = 0; i < elements.length; ++i) { - elements[i].style[propertyName] = value; - } +const setDimensionProperty = function (elements, propertyName, value) { + if (elements) { + // @ts-expect-error number + string + value = isNumeric(value) ? value += 'px' : value; + for (let i = 0; i < elements.length; ++i) { + elements[i].style[propertyName] = value; } + } }; -const setWidth = function(elements, value) { - setDimensionProperty(elements, 'width', value); +const setWidth = function (elements, value) { + setDimensionProperty(elements, 'width', value); }; -const setHeight = function(elements, value) { - setDimensionProperty(elements, 'height', value); +const setHeight = function (elements, value) { + setDimensionProperty(elements, 'height', value); }; -const setStyle = function(element, styleString, resetStyle = true) { - if(resetStyle) { - const styleList = [].slice.call(element.style); - styleList.forEach((propertyName) => { - element.style.removeProperty(propertyName); - }); - } - styleString.split(';').forEach((style) => { - const parts = style.split(':').map(stylePart => stylePart.trim()); - if(parts.length === 2) { - const [property, value] = parts; - element.style[property] = value; - } +const setStyle = function (element, styleString, resetStyle = true) { + if (resetStyle) { + const styleList = [].slice.call(element.style); + styleList.forEach((propertyName) => { + element.style.removeProperty(propertyName); }); + } + styleString.split(';').forEach((style) => { + const parts = style.split(':').map((stylePart) => stylePart.trim()); + if (parts.length === 2) { + const [property, value] = parts; + element.style[property] = value; + } + }); }; export { - styleProp, - setStyle, - stylePropPrefix, - normalizeStyleProp, - parsePixelValue, - setWidth, - setHeight + normalizeStyleProp, + parsePixelValue, + setHeight, + setStyle, + setWidth, + styleProp, + stylePropPrefix, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_support.ts b/packages/devextreme/js/__internal/core/utils/m_support.ts index 0d0e718df927..c1c0927d4b92 100644 --- a/packages/devextreme/js/__internal/core/utils/m_support.ts +++ b/packages/devextreme/js/__internal/core/utils/m_support.ts @@ -1,74 +1,91 @@ -import domAdapter from '../dom_adapter'; -import callOnce from './call_once'; -import { getNavigator, hasProperty } from './window'; -import devices from '../devices'; -import { stylePropPrefix, styleProp } from './style'; +import devices from '@js/core/devices'; +import domAdapter from '@js/core/dom_adapter'; +import callOnce from '@js/core/utils/call_once'; +import { styleProp, stylePropPrefix } from '@js/core/utils/style'; +import { getNavigator, hasProperty } from '@js/core/utils/window'; const { - maxTouchPoints, + maxTouchPoints, } = getNavigator(); const transitionEndEventNames = { - 'webkitTransition': 'webkitTransitionEnd', - 'MozTransition': 'transitionend', - 'OTransition': 'oTransitionEnd', - 'transition': 'transitionend' + webkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd', + transition: 'transitionend', }; -const supportProp = function(prop) { - return !!styleProp(prop); +const supportProp = function (prop) { + return !!styleProp(prop); }; -const isNativeScrollingSupported = function() { - const { platform, mac: isMac } = devices.real(); - const isNativeScrollDevice = platform === 'ios' || platform === 'android' || isMac; +const isNativeScrollingSupported = function () { + // @ts-expect-error mac doesnt exist in public type + const { platform, mac: isMac } = devices.real(); + const isNativeScrollDevice = platform === 'ios' || platform === 'android' || isMac; - return isNativeScrollDevice; + return isNativeScrollDevice; }; -const inputType = function(type) { - if(type === 'text') { - return true; - } +const inputType = function (type) { + if (type === 'text') { + return true; + } - const input = domAdapter.createElement('input'); - try { - input.setAttribute('type', type); - input.value = 'wrongValue'; - return !input.value; - } catch(e) { - return false; - } + const input = domAdapter.createElement('input'); + try { + input.setAttribute('type', type); + // @ts-expect-error need smarter typing + input.value = 'wrongValue'; + // @ts-expect-error need smarter typing + return !input.value; + } catch (e) { + return false; + } }; -const detectTouchEvents = function(hasWindowProperty, maxTouchPoints) { - return (hasWindowProperty('ontouchstart') || !!maxTouchPoints) && !hasWindowProperty('callPhantom'); +const detectTouchEvents = function (hasWindowProperty, maxTouchPoints) { + return (hasWindowProperty('ontouchstart') || !!maxTouchPoints) && !hasWindowProperty('callPhantom'); }; -const detectPointerEvent = function(hasWindowProperty) { - return hasWindowProperty('PointerEvent'); +const detectPointerEvent = function (hasWindowProperty) { + return hasWindowProperty('PointerEvent'); }; const touchEvents = detectTouchEvents(hasProperty, maxTouchPoints); const pointerEvents = detectPointerEvent(hasProperty); const touchPointersPresent = !!maxTouchPoints; -///#DEBUG +/// #DEBUG export { - detectTouchEvents, - detectPointerEvent + detectPointerEvent, + detectTouchEvents, }; -///#ENDDEBUG +/// #ENDDEBUG export { - touchEvents, - pointerEvents, - styleProp, - stylePropPrefix, - supportProp, - inputType + inputType, + pointerEvents, + styleProp, + stylePropPrefix, + supportProp, + touchEvents, }; export const touch = touchEvents || pointerEvents && touchPointersPresent; -export const transition = callOnce(function() { return supportProp('transition'); }); -export const transitionEndEventName = callOnce(function() { return transitionEndEventNames[styleProp('transition')]; }); -export const animation = callOnce(function() { return supportProp('animation'); }); +export const transition = callOnce(function () { return supportProp('transition'); }); +export const transitionEndEventName = callOnce(function () { return transitionEndEventNames[styleProp('transition')]; }); +export const animation = callOnce(function () { return supportProp('animation'); }); export const nativeScrolling = isNativeScrollingSupported(); + +export default { + animation, + inputType, + nativeScrolling, + pointerEvents, + styleProp, + stylePropPrefix, + supportProp, + touch, + touchEvents, + transition, + transitionEndEventName, +}; diff --git a/packages/devextreme/js/__internal/core/utils/m_svg.ts b/packages/devextreme/js/__internal/core/utils/m_svg.ts index aaec2b50229b..98d2f785daca 100644 --- a/packages/devextreme/js/__internal/core/utils/m_svg.ts +++ b/packages/devextreme/js/__internal/core/utils/m_svg.ts @@ -1,65 +1,72 @@ -import domAdapter from '../../core/dom_adapter'; -import { getWindow } from './window'; -import $ from '../../core/renderer'; -import { isRenderer, isString } from './type'; +import domAdapter from '@js/core/dom_adapter'; +import $ from '@js/core/renderer'; +import { isRenderer, isString } from '@js/core/utils/type'; +import { getWindow } from '@js/core/utils/window'; const window = getWindow(); function getMarkup(element, backgroundColor) { - const temp = domAdapter.createElement('div'); - const clone = element.cloneNode(true); - if(backgroundColor) { - $(clone).css('backgroundColor', backgroundColor); - } - temp.appendChild(clone); - return temp.innerHTML; + const temp = domAdapter.createElement('div'); + const clone = element.cloneNode(true); + if (backgroundColor) { + $(clone).css('backgroundColor', backgroundColor); + } + temp.appendChild(clone); + return temp.innerHTML; } function fixNamespaces(markup) { - let first = true; + let first = true; - if(markup.indexOf('xmlns:xlink') === -1) { - markup = markup.replace(' { - const optionsAttributeName = 'data-options'; - const templates = $(element).contents().filter(`[${optionsAttributeName}*="${name}"]`); - - return [].slice.call(templates).map((element) => { - const optionsString = $(element).attr(optionsAttributeName) || ''; - return { - element, - options: config().optionsParser(optionsString)[name] - }; - }).filter(template => !!template.options); + const optionsAttributeName = 'data-options'; + const templates = $(element).contents().filter(`[${optionsAttributeName}*="${name}"]`); + + return [].slice.call(templates).map((element) => { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const optionsString = $(element).attr(optionsAttributeName) || ''; + return { + element, + // @ts-expect-error optionsParser do not exist in public type + options: config().optionsParser(optionsString)[name], + }; + }).filter((template) => !!template.options); }; export const suitableTemplatesByName = (rawTemplates) => { - const templatesMap = groupBy(rawTemplates, (template) => template.options.name); + const templatesMap = groupBy(rawTemplates, (template) => template.options.name); - if(templatesMap['undefined']) { - throw Errors.Error('E0023'); - } + if (templatesMap.undefined) { + throw Errors.Error('E0023'); + } - const result = {}; + const result = {}; - Object.keys(templatesMap).forEach((name) => { - const suitableTemplate = findBestMatches( - devices.current(), - templatesMap[name], - template => template.options - )[0]?.element; + Object.keys(templatesMap).forEach((name) => { + const suitableTemplate = findBestMatches( + devices.current(), + templatesMap[name], + (template) => template.options, + )[0]?.element; - if(suitableTemplate) { - result[name] = suitableTemplate; - } - }); + if (suitableTemplate) { + result[name] = suitableTemplate; + } + }); - return result; + return result; }; export const addOneRenderedCall = (template) => { - const render = template.render.bind(template); - return extend({}, template, { - render(options) { - const templateResult = render(options); - options && options.onRendered && options.onRendered(); - return templateResult; - } - }); + const render = template.render.bind(template); + return extend({}, template, { + render(options) { + const templateResult = render(options); + options && options.onRendered && options.onRendered(); + return templateResult; + }, + }); }; export const addPublicElementNormalization = (template) => { - const render = template.render.bind(template); - return extend({}, template, { - render(options) { - const $container = $(options.container); - return render({ ...options, container: getPublicElement($container) }); - } - }); + const render = template.render.bind(template); + return extend({}, template, { + render(options) { + const $container = $(options.container); + return render({ ...options, container: getPublicElement($container) }); + }, + }); }; export const getNormalizedTemplateArgs = (options) => { - const args = []; + const args: any[] = []; - if('model' in options) { - args.push(options.model); - } - if('index' in options) { - args.push(options.index); - } - args.push(options.container); + if ('model' in options) { + args.push(options.model); + } + if ('index' in options) { + args.push(options.index); + } + args.push(options.container); - return args; + return args; }; -export const validateTemplateSource = (templateSource) => { - return typeof templateSource === 'string' - ? normalizeTemplateElement(templateSource) - : templateSource; -}; +export const validateTemplateSource = (templateSource) => (typeof templateSource === 'string' + ? domUtils.normalizeTemplateElement(templateSource) + : templateSource); -export const templateKey = (templateSource) => { - return (isRenderer(templateSource) && templateSource[0]) || templateSource; -}; +export const templateKey = (templateSource) => (typeUtils.isRenderer(templateSource) && templateSource[0]) || templateSource; -export const defaultCreateElement = element => new Template(element); +export const defaultCreateElement = (element) => new Template(element); export const acquireIntegrationTemplate = (templateSource, templates, isAsyncTemplate, skipTemplates) => { - let integrationTemplate = null; - - if(!skipTemplates || skipTemplates.indexOf(templateSource) === -1) { - integrationTemplate = templates[templateSource]; - if(integrationTemplate && !(integrationTemplate instanceof TemplateBase)) { - if(isFunction(integrationTemplate.render)) { - integrationTemplate = addPublicElementNormalization(integrationTemplate); - } - - if(!isAsyncTemplate) { - integrationTemplate = addOneRenderedCall(integrationTemplate); - } - } + let integrationTemplate: any = null; + + if (!skipTemplates || skipTemplates.indexOf(templateSource) === -1) { + integrationTemplate = templates[templateSource]; + if (integrationTemplate && !(integrationTemplate instanceof TemplateBase)) { + if (typeUtils.isFunction(integrationTemplate.render)) { + integrationTemplate = addPublicElementNormalization(integrationTemplate); + } + + if (!isAsyncTemplate) { + integrationTemplate = addOneRenderedCall(integrationTemplate); + } } + } - return integrationTemplate; + return integrationTemplate; }; export const acquireTemplate = (templateSource, createTemplate, templates, isAsyncTemplate, skipTemplates, defaultTemplates) => { - if(templateSource == null) { - return new EmptyTemplate(); - } - - if(templateSource instanceof ChildDefaultTemplate) { - return defaultTemplates[templateSource.name]; - } - - if(templateSource instanceof TemplateBase) { - return templateSource; - } - - // TODO: templateSource.render is needed for angular2 integration. Try to remove it after supporting TypeScript modules. - if(isFunction(templateSource.render) && !isRenderer(templateSource)) { - return isAsyncTemplate ? templateSource : addOneRenderedCall(templateSource); - } - - if(templateSource.nodeType || isRenderer(templateSource)) { - return createTemplate($(templateSource)); - } + if (templateSource == null) { + return new EmptyTemplate(); + } + + if (templateSource instanceof ChildDefaultTemplate) { + return defaultTemplates[templateSource.name]; + } + + if (templateSource instanceof TemplateBase) { + return templateSource; + } + + // TODO: templateSource.render is needed for angular2 integration. Try to remove it after supporting TypeScript modules. + if (typeUtils.isFunction(templateSource.render) && !typeUtils.isRenderer(templateSource)) { + return isAsyncTemplate ? templateSource : addOneRenderedCall(templateSource); + } + + if (templateSource.nodeType || typeUtils.isRenderer(templateSource)) { + return createTemplate($(templateSource)); + } + + return acquireIntegrationTemplate(templateSource, templates, isAsyncTemplate, skipTemplates) + || defaultTemplates[templateSource] + || createTemplate(templateSource); +}; - return acquireIntegrationTemplate(templateSource, templates, isAsyncTemplate, skipTemplates) - || defaultTemplates[templateSource] - || createTemplate(templateSource); +export default { + findTemplates, + suitableTemplatesByName, + addOneRenderedCall, + addPublicElementNormalization, + getNormalizedTemplateArgs, + validateTemplateSource, + templateKey, + defaultCreateElement, + acquireIntegrationTemplate, + acquireTemplate, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_type.ts b/packages/devextreme/js/__internal/core/utils/m_type.ts index 560f45ed8375..8e8a1a20a1c3 100644 --- a/packages/devextreme/js/__internal/core/utils/m_type.ts +++ b/packages/devextreme/js/__internal/core/utils/m_type.ts @@ -1,119 +1,140 @@ const types = { - '[object Array]': 'array', - '[object Date]': 'date', - '[object Object]': 'object', - '[object String]': 'string' + '[object Array]': 'array', + '[object Date]': 'date', + '[object Object]': 'object', + '[object String]': 'string', }; -const type = function(object) { - if(object === null) { - return 'null'; - } +const type = function (object) { + if (object === null) { + return 'null'; + } - const typeOfObject = Object.prototype.toString.call(object); + const typeOfObject = Object.prototype.toString.call(object); - return typeof object === 'object' ? - types[typeOfObject] || 'object' : typeof object; + return typeof object === 'object' + ? types[typeOfObject] || 'object' : typeof object; }; -const isBoolean = function(object) { - return typeof object === 'boolean'; +const isBoolean = function (object) { + return typeof object === 'boolean'; }; -const isExponential = function(value) { - return isNumeric(value) && value.toString().indexOf('e') !== -1; +const isExponential = function (value) { + return isNumeric(value) && value.toString().indexOf('e') !== -1; }; -const isDate = function(object) { - return type(object) === 'date'; +const isDate = function (object) { + return type(object) === 'date'; }; -const isDefined = function(object) { - return (object !== null) && (object !== undefined); +const isDefined = function (object) { + return (object !== null) && (object !== undefined); }; -const isFunction = function(object) { - return typeof object === 'function'; +const isFunction = function (object) { + return typeof object === 'function'; }; -const isString = function(object) { - return typeof object === 'string'; +const isString = function (object) { + return typeof object === 'string'; }; -const isNumeric = function(object) { - return ((typeof object === 'number') && isFinite(object) || !isNaN(object - parseFloat(object))); +const isNumeric = function (object) { + return (typeof object === 'number') && isFinite(object) || !isNaN(object - parseFloat(object)); }; -const isObject = function(object) { - return type(object) === 'object'; +const isObject = function (object) { + return type(object) === 'object'; }; -const isEmptyObject = function(object) { - let property; +const isEmptyObject = function (object) { + let property; - for(property in object) { - return false; - } + // eslint-disable-next-line no-unreachable-loop + for (property in object) { + return false; + } - return true; + return true; }; -const isPlainObject = function(object) { - if(!object || type(object) !== 'object') { - return false; - } - const proto = Object.getPrototypeOf(object); +const isPlainObject = function (object) { + if (!object || type(object) !== 'object') { + return false; + } + const proto = Object.getPrototypeOf(object); - if(!proto) { - return true; - } + if (!proto) { + return true; + } - const ctor = Object.hasOwnProperty.call(proto, 'constructor') && proto.constructor; + const ctor = Object.hasOwnProperty.call(proto, 'constructor') && proto.constructor; - return typeof ctor === 'function' - && Object.toString.call(ctor) === Object.toString.call(Object); + return typeof ctor === 'function' + && Object.toString.call(ctor) === Object.toString.call(Object); }; -const isPrimitive = function(value) { - return ['object', 'array', 'function'].indexOf(type(value)) === -1; +const isPrimitive = function (value) { + return !['object', 'array', 'function'].includes(type(value)); }; -const isWindow = function(object) { - return object != null && object === object.window; +const isWindow = function (object) { + return object != null && object === object.window; }; -const isRenderer = function(object) { - return !!object && !!(object.jquery || object.dxRenderer); +const isRenderer = function (object) { + return !!object && !!(object.jquery || object.dxRenderer); }; -const isPromise = function(object) { - return !!object && isFunction(object.then); +const isPromise = function (object) { + return !!object && isFunction(object.then); }; -const isDeferred = function(object) { - return !!object && isFunction(object.done) && isFunction(object.fail); +const isDeferred = function (object) { + return !!object && isFunction(object.done) && isFunction(object.fail); }; -const isEvent = function(object) { - return !!(object && object.preventDefault); +const isEvent = function (object) { + return !!(object && object.preventDefault); }; export { - isBoolean, - isExponential, - isDate, - isDefined, - isFunction, - isString, - isNumeric, - isObject, - isEmptyObject, - isPlainObject, - isPrimitive, - isWindow, - isRenderer, - isPromise, - isDeferred, - type, - isEvent + isBoolean, + isDate, + isDeferred, + isDefined, + isEmptyObject, + isEvent, + isExponential, + isFunction, + isNumeric, + isObject, + isPlainObject, + isPrimitive, + isPromise, + isRenderer, + isString, + isWindow, + type, +}; + +export default { + isBoolean, + isDate, + isDeferred, + isDefined, + isEmptyObject, + isEvent, + isExponential, + isFunction, + isNumeric, + isObject, + isPlainObject, + isPrimitive, + isPromise, + isRenderer, + isString, + isWindow, + type, }; diff --git a/packages/devextreme/js/__internal/core/utils/m_variable_wrapper.ts b/packages/devextreme/js/__internal/core/utils/m_variable_wrapper.ts index 083381210272..b1c82d0e17e3 100644 --- a/packages/devextreme/js/__internal/core/utils/m_variable_wrapper.ts +++ b/packages/devextreme/js/__internal/core/utils/m_variable_wrapper.ts @@ -1,20 +1,22 @@ -import { logger } from './console'; -import dependencyInjector from './dependency_injector'; +/* eslint-disable object-shorthand */ +import { logger } from '@js/core/utils/console'; +import dependencyInjector from '@js/core/utils/dependency_injector'; -export default dependencyInjector({ - isWrapped: function() { - return false; - }, - isWritableWrapped: function() { - return false; - }, - wrap: function(value) { - return value; - }, - unwrap: function(value) { - return value; - }, - assign: function() { - logger.error('Method \'assign\' should not be used for not wrapped variables. Use \'isWrapped\' method for ensuring.'); - } +const variableWrapper = dependencyInjector({ + isWrapped: function () { + return false; + }, + isWritableWrapped: function () { + return false; + }, + wrap: function (value) { + return value; + }, + unwrap: function (value) { + return value; + }, + assign: function () { + logger.error('Method \'assign\' should not be used for not wrapped variables. Use \'isWrapped\' method for ensuring.'); + }, }); +export { variableWrapper }; diff --git a/packages/devextreme/js/__internal/core/utils/m_version.ts b/packages/devextreme/js/__internal/core/utils/m_version.ts index f8535e0be6bc..df53961d1a65 100644 --- a/packages/devextreme/js/__internal/core/utils/m_version.ts +++ b/packages/devextreme/js/__internal/core/utils/m_version.ts @@ -1,35 +1,34 @@ -export function compare(x, y, maxLevel) { - - function normalizeArg(value) { - if(typeof value === 'string') { - return value.split('.'); - } - if(typeof value === 'number') { - return [value]; - } - return value; +export function compare(x, y, maxLevel?) { + function normalizeArg(value) { + if (typeof value === 'string') { + return value.split('.'); + } + if (typeof value === 'number') { + return [value]; } + return value; + } - x = normalizeArg(x); - y = normalizeArg(y); + x = normalizeArg(x); + y = normalizeArg(y); - let length = Math.max(x.length, y.length); + let length = Math.max(x.length, y.length); - if(isFinite(maxLevel)) { - length = Math.min(length, maxLevel); - } + if (isFinite(maxLevel)) { + length = Math.min(length, maxLevel); + } - for(let i = 0; i < length; i++) { - const xItem = parseInt(x[i] || 0, 10); - const yItem = parseInt(y[i] || 0, 10); + for (let i = 0; i < length; i++) { + const xItem = parseInt(x[i] || 0, 10); + const yItem = parseInt(y[i] || 0, 10); - if(xItem < yItem) { - return -1; - } - if(xItem > yItem) { - return 1; - } + if (xItem < yItem) { + return -1; + } + if (xItem > yItem) { + return 1; } + } - return 0; + return 0; } diff --git a/packages/devextreme/js/__internal/core/utils/m_view_port.ts b/packages/devextreme/js/__internal/core/utils/m_view_port.ts index f9296f0b502c..c0bb4d30fb34 100644 --- a/packages/devextreme/js/__internal/core/utils/m_view_port.ts +++ b/packages/devextreme/js/__internal/core/utils/m_view_port.ts @@ -1,36 +1,37 @@ -import $ from '../renderer'; -import readyCallbacks from './ready_callbacks'; +import $ from '@js/core/renderer'; +import callbacks from '@js/core/utils/callbacks'; +import readyCallbacks from '@js/core/utils/ready_callbacks'; + const ready = readyCallbacks.add; -import callbacks from './callbacks'; const changeCallback = callbacks(); let $originalViewPort = $(); -const value = (function() { - let $current; +const value: any = (function () { + let $current; - return function(element) { - if(!arguments.length) { - return $current; - } + return function (element) { + if (!arguments.length) { + return $current; + } - const $element = $(element); - $originalViewPort = $element; - const isNewViewportFound = !!$element.length; - const prevViewPort = value(); - $current = isNewViewportFound ? $element : $('body'); - changeCallback.fire(isNewViewportFound ? value() : $(), prevViewPort); - }; + const $element = $(element); + $originalViewPort = $element; + const isNewViewportFound = !!$element.length; + const prevViewPort = value(); + $current = isNewViewportFound ? $element : $('body'); + changeCallback.fire(isNewViewportFound ? value() : $(), prevViewPort); + }; })(); -ready(function() { - value('.dx-viewport'); +ready(function () { + value('.dx-viewport'); }); export { - value, - changeCallback + changeCallback, + value, }; export function originalViewPort() { - return $originalViewPort; + return $originalViewPort; } diff --git a/packages/devextreme/js/__internal/core/utils/m_window.ts b/packages/devextreme/js/__internal/core/utils/m_window.ts index 49c14fbd7893..f2e1dffbff3b 100644 --- a/packages/devextreme/js/__internal/core/utils/m_window.ts +++ b/packages/devextreme/js/__internal/core/utils/m_window.ts @@ -1,58 +1,67 @@ /* global window */ -import domAdapter from '../dom_adapter'; +import domAdapter from '@js/core/dom_adapter'; let hasWindowValue = typeof window !== 'undefined'; const hasWindow = () => hasWindowValue; -let windowObject = hasWindow() ? window : undefined; +let windowObject: any = hasWindow() ? window : undefined; -if(!windowObject) { - windowObject = {}; - windowObject.window = windowObject; +if (!windowObject) { + windowObject = {}; + windowObject.window = windowObject; } const getWindow = () => windowObject; const setWindow = (newWindowObject, hasWindow) => { - if(hasWindow === undefined) { - hasWindowValue = typeof window !== 'undefined' && window === newWindowObject; - } else { - hasWindowValue = hasWindow; - } - windowObject = newWindowObject; + if (hasWindow === undefined) { + hasWindowValue = typeof window !== 'undefined' && window === newWindowObject; + } else { + hasWindowValue = hasWindow; + } + windowObject = newWindowObject; }; const hasProperty = (prop) => hasWindow() && prop in windowObject; const defaultScreenFactorFunc = (width) => { - if(width < 768) { - return 'xs'; - } else if(width < 992) { - return 'sm'; - } else if(width < 1200) { - return 'md'; - } else { - return 'lg'; - } + if (width < 768) { + return 'xs'; + } if (width < 992) { + return 'sm'; + } if (width < 1200) { + return 'md'; + } + return 'lg'; }; const getCurrentScreenFactor = (screenFactorCallback) => { - const screenFactorFunc = screenFactorCallback || defaultScreenFactorFunc; - const windowWidth = domAdapter.getDocumentElement()['clientWidth']; + const screenFactorFunc = screenFactorCallback || defaultScreenFactorFunc; + const windowWidth = domAdapter.getDocumentElement().clientWidth; - return screenFactorFunc(windowWidth); + return screenFactorFunc(windowWidth); }; -const getNavigator = () => hasWindow() ? windowObject.navigator : { userAgent: '' }; +const getNavigator = () => (hasWindow() ? windowObject?.navigator : { userAgent: '' }); export { - hasWindow, - getWindow, - setWindow, - hasProperty, - defaultScreenFactorFunc, - getCurrentScreenFactor, - getNavigator + defaultScreenFactorFunc, + getCurrentScreenFactor, + getNavigator, + getWindow, + hasProperty, + hasWindow, + setWindow, +}; + +export default { + defaultScreenFactorFunc, + getCurrentScreenFactor, + getNavigator, + getWindow, + hasProperty, + hasWindow, + setWindow, }; diff --git a/packages/devextreme/js/__internal/core/widget/component.ts b/packages/devextreme/js/__internal/core/widget/component.ts index c048bcc57352..17ae60df9b1a 100644 --- a/packages/devextreme/js/__internal/core/widget/component.ts +++ b/packages/devextreme/js/__internal/core/widget/component.ts @@ -43,7 +43,8 @@ OptionChangedEventInfo export class Component< TComponent extends Component, TProperties extends Properties, -// eslint-disable-next-line @typescript-eslint/ban-types + // @ts-expect-error dxClass inheritance issue + // eslint-disable-next-line @typescript-eslint/ban-types > extends (Class.inherit({}) as new() => {}) { _deprecatedOptions!: Partial; @@ -492,7 +493,7 @@ export class Component< // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types option(...args): TProperties { // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this._options.option(...args); + return this._options.option(...args as [never, never]); } resetOption(name: string): void { diff --git a/packages/devextreme/js/__internal/core/widget/dom_component.ts b/packages/devextreme/js/__internal/core/widget/dom_component.ts index be5a88c4f504..2f178dd41f63 100644 --- a/packages/devextreme/js/__internal/core/widget/dom_component.ts +++ b/packages/devextreme/js/__internal/core/widget/dom_component.ts @@ -5,7 +5,6 @@ import { cleanDataRecursive } from '@js/core/element_data'; import errors from '@js/core/errors'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; -import { TemplateManager } from '@js/core/template_manager'; // @ts-expect-error import { grep, noop } from '@js/core/utils/common'; import { extend } from '@js/core/utils/extend'; @@ -17,6 +16,7 @@ import { isDefined, isFunction, isString } from '@js/core/utils/type'; import { hasWindow } from '@js/core/utils/window'; import { resize as resizeEvent, visibility as visibilityEvents } from '@js/events/short'; import license, { peekValidationPerformed } from '@ts/core/license/license_validation'; +import TemplateManagerModule from '@ts/core/m_template_manager'; import { Component } from './component'; import type { OptionChanged } from './types'; @@ -82,8 +82,7 @@ class DOMComponent< disabled: false, integrationOptions: {}, - // @ts-expect-error - }, this._useTemplates() ? TemplateManager.createDefaultOptions() : {}); + }, this._useTemplates() ? TemplateManagerModule.TemplateManager.createDefaultOptions() : {}); } ctor(element: Element, options: TProperties): void { @@ -225,7 +224,6 @@ class DOMComponent< const height = this._getOptionValue('height', element); if (this._isCssUpdateRequired(element, height, width)) { - // @ts-expect-error $element.css({ width: width === null ? '' : width, height: height === null ? '' : height, @@ -533,8 +531,7 @@ class DOMComponent< const { integrationOptions = {} } = this.option(); const { createTemplate } = integrationOptions; - this._templateManager = new TemplateManager( - // @ts-expect-error + this._templateManager = new TemplateManagerModule.TemplateManager( createTemplate, this._getAnonymousTemplateName(), ); diff --git a/packages/devextreme/js/__internal/data/data_source/m_data_source.ts b/packages/devextreme/js/__internal/data/data_source/m_data_source.ts index 8d4cb489f91b..be4f4ea3fd45 100644 --- a/packages/devextreme/js/__internal/data/data_source/m_data_source.ts +++ b/packages/devextreme/js/__internal/data/data_source/m_data_source.ts @@ -1,7 +1,5 @@ import Class from '@js/core/class'; import { EventsStrategy } from '@js/core/events_strategy'; -// @ts-expect-error -import { executeAsync } from '@js/core/utils/common'; import { Deferred, when } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; import { each } from '@js/core/utils/iterator'; @@ -24,6 +22,7 @@ import { import { errors } from '@js/data/errors'; // @ts-expect-error import { throttleChanges } from '@js/data/utils'; +import commonUtils from '@ts/core/utils/m_common'; export const DataSource = Class.inherit({ ctor(options) { @@ -422,7 +421,7 @@ export const DataSource = Class.inherit({ this._loadQueue.add(() => { if (typeof loadOperation.delay === 'number') { - this._delayedLoadTask = executeAsync(loadTask, loadOperation.delay); + this._delayedLoadTask = commonUtils.executeAsync(loadTask, loadOperation.delay); } else { loadTask(); } diff --git a/packages/devextreme/js/__internal/data/m_abstract_store.ts b/packages/devextreme/js/__internal/data/m_abstract_store.ts index 30462a072449..9e2a8b6fb1a6 100644 --- a/packages/devextreme/js/__internal/data/m_abstract_store.ts +++ b/packages/devextreme/js/__internal/data/m_abstract_store.ts @@ -229,7 +229,6 @@ Store.registerClass = function (type, alias) { } return type; }; -// @ts-expect-error Store.inherit = (function (inheritor) { return function (members, alias) { const type = inheritor.apply(this, [members]); diff --git a/packages/devextreme/js/__internal/data/m_array_query.ts b/packages/devextreme/js/__internal/data/m_array_query.ts index ee39872072ed..6c02d4285a66 100644 --- a/packages/devextreme/js/__internal/data/m_array_query.ts +++ b/packages/devextreme/js/__internal/data/m_array_query.ts @@ -1,5 +1,4 @@ import Class from '@js/core/class'; -// @ts-expect-error import { compileGetter, toComparable } from '@js/core/utils/data'; import { Deferred } from '@js/core/utils/deferred'; import { each, map } from '@js/core/utils/iterator'; @@ -161,7 +160,6 @@ const SortIterator = Iterator.inherit({ thenBy(getter, desc, compare) { const result = new SortIterator(this.sortedIter || this.iter, getter, desc, compare); if (!this.sortedIter) { - // @ts-expect-error result.rules = this.rules.concat(result.rules); } return result; @@ -648,7 +646,6 @@ const arrayQueryImpl = function (iter, queryOptions) { thenBy(getter, desc, compare) { if (iter instanceof SortIterator) { - // @ts-expect-error return chainQuery(iter.thenBy(getter, desc, compare)); } diff --git a/packages/devextreme/js/__internal/data/m_local_store.ts b/packages/devextreme/js/__internal/data/m_local_store.ts index ca9df92775bf..118cea0ecf27 100644 --- a/packages/devextreme/js/__internal/data/m_local_store.ts +++ b/packages/devextreme/js/__internal/data/m_local_store.ts @@ -25,7 +25,6 @@ const LocalStoreBackend = Class.inherit({ eventsEngine.on(window, 'beforeunload', saveProxy); // @ts-expect-error if (window.cordova) { - // @ts-expect-error domAdapter.listen(domAdapter.getDocument(), 'pause', saveProxy, false); } } diff --git a/packages/devextreme/js/__internal/data/m_utils.ts b/packages/devextreme/js/__internal/data/m_utils.ts index bc36f932c7d9..ea0a65a494d8 100644 --- a/packages/devextreme/js/__internal/data/m_utils.ts +++ b/packages/devextreme/js/__internal/data/m_utils.ts @@ -70,7 +70,6 @@ export const errorMessageFromXhr = (function () { let unloading; ready(() => { const window = getWindow(); - // @ts-expect-error domAdapter.listen(window, 'beforeunload', () => { unloading = true; }); }); diff --git a/packages/devextreme/js/__internal/data_controller.ts b/packages/devextreme/js/__internal/data_controller.ts index 71c9c2782029..45aaa57acaf9 100644 --- a/packages/devextreme/js/__internal/data_controller.ts +++ b/packages/devextreme/js/__internal/data_controller.ts @@ -76,7 +76,6 @@ class DataController { _updateDataSourceByItems(items: unknown[]): void { // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error this._dataSource = new DataSource({ store: new ArrayStore({ key: this.key(), diff --git a/packages/devextreme/js/__internal/events/core/m_emitter.feedback.ts b/packages/devextreme/js/__internal/events/core/m_emitter.feedback.ts index bf19246fa872..1649da5afd88 100644 --- a/packages/devextreme/js/__internal/events/core/m_emitter.feedback.ts +++ b/packages/devextreme/js/__internal/events/core/m_emitter.feedback.ts @@ -1,11 +1,11 @@ import Class from '@js/core/class'; -import devices from '@js/core/devices'; import { ensureDefined, noop } from '@js/core/utils/common'; import { contains } from '@js/core/utils/dom'; import Emitter from '@js/events/core/emitter'; import registerEmitter from '@js/events/core/emitter_registrator'; import pointerEvents from '@js/events/pointer'; import { isMouseEvent } from '@js/events/utils/index'; +import devices from '@ts/core/m_devices'; const ACTIVE_EVENT_NAME = 'dxactive'; const INACTIVE_EVENT_NAME = 'dxinactive'; @@ -158,7 +158,7 @@ const FeedbackEmitter = Emitter.inherit({ }, }); -// @ts-expect-error + FeedbackEmitter.lock = function (deferred) { const lockInactive = activeFeedback ? activeFeedback.lockInactive() : noop; @@ -173,7 +173,6 @@ registerEmitter({ ], }); -// @ts-expect-error export const { lock } = FeedbackEmitter; export { ACTIVE_EVENT_NAME as active, diff --git a/packages/devextreme/js/__internal/events/core/m_emitter_registrator.ts b/packages/devextreme/js/__internal/events/core/m_emitter_registrator.ts index 77540f77ce3c..48d06a7f38bd 100644 --- a/packages/devextreme/js/__internal/events/core/m_emitter_registrator.ts +++ b/packages/devextreme/js/__internal/events/core/m_emitter_registrator.ts @@ -284,9 +284,7 @@ const registerEmitter = function (emitterConfig) { }); if (disposeEmitter) { - // @ts-expect-error if (eventManager.isActive(element)) { - // @ts-expect-error eventManager.resetEmitter(emitter); } diff --git a/packages/devextreme/js/__internal/events/core/m_events_engine.ts b/packages/devextreme/js/__internal/events/core/m_events_engine.ts index 75b3058cd4db..53f51b8a8fd8 100644 --- a/packages/devextreme/js/__internal/events/core/m_events_engine.ts +++ b/packages/devextreme/js/__internal/events/core/m_events_engine.ts @@ -61,7 +61,6 @@ const EVENT_PROPERTIES = [ ]; function matchesSafe(target, selector) { - // @ts-expect-error return !isWindow(target) && target.nodeName !== '#document' && domAdapter.elementMatches(target, selector); } const elementDataMap = new WeakMap(); @@ -322,8 +321,6 @@ function getHandlersController(element, eventName) { passive: false, }; } - - // @ts-expect-error eventData.removeListener = domAdapter.listen(element, NATIVE_EVENTS_TO_SUBSCRIBE[eventName] || eventName, eventData.nativeHandler, nativeListenerOptions); } diff --git a/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.scroll.ts b/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.scroll.ts index b8ba6593c113..abd66c8d2c0d 100644 --- a/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.scroll.ts +++ b/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.scroll.ts @@ -1,12 +1,12 @@ import { cancelAnimationFrame, requestAnimationFrame } from '@js/animation/frame'; import Class from '@js/core/class'; -import devices from '@js/core/devices'; import registerEmitter from '@js/events/core/emitter_registrator'; import eventsEngine from '@js/events/core/events_engine'; import GestureEmitter from '@js/events/gesture/emitter.gesture'; import { addNamespace, eventData, eventDelta, isDxMouseWheelEvent, isMouseEvent, } from '@js/events/utils/index'; +import devices from '@ts/core/m_devices'; const { abstract } = Class; diff --git a/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.ts b/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.ts index b74fd5ff811b..c507772f7c90 100644 --- a/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.ts +++ b/packages/devextreme/js/__internal/events/gesture/m_emitter.gesture.ts @@ -1,8 +1,6 @@ -import devices from '@js/core/devices'; import $ from '@js/core/renderer'; import callOnce from '@js/core/utils/call_once'; import { noop } from '@js/core/utils/common'; -import { clearSelection, resetActiveElement } from '@js/core/utils/dom'; import { sign } from '@js/core/utils/math'; import readyCallbacks from '@js/core/utils/ready_callbacks'; import { styleProp } from '@js/core/utils/style'; @@ -12,6 +10,8 @@ import eventsEngine from '@js/events/core/events_engine'; import { createEvent, eventData, eventDelta, isDxMouseWheelEvent, isTouchEvent, needSkipEvent, } from '@js/events/utils/index'; +import devices from '@ts/core/m_devices'; +import domUtils from '@ts/core/utils/m_dom'; const ready = readyCallbacks.add; const { abs } = Math; @@ -180,7 +180,7 @@ const GestureEmitter = Emitter.inherit({ _resetActiveElement() { if (devices.real().platform === 'ios' && this.getElement().find(':focus').length) { - resetActiveElement(); + domUtils.resetActiveElement(); } }, @@ -201,7 +201,7 @@ const GestureEmitter = Emitter.inherit({ return; } - clearSelection(); + domUtils.clearSelection(); }, end(e) { @@ -229,9 +229,7 @@ const GestureEmitter = Emitter.inherit({ _end: noop, }); -// @ts-expect-error GestureEmitter.initialTouchBoundary = TOUCH_BOUNDARY; -// @ts-expect-error GestureEmitter.touchBoundary = function (newBoundary) { if (isDefined(newBoundary)) { TOUCH_BOUNDARY = newBoundary; diff --git a/packages/devextreme/js/__internal/events/m_click.ts b/packages/devextreme/js/__internal/events/m_click.ts index adbe5737fb8c..6b1804bc55e2 100644 --- a/packages/devextreme/js/__internal/events/m_click.ts +++ b/packages/devextreme/js/__internal/events/m_click.ts @@ -1,8 +1,6 @@ import { cancelAnimationFrame, requestAnimationFrame } from '@js/animation/frame'; -import devices from '@js/core/devices'; import domAdapter from '@js/core/dom_adapter'; import $ from '@js/core/renderer'; -import { resetActiveElement } from '@js/core/utils/dom'; import Emitter from '@js/events/core/emitter'; import registerEmitter from '@js/events/core/emitter_registrator'; import eventsEngine from '@js/events/core/events_engine'; @@ -10,6 +8,8 @@ import pointerEvents from '@js/events/pointer'; import { subscribeNodesDisposing, unsubscribeNodesDisposing } from '@js/events/utils/event_nodes_disposing'; import { getEventTarget } from '@js/events/utils/event_target'; import { addNamespace, fireEvent } from '@js/events/utils/index'; +import devices from '@ts/core/m_devices'; +import domUtils from '@ts/core/utils/m_dom'; const CLICK_EVENT_NAME = 'dxclick'; @@ -89,7 +89,7 @@ const ClickEmitter = Emitter.inherit({ const $target = getTarget(e); if (!blurPrevented && startTarget && !$target.is(startTarget) && !$(startTarget).is('label') && isInput($target)) { - resetActiveElement(); + domUtils.resetActiveElement(); } startTarget = null; diff --git a/packages/devextreme/js/__internal/events/m_contextmenu.ts b/packages/devextreme/js/__internal/events/m_contextmenu.ts index 958534cfd4d8..d0816416647c 100644 --- a/packages/devextreme/js/__internal/events/m_contextmenu.ts +++ b/packages/devextreme/js/__internal/events/m_contextmenu.ts @@ -1,11 +1,11 @@ import Class from '@js/core/class'; -import devices from '@js/core/devices'; import $ from '@js/core/renderer'; -import { touch } from '@js/core/utils/support'; import registerEvent from '@js/events/core/event_registrator'; import eventsEngine from '@js/events/core/events_engine'; import holdEvent from '@js/events/hold'; import { addNamespace, fireEvent, isMouseEvent } from '@js/events/utils/index'; +import devices from '@ts/core/m_devices'; +import supportUtils from '@ts/core/utils/m_support'; const CONTEXTMENU_NAMESPACE = 'dxContexMenu'; @@ -21,7 +21,7 @@ const ContextMenu = Class.inherit({ eventsEngine.on($element, CONTEXTMENU_NAMESPACED_EVENT_NAME, this._contextMenuHandler.bind(this)); - if (touch || devices.isSimulator()) { + if (supportUtils.touch || devices.isSimulator()) { eventsEngine.on($element, HOLD_NAMESPACED_EVENT_NAME, this._holdHandler.bind(this)); } }, diff --git a/packages/devextreme/js/__internal/events/m_hover.ts b/packages/devextreme/js/__internal/events/m_hover.ts index d28353334c2b..ef963775cc64 100644 --- a/packages/devextreme/js/__internal/events/m_hover.ts +++ b/packages/devextreme/js/__internal/events/m_hover.ts @@ -1,10 +1,10 @@ import Class from '@js/core/class'; -import devices from '@js/core/devices'; import { data as elementData, removeData } from '@js/core/element_data'; import registerEvent from '@js/events/core/event_registrator'; import eventsEngine from '@js/events/core/events_engine'; import pointerEvents from '@js/events/pointer'; import { addNamespace, fireEvent, isTouchEvent } from '@js/events/utils/index'; +import devices from '@ts/core/m_devices'; const HOVERSTART_NAMESPACE = 'dxHoverStart'; const HOVERSTART = 'dxhoverstart'; diff --git a/packages/devextreme/js/__internal/events/m_pointer.ts b/packages/devextreme/js/__internal/events/m_pointer.ts index 7b1f09b1aae5..e4025dbd0371 100644 --- a/packages/devextreme/js/__internal/events/m_pointer.ts +++ b/packages/devextreme/js/__internal/events/m_pointer.ts @@ -1,11 +1,11 @@ import GlobalConfig from '@js/core/config'; -import devices from '@js/core/devices'; import { each } from '@js/core/utils/iterator'; -import * as support from '@js/core/utils/support'; import registerEvent from '@js/events/core/event_registrator'; import MouseStrategy from '@js/events/pointer/mouse'; import MouseAndTouchStrategy from '@js/events/pointer/mouse_and_touch'; import TouchStrategy from '@js/events/pointer/touch'; +import devices from '@ts/core/m_devices'; +import support from '@ts/core/utils/m_support'; const getStrategy = (support, { tablet, phone }) => { const pointerEventStrategy = getStrategyFromGlobalConfig(); @@ -24,7 +24,6 @@ const getStrategy = (support, { tablet, phone }) => { return MouseStrategy; }; -// @ts-expect-error const EventStrategy = getStrategy(support, devices.real()); each(EventStrategy.map, (pointerEvent, originalEvents) => { diff --git a/packages/devextreme/js/__internal/events/pointer/m_mouse.ts b/packages/devextreme/js/__internal/events/pointer/m_mouse.ts index 87cf81e5e738..6923ca95f16e 100644 --- a/packages/devextreme/js/__internal/events/pointer/m_mouse.ts +++ b/packages/devextreme/js/__internal/events/pointer/m_mouse.ts @@ -48,13 +48,10 @@ const MouseStrategy = BaseStrategy.inherit({ }, }); -// @ts-expect-error + MouseStrategy.map = eventMap; -// @ts-expect-error MouseStrategy.normalize = normalizeMouseEvent; -// @ts-expect-error MouseStrategy.activate = activateStrategy; -// @ts-expect-error MouseStrategy.resetObserver = function () { observer.reset(); }; diff --git a/packages/devextreme/js/__internal/events/pointer/m_mouse_and_touch.ts b/packages/devextreme/js/__internal/events/pointer/m_mouse_and_touch.ts index ca198b4a1bf0..ace13e48880c 100644 --- a/packages/devextreme/js/__internal/events/pointer/m_mouse_and_touch.ts +++ b/packages/devextreme/js/__internal/events/pointer/m_mouse_and_touch.ts @@ -21,7 +21,6 @@ const activateStrategy = function () { if (activated) { return; } - // @ts-expect-error MouseStrategy.activate(); activated = true; @@ -66,7 +65,6 @@ const MouseAndTouchStrategy = BaseStrategy.inherit({ }, _fireEvent(args) { - // @ts-expect-error const normalizer = isMouseEvent(args.originalEvent) ? MouseStrategy.normalize : TouchStrategy.normalize; return this.callBase(extend(normalizer(args.originalEvent), args)); @@ -80,9 +78,7 @@ const MouseAndTouchStrategy = BaseStrategy.inherit({ }, }); -// @ts-expect-error MouseAndTouchStrategy.map = eventMap; -// @ts-expect-error MouseAndTouchStrategy.resetObserver = MouseStrategy.resetObserver; export default MouseAndTouchStrategy; diff --git a/packages/devextreme/js/__internal/events/pointer/m_observer.ts b/packages/devextreme/js/__internal/events/pointer/m_observer.ts index 1a50a5f8f5cd..02b54bb9cf4f 100644 --- a/packages/devextreme/js/__internal/events/pointer/m_observer.ts +++ b/packages/devextreme/js/__internal/events/pointer/m_observer.ts @@ -7,7 +7,6 @@ const addEventsListener = function (events, handler) { events .split(' ') .forEach((event) => { - // @ts-expect-error domAdapter.listen(domAdapter.getDocument(), event, handler, true); }); }); diff --git a/packages/devextreme/js/__internal/events/pointer/m_touch.ts b/packages/devextreme/js/__internal/events/pointer/m_touch.ts index 102f75060d26..f6fc7b28f21f 100644 --- a/packages/devextreme/js/__internal/events/pointer/m_touch.ts +++ b/packages/devextreme/js/__internal/events/pointer/m_touch.ts @@ -1,7 +1,7 @@ -import devices from '@js/core/devices'; import { extend } from '@js/core/utils/extend'; import { each } from '@js/core/utils/iterator'; import BaseStrategy from '@js/events/pointer/base'; +import devices from '@ts/core/m_devices'; /* eslint-disable spellcheck/spell-checker */ const eventMap = { @@ -60,9 +60,7 @@ const TouchStrategy = BaseStrategy.inherit({ }, }); -// @ts-expect-error TouchStrategy.map = eventMap; -// @ts-expect-error TouchStrategy.normalize = normalizeTouchEvent; export default TouchStrategy; diff --git a/packages/devextreme/js/__internal/events/utils/m_event_nodes_disposing.ts b/packages/devextreme/js/__internal/events/utils/m_event_nodes_disposing.ts index 6d987c8aed01..3baf9abb34ae 100644 --- a/packages/devextreme/js/__internal/events/utils/m_event_nodes_disposing.ts +++ b/packages/devextreme/js/__internal/events/utils/m_event_nodes_disposing.ts @@ -11,7 +11,6 @@ function nodesByEvent(event) { } export const subscribeNodesDisposing = (event, callback) => { - // @ts-expect-error eventsEngine.one(nodesByEvent(event), removeEvent, callback); }; diff --git a/packages/devextreme/js/__internal/filter_builder/m_utils.ts b/packages/devextreme/js/__internal/filter_builder/m_utils.ts index 41748bb37999..600b85c216da 100644 --- a/packages/devextreme/js/__internal/filter_builder/m_utils.ts +++ b/packages/devextreme/js/__internal/filter_builder/m_utils.ts @@ -540,7 +540,6 @@ export function getCurrentLookupValueText(field, value, handler) { } else { const lookupDataSource = isFunction(lookup.dataSource) ? lookup.dataSource({}) : lookup.dataSource; const dataSource = new DataSource(lookupDataSource); - // @ts-expect-error DataSource is badly typed. dataSource.loadSingle(lookup.valueExpr, value).done((result) => { let valueText = ''; diff --git a/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping_expanded.ts b/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping_expanded.ts index 6b8c04afa0f9..77c4f349e578 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping_expanded.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping_expanded.ts @@ -1,4 +1,3 @@ -// @ts-expect-error import { toComparable } from '@js/core/utils/data'; import { Deferred, when } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/column_headers/m_column_headers.ts b/packages/devextreme/js/__internal/grids/grid_core/column_headers/m_column_headers.ts index 2a44ffdbb583..d0699c0323e2 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/column_headers/m_column_headers.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/column_headers/m_column_headers.ts @@ -144,10 +144,8 @@ export class ColumnHeadersView extends ColumnsView { eventsEngine.on($link, 'click', this.createAction(() => columnChooserView.showColumnChooser())); $cellContent - // @ts-expect-error .append(domAdapter.createTextNode(leftPart)) .append($link) - // @ts-expect-error .append(domAdapter.createTextNode(rightPart)); } else { $cellContent.text(textEmpty); diff --git a/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts index bc14ed0158f5..21a559db2e7e 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts @@ -6,7 +6,6 @@ import Callbacks from '@js/core/utils/callbacks'; import { compileGetter } from '@js/core/utils/data'; import { Deferred, when } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; -import { captionize } from '@js/core/utils/inflector'; import { each, map } from '@js/core/utils/iterator'; import { orderEach } from '@js/core/utils/object'; import { @@ -21,6 +20,7 @@ import dateLocalization from '@js/localization/date'; import messageLocalization from '@js/localization/message'; import filterUtils from '@js/ui/shared/filtering'; import errors from '@js/ui/widget/ui.errors'; +import inflector from '@ts/core/utils/m_inflector'; import type { DataController } from '@ts/grids/grid_core/data_controller/m_data_controller'; import type { FocusController } from '@ts/grids/grid_core/focus/m_focus'; import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_core'; @@ -1605,7 +1605,7 @@ export class ColumnsController extends modules.Controller { if (isString(dataField)) { const getter = compileGetter(dataField); calculatedColumnOptions = { - caption: captionize(dataField), + caption: inflector.captionize(dataField), calculateCellValue(data, skipDeserialization) { // @ts-expect-error const value = getter(data); diff --git a/packages/devextreme/js/__internal/grids/grid_core/context_menu/m_context_menu.ts b/packages/devextreme/js/__internal/grids/grid_core/context_menu/m_context_menu.ts index 566a7230ffc3..4fcab10b261d 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/context_menu/m_context_menu.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/context_menu/m_context_menu.ts @@ -48,13 +48,11 @@ export class ContextMenuController extends modules.ViewController { targetElement: getPublicElement($targetElement), target: viewName[this], rowIndex, - // @ts-expect-error row: view._getRows()[rowIndex], columnIndex, column: rowOptions?.cells?.[columnIndex]?.column, }; - // @ts-expect-error options.items = view.getContextMenuItems && view.getContextMenuItems(options); that.executeAction('onContextMenuPreparing', options); diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/m_data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/m_data_controller.ts index 684022d0eccf..5c3ac2ed2f65 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/m_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/m_data_controller.ts @@ -1578,7 +1578,7 @@ export class DataController extends DataHelperMixin(modules.Controller) { // @ts-expect-error const result = new Deferred(); const deferreds: any[] = []; - const data = []; + const data: any[] = []; each(rowKeys, (index, key) => { deferreds.push(that.byKey(key).done((keyData) => { diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts index c932744b0c01..abc0466823e5 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-dynamic-delete */ import Callbacks from '@js/core/utils/callbacks'; -// @ts-expect-error import { getKeyHash } from '@js/core/utils/common'; import { Deferred, when } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter_utils.ts b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter_utils.ts index 0067be9aa318..6089a4c9dd0e 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter_utils.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter_utils.ts @@ -1,7 +1,6 @@ -// @ts-expect-error -import { executeAsync } from '@js/core/utils/common'; import { extend } from '@js/core/utils/extend'; import { isDefined } from '@js/core/utils/type'; +import commonUtils from '@ts/core/utils/m_common'; import gridCoreUtils from '../m_utils'; @@ -45,7 +44,7 @@ export const calculateOperationTypes = function (loadOptions, lastLoadOptions, i export const executeTask = function (action, timeout) { if (isDefined(timeout)) { - executeAsync(action, timeout); + commonUtils.executeAsync(action, timeout); } else { action(); } diff --git a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts index 28d3567affff..909f40ff90a3 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts @@ -9,7 +9,6 @@ import { equalByValue } from '@js/core/utils/common'; import type { DeferredObj } from '@js/core/utils/deferred'; // @ts-expect-error import { Deferred, fromPromise, when } from '@js/core/utils/deferred'; -import { resetActiveElement } from '@js/core/utils/dom'; import { extend } from '@js/core/utils/extend'; import * as iconUtils from '@js/core/utils/icon'; import { each } from '@js/core/utils/iterator'; @@ -27,6 +26,7 @@ import { addNamespace } from '@js/events/utils/index'; import messageLocalization from '@js/localization/message'; import { confirm } from '@js/ui/dialog'; import { current, isFluent } from '@js/ui/themes'; +import domUtils from '@ts/core/utils/m_dom'; import type { DataController } from '@ts/grids/grid_core/data_controller/m_data_controller'; import type { HeaderPanel } from '@ts/grids/grid_core/header_panel/m_header_panel'; import type { RowsView } from '@ts/grids/grid_core/views/m_rows_view'; @@ -2687,7 +2687,7 @@ const rowsView = (Base: ModuleType) => class RowsViewEditingExtender e if (eventName === 'down') { if (devices.real().ios || devices.real().android) { - resetActiveElement(); + domUtils.resetActiveElement(); } return isShowEditorAlways && allowEditing && editingController.editCell(e.rowIndex, columnIndex); diff --git a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_custom_operations.ts b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_custom_operations.ts index e67fbf9e3052..b852a5466d81 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_custom_operations.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_custom_operations.ts @@ -63,7 +63,7 @@ function baseOperation(grid) { column = extend({}, column, { filterType: 'include', filterValues: values }); const dataSourceOptions = headerFilterController.getDataSource(column); dataSourceOptions.paginate = false; - const dataSource = new DataSource(dataSourceOptions) as any; + const dataSource = new DataSource(dataSourceOptions); const key = dataSource.store().key(); if (key) { diff --git a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_panel.ts b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_panel.ts index 7f4bafe41755..28085ef378dd 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_panel.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_panel.ts @@ -2,11 +2,11 @@ import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; import { Deferred, when } from '@js/core/utils/deferred'; -import { captionize } from '@js/core/utils/inflector'; import { isDefined } from '@js/core/utils/type'; import eventsEngine from '@js/events/core/events_engine'; import messageLocalization from '@js/localization/message'; import CheckBox from '@js/ui/check_box'; +import inflector from '@ts/core/utils/m_inflector'; import { getCaptionByOperation, getCurrentLookupValueText, getCurrentValueText, getCustomOperation, getField, getGroupValue, isCondition, isGroup, @@ -244,7 +244,7 @@ export class FilterPanelView extends modules.View { const value = filterValue[2]; if (customOperation) { - operationText = customOperation.caption || captionize(customOperation.name); + operationText = customOperation.caption || inflector.captionize(customOperation.name); } else if (value === null) { operationText = getCaptionByOperation(operation === '=' ? 'isblank' : 'isnotblank', options.filterOperationDescriptions); } else { diff --git a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts index 932b0757a150..b6784d45361e 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts @@ -227,7 +227,6 @@ const columnHeadersView = (Base: ModuleType) => class ColumnH if (gridCoreUtils.checkChanges(optionNames, ['filterValue', 'bufferedFilterValue', 'selectedFilterOperation', 'bufferedSelectedFilterOperation', 'filterValues', 'filterType']) && e.columnIndex !== undefined) { const visibleIndex = that._columnsController.getVisibleIndex(e.columnIndex); const column = that._columnsController.columnOption(e.columnIndex); - // @ts-expect-error $cell = that._getCellElement(that.element().find(`.${that.addWidgetPrefix(FILTER_ROW_CLASS)}`).index(), visibleIndex) ?? $(); $editorContainer = $cell.find(`.${EDITOR_CONTAINER_CLASS}`).first(); @@ -685,7 +684,7 @@ const columnHeadersView = (Base: ModuleType) => class ColumnH private _getFilterOperationMenuItems(column) { const that = this; - let result = [{}]; + let result: any = [{}]; const filterRowOptions = that.option('filterRow'); const operationDescriptions = filterRowOptions && filterRowOptions.operationDescriptions || {}; diff --git a/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts b/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts index bf4a374691c4..3922a217851a 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts @@ -918,7 +918,6 @@ const rowsView = (Base: ModuleType) => class RowsViewFocusController e private scrollToRowElement(key) { const rowIndex = this._dataController.getRowIndexByKey(key); - // @ts-expect-error const $row = $(this.getRow(rowIndex)); return this.scrollToElementVertically($row); diff --git a/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts b/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts index 057a98050234..96222c594410 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts @@ -1461,7 +1461,6 @@ export class KeyboardNavigationController extends modules.ViewController { .removeAttr('tabindex'); } - // @ts-expect-error eventsEngine.one($focusElement, 'blur', (e) => { if (e.relatedTarget) { $focusElement @@ -2145,7 +2144,6 @@ export class KeyboardNavigationController extends modules.ViewController { const $widgetContainer = $input.closest(`.${WIDGET_CLASS}`); eventsEngine.off($widgetContainer, 'focusout'); // for NumberBox to save entered symbol - // @ts-expect-error eventsEngine.one($widgetContainer, 'focusout', () => { // @ts-expect-error eventsEngine.trigger($input, 'change'); diff --git a/packages/devextreme/js/__internal/grids/grid_core/m_modules.ts b/packages/devextreme/js/__internal/grids/grid_core/m_modules.ts index 33605e9b8abb..33c4b6202543 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/m_modules.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/m_modules.ts @@ -45,7 +45,6 @@ export class ModuleItem { flags.unique = true; flags.syncStrategy = true; - // @ts-expect-error that[this] = Callbacks(flags); }); } diff --git a/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts b/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts index 1e0a638b3df8..546b2d93f3a9 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts @@ -2,7 +2,6 @@ import $ from '@js/core/renderer'; import { equalByValue } from '@js/core/utils/common'; -// @ts-expect-error import { toComparable } from '@js/core/utils/data'; import { Deferred, when } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; @@ -719,7 +718,6 @@ export default { }); newDataSource - // @ts-expect-error .load() .done(d.resolve) .fail(d.fail); diff --git a/packages/devextreme/js/__internal/grids/grid_core/pager/m_pager.ts b/packages/devextreme/js/__internal/grids/grid_core/pager/m_pager.ts index 0f1c955d795b..a8923b263667 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/pager/m_pager.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/pager/m_pager.ts @@ -1,7 +1,7 @@ import { isDefined } from '@js/core/utils/type'; import { hasWindow } from '@js/core/utils/window'; import messageLocalization from '@js/localization/message'; -import Pager from '@js/ui/pager'; +import Pager from '@ts/pager/wrappers/pager'; import modules from '../m_modules'; @@ -30,7 +30,7 @@ export class PagerView extends modules.View { pageIndex: getPageIndex(dataController), pageSize: dataController.pageSize(), pageCount: dataController.pageCount(), - totalCount: dataController.totalCount(), + itemCount: dataController.totalCount(), hasKnownLastPage: dataController.hasKnownLastPage(), }); } else { @@ -95,7 +95,7 @@ export class PagerView extends modules.View { showNavigationButtons: pagerOptions.showNavigationButtons, label: pagerOptions.label, allowedPageSizes: that.getPageSizes(), - totalCount: dataController.totalCount(), + itemCount: dataController.totalCount(), hasKnownLastPage: dataController.hasKnownLastPage(), rtlEnabled: that.option('rtlEnabled'), _skipValidation: true, diff --git a/packages/devextreme/js/__internal/grids/grid_core/search/m_search.ts b/packages/devextreme/js/__internal/grids/grid_core/search/m_search.ts index f15503efb992..f88bd74c25cc 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/search/m_search.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/search/m_search.ts @@ -2,7 +2,6 @@ /* eslint-disable @typescript-eslint/method-signature-style */ import domAdapter from '@js/core/dom_adapter'; import $ from '@js/core/renderer'; -// @ts-expect-error import { compileGetter, toComparable } from '@js/core/utils/data'; import dataQuery from '@js/data/query'; import messageLocalization from '@js/localization/message'; @@ -285,7 +284,6 @@ const rowsView = ( } $textNode.after($searchTextSpan.text(text.substr(index, searchText.length))); - // @ts-expect-error $textNode = $(domAdapter.createTextNode(text.substr(index + searchText.length))).insertAfter($searchTextSpan); return that._highlightSearchTextCore($textNode, searchText); diff --git a/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts b/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts index ed2a474e10de..f285d250cc38 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts @@ -5,7 +5,6 @@ import type { DeferredObj } from '@js/core/utils/deferred'; import { Deferred } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; import { each } from '@js/core/utils/iterator'; -import { touch } from '@js/core/utils/support'; import { isDefined } from '@js/core/utils/type'; import { applyBatch } from '@js/data/array_utils'; import { name as clickEventName } from '@js/events/click'; @@ -14,6 +13,7 @@ import holdEvent from '@js/events/hold'; import { addNamespace, isCommandKeyPressed } from '@js/events/utils/index'; import messageLocalization from '@js/localization/message'; import errors from '@js/ui/widget/ui.errors'; +import supportUtils from '@ts/core/utils/m_support'; import type { ColumnHeadersView } from '@ts/grids/grid_core/column_headers/m_column_headers'; import type { ColumnsController } from '@ts/grids/grid_core/columns_controller/m_columns_controller'; import type { ContextMenuController } from '@ts/grids/grid_core/context_menu/m_context_menu'; @@ -890,7 +890,7 @@ export const rowsViewSelectionExtenderMixin = (Base: ModuleType) => cl const $table = super._createTable.apply(that, arguments as any); if (selectionMode !== 'none') { - if (that.option(SHOW_CHECKBOXES_MODE) === 'onLongTap' || !touch) { + if (that.option(SHOW_CHECKBOXES_MODE) === 'onLongTap' || !supportUtils.touch) { // TODO Not working timeout by hold when it is larger than other timeouts by hold eventsEngine.on($table, addNamespace(holdEvent.name, 'dxDataGridRowsView'), `.${DATA_ROW_CLASS}`, that.createAction((e) => { processLongTap(that.component, e.event); diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts index d2c1234c692d..9b2b72cadc0d 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts @@ -1,5 +1,4 @@ /* eslint-disable max-classes-per-file */ -// @ts-expect-error import { equalByValue, getKeyHash } from '@js/core/utils/common'; import { Deferred } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_core.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_core.ts index 5db0ddc0b4c1..62a492635cf6 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_core.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_core.ts @@ -113,7 +113,6 @@ export class StateStoringController extends modules.ViewController { return options.customLoad && options.customLoad(); } try { - // @ts-expect-error return JSON.parse(getStorage(options).getItem(getUniqueStorageKey(options))); } catch (e: any) { errors.log('W1022', 'State storing', e.message); diff --git a/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts b/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts index 3dad9cbb612d..689413f2c0c5 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts @@ -2,7 +2,6 @@ /* eslint-disable max-classes-per-file */ import $ from '@js/core/renderer'; import browser from '@js/core/utils/browser'; -// @ts-expect-error import { deferUpdate, equalByValue, getKeyHash } from '@js/core/utils/common'; import type { DeferredObj } from '@js/core/utils/deferred'; // @ts-expect-error diff --git a/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts b/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts index e7a5694f9506..37ce61f12829 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts @@ -16,7 +16,6 @@ import { getOuterHeight, getOuterWidth, getWidth, } from '@js/core/utils/size'; import { setWidth } from '@js/core/utils/style'; -import { nativeScrolling } from '@js/core/utils/support'; import { isDefined, isFunction, isNumeric, isRenderer, isString, @@ -27,6 +26,7 @@ import eventsEngine from '@js/events/core/events_engine'; import { name as dblclickEvent } from '@js/events/double_click'; import pointerEvents from '@js/events/pointer'; import { removeEvent } from '@js/events/remove'; +import supportUtils from '@ts/core/utils/m_support'; import type { AdaptiveColumnsController } from '@ts/grids/grid_core/adaptivity/m_adaptivity'; import type { ColumnChooserController, ColumnChooserView } from '@ts/grids/grid_core/column_chooser/m_column_chooser'; import { ColumnStateMixin } from '@ts/grids/grid_core/column_state_mixin/m_column_state_mixin'; @@ -563,7 +563,6 @@ export class ColumnsView extends ColumnStateMixin(modules.View) { const doc = domAdapter.getRootNode($(options.container).get(0)); const needWaitAsyncTemplates = this.needWaitAsyncTemplates(); - // @ts-expect-error if (!isAsync || $(options.container).closest(doc).length || needWaitAsyncTemplates) { if (change) { options.change = change; @@ -998,7 +997,6 @@ export class ColumnsView extends ColumnStateMixin(modules.View) { * @extended: column_fixing */ public getTableElements() { - // @ts-expect-error return this._tableElement || $(); } @@ -1069,7 +1067,7 @@ export class ColumnsView extends ColumnStateMixin(modules.View) { const $scrollContainer = $('
'); const useNative = this.option('scrolling.useNative'); - if (useNative === false || (useNative === 'auto' && !nativeScrolling)) { + if (useNative === false || (useNative === 'auto' && !supportUtils.nativeScrolling)) { $scrollContainer.addClass(this.addWidgetPrefix(SCROLLABLE_SIMULATED_CLASS)); } @@ -1325,7 +1323,6 @@ export class ColumnsView extends ColumnStateMixin(modules.View) { private _getRowElement(rowIndex) { const that = this; - // @ts-expect-error let $rowElement = $(); const $tableElements = that.getTableElements(); @@ -1420,7 +1417,6 @@ export class ColumnsView extends ColumnStateMixin(modules.View) { return tBodies && tBodies.length ? tBodies : tableElement.find('> tbody > ' + `.${ROW_CLASS}, > .${ROW_CLASS}`); } - // @ts-expect-error return $(); } diff --git a/packages/devextreme/js/__internal/grids/grid_core/views/m_grid_view.ts b/packages/devextreme/js/__internal/grids/grid_core/views/m_grid_view.ts index 8dd3599d6576..8f16b49b3026 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/views/m_grid_view.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/views/m_grid_view.ts @@ -804,7 +804,6 @@ export class ResizingController extends modules.ViewController { each(VIEW_NAMES, (index, viewName) => { // TODO getView - // @ts-expect-error const view = that.getView(viewName); if (view) { view.resize(); diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/data_area/m_data_area.ts b/packages/devextreme/js/__internal/grids/pivot_grid/data_area/m_data_area.ts index de60463166e9..7234869e4c92 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/data_area/m_data_area.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/data_area/m_data_area.ts @@ -1,5 +1,5 @@ import $ from '@js/core/renderer'; -import { nativeScrolling } from '@js/core/utils/support'; +import supportUtils from '@ts/core/utils/m_support'; import { AreaItem } from '../area_item/m_area_item'; import { calculateScrollbarWidth } from '../m_widget_utils'; @@ -63,7 +63,7 @@ const DataArea = AreaItem.inherit({ const { useNative } = this.component.option('scrolling'); return useNative === 'auto' - ? !!nativeScrolling + ? !!supportUtils.nativeScrolling : !!useNative; }, diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts index 2782913a3b09..e918861e9f53 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts @@ -1,11 +1,8 @@ import Class from '@js/core/class'; import { EventsStrategy } from '@js/core/events_strategy'; import { normalizeIndexes } from '@js/core/utils/array'; -// @ts-expect-error -import { executeAsync } from '@js/core/utils/common'; import { Deferred, when } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; -import { titleize } from '@js/core/utils/inflector'; import { each } from '@js/core/utils/iterator'; import { isDefined, isFunction, isNumeric, isPlainObject, @@ -13,6 +10,8 @@ import { } from '@js/core/utils/type'; import Store from '@js/data/abstract_store'; import { normalizeDataSourceOptions } from '@js/data/data_source/utils'; +import commonUtils from '@ts/core/utils/m_common'; +import inflector from '@ts/core/utils/m_inflector'; import { LocalStore } from '../local_store/m_local_store'; import { @@ -74,7 +73,7 @@ function createCaption(field) { summaryType = ''; } - return titleize(caption) + summaryType; + return inflector.titleize(caption) + summaryType; } function resetFieldState(field, properties) { @@ -772,7 +771,7 @@ const PivotGridDataSource = Class.inherit((function () { } } if (that.store()) { - that._delayedLoadTask = executeAsync(loadTask); + that._delayedLoadTask = commonUtils.executeAsync(loadTask); } else { loadTask(); } diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts index af085a871333..8bf174c771ab 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts @@ -1,6 +1,5 @@ import Class from '@js/core/class'; import { noop } from '@js/core/utils/common'; -// @ts-expect-error import { compileGetter, toComparable } from '@js/core/utils/data'; import dateSerialization from '@js/core/utils/date_serialization'; import { Deferred, when } from '@js/core/utils/deferred'; diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts index 999e0ca65a36..0c169ba4ca76 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts @@ -918,7 +918,7 @@ const XmlaStore = Class.inherit((function () { }; each($(xml).find('row'), function () { - const $row = $(this as any); + const $row = $(this); const type = $row.children('DIMENSION_TYPE').text(); const dimensionName = type === MD_DIMTYPE_MEASURE ? MEASURE_DEMENSION_KEY : $row.children('DIMENSION_UNIQUE_NAME').text(); diff --git a/packages/devextreme/js/__internal/pager/common/base_pager_props.ts b/packages/devextreme/js/__internal/pager/common/base_pager_props.ts index 206c18bf88cc..0611abc32186 100644 --- a/packages/devextreme/js/__internal/pager/common/base_pager_props.ts +++ b/packages/devextreme/js/__internal/pager/common/base_pager_props.ts @@ -1,4 +1,5 @@ -import type { PagerDisplayMode } from '@js/common/grids'; +import type { DisplayMode } from '@js/common'; +import type { PageSize } from '@js/ui/pagination_types'; import messageLocalization from '../../../localization/message'; import type { EventCallback } from '../../core/r1/event_callback'; @@ -10,7 +11,7 @@ export interface BasePagerProps extends BaseWidgetProps { showInfo?: boolean; infoText?: string; lightModeEnabled?: boolean; - displayMode?: PagerDisplayMode; + displayMode?: DisplayMode; maxPagesCount: number; pageCount: number; pagesCountText?: string; @@ -18,10 +19,10 @@ export interface BasePagerProps extends BaseWidgetProps { hasKnownLastPage?: boolean; pagesNavigatorVisible?: boolean | 'auto'; showPageSizeSelector?: boolean; - allowedPageSizes: (number | 'all')[]; + allowedPageSizes: (number | PageSize)[]; rtlEnabled?: boolean; showNavigationButtons?: boolean; - totalCount?: number; + itemCount?: number; label?: string; onKeyDown?: EventCallback; } @@ -39,6 +40,6 @@ export const BasePagerDefaultProps: BasePagerProps = { showPageSizeSelector: true, allowedPageSizes: [5, 10], showNavigationButtons: false, - totalCount: 1, + itemCount: 1, label: messageLocalization.format('dxPager-ariaLabel'), }; diff --git a/packages/devextreme/js/__internal/pager/content.tsx b/packages/devextreme/js/__internal/pager/content.tsx index f5382ad4ae9c..cfac37eb3ba8 100644 --- a/packages/devextreme/js/__internal/pager/content.tsx +++ b/packages/devextreme/js/__internal/pager/content.tsx @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { InfernoComponent, InfernoEffect } from '@devextreme/runtime/inferno'; import type { RefObject } from '@devextreme-generator/declarations'; -import type { PagerDisplayMode } from '@js/common/grids'; +import type { DisplayMode } from '@js/common'; import { createRef as infernoCreateRef } from 'inferno'; import { registerKeyboardAction } from '../../ui/shared/accessibility'; @@ -118,7 +118,7 @@ export class PagerContent extends InfernoComponent { return this.props.pageSize !== 0; } - getNormalizedDisplayMode(): PagerDisplayMode { + getNormalizedDisplayMode(): DisplayMode { const { displayMode, lightModeEnabled, @@ -187,7 +187,7 @@ export class PagerContent extends InfernoComponent { infoText, pageCount, pageIndex, - totalCount, + itemCount, pagesRef, hasKnownLastPage, maxPagesCount, @@ -250,7 +250,7 @@ export class PagerContent extends InfernoComponent { infoText={infoText} pageCount={pageCount} pageIndex={pageIndex} - totalCount={totalCount} + itemCount={itemCount} /> )} {this.getPageIndexSelectorVisible() && ( @@ -267,7 +267,7 @@ export class PagerContent extends InfernoComponent { pageIndexChangedInternal={pageIndexChangedInternal} pagesCountText={pagesCountText} showNavigationButtons={showNavigationButtons} - totalCount={totalCount} + itemCount={itemCount} />
)} diff --git a/packages/devextreme/js/__internal/pager/info.tsx b/packages/devextreme/js/__internal/pager/info.tsx index b14ee9031014..ce984bc71f91 100644 --- a/packages/devextreme/js/__internal/pager/info.tsx +++ b/packages/devextreme/js/__internal/pager/info.tsx @@ -13,12 +13,12 @@ export interface InfoTextProps { rootElementRef?: RefObject; } -export type InfoTextPropsType = InfoTextProps & Pick; +export type InfoTextPropsType = InfoTextProps & Pick; const InfoTextDefaultProps: InfoTextPropsType = { pageCount: PagerDefaultProps.pageCount, pageIndex: PagerDefaultProps.pageIndex, - totalCount: PagerDefaultProps.totalCount, + itemCount: PagerDefaultProps.itemCount, }; export class InfoText extends BaseInfernoComponent { @@ -37,13 +37,13 @@ export class InfoText extends BaseInfernoComponent { const { pageCount, pageIndex, - totalCount, + itemCount, } = this.props; return format( this.getInfoText(), (pageIndex + 1).toString(), pageCount?.toString(), - totalCount?.toString(), + itemCount?.toString(), ) as string; } diff --git a/packages/devextreme/js/__internal/pager/pages/page_index_selector.tsx b/packages/devextreme/js/__internal/pager/pages/page_index_selector.tsx index 27234d8ca0be..a738cded6d7d 100644 --- a/packages/devextreme/js/__internal/pager/pages/page_index_selector.tsx +++ b/packages/devextreme/js/__internal/pager/pages/page_index_selector.tsx @@ -46,7 +46,7 @@ type PageIndexSelectorPropsType = Pick & PageIndexSelectorProps; @@ -57,7 +57,7 @@ const PageIndexSelectorDefaultProps: PageIndexSelectorPropsType = { pageIndex: PagerDefaultProps.pageIndex, pageIndexChangedInternal: PagerDefaultProps.pageIndexChangedInternal, showNavigationButtons: PagerDefaultProps.showNavigationButtons, - totalCount: PagerDefaultProps.totalCount, + itemCount: PagerDefaultProps.itemCount, }; interface NavigationButtonProps extends Pick {navigate: LightButtonProps['onClick']} diff --git a/packages/devextreme/js/__internal/pager/resizable_container.tsx b/packages/devextreme/js/__internal/pager/resizable_container.tsx index 71a7ca77d4de..980e25fad67a 100644 --- a/packages/devextreme/js/__internal/pager/resizable_container.tsx +++ b/packages/devextreme/js/__internal/pager/resizable_container.tsx @@ -156,7 +156,7 @@ export class ResizableContainer extends InfernoComponent { const { pageSize, pageIndex, - totalCount, + itemCount, pageCount, } = result; expect(pageSize).toEqual(expectedPageSize); expect(pageIndex).toEqual(expectedPageIndex); - expect(totalCount).toEqual(expectedItemCount); + expect(itemCount).toEqual(expectedItemCount); expect(pageCount).toEqual(expectedPageCount); }); }); diff --git a/packages/devextreme/js/__internal/pager/utils/validation_utils.ts b/packages/devextreme/js/__internal/pager/utils/validation_utils.ts index 5a4f9da41470..134f5e993203 100644 --- a/packages/devextreme/js/__internal/pager/utils/validation_utils.ts +++ b/packages/devextreme/js/__internal/pager/utils/validation_utils.ts @@ -41,7 +41,7 @@ export function validateOptions( return { pageSize, pageIndex, - totalCount: itemCount, + itemCount, pageCount, }; } diff --git a/packages/devextreme/js/__internal/pager/wrappers/grid_pager.ts b/packages/devextreme/js/__internal/pager/wrappers/grid_pager.ts index 155a1b48e4cc..cccd889179be 100644 --- a/packages/devextreme/js/__internal/pager/wrappers/grid_pager.ts +++ b/packages/devextreme/js/__internal/pager/wrappers/grid_pager.ts @@ -25,6 +25,10 @@ export class GridPagerWrapper extends ComponentWrapper { super._optionChanged(args); } + public getPageCount(): number { + return this.option('pageCount') as number; + } + _validateOptions(options: Record): Record { if (options._skipValidation || this.option('_skipValidation')) { return options; @@ -34,7 +38,7 @@ export class GridPagerWrapper extends ComponentWrapper { let { pageSize, pageIndex, - totalCount, + itemCount, // eslint-disable-next-line prefer-const ...rest } = initialOptions; @@ -47,14 +51,14 @@ export class GridPagerWrapper extends ComponentWrapper { pageIndex = this.option('pageIndex') as number; } - if (totalCount === undefined) { - totalCount = this.option('totalCount') as number; + if (itemCount === undefined) { + itemCount = this.option('itemCount') as number; } const validatedOptions = validateOptions( pageSize as number, pageIndex as number, - totalCount as number, + itemCount as number, ); return { diff --git a/packages/devextreme/js/__internal/pager/wrappers/pager.ts b/packages/devextreme/js/__internal/pager/wrappers/pager.ts index 1197fe7c4ec9..99fb904eea97 100644 --- a/packages/devextreme/js/__internal/pager/wrappers/pager.ts +++ b/packages/devextreme/js/__internal/pager/wrappers/pager.ts @@ -41,7 +41,7 @@ export default class Pager extends GridPagerWrapper { 'allowedPageSizes', 'rtlEnabled', 'showNavigationButtons', - 'totalCount', + 'itemCount', 'label', 'onKeyDown', 'pageSize', diff --git a/packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_appointment_filter.ts b/packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_appointment_filter.ts index 3d814110313d..f3cc15047a10 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_appointment_filter.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_appointment_filter.ts @@ -270,7 +270,7 @@ export class AppointmentFilterBaseStrategy { } const appointmentResourceValues = wrapToArray(resource); - const resourceData = map( + const resourceData: any[] = map( resources[resourceIndex].items, ({ id }) => id, ); diff --git a/packages/devextreme/js/__internal/scheduler/appointments/m_appointment.ts b/packages/devextreme/js/__internal/scheduler/appointments/m_appointment.ts index 80d1967897d7..0dd31f4410de 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/m_appointment.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/m_appointment.ts @@ -150,10 +150,9 @@ export class Appointment extends DOMComponent { this._renderDragSourceClass(); this._renderDirection(); - (this.$element() as any).data('dxAppointmentStartDate', this.option('startDate')); - const text = ExpressionUtils.getField(this.option('dataAccessors'), 'text', this.rawAppointment); (this.$element() as any).attr('title', text); + (this.$element() as any).data('dxAppointmentStartDate', this.option('startDate')); (this.$element() as any).attr('role', 'button'); this._renderRecurrenceClass(); @@ -208,14 +207,13 @@ export class Appointment extends DOMComponent { _renderAriaLabel() { // @ts-expect-error const $element: dxElementWrapper = this.$element(); - const ariaLabel = [ this._getDateText(), this._getGroupText(), ] .filter((label) => !!label) .join(', '); - $element.attr('aria-label', `${ariaLabel}, `); + $element.attr('aria-roledescription', `${ariaLabel}, `); } _renderAppointmentGeometry() { diff --git a/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_layout.ts b/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_layout.ts index 594c4fbcf02b..460f0fbd9ca7 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_layout.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_layout.ts @@ -5,6 +5,7 @@ import messageLocalization from '@js/localization/message'; import { APPOINTMENT_CONTENT_CLASSES } from '../m_classes'; const allDayText = ` ${messageLocalization.format('dxScheduler-allDay')}: `; +const recurringText = messageLocalization.format('dxScheduler-appointmentAriaLabel-recurring'); export const createAppointmentLayout = (formatText, config) => { const result = $((domAdapter as any).createDocumentFragment()); @@ -23,7 +24,8 @@ export const createAppointmentLayout = (formatText, config) => { $('
').addClass(APPOINTMENT_CONTENT_CLASSES.APPOINTMENT_DATE).text(formatText.formatDate).appendTo($contentDetails); config.isRecurrence - && $('').addClass(`${APPOINTMENT_CONTENT_CLASSES.RECURRING_ICON} dx-icon-repeat`).appendTo(result); + && $('').addClass(`${APPOINTMENT_CONTENT_CLASSES.RECURRING_ICON} dx-icon-repeat`).attr('aria-label', recurringText) + .appendTo(result); config.isAllDay && $('
') @@ -51,7 +53,8 @@ export const createAgendaAppointmentLayout = (formatText, config) => { .appendTo(leftLayoutContainer); config.isRecurrence - && $('').addClass(`${APPOINTMENT_CONTENT_CLASSES.RECURRING_ICON} dx-icon-repeat`).appendTo(marker); + && $('').addClass(`${APPOINTMENT_CONTENT_CLASSES.RECURRING_ICON} dx-icon-repeat`).attr('aria-label', recurringText) + .appendTo(marker); // eslint-disable-next-line @typescript-eslint/no-unused-vars const text = $('
') diff --git a/packages/devextreme/js/__internal/scheduler/resources/m_utils.ts b/packages/devextreme/js/__internal/scheduler/resources/m_utils.ts index f8ca6d62d972..a6950525075d 100644 --- a/packages/devextreme/js/__internal/scheduler/resources/m_utils.ts +++ b/packages/devextreme/js/__internal/scheduler/resources/m_utils.ts @@ -524,7 +524,7 @@ export const loadResources = (groups, resources, resourceLoaderMap) => { const name = getFieldExpr(resource); deferreds.push(deferred); - const dataSourcePromise = (getWrappedDataSource(resource.dataSource) as any).load(); + const dataSourcePromise = getWrappedDataSource(resource.dataSource).load(); resourceLoaderMap.set(name, dataSourcePromise); dataSourcePromise 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 046f397f835a..2b37d4249bba 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 @@ -1,4 +1,4 @@ -import { touch } from '@js/core/utils/support'; +import supportUtils from '@ts/core/utils/m_support'; import Tooltip from '@ts/ui/m_tooltip'; import { TooltipStrategyBase } from './m_tooltip_strategy_base'; @@ -35,7 +35,7 @@ export class DesktopTooltipStrategy extends TooltipStrategyBase { const result: any = super._createListOption(target, dataList); // TODO: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 = touch ? 'always' : 'onHover'; + result.showScrollbar = supportUtils.touch ? 'always' : 'onHover'; return result; } diff --git a/packages/devextreme/js/__internal/ui/chat/chat.ts b/packages/devextreme/js/__internal/ui/chat/chat.ts index 25efed0b35df..4a214ff9b74e 100644 --- a/packages/devextreme/js/__internal/ui/chat/chat.ts +++ b/packages/devextreme/js/__internal/ui/chat/chat.ts @@ -166,7 +166,6 @@ class Chat extends Widget { text, }; - this.renderMessage(message); this._messageSendAction?.({ message, event }); } diff --git a/packages/devextreme/js/__internal/ui/collection/m_collection_widget.base.ts b/packages/devextreme/js/__internal/ui/collection/m_collection_widget.base.ts index 9123c3bc0dc5..718be5a55af9 100644 --- a/packages/devextreme/js/__internal/ui/collection/m_collection_widget.base.ts +++ b/packages/devextreme/js/__internal/ui/collection/m_collection_widget.base.ts @@ -415,7 +415,6 @@ const CollectionWidget = Widget.inherit({ }, _findItemElementByItem(item) { - // @ts-expect-error let result = $(); const that = this; // @ts-expect-error @@ -743,7 +742,6 @@ const CollectionWidget = Widget.inherit({ return $target; } $target = $target.parent(); - // @ts-expect-error while ($target.length && !domAdapter.isDocument($target.get(0)) && !domAdapter.isDocumentFragment($target.get(0))) { if ($target.is(focusable)) { return $target; @@ -821,7 +819,6 @@ const CollectionWidget = Widget.inherit({ _renderItems(items) { if (items.length) { each(items, (index, itemData) => { - // @ts-expect-error this._renderItem(this._renderedItemsCount + index, itemData); }); } diff --git a/packages/devextreme/js/__internal/ui/collection/m_collection_widget.live_update.ts b/packages/devextreme/js/__internal/ui/collection/m_collection_widget.live_update.ts index 0fc9f79f545c..2d0dc6e585f6 100644 --- a/packages/devextreme/js/__internal/ui/collection/m_collection_widget.live_update.ts +++ b/packages/devextreme/js/__internal/ui/collection/m_collection_widget.live_update.ts @@ -48,7 +48,6 @@ export default CollectionWidget.inherit({ }, _findItemElementByKey(key) { - // @ts-expect-error let result = $(); const keyExpr = this.key(); // @ts-expect-error diff --git a/packages/devextreme/js/__internal/ui/context_menu/m_context_menu.ts b/packages/devextreme/js/__internal/ui/context_menu/m_context_menu.ts index cbd0df7fabc1..db6054566a6b 100644 --- a/packages/devextreme/js/__internal/ui/context_menu/m_context_menu.ts +++ b/packages/devextreme/js/__internal/ui/context_menu/m_context_menu.ts @@ -607,7 +607,6 @@ class ContextMenu extends MenuBase { if (!this._shouldHideOnOutsideClick(e)) { return false; } - // @ts-expect-error if (domAdapter.isDocument(e.target)) { return true; } diff --git a/packages/devextreme/js/__internal/ui/context_menu/m_menu_base.ts b/packages/devextreme/js/__internal/ui/context_menu/m_menu_base.ts index 131c2539e4a5..7ed3c54fbca2 100644 --- a/packages/devextreme/js/__internal/ui/context_menu/m_menu_base.ts +++ b/packages/devextreme/js/__internal/ui/context_menu/m_menu_base.ts @@ -167,7 +167,6 @@ class MenuBase extends HierarchicalCollectionWidget { const { html, url } = itemData; if (url) { - // @ts-expect-error $container.html(html); const link = this._getLinkContainer( this._getIconContainer(itemData), @@ -300,6 +299,7 @@ class MenuBase extends HierarchicalCollectionWidget { _initEditStrategy() { const Strategy = MenuBaseEditStrategy; + // @ts-expect-error dxClass inheritance issue this._editStrategy = new Strategy(this); } @@ -662,7 +662,6 @@ class MenuBase extends HierarchicalCollectionWidget { let result; each(this._itemElements(), (_, itemElement) => { - // @ts-expect-error if ($(itemElement).data(this._itemDataKey()) !== itemData) { return true; } diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts index 58f2e97dfb03..106a665a570e 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts @@ -89,7 +89,6 @@ class DateViewRoller extends Scrollable { _renderItems() { const items = this.option('items') || []; - // @ts-expect-error let $items = $(); $(this.content()).empty(); diff --git a/packages/devextreme/js/__internal/ui/date_range_box/m_date_range_box.ts b/packages/devextreme/js/__internal/ui/date_range_box/m_date_range_box.ts index 717e8b3150bd..5261da4a7cef 100644 --- a/packages/devextreme/js/__internal/ui/date_range_box/m_date_range_box.ts +++ b/packages/devextreme/js/__internal/ui/date_range_box/m_date_range_box.ts @@ -1049,7 +1049,6 @@ class DateRangeBox extends Editor { this._applyCustomValidation(newValue); this._updateDateBoxesValue(newValue); - // @ts-expect-error this.getStartDateBox().getStrategy().renderValue(); this._toggleEmptinessState(); diff --git a/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts b/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts index dc7fd18559b5..c8137ddf56da 100644 --- a/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts +++ b/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts @@ -27,7 +27,6 @@ class RangeCalendarStrategy extends CalendarStrategy { } popupConfig(popupConfig) { - // @ts-expect-error return extend(true, super.popupConfig(popupConfig), { position: { of: this.getDateRangeBox().$element() }, }); @@ -48,7 +47,6 @@ class RangeCalendarStrategy extends CalendarStrategy { const dateRangeBox = this.getDateRangeBox(); return { - // @ts-expect-error ...super.supportedKeys(), rightArrow: () => { if (dateRangeBox.option('opened')) { @@ -129,7 +127,6 @@ class RangeCalendarStrategy extends CalendarStrategy { ? this._injectComponent(disabledDatesValue) : disabledDatesValue ?? undefined; - // @ts-expect-error return extend(super._getWidgetOptions(), { disabledDates, value, diff --git a/packages/devextreme/js/__internal/ui/drop_down_editor/m_drop_down_list.ts b/packages/devextreme/js/__internal/ui/drop_down_editor/m_drop_down_list.ts index ec47661310bc..d3414175c387 100644 --- a/packages/devextreme/js/__internal/ui/drop_down_editor/m_drop_down_list.ts +++ b/packages/devextreme/js/__internal/ui/drop_down_editor/m_drop_down_list.ts @@ -221,7 +221,6 @@ const DropDownList = DropDownEditor.inherit({ // @ts-expect-error each(items, (index, item) => { if (this._isValueEquals(item, selectedItem)) { - // @ts-expect-error result = index; return false; } @@ -417,7 +416,6 @@ const DropDownList = DropDownEditor.inherit({ }, _listItemElements() { - // @ts-expect-error return this._$list ? this._$list.find(LIST_ITEM_SELECTOR) : $(); }, diff --git a/packages/devextreme/js/__internal/ui/editor/m_data_expression.ts b/packages/devextreme/js/__internal/ui/editor/m_data_expression.ts index dac4f256247e..c61e64b46529 100644 --- a/packages/devextreme/js/__internal/ui/editor/m_data_expression.ts +++ b/packages/devextreme/js/__internal/ui/editor/m_data_expression.ts @@ -1,7 +1,6 @@ import { ensureDefined, noop } from '@js/core/utils/common'; import { compileGetter, - // @ts-expect-error toComparable, } from '@js/core/utils/data'; import { Deferred } from '@js/core/utils/deferred'; diff --git a/packages/devextreme/js/__internal/ui/editor/m_editor.ts b/packages/devextreme/js/__internal/ui/editor/m_editor.ts index 98d0c322468b..fc2201b1b3e3 100644 --- a/packages/devextreme/js/__internal/ui/editor/m_editor.ts +++ b/packages/devextreme/js/__internal/ui/editor/m_editor.ts @@ -3,7 +3,6 @@ import Guid from '@js/core/guid'; import $ from '@js/core/renderer'; import Callbacks from '@js/core/utils/callbacks'; import { noop } from '@js/core/utils/common'; -import { resetActiveElement } from '@js/core/utils/dom'; import { extend } from '@js/core/utils/extend'; import { hasWindow } from '@js/core/utils/window'; import EventsEngine from '@js/events/core/events_engine'; @@ -12,6 +11,8 @@ import ValidationEngine from '@js/ui/validation_engine'; import ValidationMessage from '@js/ui/validation_message'; import Widget from '@js/ui/widget/ui.widget'; +import domUtils from '../../core/utils/m_dom'; + const INVALID_MESSAGE_AUTO = 'dx-invalid-message-auto'; const READONLY_STATE_CLASS = 'dx-state-readonly'; const INVALID_CLASS = 'dx-invalid'; @@ -389,7 +390,7 @@ const Editor = Widget.inherit({ blur() { if (this._hasActiveElement()) { - resetActiveElement(); + domUtils.resetActiveElement(); } }, diff --git a/packages/devextreme/js/__internal/ui/hierarchical_collection/m_data_adapter.ts b/packages/devextreme/js/__internal/ui/hierarchical_collection/m_data_adapter.ts index bc0f6964a036..6825fae3427e 100644 --- a/packages/devextreme/js/__internal/ui/hierarchical_collection/m_data_adapter.ts +++ b/packages/devextreme/js/__internal/ui/hierarchical_collection/m_data_adapter.ts @@ -286,7 +286,6 @@ const DataAdapter = Class.inherit({ const items = extend([], this._dataStructure); each(items, (index, item) => { if (!item) { - // @ts-expect-error that._dataStructure.splice(index - counter, 1); counter++; } diff --git a/packages/devextreme/js/__internal/ui/html_editor/converters/m_markdown.ts b/packages/devextreme/js/__internal/ui/html_editor/converters/m_markdown.ts deleted file mode 100644 index 79f9d2319043..000000000000 --- a/packages/devextreme/js/__internal/ui/html_editor/converters/m_markdown.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { getWindow } from '@js/core/utils/window'; -import Errors from '@js/ui/widget/ui.errors'; -import ShowDown from 'showdown'; -import TurnDown from 'turndown'; - -import converterController from '../m_converterController'; - -class MarkdownConverter { - _markdown2Html: any; - - _html2Markdown: any; - - constructor() { - const window = getWindow(); - // @ts-expect-error - const turndown = window && window.TurndownService || TurnDown; - // @ts-expect-error - const showdown = window && window.showdown || ShowDown; - - if (!turndown) { - throw Errors.Error('E1041', 'Turndown'); - } - - if (!showdown) { - throw Errors.Error('E1041', 'Showdown'); - } - - // eslint-disable-next-line new-cap - this._html2Markdown = new turndown(); - - if (this._html2Markdown?.addRule) { - this._html2Markdown.addRule('emptyLine', { - filter: (element) => element.nodeName.toLowerCase() === 'p' && element.innerHTML === '
', - replacement() { - return '
'; - }, - }); - this._html2Markdown.keep(['table']); - } - - this._markdown2Html = new showdown.Converter({ - simpleLineBreaks: true, - strikethrough: true, - tables: true, - }); - } - - toMarkdown(htmlMarkup) { - return this._html2Markdown.turndown(htmlMarkup || ''); - } - - toHtml(markdownMarkup) { - let markup = this._markdown2Html.makeHtml(markdownMarkup); - - if (markup) { - markup = markup.replace(new RegExp('\\r?\\n', 'g'), ''); - } - - return markup; - } -} - -converterController.addConverter('markdown', MarkdownConverter); - -export default MarkdownConverter; diff --git a/packages/devextreme/js/__internal/ui/html_editor/m_html_editor.ts b/packages/devextreme/js/__internal/ui/html_editor/m_html_editor.ts index 647fde20262a..06b24c7250f5 100644 --- a/packages/devextreme/js/__internal/ui/html_editor/m_html_editor.ts +++ b/packages/devextreme/js/__internal/ui/html_editor/m_html_editor.ts @@ -9,7 +9,6 @@ import { EmptyTemplate } from '@js/core/templates/empty_template'; import Callbacks from '@js/core/utils/callbacks'; import { deferRender, - ensureDefined, // @ts-expect-error executeAsync, noop, @@ -24,7 +23,6 @@ import { Event as dxEvent } from '@js/events/index'; import pointerEvents from '@js/events/pointer'; import { addNamespace } from '@js/events/utils/index'; import Editor from '@js/ui/editor/editor'; -import Errors from '@js/ui/widget/ui.errors'; import { prepareScrollData } from '@ts/ui/text_box/m_utils.scroll'; import ConverterController from './m_converterController'; @@ -39,8 +37,6 @@ const QUILL_CLIPBOARD_CLASS = 'ql-clipboard'; const HTML_EDITOR_SUBMIT_ELEMENT_CLASS = 'dx-htmleditor-submit-element'; const HTML_EDITOR_CONTENT_CLASS = 'dx-htmleditor-content'; -const MARKDOWN_VALUE_TYPE = 'markdown'; - const ANONYMOUS_TEMPLATE_NAME = 'htmlContent'; const isIos = devices.current().platform === 'ios'; @@ -52,7 +48,6 @@ const HtmlEditor = Editor.inherit({ _getDefaultOptions() { return extend(this.callBase(), { focusStateEnabled: true, - valueType: 'html', placeholder: '', toolbar: null, variables: null, @@ -235,29 +230,14 @@ const HtmlEditor = Editor.inherit({ }, _updateContainerMarkup() { - let markup = this.option('value'); - - if (this._isMarkdownValue()) { - this._prepareMarkdownConverter(); - markup = this._markdownConverter.toHtml(markup); - } + const { value } = this.option(); - if (markup) { - const sanitizedMarkup = this._removeXSSVulnerableHtml(markup); + if (value) { + const sanitizedMarkup = this._removeXSSVulnerableHtml(value); this._$htmlContainer.html(sanitizedMarkup); } }, - _prepareMarkdownConverter() { - const MarkdownConverter = ConverterController.getConverter('markdown'); - - if (MarkdownConverter) { - this._markdownConverter = new MarkdownConverter(); - } else { - throw Errors.Error('E1051', 'markdown'); - } - }, - _render() { this._prepareConverters(); @@ -284,10 +264,6 @@ const HtmlEditor = Editor.inherit({ this._deltaConverter = new DeltaConverter(); } } - - if (this.option('valueType') === MARKDOWN_VALUE_TYPE && !this._markdownConverter) { - this._prepareMarkdownConverter(); - } }, _renderContentImpl() { @@ -450,13 +426,14 @@ const HtmlEditor = Editor.inherit({ return modules; }, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _textChangeHandler(newDelta, oldDelta, source) { - const htmlMarkup = this._deltaConverter.toHtml(); - const convertedValue = this._isMarkdownValue() ? this._updateValueByType(MARKDOWN_VALUE_TYPE, htmlMarkup) : htmlMarkup; - const currentValue = this.option('value'); + _textChangeHandler() { + const { value: currentValue } = this.option(); + const convertedValue = this._deltaConverter.toHtml(); - if (currentValue !== convertedValue && !this._isNullValueConverted(currentValue, convertedValue)) { + if ( + currentValue !== convertedValue + && !this._isNullValueConverted(currentValue, convertedValue) + ) { this._isEditorUpdating = true; this.option('value', convertedValue); } @@ -477,22 +454,6 @@ const HtmlEditor = Editor.inherit({ } }, - _updateValueByType(valueType, value) { - const converter = this._markdownConverter; - - if (!isDefined(converter)) { - return; - } - - const currentValue = ensureDefined(value, this.option('value')); - - return valueType === MARKDOWN_VALUE_TYPE ? converter.toMarkdown(currentValue) : converter.toHtml(currentValue); - }, - - _isMarkdownValue() { - return this.option('valueType') === MARKDOWN_VALUE_TYPE; - }, - _resetEnabledState() { if (this._quillInstance) { const isEnabled = !(this.option('readOnly') || this.option('disabled')); @@ -549,10 +510,8 @@ const HtmlEditor = Editor.inherit({ if (this._isEditorUpdating) { this._isEditorUpdating = false; } else { - const updatedValue = this._isMarkdownValue() ? this._updateValueByType('HTML', args.value) : args.value; - this._suppressValueChangeAction(); - this._updateHtmlContent(updatedValue); + this._updateHtmlContent(args.value); this._resumeValueChangeAction(); } } else { @@ -578,17 +537,6 @@ const HtmlEditor = Editor.inherit({ case 'tableResizing': this._moduleOptionChanged('tableResizing', args); break; - case 'valueType': { - this._prepareConverters(); - const newValue = this._updateValueByType(args.value); - - if (args.value === 'html' && this._quillInstance) { - this._updateHtmlContent(newValue); - } else { - this.option('value', newValue); - } - break; - } case 'stylingMode': this._renderStylingMode(); break; diff --git a/packages/devextreme/js/__internal/ui/html_editor/modules/m_popup.ts b/packages/devextreme/js/__internal/ui/html_editor/modules/m_popup.ts index 3b94be8ce920..c9c1887b245d 100644 --- a/packages/devextreme/js/__internal/ui/html_editor/modules/m_popup.ts +++ b/packages/devextreme/js/__internal/ui/html_editor/modules/m_popup.ts @@ -1,12 +1,12 @@ import $ from '@js/core/renderer'; import { extend } from '@js/core/utils/extend'; import { getHeight } from '@js/core/utils/size'; -import { getWindow } from '@js/core/utils/window'; import eventsEngine from '@js/events/core/events_engine'; import { addNamespace } from '@js/events/utils/index'; import type ListType from '@js/ui/list'; import List from '@js/ui/list_light'; import Popup from '@js/ui/popup'; +import windowUtils from '@ts/core/utils/m_window'; import Quill from 'devextreme-quill'; import BaseModule from './m_base'; @@ -107,7 +107,7 @@ if (Quill) { } get maxHeight() { - const window = getWindow(); + const window = windowUtils.getWindow(); const windowHeight = window && getHeight(window) || 0; return Math.max(MIN_HEIGHT, windowHeight * 0.5); } diff --git a/packages/devextreme/js/__internal/ui/html_editor/modules/m_resizing.ts b/packages/devextreme/js/__internal/ui/html_editor/modules/m_resizing.ts index db39e87413c8..886c663b42d9 100644 --- a/packages/devextreme/js/__internal/ui/html_editor/modules/m_resizing.ts +++ b/packages/devextreme/js/__internal/ui/html_editor/modules/m_resizing.ts @@ -143,7 +143,6 @@ export default class ResizingModule extends BaseModule { const borderWidth = this._getBorderWidth(); this._$resizeFrame - // @ts-expect-error .css({ height, width, diff --git a/packages/devextreme/js/__internal/ui/html_editor/modules/m_tableResizing.ts b/packages/devextreme/js/__internal/ui/html_editor/modules/m_tableResizing.ts index b0d6f348ef4e..b5661d37ac40 100644 --- a/packages/devextreme/js/__internal/ui/html_editor/modules/m_tableResizing.ts +++ b/packages/devextreme/js/__internal/ui/html_editor/modules/m_tableResizing.ts @@ -165,7 +165,6 @@ export default class TableResizingModule extends BaseModule { this._windowResizeTimeout = setTimeout(() => { const $tables = this._findTables(); each($tables, (index, table) => { - // @ts-expect-error const $table = $(table); const frame = this._tableResizeFrames[index]; const actualTableWidth = getOuterWidth($table); @@ -257,7 +256,6 @@ export default class TableResizingModule extends BaseModule { } else { // @ts-expect-error each($tables, (index, table) => { - // @ts-expect-error const $table = $(table); const frame = this._tableResizeFrames[index]; const isColumnsCountChanged = frame?.columnsCount !== this._getTableDeterminantElements($table, 'horizontal').length; @@ -396,7 +394,6 @@ export default class TableResizingModule extends BaseModule { this._removeDraggable($currentLineSeparator, directionInfo.lineResizerClass); styleOptions[directionInfo.positionCoordinate] = currentPosition - DRAGGABLE_ELEMENT_OFFSET; - // @ts-expect-error $($currentLineSeparator).css(styleOptions); const attachSeparatorData = { @@ -650,7 +647,7 @@ export default class TableResizingModule extends BaseModule { } _getColumnElementsSum(columnElements) { - const columnsWidths = []; + const columnsWidths: any[] = []; let columnsSum = 0; each(columnElements, (index, element) => { diff --git a/packages/devextreme/js/__internal/ui/list/m_list.base.ts b/packages/devextreme/js/__internal/ui/list/m_list.base.ts index 4f39d2db85ac..bdd5b42222dd 100644 --- a/packages/devextreme/js/__internal/ui/list/m_list.base.ts +++ b/packages/devextreme/js/__internal/ui/list/m_list.base.ts @@ -11,7 +11,6 @@ import { extend } from '@js/core/utils/extend'; import { getImageContainer } from '@js/core/utils/icon'; import { each } from '@js/core/utils/iterator'; import { getHeight, getOuterHeight, setHeight } from '@js/core/utils/size'; -import { nativeScrolling } from '@js/core/utils/support'; import { isDefined, isPlainObject } from '@js/core/utils/type'; import { hasWindow } from '@js/core/utils/window'; import { name as clickEventName } from '@js/events/click'; @@ -25,6 +24,7 @@ import CollectionWidget from '@js/ui/collection/ui.collection_widget.live_update import ScrollView from '@js/ui/scroll_view'; import { current, isMaterial, isMaterialBased } from '@js/ui/themes'; import { render } from '@js/ui/widget/utils.ink_ripple'; +import supportUtils from '@ts/core/utils/m_support'; import { deviceDependentOptions } from '@ts/ui/scroll_view/m_scrollable.device'; import DataConverterMixin from '@ts/ui/shared/m_grouped_data_converter_mixin'; @@ -85,7 +85,6 @@ export const ListBase = CollectionWidget.inherit({ let isItemVisible = true; if (!$item.length) { - // @ts-expect-error return $(); } @@ -203,7 +202,7 @@ export const ListBase = CollectionWidget.inherit({ return this.callBase().concat(deviceDependentOptions(), [ { device() { - return !nativeScrolling; + return !supportUtils.nativeScrolling; }, options: { useNativeScrolling: false, @@ -211,7 +210,7 @@ export const ListBase = CollectionWidget.inherit({ }, { device(device) { - return !nativeScrolling && !devices.isSimulator() && devices.real().deviceType === 'desktop' && device.platform === 'generic'; + return !supportUtils.nativeScrolling && !devices.isSimulator() && devices.real().deviceType === 'desktop' && device.platform === 'generic'; }, options: { showScrollbar: 'onHover', @@ -677,7 +676,6 @@ export const ListBase = CollectionWidget.inherit({ }, _initMarkup() { - // @ts-expect-error this._itemElementsCache = $(); this.$element().addClass(LIST_CLASS); diff --git a/packages/devextreme/js/__internal/ui/list/m_list.edit.decorator.switchable.ts b/packages/devextreme/js/__internal/ui/list/m_list.edit.decorator.switchable.ts index e43544b6c881..320f64e8804d 100644 --- a/packages/devextreme/js/__internal/ui/list/m_list.edit.decorator.switchable.ts +++ b/packages/devextreme/js/__internal/ui/list/m_list.edit.decorator.switchable.ts @@ -145,7 +145,6 @@ const SwitchableEditDecorator = EditDecorator.inherit({ _enablePositioning($itemElement) { $itemElement.addClass(SWITCHABLE_MENU_ITEM_SHIELD_POSITIONING_CLASS); eventsEngine.on($itemElement, ACTIVE_EVENT_NAME, noop); - // @ts-expect-error eventsEngine.one($itemElement, pointerEvents.up, this._disablePositioning.bind(this, $itemElement)); }, diff --git a/packages/devextreme/js/__internal/ui/list/m_list.edit.ts b/packages/devextreme/js/__internal/ui/list/m_list.edit.ts index b107f79f7147..c464c048dcaf 100644 --- a/packages/devextreme/js/__internal/ui/list/m_list.edit.ts +++ b/packages/devextreme/js/__internal/ui/list/m_list.edit.ts @@ -322,7 +322,6 @@ const ListEdit = ListBase.inherit({ const $itemElements = this._itemElements(); if (flatIndex < 0 || flatIndex >= $itemElements.length) { - // @ts-expect-error return $(); } diff --git a/packages/devextreme/js/__internal/ui/m_accordion.ts b/packages/devextreme/js/__internal/ui/m_accordion.ts index dde5d78e796c..a46f7b9992ad 100644 --- a/packages/devextreme/js/__internal/ui/m_accordion.ts +++ b/packages/devextreme/js/__internal/ui/m_accordion.ts @@ -112,7 +112,6 @@ const Accordion = CollectionWidget.inherit({ } if (isDefined(data.title) && !isPlainObject(data.title)) { - // @ts-expect-error $container.append(domAdapter.createTextNode(data.title)); } } else if (isDefined(data)) { diff --git a/packages/devextreme/js/__internal/ui/m_box.ts b/packages/devextreme/js/__internal/ui/m_box.ts index 5ee1bd5a79e7..60d956498ba9 100644 --- a/packages/devextreme/js/__internal/ui/m_box.ts +++ b/packages/devextreme/js/__internal/ui/m_box.ts @@ -62,9 +62,9 @@ const setFlexProp = (element, prop, value) => { } }; +// @ts-expect-error dxClass inheritance issue class BoxItem extends CollectionWidgetItem { _renderVisible(value, oldValue) { - // @ts-expect-error super._renderVisible(value); if (isDefined(oldValue)) { // @ts-expect-error @@ -124,7 +124,6 @@ class LayoutStrategy { const $item = $(this); const item = $item.data(BOX_ITEM_DATA_KEY) as any; - // @ts-expect-error $item.css({ display: `${flexPropPrefix}flex` }) .css(MAXSIZE_MAP[direction], item.maxSize || 'none') .css(MINSIZE_MAP[direction], item.minSize || '0'); @@ -135,7 +134,6 @@ class LayoutStrategy { // @ts-expect-error $item.children().each((_, itemContent) => { - // @ts-expect-error $(itemContent).css({ width: 'auto', height: 'auto', @@ -285,7 +283,6 @@ class Box extends CollectionWidget { _createItemByTemplate(itemTemplate, args) { if (args.itemData.box) { - // @ts-expect-error return itemTemplate.source ? itemTemplate.source() : $(); } return super._createItemByTemplate(itemTemplate, args); diff --git a/packages/devextreme/js/__internal/ui/m_dialog.ts b/packages/devextreme/js/__internal/ui/m_dialog.ts index 055acda52b7a..5bf591ec0c58 100644 --- a/packages/devextreme/js/__internal/ui/m_dialog.ts +++ b/packages/devextreme/js/__internal/ui/m_dialog.ts @@ -5,7 +5,6 @@ import Guid from '@js/core/guid'; import $ from '@js/core/renderer'; import { ensureDefined } from '@js/core/utils/common'; import { Deferred } from '@js/core/utils/deferred'; -import { resetActiveElement } from '@js/core/utils/dom'; import { extend } from '@js/core/utils/extend'; import { getHeight, getWidth } from '@js/core/utils/size'; import { isPlainObject } from '@js/core/utils/type'; @@ -16,6 +15,7 @@ import messageLocalization from '@js/localization/message'; import Popup from '@js/ui/popup/ui.popup'; import { isFluent } from '@js/ui/themes'; import errors from '@js/ui/widget/ui.errors'; +import domUtils from '@ts/core/utils/m_dom'; const window = getWindow(); @@ -111,7 +111,7 @@ export const custom = function (options) { .find(`.${DX_BUTTON_CLASSNAME}`) .addClass(DX_DIALOG_BUTTON_CLASSNAME); - resetActiveElement(); + domUtils.resetActiveElement(); }, onShown(e) { const $firstButton = e.component diff --git a/packages/devextreme/js/__internal/ui/m_file_uploader.ts b/packages/devextreme/js/__internal/ui/m_file_uploader.ts index 5ab6a24468a7..a40626874bc1 100644 --- a/packages/devextreme/js/__internal/ui/m_file_uploader.ts +++ b/packages/devextreme/js/__internal/ui/m_file_uploader.ts @@ -365,7 +365,6 @@ class FileUploader extends Editor { _getFiles(fileList: File[]) { const values: File[] = []; - // @ts-expect-error each(fileList, (_, value) => values.push(value)); return values; diff --git a/packages/devextreme/js/__internal/ui/m_load_indicator.ts b/packages/devextreme/js/__internal/ui/m_load_indicator.ts index ad0691be98dd..fb3f48ba0749 100644 --- a/packages/devextreme/js/__internal/ui/m_load_indicator.ts +++ b/packages/devextreme/js/__internal/ui/m_load_indicator.ts @@ -3,14 +3,14 @@ import devices from '@js/core/devices'; import $ from '@js/core/renderer'; import { extend } from '@js/core/utils/extend'; import { getHeight, getWidth } from '@js/core/utils/size'; -import { animation } from '@js/core/utils/support'; -// @ts-expect-error import { getNavigator } from '@js/core/utils/window'; import messageLocalization from '@js/localization/message'; // @ts-expect-error import { current, isGeneric, isMaterialBased } from '@js/ui/themes'; import Widget from '@js/ui/widget/ui.widget'; +import supportUtils from '../core/utils/m_support'; + const navigator = getNavigator(); const LOADINDICATOR_CLASS = 'dx-loadindicator'; @@ -106,7 +106,7 @@ const LoadIndicator = Widget.inherit({ _renderMarkup() { const { viaImage, indicatorSrc } = this.option(); - if (animation() && !viaImage && !indicatorSrc) { // B236922 + if (supportUtils.animation() && !viaImage && !indicatorSrc) { // B236922 this._renderMarkupForAnimation(); } else { this._renderMarkupForImage(); @@ -139,7 +139,7 @@ const LoadIndicator = Widget.inherit({ if (indicatorSrc) { this._$wrapper.addClass(LOADINDICATOR_IMAGE_CLASS); this._$wrapper.css('backgroundImage', `url(${indicatorSrc})`); - } else if (animation()) { + } else if (supportUtils.animation()) { this._renderMarkupForAnimation(); } }, diff --git a/packages/devextreme/js/__internal/ui/m_lookup.ts b/packages/devextreme/js/__internal/ui/m_lookup.ts index 7079b955b6a2..8127fe167a4d 100644 --- a/packages/devextreme/js/__internal/ui/m_lookup.ts +++ b/packages/devextreme/js/__internal/ui/m_lookup.ts @@ -11,7 +11,6 @@ import { each } from '@js/core/utils/iterator'; import { getHeight, getOuterHeight, getOuterWidth, getWidth, } from '@js/core/utils/size'; -import { nativeScrolling } from '@js/core/utils/support'; import { isDefined } from '@js/core/utils/type'; import { getWindow } from '@js/core/utils/window'; import eventsEngine from '@js/events/core/events_engine'; @@ -20,6 +19,7 @@ import DropDownList from '@js/ui/drop_down_editor/ui.drop_down_list'; import Popover from '@js/ui/popover/ui.popover'; import TextBox from '@js/ui/text_box'; import { current, isMaterial } from '@js/ui/themes'; +import supportUtils from '@ts/core/utils/m_support'; import { getElementWidth } from '@ts/ui/drop_down_editor/m_utils'; const window = getWindow(); @@ -136,7 +136,7 @@ const Lookup = DropDownList.inherit({ return this.callBase().concat([ { device() { - return !nativeScrolling; + return !supportUtils.nativeScrolling; }, options: { useNativeScrolling: false, diff --git a/packages/devextreme/js/__internal/ui/m_multi_view.ts b/packages/devextreme/js/__internal/ui/m_multi_view.ts index 3d7abf6ff7a0..f3e8226a0ab2 100644 --- a/packages/devextreme/js/__internal/ui/m_multi_view.ts +++ b/packages/devextreme/js/__internal/ui/m_multi_view.ts @@ -110,6 +110,12 @@ const MultiView = CollectionWidget.inherit({ index -= count; } + const step = this._swipeDirection > 0 ? -1 : 1; + + while (!this._isItemVisible(index)) { + index = (index + step) % count; + } + return index; }, @@ -260,6 +266,10 @@ const MultiView = CollectionWidget.inherit({ } }, + _isItemVisible(index) { + return this.option('items')[index]?.visible ?? true; + }, + _updateItemsVisibility(selectedIndex, newIndex) { const $itemElements = this._itemElements(); @@ -353,8 +363,9 @@ const MultiView = CollectionWidget.inherit({ items.forEach((item, index) => { const isDisabled = Boolean(item?.disabled); + const isVisible = this._isItemVisible(index); - if (!isDisabled) { + if (!isDisabled && isVisible) { firstIndex ??= index; lastIndex = index; } @@ -388,16 +399,19 @@ const MultiView = CollectionWidget.inherit({ const { offset } = e; const swipeDirection = sign(offset) * this._getRTLSignCorrection(); - _translator.move(this._$itemContainer, offset * this._itemWidth()); - if (swipeDirection !== this._swipeDirection) { this._swipeDirection = swipeDirection; + } - const selectedIndex = this.option('selectedIndex'); - const newIndex = this._normalizeIndex(selectedIndex - swipeDirection); + const selectedIndex = this.option('selectedIndex'); + const newIndex = this._normalizeIndex(selectedIndex - swipeDirection); - this._updateItems(selectedIndex, newIndex); + if (selectedIndex === newIndex) { + return; } + + _translator.move(this._$itemContainer, offset * this._itemWidth()); + this._updateItems(selectedIndex, newIndex); }, _findNextAvailableIndex(index, offset) { @@ -419,8 +433,8 @@ const MultiView = CollectionWidget.inherit({ for (let i = index + offset; i >= firstAvailableIndex && i <= lastAvailableIndex; i += offset) { const isDisabled = Boolean(items[i].disabled); - - if (!isDisabled) { + const isVisible = this._isItemVisible(i); + if (!isDisabled && isVisible) { return i; } } diff --git a/packages/devextreme/js/__internal/ui/m_resizable.ts b/packages/devextreme/js/__internal/ui/m_resizable.ts index 576ddaf7b759..d02ec6cb39c0 100644 --- a/packages/devextreme/js/__internal/ui/m_resizable.ts +++ b/packages/devextreme/js/__internal/ui/m_resizable.ts @@ -139,7 +139,6 @@ const Resizable = DOMComponent.inherit({ _detachEventHandlers() { this._handles.forEach((handleElement) => { - // @ts-expect-error eventsEngine.off(handleElement); }); }, diff --git a/packages/devextreme/js/__internal/ui/m_tag_box.ts b/packages/devextreme/js/__internal/ui/m_tag_box.ts index 7080c1eeb6d9..00a424704b45 100644 --- a/packages/devextreme/js/__internal/ui/m_tag_box.ts +++ b/packages/devextreme/js/__internal/ui/m_tag_box.ts @@ -429,7 +429,6 @@ const TagBox = (SelectBox as any).inherit({ }, _initMarkup() { - // @ts-expect-error this._tagElementsCache = $(); const isSingleLineMode = !this.option('multiline'); @@ -1330,7 +1329,6 @@ const TagBox = (SelectBox as any).inherit({ each(values, (index, selectedValue) => { if (this._isValueEquals(value, selectedValue)) { - // @ts-expect-error result = index; return false; } diff --git a/packages/devextreme/js/__internal/ui/m_tile_view.ts b/packages/devextreme/js/__internal/ui/m_tile_view.ts index 4d6423492527..53e568889378 100644 --- a/packages/devextreme/js/__internal/ui/m_tile_view.ts +++ b/packages/devextreme/js/__internal/ui/m_tile_view.ts @@ -13,12 +13,13 @@ import { setHeight, setWidth, } from '@js/core/utils/size'; -import { nativeScrolling } from '@js/core/utils/support'; import { isDefined } from '@js/core/utils/type'; import { hasWindow } from '@js/core/utils/window'; import CollectionWidget from '@js/ui/collection/ui.collection_widget.edit'; import ScrollView from '@js/ui/scroll_view'; +import supportUtils from '../core/utils/m_support'; + const TILEVIEW_CLASS = 'dx-tileview'; const TILEVIEW_CONTAINER_CLASS = 'dx-tileview-wrapper'; const TILEVIEW_ITEM_CLASS = 'dx-tile'; @@ -80,7 +81,7 @@ const TileView = CollectionWidget.inherit({ }, { device() { - return nativeScrolling; + return supportUtils.nativeScrolling; }, options: { showScrollbar: 'onScroll', diff --git a/packages/devextreme/js/__internal/ui/map/m_map.ts b/packages/devextreme/js/__internal/ui/map/m_map.ts index 2f70418c9eca..0978656a6b6b 100644 --- a/packages/devextreme/js/__internal/ui/map/m_map.ts +++ b/packages/devextreme/js/__internal/ui/map/m_map.ts @@ -15,12 +15,14 @@ import { addNamespace } from '@js/events/utils/index'; import errors from '@js/ui/widget/ui.errors'; import Widget from '@js/ui/widget/ui.widget'; +import azure from './m_provider.dynamic.azure'; import bing from './m_provider.dynamic.bing'; import google from './m_provider.dynamic.google'; // NOTE external urls must have protocol explicitly specified (because inside Cordova package the protocol is "file:") import googleStatic from './m_provider.google_static'; const PROVIDERS = { + azure, googleStatic, google, bing, @@ -86,6 +88,23 @@ const Map = Widget.inherit({ ]); }, + ctor(element, options) { + this.callBase(element, options); + + if (options) { + if ('provider' in options && options.provider === 'bing') { + this._logDeprecatedBingProvider(); + } + } + }, + + _logDeprecatedBingProvider() { + this._logDeprecatedOptionWarning('provider: bing', { + since: '24.2', + message: 'Use other map providers, such as Azure, Google, or GoogleStatic.', + }); + }, + _setDeprecatedOptions() { this.callBase(); extend(this._deprecatedOptions, { @@ -190,7 +209,7 @@ const Map = Widget.inherit({ }, _optionChanged(args) { - const { name } = args; + const { name, value } = args; const changeBag = this._optionChangeBag; this._optionChangeBag = null; @@ -199,6 +218,7 @@ const Map = Widget.inherit({ case 'disabled': this._renderShield(); this.callBase(args); + this._queueAsyncAction('updateDisabled'); break; case 'width': case 'height': @@ -208,6 +228,9 @@ const Map = Widget.inherit({ case 'provider': this._suppressAsyncAction = true; this._invalidate(); + if (value === 'bing') { + this._logDeprecatedBingProvider(); + } break; case 'apiKey': errors.log('W1001'); diff --git a/packages/devextreme/js/__internal/ui/map/m_provider.dynamic.azure.ts b/packages/devextreme/js/__internal/ui/map/m_provider.dynamic.azure.ts new file mode 100644 index 000000000000..53f07e9ff85a --- /dev/null +++ b/packages/devextreme/js/__internal/ui/map/m_provider.dynamic.azure.ts @@ -0,0 +1,488 @@ +import Color from '@js/color'; +import $ from '@js/core/renderer'; +import ajax from '@js/core/utils/ajax'; +import { noop } from '@js/core/utils/common'; +import { map } from '@js/core/utils/iterator'; +import { isDefined } from '@js/core/utils/type'; +import { getWindow } from '@js/core/utils/window'; +import errors from '@js/ui/widget/ui.errors'; + +import DynamicProvider from './m_provider.dynamic'; + +const window = getWindow(); + +declare let atlas: any; + +const AZURE_BASE_LINK = 'https://atlas.microsoft.com/'; +let AZURE_JS_URL = `${AZURE_BASE_LINK}sdk/javascript/mapcontrol/3/atlas.min.js`; +let AZURE_CSS_URL = `${AZURE_BASE_LINK}/sdk/javascript/mapcontrol/3/atlas.min.css`; +let CUSTOM_URL; + +const MAP_MARKER_TOOLTIP_CLASS = 'dx-map-marker-tooltip'; + +const CAMERA_PADDING = 50; + +const azureMapsLoaded = function () { + // @ts-expect-error + return window.atlas && window.atlas.Map; +}; + +let azureMapsLoader; + +const AzureProvider = DynamicProvider.inherit({ + _mapType(type) { + const mapTypes = { + roadmap: 'road', + satellite: 'satellite', + hybrid: 'satellite_road_labels', + }; + return mapTypes[type] || mapTypes.roadmap; + }, + + _movementMode(type) { + const movementTypes = { + driving: 'car', + walking: 'pedestrian', + }; + return movementTypes[type] || movementTypes.driving; + }, + + _resolveLocation(location) { + return new Promise((resolve) => { + const latLng = this._getLatLng(location); + if (latLng) { + resolve(new atlas.data.Position(latLng.lng, latLng.lat)); + } else { + this._geocodeLocation(location).then((geocodedLocation) => { + resolve(geocodedLocation); + }); + } + }); + }, + + _geocodedLocations: {}, + _geocodeLocationImpl(location) { + return new Promise((resolve) => { + if (!isDefined(location)) { + resolve(new atlas.data.Position(0, 0)); + return; + } + + const searchURL = `${AZURE_BASE_LINK}geocode?subscription-key=${this._keyOption('azure')}&api-version=2023-06-01&query=${location}&limit=1`; + + ajax.sendRequest({ + url: CUSTOM_URL ?? searchURL, + dataType: 'json', + }).then((result) => { + const coordinates = result?.features[0]?.geometry?.coordinates; + + if (coordinates) { + resolve(new atlas.data.Position(coordinates[0], coordinates[1])); + } else { + resolve(new atlas.data.Position(0, 0)); + } + }); + }); + }, + + _normalizeLocation(location) { + return { + lat: location[1], + lng: location[0], + }; + }, + + _normalizeLocationRect(locationRect) { + return { + northEast: { + lat: locationRect[1], + lng: locationRect[2], + }, + southWest: { + lat: locationRect[3], + lng: locationRect[0], + }, + }; + }, + + _loadImpl() { + return new Promise((resolve) => { + if (azureMapsLoaded()) { + resolve(); + } + + if (!azureMapsLoader) { + azureMapsLoader = this._loadMapResources(); + } + + azureMapsLoader.then(() => { + if (azureMapsLoaded()) { + resolve(); + return; + } + + this._loadMapResources().then(resolve); + }); + }); + }, + + _loadMapResources() { + return Promise.all([ + this._loadMapScript(), + this._loadMapStyles(), + ]); + }, + + _loadMapScript() { + return new Promise((resolve) => { + ajax.sendRequest({ + url: AZURE_JS_URL, + dataType: 'script', + }).then(() => { + resolve(); + }); + }); + }, + + _loadMapStyles() { + return new Promise((resolve) => { + ajax.sendRequest({ + url: AZURE_CSS_URL, + dataType: 'text', + }).then((css) => { + $('