@syncfusion/ej2-navigations 20.1.47 → 20.1.51-10460
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +243 -243
- package/CHANGELOG.md +1601 -1570
- package/README.md +194 -194
- package/dist/ej2-navigations.min.js +1 -0
- package/dist/ej2-navigations.umd.min.js +1 -10
- package/dist/ej2-navigations.umd.min.js.map +1 -1
- package/dist/es6/ej2-navigations.es2015.js +92 -80
- package/dist/es6/ej2-navigations.es2015.js.map +1 -1
- package/dist/es6/ej2-navigations.es5.js +251 -239
- package/dist/es6/ej2-navigations.es5.js.map +1 -1
- package/dist/global/ej2-navigations.min.js +1 -10
- package/dist/global/ej2-navigations.min.js.map +1 -1
- package/dist/global/index.d.ts +0 -9
- package/dist/ts/accordion/accordion.ts +1545 -0
- package/dist/ts/breadcrumb/breadcrumb.ts +873 -0
- package/dist/ts/carousel/carousel.ts +1181 -0
- package/dist/ts/common/h-scroll.ts +477 -0
- package/dist/ts/common/menu-base.ts +2357 -0
- package/dist/ts/common/menu-scroll.ts +105 -0
- package/dist/ts/common/v-scroll.ts +454 -0
- package/{src/context-menu/context-menu.d.ts → dist/ts/context-menu/context-menu.ts} +134 -88
- package/dist/ts/menu/menu.ts +302 -0
- package/dist/ts/sidebar/sidebar.ts +874 -0
- package/dist/ts/tab/tab.ts +2637 -0
- package/dist/ts/toolbar/toolbar.ts +2378 -0
- package/dist/ts/treeview/treeview.ts +5768 -0
- package/helpers/e2e/accordionHelper.js +70 -53
- package/helpers/e2e/contextmenuHelper.js +52 -35
- package/helpers/e2e/index.js +14 -12
- package/helpers/e2e/menuHelper.js +52 -35
- package/helpers/e2e/sidebarHelper.js +109 -92
- package/helpers/e2e/tabHelper.js +73 -56
- package/helpers/e2e/toolbarHelper.js +73 -56
- package/helpers/e2e/treeview.js +79 -61
- package/license +10 -10
- package/package.json +164 -164
- package/src/accordion/accordion-model.d.ts +190 -190
- package/src/accordion/accordion.js +19 -19
- package/src/breadcrumb/breadcrumb-model.d.ts +105 -105
- package/src/breadcrumb/breadcrumb.js +19 -19
- package/src/carousel/carousel-model.d.ts +148 -148
- package/src/carousel/carousel.js +19 -19
- package/src/common/h-scroll-model.d.ts +6 -6
- package/src/common/h-scroll.js +23 -21
- package/src/common/menu-base-model.d.ts +206 -206
- package/src/common/menu-base.js +31 -25
- package/src/common/v-scroll-model.d.ts +6 -6
- package/src/common/v-scroll.js +19 -19
- package/src/context-menu/context-menu-model.d.ts +18 -18
- package/src/context-menu/context-menu.js +19 -19
- package/src/menu/menu-model.d.ts +43 -43
- package/src/menu/menu.js +19 -19
- package/src/sidebar/sidebar-model.d.ts +191 -191
- package/src/sidebar/sidebar.js +19 -19
- package/src/tab/tab-model.d.ts +291 -291
- package/src/tab/tab.js +21 -21
- package/src/toolbar/toolbar-model.d.ts +195 -195
- package/src/toolbar/toolbar.js +23 -19
- package/src/treeview/treeview-model.d.ts +411 -411
- package/src/treeview/treeview.js +20 -20
- package/styles/accordion/_bds-definition.scss +167 -0
- package/styles/accordion/_bigger.scss +121 -0
- package/styles/accordion/_bootstrap5.3-definition.scss +168 -0
- package/styles/accordion/_fluent2-definition.scss +167 -0
- package/styles/accordion/_fusionnew-definition.scss +168 -0
- package/styles/accordion/_material3-dark-definition.scss +1 -0
- package/styles/accordion/_material3-definition.scss +168 -0
- package/styles/accordion/fluent2.scss +4 -0
- package/styles/accordion/icons/_bds.scss +15 -0
- package/styles/accordion/icons/_bootstrap5.3.scss +15 -0
- package/styles/accordion/icons/_fluent2.scss +15 -0
- package/styles/accordion/icons/_fusionnew.scss +15 -0
- package/styles/accordion/icons/_material3-dark.scss +1 -0
- package/styles/accordion/icons/_material3.scss +15 -0
- package/styles/accordion/material3-dark.scss +4 -0
- package/styles/accordion/material3.scss +4 -0
- package/styles/appbar/_all.scss +2 -0
- package/styles/appbar/_bds-definition.scss +25 -0
- package/styles/appbar/_bigger.scss +15 -0
- package/styles/appbar/_bootstrap-dark-definition.scss +6 -0
- package/styles/appbar/_bootstrap-definition.scss +6 -0
- package/styles/appbar/_bootstrap4-definition.scss +6 -0
- package/styles/appbar/_bootstrap5-definition.scss +6 -0
- package/styles/appbar/_bootstrap5.3-definition.scss +6 -0
- package/styles/appbar/_fabric-dark-definition.scss +6 -0
- package/styles/appbar/_fabric-definition.scss +6 -0
- package/styles/appbar/_fluent-definition.scss +6 -0
- package/styles/appbar/_fluent2-definition.scss +24 -0
- package/styles/appbar/_fusionnew-definition.scss +6 -0
- package/styles/appbar/_highcontrast-definition.scss +6 -0
- package/styles/appbar/_highcontrast-light-definition.scss +6 -0
- package/styles/appbar/_layout.scss +76 -0
- package/styles/appbar/_material-dark-definition.scss +6 -0
- package/styles/appbar/_material-definition.scss +6 -0
- package/styles/appbar/_material3-definition.scss +6 -0
- package/styles/appbar/_tailwind-definition.scss +6 -0
- package/styles/appbar/_theme.scss +216 -0
- package/styles/bootstrap-dark.css +1 -1
- package/styles/bootstrap.css +1 -1
- package/styles/bootstrap4.css +1 -1
- package/styles/bootstrap5-dark.css +1 -1
- package/styles/bootstrap5.css +1 -1
- package/styles/breadcrumb/_bds-definition.scss +60 -0
- package/styles/breadcrumb/_bigger.scss +160 -0
- package/styles/breadcrumb/_bootstrap5.3-definition.scss +61 -0
- package/styles/breadcrumb/_fluent2-definition.scss +61 -0
- package/styles/breadcrumb/_fusionnew-definition.scss +59 -0
- package/styles/breadcrumb/_layout.scss +1 -1
- package/styles/breadcrumb/_material3-dark-definition.scss +1 -0
- package/styles/breadcrumb/_material3-definition.scss +60 -0
- package/styles/breadcrumb/_tailwind-dark-definition.scss +1 -60
- package/styles/breadcrumb/_tailwind-definition.scss +3 -3
- package/styles/breadcrumb/bootstrap-dark.css +1 -1
- package/styles/breadcrumb/bootstrap.css +1 -1
- package/styles/breadcrumb/bootstrap4.css +1 -1
- package/styles/breadcrumb/bootstrap5-dark.css +1 -1
- package/styles/breadcrumb/bootstrap5.css +1 -1
- package/styles/breadcrumb/fabric-dark.css +1 -1
- package/styles/breadcrumb/fabric.css +1 -1
- package/styles/breadcrumb/fluent-dark.css +1 -1
- package/styles/breadcrumb/fluent.css +1 -1
- package/styles/breadcrumb/fluent2.scss +4 -0
- package/styles/breadcrumb/highcontrast-light.css +1 -1
- package/styles/breadcrumb/highcontrast.css +1 -1
- package/styles/breadcrumb/icons/_bds.scss +23 -0
- package/styles/breadcrumb/icons/_bootstrap5.3.scss +23 -0
- package/styles/breadcrumb/icons/_fluent2.scss +23 -0
- package/styles/breadcrumb/icons/_fusionnew.scss +23 -0
- package/styles/breadcrumb/icons/_material3-dark.scss +1 -0
- package/styles/breadcrumb/icons/_material3.scss +12 -0
- package/styles/breadcrumb/material-dark.css +1 -1
- package/styles/breadcrumb/material.css +1 -1
- package/styles/breadcrumb/material3-dark.scss +4 -0
- package/styles/breadcrumb/material3.scss +4 -0
- package/styles/breadcrumb/tailwind-dark.css +8 -8
- package/styles/breadcrumb/tailwind.css +8 -8
- package/styles/carousel/_bds-definition.scss +20 -0
- package/styles/carousel/_bootstrap5.3-definition.scss +20 -0
- package/styles/carousel/_fluent2-definition.scss +23 -0
- package/styles/carousel/_fusionnew-definition.scss +20 -0
- package/styles/carousel/_material3-dark-definition.scss +1 -0
- package/styles/carousel/_material3-definition.scss +21 -0
- package/styles/carousel/fluent2.scss +4 -0
- package/styles/carousel/icons/_bds.scss +30 -0
- package/styles/carousel/icons/_bootstrap5.3.scss +30 -0
- package/styles/carousel/icons/_fluent2.scss +30 -0
- package/styles/carousel/icons/_fusionnew.scss +30 -0
- package/styles/carousel/icons/_material3-dark.scss +1 -0
- package/styles/carousel/icons/_material3.scss +30 -0
- package/styles/carousel/material3-dark.scss +4 -0
- package/styles/carousel/material3.scss +4 -0
- package/styles/context-menu/_bds-definition.scss +68 -0
- package/styles/context-menu/_bigger.scss +96 -0
- package/styles/context-menu/_bootstrap5.3-definition.scss +52 -0
- package/styles/context-menu/_fluent2-definition.scss +52 -0
- package/styles/context-menu/_fusionnew-definition.scss +51 -0
- package/styles/context-menu/_material3-dark-definition.scss +1 -0
- package/styles/context-menu/_material3-definition.scss +51 -0
- package/styles/context-menu/fluent2.scss +4 -0
- package/styles/context-menu/icons/_bds.scss +31 -0
- package/styles/context-menu/icons/_bootstrap5.3.scss +31 -0
- package/styles/context-menu/icons/_fluent2.scss +31 -0
- package/styles/context-menu/icons/_fusionnew.scss +31 -0
- package/styles/context-menu/icons/_material3-dark.scss +1 -0
- package/styles/context-menu/icons/_material3.scss +31 -0
- package/styles/context-menu/material3-dark.scss +4 -0
- package/styles/context-menu/material3.scss +4 -0
- package/styles/fabric-dark.css +1 -1
- package/styles/fabric.css +1 -1
- package/styles/fluent-dark.css +1 -1
- package/styles/fluent.css +1 -1
- package/styles/fluent2.scss +34 -0
- package/styles/h-scroll/_bds-definition.scss +83 -0
- package/styles/h-scroll/_bigger.scss +39 -0
- package/styles/h-scroll/_bootstrap5.3-definition.scss +83 -0
- package/styles/h-scroll/_fluent2-definition.scss +83 -0
- package/styles/h-scroll/_fusionnew-definition.scss +83 -0
- package/styles/h-scroll/_material3-dark-definition.scss +1 -0
- package/styles/h-scroll/_material3-definition.scss +83 -0
- package/styles/h-scroll/fluent2.scss +4 -0
- package/styles/h-scroll/icons/_bds.scss +49 -0
- package/styles/h-scroll/icons/_bootstrap5.3.scss +49 -0
- package/styles/h-scroll/icons/_fluent2.scss +49 -0
- package/styles/h-scroll/icons/_fusionnew.scss +49 -0
- package/styles/h-scroll/icons/_material3-dark.scss +1 -0
- package/styles/h-scroll/icons/_material3.scss +49 -0
- package/styles/h-scroll/material3-dark.scss +4 -0
- package/styles/h-scroll/material3.scss +4 -0
- package/styles/highcontrast-light.css +1 -1
- package/styles/highcontrast.css +1 -1
- package/styles/material-dark.css +1 -1
- package/styles/material.css +1 -1
- package/styles/material3-dark.scss +34 -0
- package/styles/material3.scss +34 -0
- package/styles/menu/_bds-definition.scss +65 -0
- package/styles/menu/_bigger.scss +355 -0
- package/styles/menu/_bootstrap5.3-definition.scss +66 -0
- package/styles/menu/_fluent2-definition.scss +67 -0
- package/styles/menu/_fusionnew-definition.scss +66 -0
- package/styles/menu/_material3-dark-definition.scss +1 -0
- package/styles/menu/_material3-definition.scss +66 -0
- package/styles/menu/fluent2.scss +7 -0
- package/styles/menu/icons/_bds.scss +104 -0
- package/styles/menu/icons/_bootstrap5.3.scss +104 -0
- package/styles/menu/icons/_fluent2.scss +104 -0
- package/styles/menu/icons/_fusionnew.scss +104 -0
- package/styles/menu/icons/_material3-dark.scss +1 -0
- package/styles/menu/icons/_material3.scss +104 -0
- package/styles/menu/material3-dark.scss +7 -0
- package/styles/menu/material3.scss +7 -0
- package/styles/pager/_all.scss +2 -0
- package/styles/pager/_bds-definition.scss +152 -0
- package/styles/pager/_bigger.scss +311 -0
- package/styles/pager/_bootstrap-dark-definition.scss +151 -0
- package/styles/pager/_bootstrap-definition.scss +151 -0
- package/styles/pager/_bootstrap4-definition.scss +151 -0
- package/styles/pager/_bootstrap5-definition.scss +166 -0
- package/styles/pager/_bootstrap5.3-definition.scss +166 -0
- package/styles/pager/_fabric-dark-definition.scss +149 -0
- package/styles/pager/_fabric-definition.scss +149 -0
- package/styles/pager/_fluent-definition.scss +153 -0
- package/styles/pager/_fluent2-definition.scss +152 -0
- package/styles/pager/_fusionnew-definition.scss +166 -0
- package/styles/pager/_highcontrast-definition.scss +149 -0
- package/styles/pager/_highcontrast-light-definition.scss +149 -0
- package/styles/pager/_layout.scss +742 -0
- package/styles/pager/_material-dark-definition.scss +150 -0
- package/styles/pager/_material-definition.scss +150 -0
- package/styles/pager/_material3-definition.scss +166 -0
- package/styles/pager/_tailwind-definition.scss +152 -0
- package/styles/pager/_theme.scss +189 -0
- package/styles/pager/icons/_bds.scss +50 -0
- package/styles/pager/icons/_bootstrap-dark.scss +50 -0
- package/styles/pager/icons/_bootstrap.scss +50 -0
- package/styles/pager/icons/_bootstrap4.scss +50 -0
- package/styles/pager/icons/_bootstrap5.3.scss +50 -0
- package/styles/pager/icons/_bootstrap5.scss +50 -0
- package/styles/pager/icons/_fabric-dark.scss +50 -0
- package/styles/pager/icons/_fabric.scss +50 -0
- package/styles/pager/icons/_fluent.scss +50 -0
- package/styles/pager/icons/_fluent2.scss +50 -0
- package/styles/pager/icons/_fusionnew.scss +50 -0
- package/styles/pager/icons/_highcontrast-light.scss +50 -0
- package/styles/pager/icons/_highcontrast.scss +46 -0
- package/styles/pager/icons/_material-dark.scss +50 -0
- package/styles/pager/icons/_material.scss +46 -0
- package/styles/pager/icons/_material3.scss +50 -0
- package/styles/pager/icons/_tailwind.scss +50 -0
- package/styles/sidebar/_bds-definition.scss +53 -0
- package/styles/sidebar/_bootstrap5.3-definition.scss +6 -0
- package/styles/sidebar/_fluent2-definition.scss +8 -0
- package/styles/sidebar/_fusionnew-definition.scss +6 -0
- package/styles/sidebar/_material3-dark-definition.scss +1 -0
- package/styles/sidebar/_material3-definition.scss +4 -0
- package/styles/sidebar/fluent2.scss +3 -0
- package/styles/sidebar/material3-dark.scss +3 -0
- package/styles/sidebar/material3.scss +3 -0
- package/styles/stepper/_all.scss +2 -0
- package/styles/stepper/_bds-definition.scss +72 -0
- package/styles/stepper/_bigger.scss +53 -0
- package/styles/stepper/_bootstrap-dark-definition.scss +72 -0
- package/styles/stepper/_bootstrap-definition.scss +72 -0
- package/styles/stepper/_bootstrap4-definition.scss +72 -0
- package/styles/stepper/_bootstrap5-definition.scss +73 -0
- package/styles/stepper/_bootstrap5.3-definition.scss +72 -0
- package/styles/stepper/_fabric-dark-definition.scss +72 -0
- package/styles/stepper/_fabric-definition.scss +72 -0
- package/styles/stepper/_fluent-definition.scss +72 -0
- package/styles/stepper/_fluent2-definition.scss +72 -0
- package/styles/stepper/_fusionnew-definition.scss +72 -0
- package/styles/stepper/_highcontrast-definition.scss +72 -0
- package/styles/stepper/_highcontrast-light-definition.scss +72 -0
- package/styles/stepper/_layout.scss +431 -0
- package/styles/stepper/_material-dark-definition.scss +72 -0
- package/styles/stepper/_material-definition.scss +72 -0
- package/styles/stepper/_material3-definition.scss +72 -0
- package/styles/stepper/_tailwind-definition.scss +72 -0
- package/styles/stepper/_theme.scss +195 -0
- package/styles/stepper/icons/_bds.scss +5 -0
- package/styles/stepper/icons/_bootstrap-dark.scss +5 -0
- package/styles/stepper/icons/_bootstrap.scss +5 -0
- package/styles/stepper/icons/_bootstrap4.scss +5 -0
- package/styles/stepper/icons/_bootstrap5.3.scss +5 -0
- package/styles/stepper/icons/_bootstrap5.scss +5 -0
- package/styles/stepper/icons/_fabric-dark.scss +5 -0
- package/styles/stepper/icons/_fabric.scss +5 -0
- package/styles/stepper/icons/_fluent.scss +5 -0
- package/styles/stepper/icons/_fluent2.scss +5 -0
- package/styles/stepper/icons/_fusionnew.scss +5 -0
- package/styles/stepper/icons/_highcontrast-light.scss +5 -0
- package/styles/stepper/icons/_highcontrast.scss +5 -0
- package/styles/stepper/icons/_material-dark.scss +5 -0
- package/styles/stepper/icons/_material.scss +5 -0
- package/styles/stepper/icons/_material3.scss +5 -0
- package/styles/stepper/icons/_tailwind.scss +5 -0
- package/styles/tab/_bds-definition.scss +661 -0
- package/styles/tab/_bigger.scss +1270 -0
- package/styles/tab/_bootstrap5.3-definition.scss +636 -0
- package/styles/tab/_fluent2-definition.scss +667 -0
- package/styles/tab/_fusionnew-definition.scss +634 -0
- package/styles/tab/_material3-dark-definition.scss +1 -0
- package/styles/tab/_material3-definition.scss +636 -0
- package/styles/tab/fluent2.scss +5 -0
- package/styles/tab/icons/_bds.scss +90 -0
- package/styles/tab/icons/_bootstrap5.3.scss +90 -0
- package/styles/tab/icons/_fluent2.scss +98 -0
- package/styles/tab/icons/_fusionnew.scss +90 -0
- package/styles/tab/icons/_material3-dark.scss +1 -0
- package/styles/tab/icons/_material3.scss +90 -0
- package/styles/tab/material3-dark.scss +5 -0
- package/styles/tab/material3.scss +5 -0
- package/styles/tailwind-dark.css +8 -8
- package/styles/tailwind.css +8 -8
- package/styles/toolbar/_bds-definition.scss +197 -0
- package/styles/toolbar/_bigger.scss +309 -0
- package/styles/toolbar/_bootstrap5.3-definition.scss +198 -0
- package/styles/toolbar/_fluent2-definition.scss +198 -0
- package/styles/toolbar/_fusionnew-definition.scss +198 -0
- package/styles/toolbar/_material3-dark-definition.scss +1 -0
- package/styles/toolbar/_material3-definition.scss +199 -0
- package/styles/toolbar/fluent2.scss +6 -0
- package/styles/toolbar/icons/_bds.scss +14 -0
- package/styles/toolbar/icons/_bootstrap5.3.scss +14 -0
- package/styles/toolbar/icons/_fluent2.scss +14 -0
- package/styles/toolbar/icons/_fusionnew.scss +14 -0
- package/styles/toolbar/icons/_material3-dark.scss +1 -0
- package/styles/toolbar/icons/_material3.scss +14 -0
- package/styles/toolbar/material3-dark.scss +6 -0
- package/styles/toolbar/material3.scss +6 -0
- package/styles/treeview/_bds-definition.scss +132 -0
- package/styles/treeview/_bigger.scss +393 -0
- package/styles/treeview/_bootstrap5.3-definition.scss +119 -0
- package/styles/treeview/_fluent2-definition.scss +128 -0
- package/styles/treeview/_fusionnew-definition.scss +120 -0
- package/styles/treeview/_material3-dark-definition.scss +1 -0
- package/styles/treeview/_material3-definition.scss +110 -0
- package/styles/treeview/fluent2.scss +4 -0
- package/styles/treeview/icons/_bds.scss +44 -0
- package/styles/treeview/icons/_bootstrap5.3.scss +44 -0
- package/styles/treeview/icons/_fluent2.scss +44 -0
- package/styles/treeview/icons/_fusionnew.scss +44 -0
- package/styles/treeview/icons/_material3-dark.scss +1 -0
- package/styles/treeview/icons/_material3.scss +44 -0
- package/styles/treeview/material3-dark.scss +4 -0
- package/styles/treeview/material3.scss +4 -0
- package/styles/v-scroll/_bds-definition.scss +49 -0
- package/styles/v-scroll/_bigger.scss +28 -0
- package/styles/v-scroll/_bootstrap5.3-definition.scss +49 -0
- package/styles/v-scroll/_fluent2-definition.scss +49 -0
- package/styles/v-scroll/_fusionnew-definition.scss +49 -0
- package/styles/v-scroll/_material3-dark-definition.scss +1 -0
- package/styles/v-scroll/_material3-definition.scss +49 -0
- package/styles/v-scroll/fluent2.scss +4 -0
- package/styles/v-scroll/icons/_bds.scss +27 -0
- package/styles/v-scroll/icons/_bootstrap5.3.scss +27 -0
- package/styles/v-scroll/icons/_fluent2.scss +27 -0
- package/styles/v-scroll/icons/_fusionnew.scss +27 -0
- package/styles/v-scroll/icons/_material3-dark.scss +1 -0
- package/styles/v-scroll/icons/_material3.scss +27 -0
- package/styles/v-scroll/material3-dark.scss +4 -0
- package/styles/v-scroll/material3.scss +4 -0
- package/tslint.json +111 -111
- package/.github/PULL_REQUEST_TEMPLATE/Bug.md +0 -63
- package/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -39
- package/accordion.d.ts +0 -4
- package/accordion.js +0 -4
- package/breadcrumb.d.ts +0 -4
- package/breadcrumb.js +0 -4
- package/carousel.d.ts +0 -4
- package/carousel.js +0 -4
- package/common.d.ts +0 -4
- package/common.js +0 -4
- package/context-menu.d.ts +0 -4
- package/context-menu.js +0 -4
- package/helpers/e2e/accordionHelper.d.ts +0 -56
- package/helpers/e2e/contextmenuHelper.d.ts +0 -37
- package/helpers/e2e/index.d.ts +0 -7
- package/helpers/e2e/menuHelper.d.ts +0 -37
- package/helpers/e2e/sidebarHelper.d.ts +0 -94
- package/helpers/e2e/tabHelper.d.ts +0 -60
- package/helpers/e2e/toolbarHelper.d.ts +0 -60
- package/helpers/e2e/treeview.d.ts +0 -50
- package/index.d.ts +0 -4
- package/index.js +0 -4
- package/menu.d.ts +0 -4
- package/menu.js +0 -4
- package/sidebar.d.ts +0 -4
- package/sidebar.js +0 -4
- package/src/accordion/accordion.d.ts +0 -440
- package/src/accordion/index.d.ts +0 -5
- package/src/breadcrumb/breadcrumb.d.ts +0 -255
- package/src/breadcrumb/index.d.ts +0 -5
- package/src/carousel/carousel.d.ts +0 -338
- package/src/carousel/index.d.ts +0 -3
- package/src/common/h-scroll.d.ts +0 -105
- package/src/common/index.d.ts +0 -9
- package/src/common/menu-base.d.ts +0 -526
- package/src/common/menu-scroll.d.ts +0 -29
- package/src/common/v-scroll.d.ts +0 -106
- package/src/context-menu/index.d.ts +0 -5
- package/src/index.d.ts +0 -13
- package/src/menu/index.d.ts +0 -5
- package/src/menu/menu.d.ts +0 -121
- package/src/sidebar/index.d.ts +0 -5
- package/src/sidebar/sidebar.d.ts +0 -321
- package/src/tab/index.d.ts +0 -5
- package/src/tab/tab.d.ts +0 -650
- package/src/toolbar/index.d.ts +0 -5
- package/src/toolbar/toolbar.d.ts +0 -470
- package/src/treeview/index.d.ts +0 -5
- package/src/treeview/treeview.d.ts +0 -1256
- package/tab.d.ts +0 -4
- package/tab.js +0 -4
- package/toolbar.d.ts +0 -4
- package/toolbar.js +0 -4
- package/treeview.d.ts +0 -4
- package/treeview.js +0 -4
|
@@ -0,0 +1,2357 @@
|
|
|
1
|
+
import { Component, Property, ChildProperty, NotifyPropertyChanges, INotifyPropertyChanged, AnimationModel, isBlazor } from '@syncfusion/ej2-base';
|
|
2
|
+
import { Event, EventHandler, EmitType, BaseEventArgs, KeyboardEvents, KeyboardEventArgs, Touch, TapEventArgs } from '@syncfusion/ej2-base';
|
|
3
|
+
import { Animation, AnimationOptions, TouchEventArgs, MouseEventArgs } from '@syncfusion/ej2-base';
|
|
4
|
+
import { Browser, Collection, setValue, getValue, getUniqueID, getInstance, isNullOrUndefined } from '@syncfusion/ej2-base';
|
|
5
|
+
import { select, selectAll, closest, detach, append, rippleEffect, isVisible, Complex, addClass, removeClass } from '@syncfusion/ej2-base';
|
|
6
|
+
import { ListBase, ListBaseOptions } from '@syncfusion/ej2-lists';
|
|
7
|
+
import { getZindexPartial, calculatePosition, OffsetPosition, isCollide, fit, Popup } from '@syncfusion/ej2-popups';
|
|
8
|
+
import { extend, SanitizeHtmlHelper } from '@syncfusion/ej2-base';
|
|
9
|
+
import { getScrollableParent } from '@syncfusion/ej2-popups';
|
|
10
|
+
import { MenuItemModel, MenuBaseModel, FieldSettingsModel, MenuAnimationSettingsModel } from './menu-base-model';
|
|
11
|
+
import { HScroll } from '../common/h-scroll';
|
|
12
|
+
import { VScroll } from '../common/v-scroll';
|
|
13
|
+
import { addScrolling, destroyScroll } from '../common/menu-scroll';
|
|
14
|
+
|
|
15
|
+
type objColl = { [key: string]: Object }[];
|
|
16
|
+
type obj = { [key: string]: Object };
|
|
17
|
+
|
|
18
|
+
const ENTER: string = 'enter';
|
|
19
|
+
|
|
20
|
+
const ESCAPE: string = 'escape';
|
|
21
|
+
|
|
22
|
+
const FOCUSED: string = 'e-focused';
|
|
23
|
+
|
|
24
|
+
const HEADER: string = 'e-menu-header';
|
|
25
|
+
|
|
26
|
+
const SELECTED: string = 'e-selected';
|
|
27
|
+
|
|
28
|
+
const SEPARATOR: string = 'e-separator';
|
|
29
|
+
|
|
30
|
+
const UPARROW: string = 'uparrow';
|
|
31
|
+
|
|
32
|
+
const DOWNARROW: string = 'downarrow';
|
|
33
|
+
|
|
34
|
+
const LEFTARROW: string = 'leftarrow';
|
|
35
|
+
|
|
36
|
+
const RIGHTARROW: string = 'rightarrow';
|
|
37
|
+
|
|
38
|
+
const HOME: string = 'home';
|
|
39
|
+
|
|
40
|
+
const END: string = 'end';
|
|
41
|
+
|
|
42
|
+
const CARET: string = 'e-caret';
|
|
43
|
+
|
|
44
|
+
const ITEM: string = 'e-menu-item';
|
|
45
|
+
|
|
46
|
+
const DISABLED: string = 'e-disabled';
|
|
47
|
+
|
|
48
|
+
const HIDE: string = 'e-menu-hide';
|
|
49
|
+
|
|
50
|
+
const ICONS: string = 'e-icons';
|
|
51
|
+
|
|
52
|
+
const RTL: string = 'e-rtl';
|
|
53
|
+
|
|
54
|
+
const POPUP: string = 'e-menu-popup';
|
|
55
|
+
|
|
56
|
+
const TEMPLATE_PROPERTY: string = 'Template';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Sub menu open type
|
|
60
|
+
*/
|
|
61
|
+
export type MenuOpenType = 'Auto' | 'Click' | 'Hover';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Menu animation effects
|
|
65
|
+
*/
|
|
66
|
+
export type MenuEffect = 'None' | 'SlideDown' | 'ZoomIn' | 'FadeIn';
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Configures the field options of the Menu.
|
|
70
|
+
*/
|
|
71
|
+
export class FieldSettings extends ChildProperty<FieldSettings> {
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Specifies the itemId field for Menu item.
|
|
75
|
+
*
|
|
76
|
+
* @default 'id'
|
|
77
|
+
*/
|
|
78
|
+
@Property('id')
|
|
79
|
+
public itemId: string | string[];
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Specifies the parentId field for Menu item.
|
|
83
|
+
*
|
|
84
|
+
* @default 'parentId'
|
|
85
|
+
*/
|
|
86
|
+
@Property('parentId')
|
|
87
|
+
public parentId: string | string[];
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Specifies the text field for Menu item.
|
|
91
|
+
*
|
|
92
|
+
* @default 'text'
|
|
93
|
+
*/
|
|
94
|
+
@Property('text')
|
|
95
|
+
public text: string | string[];
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Specifies the css icon field for Menu item.
|
|
99
|
+
*
|
|
100
|
+
* @default 'iconCss'
|
|
101
|
+
*/
|
|
102
|
+
@Property('iconCss')
|
|
103
|
+
public iconCss: string | string[];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Specifies the Url field for Menu item.
|
|
107
|
+
*
|
|
108
|
+
* @default 'url'
|
|
109
|
+
*/
|
|
110
|
+
@Property('url')
|
|
111
|
+
public url: string | string[];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Specifies the separator field for Menu item.
|
|
115
|
+
*
|
|
116
|
+
* @default 'separator'
|
|
117
|
+
*/
|
|
118
|
+
@Property('separator')
|
|
119
|
+
public separator: string | string[];
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Specifies the children field for Menu item.
|
|
123
|
+
*
|
|
124
|
+
* @default 'items'
|
|
125
|
+
*/
|
|
126
|
+
@Property('items')
|
|
127
|
+
public children: string | string[];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Specifies menu items.
|
|
132
|
+
*/
|
|
133
|
+
export class MenuItem extends ChildProperty<MenuItem> {
|
|
134
|
+
/**
|
|
135
|
+
* Defines class/multiple classes separated by a space for the menu Item that is used to include an icon.
|
|
136
|
+
* Menu Item can include font icon and sprite image.
|
|
137
|
+
*
|
|
138
|
+
* @default null
|
|
139
|
+
*/
|
|
140
|
+
@Property(null)
|
|
141
|
+
public iconCss: string;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Specifies the id for menu item.
|
|
145
|
+
*
|
|
146
|
+
* @default ''
|
|
147
|
+
*/
|
|
148
|
+
@Property('')
|
|
149
|
+
public id: string;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Specifies separator between the menu items. Separator are either horizontal or vertical lines used to group menu items.
|
|
153
|
+
*
|
|
154
|
+
* @default false
|
|
155
|
+
*/
|
|
156
|
+
@Property(false)
|
|
157
|
+
public separator: boolean;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Specifies the sub menu items that is the array of MenuItem model.
|
|
161
|
+
*
|
|
162
|
+
* @default []
|
|
163
|
+
*/
|
|
164
|
+
@Collection<MenuItemModel>([], MenuItem)
|
|
165
|
+
public items: MenuItemModel[];
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Specifies text for menu item.
|
|
169
|
+
*
|
|
170
|
+
* @default ''
|
|
171
|
+
*/
|
|
172
|
+
@Property('')
|
|
173
|
+
public text: string;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Specifies url for menu item that creates the anchor link to navigate to the url provided.
|
|
177
|
+
*
|
|
178
|
+
* @default ''
|
|
179
|
+
*/
|
|
180
|
+
@Property('')
|
|
181
|
+
public url: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Animation configuration settings.
|
|
186
|
+
*/
|
|
187
|
+
export class MenuAnimationSettings extends ChildProperty<MenuAnimationSettings> {
|
|
188
|
+
/**
|
|
189
|
+
* Specifies the effect that shown in the sub menu transform.
|
|
190
|
+
* The possible effects are:
|
|
191
|
+
* * None: Specifies the sub menu transform with no animation effect.
|
|
192
|
+
* * SlideDown: Specifies the sub menu transform with slide down effect.
|
|
193
|
+
* * ZoomIn: Specifies the sub menu transform with zoom in effect.
|
|
194
|
+
* * FadeIn: Specifies the sub menu transform with fade in effect.
|
|
195
|
+
*
|
|
196
|
+
* @default 'SlideDown'
|
|
197
|
+
* @aspType Syncfusion.EJ2.Navigations.MenuEffect
|
|
198
|
+
* @blazorType Syncfusion.EJ2.Navigations.MenuEffect
|
|
199
|
+
* @isEnumeration true
|
|
200
|
+
*/
|
|
201
|
+
@Property('SlideDown')
|
|
202
|
+
public effect: MenuEffect;
|
|
203
|
+
/**
|
|
204
|
+
* Specifies the time duration to transform object.
|
|
205
|
+
*
|
|
206
|
+
* @default 400
|
|
207
|
+
*/
|
|
208
|
+
@Property(400)
|
|
209
|
+
public duration: number;
|
|
210
|
+
/**
|
|
211
|
+
* Specifies the easing effect applied while transform.
|
|
212
|
+
*
|
|
213
|
+
* @default 'ease'
|
|
214
|
+
*/
|
|
215
|
+
@Property('ease')
|
|
216
|
+
public easing: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Base class for Menu and ContextMenu components.
|
|
221
|
+
*
|
|
222
|
+
* @private
|
|
223
|
+
*/
|
|
224
|
+
@NotifyPropertyChanges
|
|
225
|
+
export abstract class MenuBase extends Component<HTMLUListElement> implements INotifyPropertyChanged {
|
|
226
|
+
private clonedElement: HTMLElement;
|
|
227
|
+
private targetElement: HTMLElement;
|
|
228
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
229
|
+
private delegateClickHandler: Function;
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
231
|
+
private delegateMoverHandler: Function;
|
|
232
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
233
|
+
private delegateMouseDownHandler: Function;
|
|
234
|
+
private navIdx: number[] = [];
|
|
235
|
+
private animation: Animation = new Animation({});
|
|
236
|
+
private isTapHold: boolean = false;
|
|
237
|
+
protected isMenu: boolean;
|
|
238
|
+
protected hamburgerMode: boolean;
|
|
239
|
+
protected title: string;
|
|
240
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
241
|
+
private rippleFn: Function;
|
|
242
|
+
private uList: HTMLElement;
|
|
243
|
+
private lItem: Element;
|
|
244
|
+
private popupObj: Popup;
|
|
245
|
+
private popupWrapper: HTMLElement;
|
|
246
|
+
private isNestedOrVertical: boolean;
|
|
247
|
+
private top: number;
|
|
248
|
+
private left: number;
|
|
249
|
+
private keyType: string;
|
|
250
|
+
private showSubMenu: boolean;
|
|
251
|
+
private action: string;
|
|
252
|
+
private cli: Element;
|
|
253
|
+
private cliIdx: number;
|
|
254
|
+
private isClosed: boolean;
|
|
255
|
+
private liTrgt: Element;
|
|
256
|
+
private isMenusClosed: boolean;
|
|
257
|
+
private isCMenu: boolean;
|
|
258
|
+
private pageX: number;
|
|
259
|
+
private pageY: number;
|
|
260
|
+
private tempItem: objColl = [];
|
|
261
|
+
private showSubMenuOn: MenuOpenType = 'Auto';
|
|
262
|
+
private defaultOption: boolean;
|
|
263
|
+
private timer: number;
|
|
264
|
+
/**
|
|
265
|
+
* Triggers while rendering each menu item.
|
|
266
|
+
*
|
|
267
|
+
* @event beforeItemRender
|
|
268
|
+
* @blazorProperty 'OnItemRender'
|
|
269
|
+
*/
|
|
270
|
+
@Event()
|
|
271
|
+
public beforeItemRender: EmitType<MenuEventArgs>;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Triggers before opening the menu item.
|
|
275
|
+
*
|
|
276
|
+
* @event beforeOpen
|
|
277
|
+
* @blazorProperty 'OnOpen'
|
|
278
|
+
*/
|
|
279
|
+
@Event()
|
|
280
|
+
public beforeOpen: EmitType<BeforeOpenCloseMenuEventArgs>;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Triggers while opening the menu item.
|
|
284
|
+
*
|
|
285
|
+
* @event onOpen
|
|
286
|
+
* @blazorProperty 'Opened'
|
|
287
|
+
*/
|
|
288
|
+
@Event()
|
|
289
|
+
public onOpen: EmitType<OpenCloseMenuEventArgs>;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Triggers before closing the menu.
|
|
293
|
+
*
|
|
294
|
+
* @event beforeClose
|
|
295
|
+
* @blazorProperty 'OnClose'
|
|
296
|
+
*/
|
|
297
|
+
@Event()
|
|
298
|
+
public beforeClose: EmitType<BeforeOpenCloseMenuEventArgs>;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Triggers while closing the menu.
|
|
302
|
+
*
|
|
303
|
+
* @event onClose
|
|
304
|
+
* @blazorProperty 'Closed'
|
|
305
|
+
*/
|
|
306
|
+
@Event()
|
|
307
|
+
public onClose: EmitType<OpenCloseMenuEventArgs>;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Triggers while selecting menu item.
|
|
311
|
+
*
|
|
312
|
+
* @event select
|
|
313
|
+
* @blazorProperty 'ItemSelected'
|
|
314
|
+
*/
|
|
315
|
+
@Event()
|
|
316
|
+
public select: EmitType<MenuEventArgs>;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Triggers once the component rendering is completed.
|
|
320
|
+
*
|
|
321
|
+
* @event created
|
|
322
|
+
* @blazorProperty 'Created'
|
|
323
|
+
*/
|
|
324
|
+
@Event()
|
|
325
|
+
public created: EmitType<Event>;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Defines class/multiple classes separated by a space in the Menu wrapper.
|
|
329
|
+
*
|
|
330
|
+
* @default ''
|
|
331
|
+
*/
|
|
332
|
+
@Property('')
|
|
333
|
+
public cssClass: string;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* If hoverDelay is set by particular number, the menu will open after that period.
|
|
337
|
+
*
|
|
338
|
+
* @default 0
|
|
339
|
+
*/
|
|
340
|
+
@Property(0)
|
|
341
|
+
public hoverDelay: number;
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Specifies whether to show the sub menu or not on click.
|
|
345
|
+
* When set to true, the sub menu will open only on mouse click.
|
|
346
|
+
*
|
|
347
|
+
* @default false
|
|
348
|
+
*/
|
|
349
|
+
@Property(false)
|
|
350
|
+
public showItemOnClick: boolean;
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Specifies target element selector in which the ContextMenu should be opened.
|
|
354
|
+
* Specifies target element to open/close Menu while click in Hamburger mode.
|
|
355
|
+
*
|
|
356
|
+
* @default ''
|
|
357
|
+
* @private
|
|
358
|
+
*/
|
|
359
|
+
@Property('')
|
|
360
|
+
public target: string;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Specifies the filter selector for elements inside the target in that the context menu will be opened.
|
|
364
|
+
* Not applicable to Menu component.
|
|
365
|
+
*
|
|
366
|
+
* @default ''
|
|
367
|
+
* @private
|
|
368
|
+
*/
|
|
369
|
+
@Property('')
|
|
370
|
+
public filter: string;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Specifies the template for Menu item.
|
|
374
|
+
* Not applicable to ContextMenu component.
|
|
375
|
+
*
|
|
376
|
+
* @default null
|
|
377
|
+
* @private
|
|
378
|
+
*/
|
|
379
|
+
@Property(null)
|
|
380
|
+
public template: string;
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Specifies whether to enable / disable the scrollable option in Menu.
|
|
384
|
+
* Not applicable to ContextMenu component.
|
|
385
|
+
*
|
|
386
|
+
* @default false
|
|
387
|
+
* @private
|
|
388
|
+
*/
|
|
389
|
+
@Property(false)
|
|
390
|
+
public enableScrolling: boolean;
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Defines whether to allow the cross-scripting site or not.
|
|
394
|
+
*
|
|
395
|
+
* @default false
|
|
396
|
+
*/
|
|
397
|
+
@Property(false)
|
|
398
|
+
public enableHtmlSanitizer: boolean;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Specifies mapping fields from the dataSource.
|
|
402
|
+
* Not applicable to ContextMenu component.
|
|
403
|
+
*
|
|
404
|
+
* @default { itemId: "id", text: "text", parentId: "parentId", iconCss: "iconCss", url: "url", separator: "separator",
|
|
405
|
+
* children: "items" }
|
|
406
|
+
* @private
|
|
407
|
+
*/
|
|
408
|
+
// eslint:disable-next-line
|
|
409
|
+
@Complex<FieldSettingsModel>({ itemId: 'id', text: 'text', parentId: 'parentId', iconCss: 'iconCss', url: 'url', separator: 'separator', children: 'items' }, FieldSettings)
|
|
410
|
+
public fields: FieldSettingsModel;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Specifies menu items with its properties which will be rendered as Menu.
|
|
414
|
+
*
|
|
415
|
+
* @default []
|
|
416
|
+
*/
|
|
417
|
+
@Collection<MenuItemModel>([], MenuItem)
|
|
418
|
+
public items: MenuItemModel[] | { [key: string]: Object }[];
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Specifies the animation settings for the sub menu open.
|
|
422
|
+
*
|
|
423
|
+
* @default { duration: 400, easing: 'ease', effect: 'SlideDown' }
|
|
424
|
+
*/
|
|
425
|
+
@Complex<MenuAnimationSettingsModel>({ duration: 400, easing: 'ease', effect: 'SlideDown' }, MenuAnimationSettings)
|
|
426
|
+
public animationSettings: MenuAnimationSettingsModel;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Constructor for creating the widget.
|
|
430
|
+
*
|
|
431
|
+
* @private
|
|
432
|
+
* @param {MenuBaseModel} options - Specifies the menu base model
|
|
433
|
+
* @param {string | HTMLUListElement} element - Specifies the element
|
|
434
|
+
*/
|
|
435
|
+
constructor(options?: MenuBaseModel, element?: string | HTMLUListElement) {
|
|
436
|
+
super(options, <HTMLUListElement | string>element);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Initialized third party configuration settings.
|
|
441
|
+
*
|
|
442
|
+
* @private
|
|
443
|
+
* @returns {void}
|
|
444
|
+
*/
|
|
445
|
+
protected preRender(): void {
|
|
446
|
+
if (!this.isMenu) {
|
|
447
|
+
let ul: HTMLUListElement;
|
|
448
|
+
if (this.element.tagName === 'EJS-CONTEXTMENU') {
|
|
449
|
+
ul = this.createElement('ul', {
|
|
450
|
+
id: getUniqueID(this.getModuleName()), className: 'e-control e-lib e-' + this.getModuleName() }) as HTMLUListElement;
|
|
451
|
+
const ejInst: Object = getValue('ej2_instances', this.element);
|
|
452
|
+
removeClass([this.element], ['e-control', 'e-lib', 'e-' + this.getModuleName()]);
|
|
453
|
+
this.clonedElement = this.element; this.element = ul;
|
|
454
|
+
setValue('ej2_instances', ejInst, this.element);
|
|
455
|
+
} else {
|
|
456
|
+
ul = this.createElement('ul', { id: getUniqueID(this.getModuleName()) }) as HTMLUListElement;
|
|
457
|
+
append([].slice.call((this.element.cloneNode(true) as Element).children), ul);
|
|
458
|
+
const refEle: Element = this.element.nextElementSibling;
|
|
459
|
+
if (refEle) {
|
|
460
|
+
this.element.parentElement.insertBefore(ul, refEle);
|
|
461
|
+
} else {
|
|
462
|
+
this.element.parentElement.appendChild(ul);
|
|
463
|
+
}
|
|
464
|
+
this.clonedElement = ul;
|
|
465
|
+
}
|
|
466
|
+
this.clonedElement.style.display = 'none';
|
|
467
|
+
}
|
|
468
|
+
if (this.element.tagName === 'EJS-MENU') {
|
|
469
|
+
let ele: Element = this.element;
|
|
470
|
+
const ejInstance: Object = getValue('ej2_instances', ele);
|
|
471
|
+
const ul: Element = this.createElement('ul');
|
|
472
|
+
const wrapper: HTMLElement = this.createElement('EJS-MENU', { className: 'e-' + this.getModuleName() + '-wrapper' });
|
|
473
|
+
for (let idx: number = 0, len: number = ele.attributes.length; idx < len; idx++) {
|
|
474
|
+
ul.setAttribute(ele.attributes[idx].nodeName, ele.attributes[idx].nodeValue);
|
|
475
|
+
}
|
|
476
|
+
ele.parentNode.insertBefore(wrapper, ele);
|
|
477
|
+
detach(ele);
|
|
478
|
+
ele = ul;
|
|
479
|
+
wrapper.appendChild(ele);
|
|
480
|
+
setValue('ej2_instances', ejInstance, ele);
|
|
481
|
+
this.clonedElement = wrapper;
|
|
482
|
+
this.element = ele as HTMLUListElement;
|
|
483
|
+
if (!this.element.id) {
|
|
484
|
+
this.element.id = getUniqueID(this.getModuleName());
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Initialize the control rendering.
|
|
491
|
+
*
|
|
492
|
+
* @private
|
|
493
|
+
* @returns {void}
|
|
494
|
+
*/
|
|
495
|
+
protected render(): void {
|
|
496
|
+
this.initialize();
|
|
497
|
+
this.renderItems();
|
|
498
|
+
this.wireEvents();
|
|
499
|
+
this.renderComplete();
|
|
500
|
+
const wrapper: HTMLElement = this.getWrapper() as HTMLElement;
|
|
501
|
+
if (this.template && this.enableScrolling && ((this as any).isReact || (this as any).isAngular)) {
|
|
502
|
+
requestAnimationFrame(() => {
|
|
503
|
+
addScrolling(this.createElement, wrapper, this.element, 'hscroll', this.enableRtl);
|
|
504
|
+
})
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
protected initialize(): void {
|
|
509
|
+
let wrapper: Element = this.getWrapper();
|
|
510
|
+
if (!wrapper) {
|
|
511
|
+
wrapper = this.createElement('div', { className: 'e-' + this.getModuleName() + '-wrapper' });
|
|
512
|
+
if (this.isMenu) {
|
|
513
|
+
this.element.parentElement.insertBefore(wrapper, this.element);
|
|
514
|
+
} else {
|
|
515
|
+
document.body.appendChild(wrapper);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (this.cssClass) {
|
|
519
|
+
addClass([wrapper], this.cssClass.split(' '));
|
|
520
|
+
}
|
|
521
|
+
if (this.enableRtl) {
|
|
522
|
+
wrapper.classList.add(RTL);
|
|
523
|
+
}
|
|
524
|
+
wrapper.appendChild(this.element);
|
|
525
|
+
if (this.isMenu && this.hamburgerMode) {
|
|
526
|
+
if (!this.target) {
|
|
527
|
+
this.createHeaderContainer(wrapper);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
this.defaultOption = this.showItemOnClick;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
private renderItems(): void {
|
|
534
|
+
if (!(this.items as objColl).length) {
|
|
535
|
+
const items: { [key: string]: Object; }[] = ListBase.createJsonFromElement(this.element, { fields: { child: 'items' } });
|
|
536
|
+
this.setProperties({ items: items }, true);
|
|
537
|
+
if (isBlazor() && !this.isMenu) {
|
|
538
|
+
this.element = this.removeChildElement(this.element);
|
|
539
|
+
} else {
|
|
540
|
+
this.element.innerHTML = '';
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const ul: Element = this.createItems(this.items as objColl);
|
|
544
|
+
append(Array.prototype.slice.call(ul.children), this.element);
|
|
545
|
+
this.element.classList.add('e-menu-parent');
|
|
546
|
+
if (this.isMenu) {
|
|
547
|
+
if (!this.hamburgerMode && this.element.classList.contains('e-vertical')) { this.setBlankIconStyle(this.element); }
|
|
548
|
+
if (this.enableScrolling) {
|
|
549
|
+
const wrapper: HTMLElement = this.getWrapper() as HTMLElement;
|
|
550
|
+
if (this.element.classList.contains('e-vertical')){
|
|
551
|
+
addScrolling(this.createElement, wrapper, this.element, 'vscroll', this.enableRtl);
|
|
552
|
+
} else {
|
|
553
|
+
addScrolling(this.createElement, wrapper, this.element, 'hscroll', this.enableRtl);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
protected wireEvents(): void {
|
|
560
|
+
const wrapper: HTMLElement = this.getWrapper() as HTMLElement;
|
|
561
|
+
if (this.target) {
|
|
562
|
+
let target: HTMLElement;
|
|
563
|
+
const targetElems: HTMLElement[] = selectAll(this.target);
|
|
564
|
+
for (let i: number = 0, len: number = targetElems.length; i < len; i++) {
|
|
565
|
+
target = targetElems[i];
|
|
566
|
+
if (this.isMenu) {
|
|
567
|
+
EventHandler.add(target, 'click', this.menuHeaderClickHandler, this);
|
|
568
|
+
} else {
|
|
569
|
+
if (Browser.isIos) {
|
|
570
|
+
new Touch(target, { tapHold: this.touchHandler.bind(this) });
|
|
571
|
+
} else {
|
|
572
|
+
EventHandler.add(target, 'contextmenu', this.cmenuHandler, this);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
this.targetElement = target;
|
|
577
|
+
if (!this.isMenu) {
|
|
578
|
+
EventHandler.add(this.targetElement, 'scroll', this.scrollHandler, this);
|
|
579
|
+
for (const parent of getScrollableParent(this.targetElement)) {
|
|
580
|
+
EventHandler.add(parent, 'scroll', this.scrollHandler, this);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (!Browser.isDevice) {
|
|
585
|
+
this.delegateMoverHandler = this.moverHandler.bind(this);
|
|
586
|
+
this.delegateMouseDownHandler = this.mouseDownHandler.bind(this);
|
|
587
|
+
EventHandler.add(this.isMenu ? document : wrapper, 'mouseover', this.delegateMoverHandler, this);
|
|
588
|
+
EventHandler.add(document, 'mousedown', this.delegateMouseDownHandler, this);
|
|
589
|
+
}
|
|
590
|
+
this.delegateClickHandler = this.clickHandler.bind(this);
|
|
591
|
+
EventHandler.add(document, 'click', this.delegateClickHandler, this);
|
|
592
|
+
this.wireKeyboardEvent(wrapper);
|
|
593
|
+
this.rippleFn = rippleEffect(wrapper, { selector: '.' + ITEM });
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
private wireKeyboardEvent(element: HTMLElement): void {
|
|
597
|
+
const keyConfigs: { [key: string]: string; } = {
|
|
598
|
+
downarrow: DOWNARROW,
|
|
599
|
+
uparrow: UPARROW,
|
|
600
|
+
enter: ENTER,
|
|
601
|
+
leftarrow: LEFTARROW,
|
|
602
|
+
rightarrow: RIGHTARROW,
|
|
603
|
+
escape: ESCAPE
|
|
604
|
+
};
|
|
605
|
+
if (this.isMenu) {
|
|
606
|
+
keyConfigs.home = HOME;
|
|
607
|
+
keyConfigs.end = END;
|
|
608
|
+
}
|
|
609
|
+
new KeyboardEvents(element, {
|
|
610
|
+
keyAction: this.keyBoardHandler.bind(this),
|
|
611
|
+
keyConfigs: keyConfigs
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
private mouseDownHandler(e: MouseEvent): void {
|
|
616
|
+
if (closest(e.target as Element, '.e-' + this.getModuleName() + '-wrapper') !== this.getWrapper()
|
|
617
|
+
&& (!closest(e.target as Element, '.e-' + this.getModuleName() + '-popup'))) {
|
|
618
|
+
this.closeMenu(this.isMenu ? null : this.navIdx.length, e);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
private keyBoardHandler(e: KeyboardEventArgs): void {
|
|
623
|
+
let actionName: string = '';
|
|
624
|
+
const trgt: Element = e.target as Element;
|
|
625
|
+
let actionNeeded: boolean = this.isMenu && !this.hamburgerMode && !this.element.classList.contains('e-vertical')
|
|
626
|
+
&& this.navIdx.length < 1;
|
|
627
|
+
e.preventDefault();
|
|
628
|
+
if (this.enableScrolling && e.keyCode === 13 && trgt.classList.contains('e-scroll-nav')) {
|
|
629
|
+
this.removeLIStateByClass([FOCUSED, SELECTED], [closest(trgt, '.e-' + this.getModuleName() + '-wrapper')]);
|
|
630
|
+
}
|
|
631
|
+
if (actionNeeded) {
|
|
632
|
+
switch (e.action) {
|
|
633
|
+
case RIGHTARROW:
|
|
634
|
+
actionName = RIGHTARROW;
|
|
635
|
+
e.action = DOWNARROW;
|
|
636
|
+
break;
|
|
637
|
+
case LEFTARROW:
|
|
638
|
+
actionName = LEFTARROW;
|
|
639
|
+
e.action = UPARROW;
|
|
640
|
+
break;
|
|
641
|
+
case DOWNARROW:
|
|
642
|
+
actionName = DOWNARROW;
|
|
643
|
+
e.action = RIGHTARROW;
|
|
644
|
+
break;
|
|
645
|
+
case UPARROW:
|
|
646
|
+
actionName = UPARROW;
|
|
647
|
+
e.action = '';
|
|
648
|
+
break;
|
|
649
|
+
}
|
|
650
|
+
} else if (this.enableRtl) {
|
|
651
|
+
switch (e.action) {
|
|
652
|
+
case LEFTARROW:
|
|
653
|
+
actionNeeded = true;
|
|
654
|
+
actionName = LEFTARROW;
|
|
655
|
+
e.action = RIGHTARROW;
|
|
656
|
+
break;
|
|
657
|
+
case RIGHTARROW:
|
|
658
|
+
actionNeeded = true;
|
|
659
|
+
actionName = RIGHTARROW;
|
|
660
|
+
e.action = LEFTARROW;
|
|
661
|
+
break;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
switch (e.action) {
|
|
665
|
+
case DOWNARROW:
|
|
666
|
+
case UPARROW:
|
|
667
|
+
case END:
|
|
668
|
+
case HOME:
|
|
669
|
+
this.upDownKeyHandler(e);
|
|
670
|
+
break;
|
|
671
|
+
case RIGHTARROW:
|
|
672
|
+
this.rightEnterKeyHandler(e);
|
|
673
|
+
break;
|
|
674
|
+
case LEFTARROW:
|
|
675
|
+
this.leftEscKeyHandler(e);
|
|
676
|
+
break;
|
|
677
|
+
case ENTER:
|
|
678
|
+
if (this.hamburgerMode && trgt.tagName === 'SPAN' && trgt.classList.contains('e-menu-icon')) {
|
|
679
|
+
this.menuHeaderClickHandler(e);
|
|
680
|
+
} else {
|
|
681
|
+
this.rightEnterKeyHandler(e);
|
|
682
|
+
}
|
|
683
|
+
break;
|
|
684
|
+
case ESCAPE:
|
|
685
|
+
this.leftEscKeyHandler(e);
|
|
686
|
+
break;
|
|
687
|
+
}
|
|
688
|
+
if (actionNeeded) {
|
|
689
|
+
e.action = actionName;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
private upDownKeyHandler(e: KeyboardEventArgs): void {
|
|
694
|
+
const cul: Element = this.getUlByNavIdx();
|
|
695
|
+
const defaultIdx: number = (e.action === DOWNARROW || e.action === HOME) ? 0 : cul.childElementCount - 1;
|
|
696
|
+
let fliIdx: number = defaultIdx;
|
|
697
|
+
const fli: Element = this.getLIByClass(cul, FOCUSED);
|
|
698
|
+
if (fli) {
|
|
699
|
+
if (e.action !== END && e.action !== HOME) {
|
|
700
|
+
fliIdx = this.getIdx(cul, fli);
|
|
701
|
+
}
|
|
702
|
+
fli.classList.remove(FOCUSED);
|
|
703
|
+
if (e.action !== END && e.action !== HOME) {
|
|
704
|
+
if (e.action === DOWNARROW){
|
|
705
|
+
fliIdx++;
|
|
706
|
+
} else {
|
|
707
|
+
fliIdx--;
|
|
708
|
+
}
|
|
709
|
+
if (fliIdx === (e.action === DOWNARROW ? cul.childElementCount : -1)) {
|
|
710
|
+
fliIdx = defaultIdx;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
const cli: Element = cul.children[fliIdx];
|
|
715
|
+
fliIdx = this.isValidLI(cli, fliIdx, e.action);
|
|
716
|
+
cul.children[fliIdx].classList.add(FOCUSED);
|
|
717
|
+
(cul.children[fliIdx] as HTMLElement).focus();
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
private isValidLI(cli: Element, index: number, action: string): number {
|
|
721
|
+
const cul: Element = this.getUlByNavIdx();
|
|
722
|
+
if (cli.classList.contains(SEPARATOR) || cli.classList.contains(DISABLED) || cli.classList.contains(HIDE)) {
|
|
723
|
+
if ((action === DOWNARROW) || (action === RIGHTARROW)) {
|
|
724
|
+
index++;
|
|
725
|
+
} else {
|
|
726
|
+
index--;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
cli = cul.children[index];
|
|
730
|
+
if (cli.classList.contains(SEPARATOR) || cli.classList.contains(DISABLED) || cli.classList.contains(HIDE)) {
|
|
731
|
+
index = this.isValidLI(cli, index, action);
|
|
732
|
+
}
|
|
733
|
+
return index;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
private getUlByNavIdx(navIdxLen: number = this.navIdx.length): HTMLElement {
|
|
737
|
+
if (this.isMenu) {
|
|
738
|
+
const popup: Element = [this.getWrapper()].concat([].slice.call(selectAll('.' + POPUP)))[navIdxLen];
|
|
739
|
+
return isNullOrUndefined(popup) ? null : select('.e-menu-parent', popup) as HTMLElement;
|
|
740
|
+
} else {
|
|
741
|
+
return this.getWrapper().children[navIdxLen] as HTMLElement;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
private rightEnterKeyHandler(e: KeyboardEventArgs): void {
|
|
746
|
+
let eventArgs: MenuEventArgs;
|
|
747
|
+
const cul: Element = this.getUlByNavIdx();
|
|
748
|
+
const fli: Element = this.getLIByClass(cul, FOCUSED);
|
|
749
|
+
if (fli) {
|
|
750
|
+
const fliIdx: number = this.getIdx(cul, fli);
|
|
751
|
+
const navIdx: number[] = this.navIdx.concat(fliIdx);
|
|
752
|
+
const item: MenuItemModel = this.getItem(navIdx);
|
|
753
|
+
if (item.items.length) {
|
|
754
|
+
this.navIdx.push(fliIdx);
|
|
755
|
+
this.keyType = 'right';
|
|
756
|
+
this.action = e.action;
|
|
757
|
+
this.openMenu(fli, item, -1, -1, e);
|
|
758
|
+
} else {
|
|
759
|
+
if (e.action === ENTER) {
|
|
760
|
+
if (this.isMenu && this.navIdx.length === 0) {
|
|
761
|
+
this.removeLIStateByClass([SELECTED], [this.getWrapper()]);
|
|
762
|
+
} else {
|
|
763
|
+
fli.classList.remove(FOCUSED);
|
|
764
|
+
}
|
|
765
|
+
fli.classList.add(SELECTED);
|
|
766
|
+
eventArgs = { element: fli as HTMLElement, item: item, event: e };
|
|
767
|
+
this.trigger('select', eventArgs);
|
|
768
|
+
this.closeMenu(null, e);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
private leftEscKeyHandler(e: KeyboardEventArgs): void {
|
|
775
|
+
if (this.navIdx.length) {
|
|
776
|
+
this.keyType = 'left';
|
|
777
|
+
this.closeMenu(this.navIdx.length, e);
|
|
778
|
+
} else {
|
|
779
|
+
if (e.action === ESCAPE) {
|
|
780
|
+
this.closeMenu(null, e);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
private scrollHandler(e: MouseEvent): void {
|
|
786
|
+
this.closeMenu(null, e);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
private touchHandler(e: TapEventArgs): void {
|
|
790
|
+
this.isTapHold = true;
|
|
791
|
+
this.cmenuHandler(e.originalEvent);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
private cmenuHandler(e: MouseEvent & (TouchEventArgs | MouseEventArgs)): void {
|
|
795
|
+
e.preventDefault();
|
|
796
|
+
this.isCMenu = true;
|
|
797
|
+
this.pageX = e.changedTouches ? e.changedTouches[0].pageX + 1 : e.pageX + 1;
|
|
798
|
+
this.pageY = e.changedTouches ? e.changedTouches[0].pageY + 1 : e.pageY + 1;
|
|
799
|
+
this.closeMenu(null, e);
|
|
800
|
+
if (this.isCMenu) {
|
|
801
|
+
if (this.canOpen(e.target as Element)) {
|
|
802
|
+
this.openMenu(null, null, this.pageY, this.pageX, e);
|
|
803
|
+
}
|
|
804
|
+
this.isCMenu = false;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// eslint:disable-next-line:max-func-body-length
|
|
809
|
+
protected closeMenu(ulIndex: number = 0, e: MouseEvent | KeyboardEvent = null, isIterated?: boolean): void {
|
|
810
|
+
if (this.isMenuVisible()) {
|
|
811
|
+
let sli: Element; let item: MenuItemModel; const wrapper: Element = this.getWrapper();
|
|
812
|
+
let beforeCloseArgs: BeforeOpenCloseMenuEventArgs; let items: MenuItemModel[]; const popups: Element[] = this.getPopups();
|
|
813
|
+
let isClose: boolean = false; const cnt: number = this.isMenu ? popups.length + 1 : wrapper.childElementCount;
|
|
814
|
+
const ul: HTMLElement = this.isMenu && cnt !== 1 ? select('.e-ul', popups[cnt - 2]) as HTMLElement
|
|
815
|
+
: selectAll('.e-menu-parent', wrapper)[cnt - 1] as HTMLElement;
|
|
816
|
+
if (this.isMenu && ul.classList.contains('e-menu')) {
|
|
817
|
+
sli = this.getLIByClass(ul, SELECTED);
|
|
818
|
+
if (sli) {
|
|
819
|
+
sli.classList.remove(SELECTED);
|
|
820
|
+
}
|
|
821
|
+
isClose = true;
|
|
822
|
+
}
|
|
823
|
+
if (!isClose) {
|
|
824
|
+
const liElem: Element = e && e.target && this.getLI(e.target as Element);
|
|
825
|
+
item = this.navIdx.length ? this.getItem(this.navIdx) : null; items = item ? item.items : this.items as objColl;
|
|
826
|
+
beforeCloseArgs = { element: ul, parentItem: item, items: items, event: e, cancel: false , isFocused: true };
|
|
827
|
+
this.trigger('beforeClose', beforeCloseArgs, (observedCloseArgs: BeforeOpenCloseMenuEventArgs) => {
|
|
828
|
+
let popupEle: HTMLElement; let closeArgs: OpenCloseMenuEventArgs; let popupId: string = '';
|
|
829
|
+
let popupObj: Popup; const isOpen: boolean = !observedCloseArgs.cancel;
|
|
830
|
+
if (isOpen || this.isCMenu) {
|
|
831
|
+
if (this.isMenu) {
|
|
832
|
+
popupEle = closest(ul, '.' + POPUP) as HTMLElement;
|
|
833
|
+
if (this.hamburgerMode) {
|
|
834
|
+
popupEle.parentElement.style.minHeight = '';
|
|
835
|
+
closest(ul, '.e-menu-item').setAttribute('aria-expanded', 'false');
|
|
836
|
+
}
|
|
837
|
+
this.unWireKeyboardEvent(popupEle);
|
|
838
|
+
destroyScroll(
|
|
839
|
+
getInstance(popupEle.children[0] as HTMLElement, VScroll) as VScroll, popupEle.children[0]);
|
|
840
|
+
popupObj = getInstance(popupEle, Popup) as Popup;
|
|
841
|
+
popupObj.hide(); popupId = popupEle.id; popupObj.destroy(); detach(popupEle);
|
|
842
|
+
} else {
|
|
843
|
+
this.toggleAnimation(ul, false);
|
|
844
|
+
}
|
|
845
|
+
closeArgs = { element: ul, parentItem: item, items: items };
|
|
846
|
+
this.trigger('onClose', closeArgs); this.navIdx.pop();
|
|
847
|
+
}
|
|
848
|
+
this.updateReactTemplate(); let trgtliId: string; let closedLi: Element; let trgtLi: Element;
|
|
849
|
+
const trgtpopUp: HTMLElement = this.getWrapper() && this.getUlByNavIdx();
|
|
850
|
+
if (this.isCMenu) {
|
|
851
|
+
if (this.canOpen(e.target as Element)) {
|
|
852
|
+
this.openMenu(null, null, this.pageY, this.pageX, e);
|
|
853
|
+
}
|
|
854
|
+
this.isCMenu = false;
|
|
855
|
+
}
|
|
856
|
+
if (this.isMenu && trgtpopUp && popupId.length) {
|
|
857
|
+
trgtliId = new RegExp('(.*)-ej2menu-' + this.element.id + '-popup').exec(popupId)[1];
|
|
858
|
+
closedLi = trgtpopUp.querySelector('[id="' + trgtliId + '"]');
|
|
859
|
+
trgtLi = (liElem && trgtpopUp.querySelector('[id="' + liElem.id + '"]'));
|
|
860
|
+
}
|
|
861
|
+
const submenus: NodeListOf<Element> = liElem && liElem.querySelectorAll('.e-menu-item');
|
|
862
|
+
if (isOpen && this.hamburgerMode && ulIndex && !(submenus.length)) {
|
|
863
|
+
this.afterCloseMenu(e as MouseEvent);
|
|
864
|
+
} else if (isOpen && !this.hamburgerMode && this.navIdx.length && closedLi && !trgtLi && this.keyType !== "left") {
|
|
865
|
+
let ele: HTMLElement = (e && (e.target as Element).classList.contains('e-vscroll'))
|
|
866
|
+
? closest(e.target as Element, '.e-menu-wrapper') as HTMLElement : null;
|
|
867
|
+
if (ele) {
|
|
868
|
+
ele = ele.querySelector('.e-menu-item');
|
|
869
|
+
if (this.showItemOnClick || (ele && this.getIndex(ele.id, true).length <= this.navIdx.length)) {
|
|
870
|
+
this.closeMenu(this.navIdx[this.navIdx.length - 1], e, true);
|
|
871
|
+
}
|
|
872
|
+
} else {
|
|
873
|
+
this.closeMenu(this.navIdx[this.navIdx.length - 1], e);
|
|
874
|
+
}
|
|
875
|
+
} else if (isOpen && !isIterated && !ulIndex && ((this.hamburgerMode && this.navIdx.length) ||
|
|
876
|
+
this.navIdx.length === 1)) {
|
|
877
|
+
this.closeMenu(null, e);
|
|
878
|
+
} else if (isOpen && isNullOrUndefined(ulIndex) && this.navIdx.length) {
|
|
879
|
+
this.closeMenu(null, e);
|
|
880
|
+
} else if (isOpen && !this.isMenu && !ulIndex && this.navIdx.length === 0 && !this.isMenusClosed) {
|
|
881
|
+
this.isMenusClosed = true;
|
|
882
|
+
this.closeMenu(0, e);
|
|
883
|
+
} else if (isOpen && this.isMenu && e && e.target &&
|
|
884
|
+
this.navIdx.length !== 0 && closest(e.target as Element, '.e-menu-parent.e-control')) {
|
|
885
|
+
this.closeMenu(0, e);
|
|
886
|
+
} else if(isOpen && !this.isMenu && selectAll('.e-menu-parent', wrapper)[ulIndex - 1] && e.which === 3) {
|
|
887
|
+
this.closeMenu(null, e);
|
|
888
|
+
} else {
|
|
889
|
+
if (isOpen && (this.keyType === 'right' || this.keyType === 'click')) {
|
|
890
|
+
this.afterCloseMenu(e as MouseEvent);
|
|
891
|
+
} else {
|
|
892
|
+
const cul: Element = this.getUlByNavIdx(); const sli: Element = this.getLIByClass(cul, SELECTED);
|
|
893
|
+
if (sli) {
|
|
894
|
+
sli.setAttribute('aria-expanded', 'false'); sli.classList.remove(SELECTED);
|
|
895
|
+
if (observedCloseArgs.isFocused && liElem || this.keyType === "left") {
|
|
896
|
+
sli.classList.add(FOCUSED); (sli as HTMLElement).focus();
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
if (!isOpen && this.hamburgerMode && liElem && liElem.getAttribute('aria-expanded') === 'false' &&
|
|
900
|
+
liElem.getAttribute('aria-haspopup') === 'true') {
|
|
901
|
+
if (closest(liElem as Element, '.e-menu-parent.e-control')) {
|
|
902
|
+
this.navIdx = [];
|
|
903
|
+
} else {
|
|
904
|
+
this.navIdx.pop();
|
|
905
|
+
}
|
|
906
|
+
this.navIdx.push(this.cliIdx); const item: MenuItemModel = this.getItem(this.navIdx);
|
|
907
|
+
liElem.setAttribute('aria-expanded', 'true'); this.openMenu(liElem, item, -1, -1, e);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
if (this.navIdx.length < 1) {
|
|
911
|
+
if (this.showSubMenuOn === 'Hover' || this.showSubMenuOn === 'Click') {
|
|
912
|
+
this.showItemOnClick = this.defaultOption; this.showSubMenuOn = 'Auto';
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
this.removeStateWrapper();
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
private updateReactTemplate(): void {
|
|
922
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
923
|
+
if ((this as any).isReact && this.template && this.navIdx.length === 0) {
|
|
924
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
925
|
+
const portals: any = (this as any).portals.splice(0, this.items.length);
|
|
926
|
+
this.clearTemplate(['template']);
|
|
927
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
928
|
+
(this as any).portals = portals; this.renderReactTemplates();
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
private getMenuItemModel(item: obj, level: number): MenuItemModel {
|
|
932
|
+
if (isNullOrUndefined(item)) { return null; }
|
|
933
|
+
if (isNullOrUndefined(level)) { level = 0; }
|
|
934
|
+
const fields: FieldsMap = this.getFields(level);
|
|
935
|
+
return <MenuItemModel>{ text: item[fields.text], id: item[fields.id], items: item[fields.child], separator: item[fields.separator],
|
|
936
|
+
iconCss: item[fields.iconCss], url: item[fields.url] };
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
private getPopups(): Element[] {
|
|
940
|
+
const popups: Element[] = [];
|
|
941
|
+
[].slice.call(document.querySelectorAll('.' + POPUP)).forEach((elem: Element) => {
|
|
942
|
+
if (!isNullOrUndefined(elem.querySelector('.' + ITEM)) && this.getIndex(elem.querySelector('.' + ITEM).id, true).length) {
|
|
943
|
+
popups.push(elem);
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
return popups;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
private isMenuVisible(): boolean {
|
|
950
|
+
return (this.navIdx.length > 0 || (this.element.classList.contains('e-contextmenu') && isVisible(this.element).valueOf()));
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
private canOpen(target: Element): boolean {
|
|
954
|
+
let canOpen: boolean = true;
|
|
955
|
+
if (this.filter) {
|
|
956
|
+
canOpen = false;
|
|
957
|
+
const filter: string[] = this.filter.split(' ');
|
|
958
|
+
for (let i: number = 0, len: number = filter.length; i < len; i++) {
|
|
959
|
+
if (closest(target, '.' + filter[i])) {
|
|
960
|
+
canOpen = true;
|
|
961
|
+
break;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return canOpen;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
protected openMenu(
|
|
969
|
+
li: Element, item: MenuItemModel | { [key: string]: Object }, top: number = 0, left: number = 0,
|
|
970
|
+
e: MouseEvent | KeyboardEvent = null, target: HTMLElement = this.targetElement): void {
|
|
971
|
+
const wrapper: Element = this.getWrapper();
|
|
972
|
+
this.lItem = li; const elemId: string = this.element.id !== '' ? this.element.id : 'menu';
|
|
973
|
+
this.isMenusClosed = false;
|
|
974
|
+
if (isNullOrUndefined(top)) {
|
|
975
|
+
top = -1;
|
|
976
|
+
}
|
|
977
|
+
if (isNullOrUndefined(left)) {
|
|
978
|
+
left = -1;
|
|
979
|
+
}
|
|
980
|
+
if (li) {
|
|
981
|
+
this.uList = this.createItems((<obj>item)[this.getField('children', this.navIdx.length - 1)] as objColl);
|
|
982
|
+
if (!this.isMenu && Browser.isDevice) {
|
|
983
|
+
(wrapper.lastChild as HTMLElement).style.display = 'none';
|
|
984
|
+
const data: { [key: string]: string } = {
|
|
985
|
+
text: (<obj>item)[this.getField('text')].toString(), iconCss: ICONS + ' e-previous'
|
|
986
|
+
};
|
|
987
|
+
const hdata: MenuItem = new MenuItem(this.items[0] as MenuItem, 'items', data, true);
|
|
988
|
+
const hli: Element = this.createItems([hdata] as MenuItemModel[]).children[0];
|
|
989
|
+
hli.classList.add(HEADER); this.uList.insertBefore(hli, this.uList.children[0]);
|
|
990
|
+
}
|
|
991
|
+
if (this.isMenu) {
|
|
992
|
+
this.popupWrapper = this.createElement('div', {
|
|
993
|
+
className: 'e-' + this.getModuleName() + '-wrapper ' + POPUP, id: li.id + '-ej2menu-' + elemId + '-popup' });
|
|
994
|
+
if (this.hamburgerMode) {
|
|
995
|
+
top = (li as HTMLElement).offsetHeight; li.appendChild(this.popupWrapper);
|
|
996
|
+
} else {
|
|
997
|
+
document.body.appendChild(this.popupWrapper);
|
|
998
|
+
}
|
|
999
|
+
this.isNestedOrVertical = this.element.classList.contains('e-vertical') || this.navIdx.length !== 1;
|
|
1000
|
+
this.popupObj = this.generatePopup(this.popupWrapper, this.uList, li as HTMLElement, this.isNestedOrVertical);
|
|
1001
|
+
if (this.template) { this.renderReactTemplates(); }
|
|
1002
|
+
if (this.hamburgerMode) {
|
|
1003
|
+
this.calculateIndentSize(this.uList, li);
|
|
1004
|
+
} else {
|
|
1005
|
+
if (this.cssClass) { addClass([this.popupWrapper], this.cssClass.split(' ')); }
|
|
1006
|
+
this.popupObj.hide();
|
|
1007
|
+
}
|
|
1008
|
+
if (!this.hamburgerMode && !this.showItemOnClick && this.hoverDelay) {
|
|
1009
|
+
window.clearInterval(this.timer);
|
|
1010
|
+
this.timer = window.setTimeout(
|
|
1011
|
+
() => { this.triggerBeforeOpen(li, this.uList, item, e, 0, 0, 'menu'); }, this.hoverDelay );
|
|
1012
|
+
} else {
|
|
1013
|
+
this.triggerBeforeOpen(li, this.uList, item, e, 0, 0, 'menu');
|
|
1014
|
+
}
|
|
1015
|
+
} else {
|
|
1016
|
+
this.uList.style.zIndex = this.element.style.zIndex; wrapper.appendChild(this.uList);
|
|
1017
|
+
if (!this.showItemOnClick && this.hoverDelay) {
|
|
1018
|
+
window.clearInterval(this.timer);
|
|
1019
|
+
this.timer = window.setTimeout(
|
|
1020
|
+
() => { this.triggerBeforeOpen(li, this.uList, item, e, top, left, 'none'); }, this.hoverDelay );
|
|
1021
|
+
} else {
|
|
1022
|
+
this.triggerBeforeOpen(li, this.uList, item, e, top, left, 'none');
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
} else {
|
|
1026
|
+
this.uList = this.element;
|
|
1027
|
+
this.uList.style.zIndex = getZindexPartial(target ? target : this.element).toString();
|
|
1028
|
+
this.triggerBeforeOpen(li, this.uList, item, e, top, left, 'none');
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
private calculateIndentSize(ul: HTMLElement, li: Element): void {
|
|
1033
|
+
const liStyle: CSSStyleDeclaration = getComputedStyle(li);
|
|
1034
|
+
let liIndent: number = parseInt(liStyle.textIndent, 10);
|
|
1035
|
+
if (this.navIdx.length < 2 && !li.classList.contains('e-blankicon')) {
|
|
1036
|
+
liIndent *= 2;
|
|
1037
|
+
} else {
|
|
1038
|
+
liIndent += (liIndent / 4);
|
|
1039
|
+
}
|
|
1040
|
+
ul.style.textIndent = liIndent + 'px';
|
|
1041
|
+
const blankIconElem: NodeList = ul.querySelectorAll('.e-blankicon');
|
|
1042
|
+
if (blankIconElem && blankIconElem.length) {
|
|
1043
|
+
const menuIconElem: HTMLElement = ul.querySelector('.e-menu-icon');
|
|
1044
|
+
const menuIconElemStyle: CSSStyleDeclaration = getComputedStyle(menuIconElem);
|
|
1045
|
+
const blankIconIndent: number = (parseInt(menuIconElemStyle.marginRight, 10) + menuIconElem.offsetWidth + liIndent);
|
|
1046
|
+
for (let i: number = 0; i < blankIconElem.length; i++) {
|
|
1047
|
+
(blankIconElem[i] as HTMLElement).style.textIndent = blankIconIndent + 'px';
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
private generatePopup(
|
|
1053
|
+
popupWrapper: HTMLElement, ul: HTMLElement, li: HTMLElement, isNestedOrVertical: boolean): Popup {
|
|
1054
|
+
const popupObj: Popup = new Popup(popupWrapper, {
|
|
1055
|
+
actionOnScroll: this.hamburgerMode ? 'none' : 'reposition',
|
|
1056
|
+
relateTo: li,
|
|
1057
|
+
collision: this.hamburgerMode ? { X: 'none', Y: 'none' } : { X: isNestedOrVertical ||
|
|
1058
|
+
this.enableRtl ? 'none' : 'flip', Y: 'fit' },
|
|
1059
|
+
position: (isNestedOrVertical && !this.hamburgerMode) ? { X: 'right', Y: 'top' } : { X: 'left', Y: 'bottom' },
|
|
1060
|
+
targetType: 'relative',
|
|
1061
|
+
enableRtl: this.enableRtl,
|
|
1062
|
+
content: ul,
|
|
1063
|
+
open: (): void => {
|
|
1064
|
+
const scrollEle: HTMLElement = select('.e-menu-vscroll', popupObj.element) as HTMLElement;
|
|
1065
|
+
if (scrollEle) {
|
|
1066
|
+
scrollEle.style.height = 'inherit';
|
|
1067
|
+
scrollEle.style.maxHeight = '';
|
|
1068
|
+
}
|
|
1069
|
+
const ul: HTMLElement = select('.e-ul', popupObj.element) as HTMLElement;
|
|
1070
|
+
popupObj.element.style.maxHeight = '';
|
|
1071
|
+
ul.focus();
|
|
1072
|
+
this.triggerOpen(ul);
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
return popupObj;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
protected createHeaderContainer(wrapper?: Element): void {
|
|
1079
|
+
wrapper = wrapper || this.getWrapper();
|
|
1080
|
+
const spanElem: HTMLElement = this.createElement('span', { className: 'e-' + this.getModuleName() + '-header' });
|
|
1081
|
+
const tempTitle: string = (this.enableHtmlSanitizer) ? SanitizeHtmlHelper.sanitize(this.title) : this.title;
|
|
1082
|
+
const spanTitle: HTMLElement = this.createElement('span', {
|
|
1083
|
+
className: 'e-' + this.getModuleName() + '-title', innerHTML: tempTitle });
|
|
1084
|
+
const spanIcon: HTMLElement = this.createElement('span', {
|
|
1085
|
+
className: 'e-icons e-' + this.getModuleName() + '-icon', attrs: { 'tabindex': '0' } });
|
|
1086
|
+
spanElem.appendChild(spanTitle);
|
|
1087
|
+
spanElem.appendChild(spanIcon);
|
|
1088
|
+
wrapper.insertBefore(spanElem, this.element);
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
protected openHamburgerMenu(e?: MouseEvent | KeyboardEvent) : void {
|
|
1092
|
+
if (this.hamburgerMode) {
|
|
1093
|
+
this.triggerBeforeOpen(null, this.element, null, e, 0, 0, 'hamburger');
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
protected closeHamburgerMenu(e?: MouseEvent | KeyboardEvent) : void {
|
|
1098
|
+
const beforeCloseArgs: BeforeOpenCloseMenuEventArgs = { element: this.element, parentItem: null, event: e,
|
|
1099
|
+
items: this.items, cancel: false };
|
|
1100
|
+
this.trigger('beforeClose', beforeCloseArgs, (observedHamburgerCloseArgs: BeforeOpenCloseMenuEventArgs) => {
|
|
1101
|
+
if (!observedHamburgerCloseArgs.cancel) {
|
|
1102
|
+
this.closeMenu(null, e);
|
|
1103
|
+
this.element.classList.add('e-hide-menu');
|
|
1104
|
+
this.trigger('onClose', { element: this.element, parentItem: null, items: this.items });
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
private callFit(element: HTMLElement, x: boolean, y: boolean, top: number, left: number): OffsetPosition {
|
|
1110
|
+
return fit(element, null, { X: x, Y: y }, { top: top, left: left });
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
private triggerBeforeOpen(
|
|
1114
|
+
li: Element, ul: HTMLElement, item: MenuItemModel, e: MouseEvent | KeyboardEvent,
|
|
1115
|
+
top: number, left: number, type: string): void {
|
|
1116
|
+
const items: MenuItemModel[] = li ? (<obj>item)[this.getField('children', this.navIdx.length - 1)] as objColl : this.items as objColl;
|
|
1117
|
+
const eventArgs: BeforeOpenCloseMenuEventArgs = {
|
|
1118
|
+
element: ul, items: items, parentItem: item, event: e, cancel: false, top: top, left: left, showSubMenuOn: 'Auto'};
|
|
1119
|
+
const menuType: string = type;
|
|
1120
|
+
this.trigger('beforeOpen', eventArgs, (observedOpenArgs: BeforeOpenCloseMenuEventArgs) => {
|
|
1121
|
+
switch (menuType) {
|
|
1122
|
+
case 'menu':
|
|
1123
|
+
if (!this.hamburgerMode) {
|
|
1124
|
+
if (observedOpenArgs.showSubMenuOn !== 'Auto') {
|
|
1125
|
+
this.showItemOnClick = !this.defaultOption; this.showSubMenuOn = observedOpenArgs.showSubMenuOn;
|
|
1126
|
+
}
|
|
1127
|
+
this.top = observedOpenArgs.top; this.left = observedOpenArgs.left;
|
|
1128
|
+
}
|
|
1129
|
+
this.popupWrapper.style.display = 'block';
|
|
1130
|
+
if (!this.hamburgerMode) {
|
|
1131
|
+
this.popupWrapper.style.maxHeight = this.popupWrapper.getBoundingClientRect().height + 'px';
|
|
1132
|
+
if (this.enableScrolling) {
|
|
1133
|
+
addScrolling(this.createElement, this.popupWrapper, this.uList, 'vscroll', this.enableRtl);
|
|
1134
|
+
}
|
|
1135
|
+
this.checkScrollOffset(e);
|
|
1136
|
+
}
|
|
1137
|
+
if (!this.hamburgerMode && !this.left && !this.top) {
|
|
1138
|
+
this.popupObj.refreshPosition(this.lItem as HTMLElement, true);
|
|
1139
|
+
this.left = parseInt(this.popupWrapper.style.left, 10); this.top = parseInt(this.popupWrapper.style.top, 10);
|
|
1140
|
+
if (this.enableRtl) {
|
|
1141
|
+
this.left =
|
|
1142
|
+
this.isNestedOrVertical ? this.left - this.popupWrapper.offsetWidth - this.lItem.parentElement.offsetWidth + 2
|
|
1143
|
+
: this.left - this.popupWrapper.offsetWidth + (this.lItem as HTMLElement).offsetWidth;
|
|
1144
|
+
}
|
|
1145
|
+
if (this.template && ((this as any).isReact || (this as any).isAngular)) {
|
|
1146
|
+
requestAnimationFrame(() => {
|
|
1147
|
+
this.collision();
|
|
1148
|
+
this.popupWrapper.style.display = '';
|
|
1149
|
+
})
|
|
1150
|
+
} else {
|
|
1151
|
+
this.collision();
|
|
1152
|
+
this.popupWrapper.style.display = '';
|
|
1153
|
+
}
|
|
1154
|
+
} else {
|
|
1155
|
+
this.popupObj.collision = { X: 'none', Y: 'none' };
|
|
1156
|
+
this.popupWrapper.style.display = '';
|
|
1157
|
+
}
|
|
1158
|
+
break;
|
|
1159
|
+
case 'none':
|
|
1160
|
+
this.top = observedOpenArgs.top; this.left = observedOpenArgs.left;
|
|
1161
|
+
break;
|
|
1162
|
+
case 'hamburger':
|
|
1163
|
+
if (!observedOpenArgs.cancel) {
|
|
1164
|
+
this.element.classList.remove('e-hide-menu'); this.triggerOpen(this.element);
|
|
1165
|
+
}
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
if (menuType !== 'hamburger') {
|
|
1169
|
+
if (observedOpenArgs.cancel) {
|
|
1170
|
+
if (this.isMenu) {
|
|
1171
|
+
this.popupObj.destroy(); detach(this.popupWrapper);
|
|
1172
|
+
} else if (ul.className.indexOf('e-ul') > -1) { detach(ul); }
|
|
1173
|
+
this.navIdx.pop();
|
|
1174
|
+
} else {
|
|
1175
|
+
if (this.isMenu) {
|
|
1176
|
+
if (this.hamburgerMode) {
|
|
1177
|
+
this.popupWrapper.style.top = this.top + 'px'; this.popupWrapper.style.left = 0 + 'px';
|
|
1178
|
+
this.toggleAnimation(this.popupWrapper);
|
|
1179
|
+
} else {
|
|
1180
|
+
this.setBlankIconStyle(this.popupWrapper);
|
|
1181
|
+
this.wireKeyboardEvent(this.popupWrapper); rippleEffect(this.popupWrapper, { selector: '.' + ITEM });
|
|
1182
|
+
this.popupWrapper.style.left = this.left + 'px';
|
|
1183
|
+
this.popupWrapper.style.top = this.top + 'px';
|
|
1184
|
+
const animationOptions: AnimationModel = this.animationSettings.effect !== 'None' ? {
|
|
1185
|
+
name: this.animationSettings.effect, duration: this.animationSettings.duration,
|
|
1186
|
+
timingFunction: this.animationSettings.easing
|
|
1187
|
+
} : null;
|
|
1188
|
+
this.popupObj.show(animationOptions, this.lItem as HTMLElement);
|
|
1189
|
+
}
|
|
1190
|
+
} else {
|
|
1191
|
+
this.setBlankIconStyle(this.uList);
|
|
1192
|
+
this.setPosition(this.lItem, this.uList, this.top, this.left); this.toggleAnimation(this.uList);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
if (this.keyType === 'right') {
|
|
1197
|
+
let cul: Element = this.getUlByNavIdx(); li.classList.remove(FOCUSED);
|
|
1198
|
+
if (this.isMenu && this.navIdx.length === 1) {
|
|
1199
|
+
this.removeLIStateByClass([SELECTED], [this.getWrapper()]);
|
|
1200
|
+
}
|
|
1201
|
+
li.classList.add(SELECTED);
|
|
1202
|
+
if (this.action === ENTER) {
|
|
1203
|
+
const eventArgs: MenuEventArgs = { element: li as HTMLElement, item: item, event: e };
|
|
1204
|
+
this.trigger('select', eventArgs);
|
|
1205
|
+
}
|
|
1206
|
+
(li as HTMLElement).focus(); cul = this.getUlByNavIdx();
|
|
1207
|
+
const index: number = this.isValidLI(cul.children[0], 0, this.action);
|
|
1208
|
+
cul.children[index].classList.add(FOCUSED); (cul.children[index] as HTMLElement).focus();
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
private collision(): void {
|
|
1214
|
+
let collide: string[];
|
|
1215
|
+
collide = isCollide(this.popupWrapper, null, this.left, this.top);
|
|
1216
|
+
if ((this.isNestedOrVertical || this.enableRtl) && (collide.indexOf('right') > -1
|
|
1217
|
+
|| collide.indexOf('left') > -1)) {
|
|
1218
|
+
this.popupObj.collision.X = 'none';
|
|
1219
|
+
const offWidth: number =
|
|
1220
|
+
(closest(this.lItem, '.e-' + this.getModuleName() + '-wrapper') as HTMLElement).offsetWidth;
|
|
1221
|
+
this.left =
|
|
1222
|
+
this.enableRtl ? calculatePosition(this.lItem, this.isNestedOrVertical ? 'right' : 'left', 'top').left
|
|
1223
|
+
: this.left - this.popupWrapper.offsetWidth - offWidth + 2;
|
|
1224
|
+
}
|
|
1225
|
+
collide = isCollide(this.popupWrapper, null, this.left, this.top);
|
|
1226
|
+
if (collide.indexOf('left') > -1 || collide.indexOf('right') > -1) {
|
|
1227
|
+
this.left = this.callFit(this.popupWrapper, true, false, this.top, this.left).left;
|
|
1228
|
+
}
|
|
1229
|
+
this.popupWrapper.style.left = this.left + 'px';
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
protected setBlankIconStyle(menu: HTMLElement): void {
|
|
1233
|
+
const blankIconList: HTMLElement[] = [].slice.call(menu.getElementsByClassName('e-blankicon'));
|
|
1234
|
+
if (!blankIconList.length) { return; }
|
|
1235
|
+
const iconLi: HTMLElement = menu.querySelector('.e-menu-item:not(.e-blankicon):not(.e-separator)') as HTMLElement;
|
|
1236
|
+
const icon: HTMLElement = iconLi.querySelector('.e-menu-icon') as HTMLElement;
|
|
1237
|
+
if (!icon) { return; }
|
|
1238
|
+
const cssProp: { padding: string, margin: string } = this.enableRtl ? { padding: 'paddingRight', margin: 'marginLeft' } :
|
|
1239
|
+
{ padding: 'paddingLeft', margin: 'marginRight' };
|
|
1240
|
+
const iconCssProps: CSSStyleDeclaration = getComputedStyle(icon);
|
|
1241
|
+
let iconSize: number = parseInt(iconCssProps.fontSize, 10);
|
|
1242
|
+
if (!!parseInt(iconCssProps.width, 10) && parseInt(iconCssProps.width, 10) > iconSize) {
|
|
1243
|
+
iconSize = parseInt(iconCssProps.width, 10);
|
|
1244
|
+
}
|
|
1245
|
+
// eslint:disable
|
|
1246
|
+
const size: string = `${iconSize + parseInt(
|
|
1247
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1248
|
+
(iconCssProps as any)[cssProp.margin], 10) + parseInt((getComputedStyle(iconLi) as any)[cssProp.padding], 10)}px`;
|
|
1249
|
+
blankIconList.forEach((li: HTMLElement): void => {
|
|
1250
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1251
|
+
(li.style as any)[cssProp.padding] = size;
|
|
1252
|
+
});
|
|
1253
|
+
// eslint:enable
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
private checkScrollOffset(e: MouseEvent | KeyboardEvent): void {
|
|
1257
|
+
const wrapper: Element = this.getWrapper();
|
|
1258
|
+
if (wrapper.children[0].classList.contains('e-menu-hscroll') && this.navIdx.length === 1) {
|
|
1259
|
+
const trgt: HTMLElement = isNullOrUndefined(e) ? this.element : closest(e.target as Element, '.' + ITEM) as HTMLElement;
|
|
1260
|
+
const offsetEle: HTMLElement = (select('.e-hscroll-bar', wrapper) as HTMLElement);
|
|
1261
|
+
if (offsetEle.scrollLeft > trgt.offsetLeft) {
|
|
1262
|
+
offsetEle.scrollLeft -= (offsetEle.scrollLeft - trgt.offsetLeft);
|
|
1263
|
+
}
|
|
1264
|
+
const offsetLeft: number = offsetEle.scrollLeft + offsetEle.offsetWidth;
|
|
1265
|
+
const offsetRight: number = trgt.offsetLeft + trgt.offsetWidth;
|
|
1266
|
+
if (offsetLeft < offsetRight) {
|
|
1267
|
+
offsetEle.scrollLeft += (offsetRight - offsetLeft);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
private setPosition(li: Element, ul: HTMLElement, top: number, left: number): void {
|
|
1273
|
+
const px: string = 'px';
|
|
1274
|
+
this.toggleVisiblity(ul);
|
|
1275
|
+
if (ul === this.element || (left > -1 && top > -1)) {
|
|
1276
|
+
let collide: string[] = isCollide(ul, null, left, top);
|
|
1277
|
+
if (collide.indexOf('right') > -1) {
|
|
1278
|
+
left = left - ul.offsetWidth;
|
|
1279
|
+
}
|
|
1280
|
+
if (collide.indexOf('bottom') > -1) {
|
|
1281
|
+
const offset: OffsetPosition = this.callFit(ul, false, true, top, left);
|
|
1282
|
+
top = offset.top - 20;
|
|
1283
|
+
if (top < 0) {
|
|
1284
|
+
const newTop: number = (pageYOffset + document.documentElement.clientHeight) - ul.getBoundingClientRect().height;
|
|
1285
|
+
if (newTop > -1) { top = newTop; }
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
collide = isCollide(ul, null, left, top);
|
|
1289
|
+
if (collide.indexOf('left') > -1) {
|
|
1290
|
+
const offset: OffsetPosition = this.callFit(ul, true, false, top, left);
|
|
1291
|
+
left = offset.left;
|
|
1292
|
+
}
|
|
1293
|
+
} else {
|
|
1294
|
+
if (Browser.isDevice) {
|
|
1295
|
+
top = Number(this.element.style.top.replace(px, ''));
|
|
1296
|
+
left = Number(this.element.style.left.replace(px, ''));
|
|
1297
|
+
} else {
|
|
1298
|
+
const x: string = this.enableRtl ? 'left' : 'right';
|
|
1299
|
+
let offset: OffsetPosition = calculatePosition(li, x, 'top');
|
|
1300
|
+
top = offset.top;
|
|
1301
|
+
left = offset.left;
|
|
1302
|
+
const collide: string[] = isCollide(ul, null, this.enableRtl ? left - ul.offsetWidth : left, top);
|
|
1303
|
+
const xCollision: boolean = collide.indexOf('left') > -1 || collide.indexOf('right') > -1;
|
|
1304
|
+
if (xCollision) {
|
|
1305
|
+
offset = calculatePosition(li, this.enableRtl ? 'right' : 'left', 'top');
|
|
1306
|
+
left = offset.left;
|
|
1307
|
+
}
|
|
1308
|
+
if (this.enableRtl || xCollision) {
|
|
1309
|
+
left = (this.enableRtl && xCollision) ? left : left - ul.offsetWidth;
|
|
1310
|
+
}
|
|
1311
|
+
if (collide.indexOf('bottom') > -1) {
|
|
1312
|
+
offset = this.callFit(ul, false, true, top, left);
|
|
1313
|
+
top = offset.top;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
this.toggleVisiblity(ul, false);
|
|
1318
|
+
ul.style.top = top + px;
|
|
1319
|
+
ul.style.left = left + px;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
private toggleVisiblity(ul: HTMLElement, isVisible: boolean = true): void {
|
|
1323
|
+
ul.style.visibility = isVisible ? 'hidden' : '';
|
|
1324
|
+
ul.style.display = isVisible ? 'block' : 'none';
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
private createItems(items: MenuItemModel[] | objColl): HTMLElement {
|
|
1328
|
+
const level: number = this.navIdx ? this.navIdx.length : 0;
|
|
1329
|
+
const fields: FieldsMap = this.getFields(level);
|
|
1330
|
+
const showIcon: boolean = this.hasField(items, this.getField('iconCss', level));
|
|
1331
|
+
const listBaseOptions: ListBaseOptions = {
|
|
1332
|
+
showIcon: showIcon,
|
|
1333
|
+
moduleName: 'menu',
|
|
1334
|
+
fields: fields,
|
|
1335
|
+
template: this.template,
|
|
1336
|
+
itemNavigable: true,
|
|
1337
|
+
itemCreating: (args: { curData: obj, fields: obj }): void => {
|
|
1338
|
+
if (!args.curData[(<obj>args.fields)[fields.id] as string]) {
|
|
1339
|
+
args.curData[(<obj>args.fields)[fields.id] as string] = getUniqueID('menuitem');
|
|
1340
|
+
}
|
|
1341
|
+
args.curData.htmlAttributes = {
|
|
1342
|
+
role: 'menuitem',
|
|
1343
|
+
tabindex: '-1'
|
|
1344
|
+
};
|
|
1345
|
+
if (this.isMenu && !(<obj>args.curData)[this.getField('separator', level)]) {
|
|
1346
|
+
(<obj>args.curData.htmlAttributes)['aria-label'] = (<obj>args.curData)[args.fields.text as string];
|
|
1347
|
+
}
|
|
1348
|
+
if (args.curData[(<obj>args.fields)[fields.iconCss] as string] === '') {
|
|
1349
|
+
args.curData[(<obj>args.fields)[fields.iconCss] as string] = null;
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
itemCreated: (args: { curData: MenuItemModel | obj, item: Element, fields: obj }): void => {
|
|
1353
|
+
if ((<obj>args.curData)[this.getField('separator', level)]) {
|
|
1354
|
+
args.item.classList.add(SEPARATOR);
|
|
1355
|
+
args.item.removeAttribute('role');
|
|
1356
|
+
}
|
|
1357
|
+
if (showIcon && !(<obj>args.curData)[args.fields.iconCss as string]
|
|
1358
|
+
&& !(<obj>args.curData)[this.getField('separator', level)]) {
|
|
1359
|
+
(args.item as HTMLElement).classList.add('e-blankicon');
|
|
1360
|
+
}
|
|
1361
|
+
if ((<obj>args.curData)[args.fields.child as string]
|
|
1362
|
+
&& (<objColl>(<obj>args.curData)[args.fields.child as string]).length) {
|
|
1363
|
+
const span: Element = this.createElement('span', { className: ICONS + ' ' + CARET });
|
|
1364
|
+
args.item.appendChild(span);
|
|
1365
|
+
args.item.setAttribute('aria-haspopup', 'true');
|
|
1366
|
+
args.item.setAttribute('aria-expanded', 'false');
|
|
1367
|
+
if (!this.isMenu) {
|
|
1368
|
+
args.item.removeAttribute('role');
|
|
1369
|
+
}
|
|
1370
|
+
(args.item as HTMLElement).classList.add('e-menu-caret-icon');
|
|
1371
|
+
}
|
|
1372
|
+
if (this.isMenu && this.template) {
|
|
1373
|
+
args.item.setAttribute('id', (<obj>args.curData)[args.fields.id as string].toString());
|
|
1374
|
+
args.item.removeAttribute('data-uid');
|
|
1375
|
+
if (args.item.classList.contains('e-level-1')) { args.item.classList.remove('e-level-1'); }
|
|
1376
|
+
if (args.item.classList.contains('e-has-child')) { args.item.classList.remove('e-has-child'); }
|
|
1377
|
+
}
|
|
1378
|
+
const eventArgs: MenuEventArgs = { item: args.curData, element: args.item as HTMLElement };
|
|
1379
|
+
this.trigger('beforeItemRender', eventArgs);
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
this.setProperties({'items': this.items}, true);
|
|
1383
|
+
if (this.isMenu) {
|
|
1384
|
+
listBaseOptions.templateID = this.element.id + TEMPLATE_PROPERTY;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
const ul: HTMLElement = ListBase.createList(
|
|
1388
|
+
this.createElement, items as objColl, listBaseOptions, !this.template, this);
|
|
1389
|
+
ul.setAttribute('tabindex', '0');
|
|
1390
|
+
if (this.isMenu) {
|
|
1391
|
+
ul.setAttribute('role', 'menu');
|
|
1392
|
+
}
|
|
1393
|
+
return ul;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
private moverHandler(e: MouseEvent): void {
|
|
1397
|
+
const trgt: Element = e.target as Element;
|
|
1398
|
+
this.liTrgt = trgt;
|
|
1399
|
+
const cli: Element = this.getLI(trgt);
|
|
1400
|
+
const wrapper: Element = cli ? closest(cli, '.e-' + this.getModuleName() + '-wrapper') : this.getWrapper();
|
|
1401
|
+
const hdrWrapper: Element = this.getWrapper(); const regex: RegExp = new RegExp('-ej2menu-(.*)-popup'); let ulId: string;
|
|
1402
|
+
let isDifferentElem: boolean = false;
|
|
1403
|
+
if (!wrapper) {
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
if (wrapper.id !== '') {
|
|
1407
|
+
ulId = regex.exec(wrapper.id)[1];
|
|
1408
|
+
} else {
|
|
1409
|
+
ulId = wrapper.querySelector('ul').id;
|
|
1410
|
+
}
|
|
1411
|
+
if (ulId !== this.element.id) {
|
|
1412
|
+
this.removeLIStateByClass([FOCUSED, SELECTED], [this.getWrapper()]);
|
|
1413
|
+
if (this.navIdx.length) {
|
|
1414
|
+
isDifferentElem = true;
|
|
1415
|
+
} else {
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
if (cli && closest(cli, '.e-' + this.getModuleName() + '-wrapper') && !isDifferentElem) {
|
|
1420
|
+
this.removeLIStateByClass([FOCUSED], this.isMenu ? [wrapper].concat(this.getPopups()) : [wrapper]);
|
|
1421
|
+
this.removeLIStateByClass([FOCUSED], this.isMenu ? [hdrWrapper].concat(this.getPopups()) : [hdrWrapper]);
|
|
1422
|
+
cli.classList.add(FOCUSED);
|
|
1423
|
+
if (!this.showItemOnClick) {
|
|
1424
|
+
this.clickHandler(e);
|
|
1425
|
+
}
|
|
1426
|
+
} else if (this.isMenu && this.showItemOnClick && !isDifferentElem) {
|
|
1427
|
+
this.removeLIStateByClass([FOCUSED], [wrapper].concat(this.getPopups()));
|
|
1428
|
+
}
|
|
1429
|
+
if (this.isMenu) {
|
|
1430
|
+
if (!this.showItemOnClick && (trgt.parentElement !== wrapper && !closest(trgt, '.e-' + this.getModuleName() + '-popup'))
|
|
1431
|
+
&& (!cli || (cli && !this.getIndex(cli.id, true).length)) && this.showSubMenuOn !== 'Hover') {
|
|
1432
|
+
this.removeLIStateByClass([FOCUSED], [wrapper]);
|
|
1433
|
+
if (this.navIdx.length) {
|
|
1434
|
+
this.isClosed = true;
|
|
1435
|
+
this.closeMenu(null, e);
|
|
1436
|
+
}
|
|
1437
|
+
} else if (isDifferentElem && !this.showItemOnClick) {
|
|
1438
|
+
if (this.navIdx.length) {
|
|
1439
|
+
this.isClosed = true;
|
|
1440
|
+
this.closeMenu(null, e);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
if (!this.isClosed) {
|
|
1444
|
+
this.removeStateWrapper();
|
|
1445
|
+
}
|
|
1446
|
+
this.isClosed = false;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
private removeStateWrapper(): void {
|
|
1450
|
+
if (this.liTrgt) {
|
|
1451
|
+
const wrapper: Element = closest(this.liTrgt, '.e-menu-vscroll');
|
|
1452
|
+
if (this.liTrgt.tagName === 'DIV' && wrapper) {
|
|
1453
|
+
this.removeLIStateByClass([FOCUSED, SELECTED], [wrapper]);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
private removeLIStateByClass(classList: string[], element: Element[]): void {
|
|
1459
|
+
let li: Element;
|
|
1460
|
+
for (let i: number = 0; i < element.length; i++) {
|
|
1461
|
+
classList.forEach((className: string) => {
|
|
1462
|
+
li = select('.' + className, element[i]);
|
|
1463
|
+
if (li) {
|
|
1464
|
+
li.classList.remove(className);
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
protected getField(propName: string, level: number = 0): string {
|
|
1471
|
+
const fieldName: object = (<obj>this.fields)[propName];
|
|
1472
|
+
return typeof fieldName === 'string' ? fieldName :
|
|
1473
|
+
(!(<obj>fieldName)[level] ? (fieldName as obj)[(<objColl>fieldName).length - 1].toString()
|
|
1474
|
+
: (<obj>fieldName)[level].toString());
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
private getFields(level: number = 0): FieldsMap {
|
|
1478
|
+
return {
|
|
1479
|
+
id: this.getField('itemId', level),
|
|
1480
|
+
iconCss: this.getField('iconCss', level),
|
|
1481
|
+
text: this.getField('text', level),
|
|
1482
|
+
url: this.getField('url', level),
|
|
1483
|
+
child: this.getField('children', level),
|
|
1484
|
+
separator: this.getField('separator', level)
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
private hasField(items: MenuItemModel[], field: string): boolean {
|
|
1489
|
+
for (let i: number = 0, len: number = items.length; i < len; i++) {
|
|
1490
|
+
if ((<obj>items[i])[field]) {
|
|
1491
|
+
return true;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
return false;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
private menuHeaderClickHandler(e: MouseEvent | KeyboardEvent): void {
|
|
1498
|
+
if (closest(e.target as Element, '.e-menu-wrapper').querySelector('ul.e-menu-parent').id !== this.element.id) {
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
if (this.element.classList.contains('e-hide-menu')) {
|
|
1502
|
+
this.openHamburgerMenu(e);
|
|
1503
|
+
} else {
|
|
1504
|
+
this.closeHamburgerMenu(e);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
private clickHandler(e: MouseEvent): void {
|
|
1509
|
+
if (this.isTapHold) {
|
|
1510
|
+
this.isTapHold = false;
|
|
1511
|
+
} else {
|
|
1512
|
+
const wrapper: Element = this.getWrapper();
|
|
1513
|
+
const trgt: Element = e.target as Element;
|
|
1514
|
+
const cli: Element = this.cli = this.getLI(trgt);
|
|
1515
|
+
const regex: RegExp = new RegExp('-ej2menu-(.*)-popup');
|
|
1516
|
+
const cliWrapper: Element = cli ? closest(cli, '.e-' + this.getModuleName() + '-wrapper') : null;
|
|
1517
|
+
const isInstLI: boolean = cli && cliWrapper && (this.isMenu ? this.getIndex(cli.id, true).length > 0
|
|
1518
|
+
: wrapper.firstElementChild.id === cliWrapper.firstElementChild.id);
|
|
1519
|
+
if (Browser.isDevice && this.isMenu) {
|
|
1520
|
+
this.removeLIStateByClass([FOCUSED], [wrapper].concat(this.getPopups()));
|
|
1521
|
+
this.mouseDownHandler(e);
|
|
1522
|
+
}
|
|
1523
|
+
if (cli && cliWrapper && this.isMenu) {
|
|
1524
|
+
const cliWrapperId: string = cliWrapper.id ? regex.exec(cliWrapper.id)[1] : cliWrapper.querySelector('.e-menu-parent').id;
|
|
1525
|
+
if (this.element.id !== cliWrapperId) {
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
if (isInstLI && e.type === 'click' && !cli.classList.contains(HEADER)) {
|
|
1530
|
+
this.setLISelected(cli);
|
|
1531
|
+
const navIdx: number[] = this.getIndex(cli.id, true);
|
|
1532
|
+
const item: MenuItemModel = this.getItem(navIdx);
|
|
1533
|
+
const eventArgs: MenuEventArgs = { element: cli as HTMLElement, item: item, event: e };
|
|
1534
|
+
this.trigger('select', eventArgs);
|
|
1535
|
+
}
|
|
1536
|
+
if (isInstLI && (e.type === 'mouseover' || Browser.isDevice || this.showItemOnClick)) {
|
|
1537
|
+
let ul: HTMLElement;
|
|
1538
|
+
if (cli.classList.contains(HEADER)) {
|
|
1539
|
+
ul = wrapper.children[this.navIdx.length - 1] as HTMLElement;
|
|
1540
|
+
this.toggleAnimation(ul);
|
|
1541
|
+
const sli: Element = this.getLIByClass(ul, SELECTED);
|
|
1542
|
+
if (sli) {
|
|
1543
|
+
sli.classList.remove(SELECTED);
|
|
1544
|
+
}
|
|
1545
|
+
detach(cli.parentNode);
|
|
1546
|
+
this.navIdx.pop();
|
|
1547
|
+
} else {
|
|
1548
|
+
if (!cli.classList.contains(SEPARATOR)) {
|
|
1549
|
+
this.showSubMenu = true;
|
|
1550
|
+
const cul: Element = cli.parentNode as Element;
|
|
1551
|
+
this.cliIdx = this.getIdx(cul, cli);
|
|
1552
|
+
if (this.isMenu || !Browser.isDevice) {
|
|
1553
|
+
const culIdx: number = this.isMenu ? Array.prototype.indexOf.call(
|
|
1554
|
+
[wrapper].concat(this.getPopups()), closest(cul, '.' + 'e-' + this.getModuleName() + '-wrapper'))
|
|
1555
|
+
: this.getIdx(wrapper, cul);
|
|
1556
|
+
if (this.navIdx[culIdx] === this.cliIdx) {
|
|
1557
|
+
this.showSubMenu = false;
|
|
1558
|
+
}
|
|
1559
|
+
if (culIdx !== this.navIdx.length && (e.type !== 'mouseover' || this.showSubMenu)) {
|
|
1560
|
+
const sli: Element = this.getLIByClass(cul, SELECTED);
|
|
1561
|
+
if (sli) {
|
|
1562
|
+
sli.classList.remove(SELECTED);
|
|
1563
|
+
}
|
|
1564
|
+
this.isClosed = true;
|
|
1565
|
+
this.keyType = 'click';
|
|
1566
|
+
if (this.showItemOnClick) { this.setLISelected(cli); }
|
|
1567
|
+
this.closeMenu(culIdx + 1, e);
|
|
1568
|
+
if (this.showItemOnClick) { this.setLISelected(cli); }
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
if (!this.isClosed) {
|
|
1572
|
+
this.afterCloseMenu(e);
|
|
1573
|
+
}
|
|
1574
|
+
this.isClosed = false;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
} else {
|
|
1578
|
+
if (this.isMenu && trgt.tagName === 'DIV' && this.navIdx.length && closest(trgt, '.e-menu-vscroll')) {
|
|
1579
|
+
const popupEle: Element = closest(trgt, '.' + POPUP);
|
|
1580
|
+
const cIdx: number = Array.prototype.indexOf.call(this.getPopups(), popupEle) + 1;
|
|
1581
|
+
if (cIdx < this.navIdx.length) {
|
|
1582
|
+
this.closeMenu(cIdx + 1, e);
|
|
1583
|
+
if (popupEle) { this.removeLIStateByClass([FOCUSED, SELECTED], [popupEle]); }
|
|
1584
|
+
}
|
|
1585
|
+
} else if (this.isMenu && this.hamburgerMode && trgt.tagName === 'SPAN'
|
|
1586
|
+
&& trgt.classList.contains('e-menu-icon')) {
|
|
1587
|
+
this.menuHeaderClickHandler(e);
|
|
1588
|
+
} else {
|
|
1589
|
+
if (trgt.tagName !== 'UL' || (this.isMenu ? trgt.parentElement.classList.contains('e-menu-wrapper') &&
|
|
1590
|
+
!this.getIndex(trgt.querySelector('.' + ITEM).id, true).length : trgt.parentElement !== wrapper)) {
|
|
1591
|
+
if (!cli) {
|
|
1592
|
+
this.removeLIStateByClass([SELECTED], [wrapper]);
|
|
1593
|
+
}
|
|
1594
|
+
if (!cli || !cli.querySelector('.' + CARET)) {
|
|
1595
|
+
if (!Browser.isIos || (Browser.isIos && !e.ctrlKey)) {
|
|
1596
|
+
this.closeMenu(null, e);
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
private afterCloseMenu(e: MouseEvent): void {
|
|
1605
|
+
let isHeader: Element;
|
|
1606
|
+
if (this.showSubMenu) {
|
|
1607
|
+
if (this.showItemOnClick && this.navIdx.length === 0) {
|
|
1608
|
+
isHeader = closest(e.target as Element, '.e-menu-parent.e-control');
|
|
1609
|
+
} else {
|
|
1610
|
+
isHeader = closest(this.element, '.e-menu-parent.e-control');
|
|
1611
|
+
}
|
|
1612
|
+
const idx: number[] = this.navIdx.concat(this.cliIdx);
|
|
1613
|
+
const item: MenuItemModel = this.getItem(idx);
|
|
1614
|
+
if (item && (<objColl>(<obj>item)[this.getField('children', idx.length - 1)]) &&
|
|
1615
|
+
(<objColl>(<obj>item)[this.getField('children', idx.length - 1)]).length) {
|
|
1616
|
+
if (e.type === 'mouseover' || (Browser.isDevice && this.isMenu)) {
|
|
1617
|
+
this.setLISelected(this.cli);
|
|
1618
|
+
}
|
|
1619
|
+
if ((!this.hamburgerMode && isHeader) || (this.hamburgerMode && this.cli.getAttribute('aria-expanded') === 'false')) {
|
|
1620
|
+
this.cli.setAttribute('aria-expanded', 'true');
|
|
1621
|
+
this.navIdx.push(this.cliIdx);
|
|
1622
|
+
this.openMenu(this.cli, item, null, null, e);
|
|
1623
|
+
}
|
|
1624
|
+
} else {
|
|
1625
|
+
if (e.type !== 'mouseover') {
|
|
1626
|
+
this.closeMenu(null, e);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
if (!isHeader) {
|
|
1630
|
+
const cul: Element = this.getUlByNavIdx();
|
|
1631
|
+
const sli: Element = this.getLIByClass(cul, SELECTED);
|
|
1632
|
+
if (sli) {
|
|
1633
|
+
sli.setAttribute('aria-expanded', 'false');
|
|
1634
|
+
sli.classList.remove(SELECTED);
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
this.keyType = '';
|
|
1639
|
+
}
|
|
1640
|
+
private setLISelected(li: Element): void {
|
|
1641
|
+
const sli: Element = this.getLIByClass(li.parentElement, SELECTED);
|
|
1642
|
+
if (sli) {
|
|
1643
|
+
sli.classList.remove(SELECTED);
|
|
1644
|
+
}
|
|
1645
|
+
if (!this.isMenu) {
|
|
1646
|
+
li.classList.remove(FOCUSED);
|
|
1647
|
+
}
|
|
1648
|
+
li.classList.add(SELECTED);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
private getLIByClass(ul: Element, classname: string): Element {
|
|
1652
|
+
for (let i: number = 0, len: number = ul.children.length; i < len; i++) {
|
|
1653
|
+
if (ul.children[i].classList.contains(classname)) {
|
|
1654
|
+
return ul.children[i];
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
return null;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
/**
|
|
1661
|
+
* This method is used to get the index of the menu item in the Menu based on the argument.
|
|
1662
|
+
*
|
|
1663
|
+
* @param {MenuItem | string} item - item be passed to get the index | id to be passed to get the item index.
|
|
1664
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
1665
|
+
* @returns {void}
|
|
1666
|
+
*/
|
|
1667
|
+
public getItemIndex(item: MenuItem | string, isUniqueId?: boolean): number[] {
|
|
1668
|
+
let idx: string;
|
|
1669
|
+
if (typeof item === 'string') {
|
|
1670
|
+
idx = item;
|
|
1671
|
+
} else {
|
|
1672
|
+
idx = item.id;
|
|
1673
|
+
}
|
|
1674
|
+
const isText: boolean = (isUniqueId === false) ? false : true;
|
|
1675
|
+
const navIdx: number[] = this.getIndex(idx, isText);
|
|
1676
|
+
return navIdx;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
/**
|
|
1680
|
+
* This method is used to set the menu item in the Menu based on the argument.
|
|
1681
|
+
*
|
|
1682
|
+
* @param {MenuItem} item - item need to be updated.
|
|
1683
|
+
* @param {string} id - id / text to be passed to update the item.
|
|
1684
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
1685
|
+
* @returns {void}
|
|
1686
|
+
*/
|
|
1687
|
+
public setItem(item: MenuItem, id?: string, isUniqueId?: boolean): void {
|
|
1688
|
+
let idx: string;
|
|
1689
|
+
if (isUniqueId) {
|
|
1690
|
+
idx = id ? id : item.id;
|
|
1691
|
+
} else {
|
|
1692
|
+
idx = id ? id : item.text;
|
|
1693
|
+
}
|
|
1694
|
+
const navIdx: number[] = this.getIndex(idx, isUniqueId);
|
|
1695
|
+
const newItem: MenuItemModel = this.getItem(navIdx);
|
|
1696
|
+
newItem.iconCss = item.iconCss || newItem.iconCss;
|
|
1697
|
+
newItem.text = item.text || newItem.text;
|
|
1698
|
+
newItem.url = item.url || newItem.url;
|
|
1699
|
+
newItem.separator = item.separator || newItem.separator;
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
private getItem(navIdx: number[]): MenuItemModel {
|
|
1703
|
+
navIdx = navIdx.slice();
|
|
1704
|
+
const idx: number = navIdx.pop();
|
|
1705
|
+
const items: MenuItemModel[] = this.getItems(navIdx);
|
|
1706
|
+
return items[idx];
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
private getItems(navIdx: number[]): objColl {
|
|
1710
|
+
let items: objColl = this.items as objColl;
|
|
1711
|
+
for (let i: number = 0; i < navIdx.length; i++) {
|
|
1712
|
+
items = (<obj>items[navIdx[i]])[this.getField('children', i)] as objColl;
|
|
1713
|
+
}
|
|
1714
|
+
return items;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
private setItems(newItems: objColl, navIdx: number[]): void {
|
|
1718
|
+
const items: objColl = this.getItems(navIdx);
|
|
1719
|
+
items.splice(0, items.length);
|
|
1720
|
+
for (let i: number = 0; i < newItems.length; i++) {
|
|
1721
|
+
items.splice(i, 0, newItems[i]);
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
private getIdx(ul: Element, li: Element, skipHdr: boolean = true): number {
|
|
1726
|
+
let idx: number = Array.prototype.indexOf.call(ul.children, li);
|
|
1727
|
+
if (skipHdr && ul.children[0].classList.contains(HEADER)) {
|
|
1728
|
+
idx--;
|
|
1729
|
+
}
|
|
1730
|
+
return idx;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
private getLI(elem: Element): Element {
|
|
1734
|
+
if (elem.tagName === 'LI' && elem.classList.contains('e-menu-item')) {
|
|
1735
|
+
return elem;
|
|
1736
|
+
}
|
|
1737
|
+
return closest(elem, 'li.e-menu-item');
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
private updateItemsByNavIdx(): void {
|
|
1741
|
+
let items: MenuItemModel[] = this.items; let count: number = 0;
|
|
1742
|
+
for (let index: number = 0; index < this.navIdx.length; index++) {
|
|
1743
|
+
items = items[index].items;
|
|
1744
|
+
if (!items) { break; }
|
|
1745
|
+
count++;
|
|
1746
|
+
const ul: HTMLUListElement = <HTMLUListElement>this.getUlByNavIdx(count);
|
|
1747
|
+
if (!ul) { break; }
|
|
1748
|
+
this.updateItem(ul, items);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
private removeChildElement(elem: HTMLUListElement): HTMLUListElement {
|
|
1753
|
+
while (elem.firstElementChild) {
|
|
1754
|
+
elem.removeChild(elem.firstElementChild);
|
|
1755
|
+
}
|
|
1756
|
+
return elem;
|
|
1757
|
+
}
|
|
1758
|
+
/**
|
|
1759
|
+
* Called internally if any of the property value changed.
|
|
1760
|
+
*
|
|
1761
|
+
* @private
|
|
1762
|
+
* @param {MenuBaseModel} newProp - Specifies the new properties
|
|
1763
|
+
* @param {MenuBaseModel} oldProp - Specifies the old properties
|
|
1764
|
+
* @returns {void}
|
|
1765
|
+
*/
|
|
1766
|
+
public onPropertyChanged(newProp: MenuBaseModel, oldProp: MenuBaseModel): void {
|
|
1767
|
+
const wrapper: HTMLElement = this.getWrapper() as HTMLElement;
|
|
1768
|
+
for (const prop of Object.keys(newProp)) {
|
|
1769
|
+
switch (prop) {
|
|
1770
|
+
case 'cssClass':
|
|
1771
|
+
if (oldProp.cssClass) {
|
|
1772
|
+
removeClass([wrapper], oldProp.cssClass.split(' '));
|
|
1773
|
+
}
|
|
1774
|
+
if (newProp.cssClass) {
|
|
1775
|
+
addClass([wrapper], newProp.cssClass.split(' '));
|
|
1776
|
+
}
|
|
1777
|
+
break;
|
|
1778
|
+
case 'enableRtl':
|
|
1779
|
+
wrapper.classList.toggle(RTL);
|
|
1780
|
+
break;
|
|
1781
|
+
case 'showItemOnClick':
|
|
1782
|
+
this.unWireEvents();
|
|
1783
|
+
this.showItemOnClick = newProp.showItemOnClick;
|
|
1784
|
+
this.wireEvents();
|
|
1785
|
+
break;
|
|
1786
|
+
case 'enableScrolling':
|
|
1787
|
+
if (newProp.enableScrolling) {
|
|
1788
|
+
let ul: HTMLElement;
|
|
1789
|
+
if (this.element.classList.contains('e-vertical')) {
|
|
1790
|
+
addScrolling(this.createElement, wrapper, this.element, 'vscroll', this.enableRtl);
|
|
1791
|
+
} else {
|
|
1792
|
+
addScrolling(this.createElement, wrapper, this.element, 'hscroll', this.enableRtl);
|
|
1793
|
+
}
|
|
1794
|
+
(this.getPopups() as HTMLElement[]).forEach((wrapper: HTMLElement) => {
|
|
1795
|
+
ul = select('.e-ul', wrapper) as HTMLElement;
|
|
1796
|
+
addScrolling(this.createElement, wrapper, ul, 'vscroll', this.enableRtl);
|
|
1797
|
+
});
|
|
1798
|
+
} else {
|
|
1799
|
+
let ul: HTMLElement = wrapper.children[0] as HTMLElement;
|
|
1800
|
+
if (this.element.classList.contains('e-vertical')) {
|
|
1801
|
+
destroyScroll(getInstance(ul, VScroll) as VScroll, ul);
|
|
1802
|
+
} else {
|
|
1803
|
+
destroyScroll(getInstance(ul, HScroll) as HScroll, ul);
|
|
1804
|
+
}
|
|
1805
|
+
wrapper.style.overflow = '';
|
|
1806
|
+
wrapper.appendChild(this.element);
|
|
1807
|
+
(this.getPopups() as HTMLElement[]).forEach((wrapper: HTMLElement) => {
|
|
1808
|
+
ul = wrapper.children[0] as HTMLElement;
|
|
1809
|
+
destroyScroll(getInstance(ul, VScroll) as VScroll, ul);
|
|
1810
|
+
wrapper.style.overflow = '';
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
break;
|
|
1814
|
+
case 'items': {
|
|
1815
|
+
let idx: number;
|
|
1816
|
+
let navIdx: number[];
|
|
1817
|
+
let item: MenuItemModel[];
|
|
1818
|
+
if (!Object.keys(oldProp.items).length) {
|
|
1819
|
+
this.updateItem(this.element, this.items);
|
|
1820
|
+
if (!this.hamburgerMode) {
|
|
1821
|
+
for (let i: number = 1, count: number = wrapper.childElementCount; i < count; i++) {
|
|
1822
|
+
detach(wrapper.lastElementChild);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
this.navIdx = [];
|
|
1826
|
+
} else {
|
|
1827
|
+
const keys: string[] = Object.keys(newProp.items);
|
|
1828
|
+
for (let i: number = 0; i < keys.length; i++) {
|
|
1829
|
+
navIdx = this.getChangedItemIndex(newProp, [], Number(keys[i]));
|
|
1830
|
+
if (navIdx.length <= this.getWrapper().children.length) {
|
|
1831
|
+
idx = navIdx.pop();
|
|
1832
|
+
item = this.getItems(navIdx);
|
|
1833
|
+
this.insertAfter([item[idx]], item[idx].text);
|
|
1834
|
+
this.removeItem(item, navIdx, idx);
|
|
1835
|
+
this.setItems(item as objColl, navIdx);
|
|
1836
|
+
}
|
|
1837
|
+
navIdx.length = 0;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
break;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
private updateItem(ul: HTMLUListElement, items: MenuItemModel[]): void {
|
|
1847
|
+
if (isBlazor() && !this.isMenu) {
|
|
1848
|
+
ul = this.removeChildElement(ul);
|
|
1849
|
+
} else {
|
|
1850
|
+
ul.innerHTML = '';
|
|
1851
|
+
}
|
|
1852
|
+
const lis: HTMLElement[] = [].slice.call(this.createItems(items).children);
|
|
1853
|
+
lis.forEach((li: HTMLElement): void => {
|
|
1854
|
+
ul.appendChild(li);
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
private getChangedItemIndex(newProp: MenuBaseModel, index: number[], idx: number): number[] {
|
|
1859
|
+
index.push(idx);
|
|
1860
|
+
const key: string = Object.keys((<objColl>newProp.items)[idx]).pop();
|
|
1861
|
+
if (key === 'items') {
|
|
1862
|
+
const item: MenuItemModel = (<objColl>newProp.items)[idx];
|
|
1863
|
+
const popStr: string = Object.keys(item.items).pop();
|
|
1864
|
+
if (popStr) {
|
|
1865
|
+
this.getChangedItemIndex(item, index, Number(popStr));
|
|
1866
|
+
}
|
|
1867
|
+
} else {
|
|
1868
|
+
if (key === 'isParentArray' && index.length > 1) {
|
|
1869
|
+
index.pop();
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
return index;
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
private removeItem(item: MenuItemModel[], navIdx: number[], idx: number): void {
|
|
1876
|
+
item.splice(idx, 1);
|
|
1877
|
+
const uls: HTMLCollection = this.getWrapper().children;
|
|
1878
|
+
const uls_length: number = this.hamburgerMode? 1 : uls.length;
|
|
1879
|
+
if (navIdx.length < uls_length) {
|
|
1880
|
+
detach(uls[this.hamburgerMode ? 1 : navIdx.length].children[idx]);
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
/**
|
|
1885
|
+
* Used to unwire the bind events.
|
|
1886
|
+
*
|
|
1887
|
+
* @private
|
|
1888
|
+
* @param {string} targetSelctor - Specifies the target selector
|
|
1889
|
+
* @returns {void}
|
|
1890
|
+
*/
|
|
1891
|
+
protected unWireEvents(targetSelctor: string = this.target): void {
|
|
1892
|
+
const wrapper: HTMLElement = this.getWrapper() as HTMLElement;
|
|
1893
|
+
if (targetSelctor) {
|
|
1894
|
+
let target: HTMLElement;
|
|
1895
|
+
let touchModule: Touch;
|
|
1896
|
+
const targetElems: HTMLElement[] = selectAll(targetSelctor);
|
|
1897
|
+
for (let i: number = 0, len: number = targetElems.length; i < len; i++) {
|
|
1898
|
+
target = targetElems[i];
|
|
1899
|
+
if (this.isMenu) {
|
|
1900
|
+
EventHandler.remove(target, 'click', this.menuHeaderClickHandler);
|
|
1901
|
+
} else {
|
|
1902
|
+
if (Browser.isIos) {
|
|
1903
|
+
touchModule = getInstance(target, Touch) as Touch;
|
|
1904
|
+
if (touchModule) {
|
|
1905
|
+
touchModule.destroy();
|
|
1906
|
+
}
|
|
1907
|
+
} else {
|
|
1908
|
+
EventHandler.remove(target, 'contextmenu', this.cmenuHandler);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
if (!this.isMenu) {
|
|
1913
|
+
EventHandler.remove(this.targetElement, 'scroll', this.scrollHandler);
|
|
1914
|
+
for (const parent of getScrollableParent(this.targetElement)) {
|
|
1915
|
+
EventHandler.remove(parent, 'scroll', this.scrollHandler);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
if (!Browser.isDevice) {
|
|
1920
|
+
EventHandler.remove(this.isMenu ? document : wrapper, 'mouseover', this.delegateMoverHandler);
|
|
1921
|
+
EventHandler.remove(document, 'mousedown', this.delegateMouseDownHandler);
|
|
1922
|
+
}
|
|
1923
|
+
EventHandler.remove(document, 'click', this.delegateClickHandler);
|
|
1924
|
+
this.unWireKeyboardEvent(wrapper);
|
|
1925
|
+
this.rippleFn();
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
private unWireKeyboardEvent(element: HTMLElement): void {
|
|
1929
|
+
const keyboardModule: KeyboardEvents = getInstance(element, KeyboardEvents) as KeyboardEvents;
|
|
1930
|
+
if (keyboardModule) {
|
|
1931
|
+
keyboardModule.destroy();
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
private toggleAnimation(ul: HTMLElement, isMenuOpen: boolean = true): void {
|
|
1936
|
+
let pUlHeight: number;
|
|
1937
|
+
let pElement: HTMLElement;
|
|
1938
|
+
if (this.animationSettings.effect === 'None' || !isMenuOpen) {
|
|
1939
|
+
this.end(ul, isMenuOpen);
|
|
1940
|
+
} else {
|
|
1941
|
+
this.animation.animate(ul, {
|
|
1942
|
+
name: this.animationSettings.effect,
|
|
1943
|
+
duration: this.animationSettings.duration,
|
|
1944
|
+
timingFunction: this.animationSettings.easing,
|
|
1945
|
+
begin: (options: AnimationOptions) => {
|
|
1946
|
+
if (this.hamburgerMode) {
|
|
1947
|
+
pElement = options.element.parentElement;
|
|
1948
|
+
options.element.style.position = 'absolute';
|
|
1949
|
+
pUlHeight = pElement.offsetHeight;
|
|
1950
|
+
options.element.style.maxHeight = options.element.offsetHeight + 'px';
|
|
1951
|
+
pElement.style.maxHeight = '';
|
|
1952
|
+
} else {
|
|
1953
|
+
options.element.style.display = 'block';
|
|
1954
|
+
options.element.style.maxHeight = options.element.getBoundingClientRect().height + 'px';
|
|
1955
|
+
}
|
|
1956
|
+
},
|
|
1957
|
+
progress: (options: AnimationOptions) => {
|
|
1958
|
+
if (this.hamburgerMode) {
|
|
1959
|
+
pElement.style.minHeight = (pUlHeight + options.element.offsetHeight) + 'px';
|
|
1960
|
+
}
|
|
1961
|
+
},
|
|
1962
|
+
end: (options: AnimationOptions) => {
|
|
1963
|
+
if (this.hamburgerMode) {
|
|
1964
|
+
options.element.style.position = '';
|
|
1965
|
+
options.element.style.maxHeight = '';
|
|
1966
|
+
pElement.style.minHeight = '';
|
|
1967
|
+
options.element.style.top = 0 + 'px';
|
|
1968
|
+
(options.element.children[0] as HTMLElement).focus();
|
|
1969
|
+
this.triggerOpen(options.element.children[0] as HTMLElement);
|
|
1970
|
+
} else {
|
|
1971
|
+
this.end(options.element, isMenuOpen);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
private triggerOpen(ul: HTMLElement): void {
|
|
1979
|
+
const item: MenuItemModel = this.navIdx.length ? this.getItem(this.navIdx) : null;
|
|
1980
|
+
const eventArgs: OpenCloseMenuEventArgs = {
|
|
1981
|
+
element: ul, parentItem: item, items: item ? item.items : this.items as objColl
|
|
1982
|
+
};
|
|
1983
|
+
this.trigger('onOpen', eventArgs);
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
private end(ul: HTMLElement, isMenuOpen: boolean): void {
|
|
1987
|
+
if (isMenuOpen) {
|
|
1988
|
+
ul.style.display = 'block';
|
|
1989
|
+
ul.style.maxHeight = '';
|
|
1990
|
+
this.triggerOpen(ul);
|
|
1991
|
+
if (ul.querySelector('.' + FOCUSED)) {
|
|
1992
|
+
(ul.querySelector('.' + FOCUSED) as HTMLElement).focus();
|
|
1993
|
+
} else {
|
|
1994
|
+
const ele: HTMLElement = this.getWrapper().children[this.getIdx(this.getWrapper(), ul) - 1] as HTMLElement;
|
|
1995
|
+
if (ele) {
|
|
1996
|
+
(ele.querySelector('.' + SELECTED) as HTMLElement).focus();
|
|
1997
|
+
} else {
|
|
1998
|
+
this.element.focus();
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
} else {
|
|
2002
|
+
if (ul === this.element) {
|
|
2003
|
+
const fli: Element = this.getLIByClass(this.element, FOCUSED);
|
|
2004
|
+
if (fli) {
|
|
2005
|
+
fli.classList.remove(FOCUSED);
|
|
2006
|
+
}
|
|
2007
|
+
const sli: Element = this.getLIByClass(this.element, SELECTED);
|
|
2008
|
+
if (sli) {
|
|
2009
|
+
sli.classList.remove(SELECTED);
|
|
2010
|
+
}
|
|
2011
|
+
ul.style.display = 'none';
|
|
2012
|
+
} else {
|
|
2013
|
+
detach(ul);
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
/**
|
|
2019
|
+
* Get the properties to be maintained in the persisted state.
|
|
2020
|
+
*
|
|
2021
|
+
* @returns {string} - Persist data
|
|
2022
|
+
*/
|
|
2023
|
+
protected getPersistData(): string {
|
|
2024
|
+
return '';
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
/**
|
|
2028
|
+
* Get wrapper element.
|
|
2029
|
+
*
|
|
2030
|
+
* @returns {Element} - Wrapper element
|
|
2031
|
+
* @private
|
|
2032
|
+
*/
|
|
2033
|
+
private getWrapper(): Element {
|
|
2034
|
+
return closest(this.element, '.e-' + this.getModuleName() + '-wrapper');
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
protected getIndex(
|
|
2038
|
+
data: string, isUniqueId?: boolean, items: MenuItemModel[] | { [key: string]: Object }[] = this.items as objColl,
|
|
2039
|
+
nIndex: number[] = [], isCallBack: boolean = false, level: number = 0): number[] {
|
|
2040
|
+
let item: MenuItemModel | obj;
|
|
2041
|
+
level = isCallBack ? level + 1 : 0;
|
|
2042
|
+
for (let i: number = 0, len: number = items.length; i < len; i++) {
|
|
2043
|
+
item = items[i];
|
|
2044
|
+
if ((isUniqueId ? (<obj>item)[this.getField('itemId', level)] : (<obj>item)[this.getField('text', level)]) === data) {
|
|
2045
|
+
nIndex.push(i);
|
|
2046
|
+
break;
|
|
2047
|
+
} else if ((<objColl>(<obj>item)[this.getField('children', level)])
|
|
2048
|
+
&& (<objColl>(<obj>item)[this.getField('children', level)]).length) {
|
|
2049
|
+
nIndex = this.getIndex(data, isUniqueId, (<objColl>(<obj>item)[this.getField('children', level)]), nIndex, true, level);
|
|
2050
|
+
if (nIndex[nIndex.length - 1] === -1) {
|
|
2051
|
+
if (i !== len - 1) {
|
|
2052
|
+
nIndex.pop();
|
|
2053
|
+
}
|
|
2054
|
+
} else {
|
|
2055
|
+
nIndex.unshift(i);
|
|
2056
|
+
break;
|
|
2057
|
+
}
|
|
2058
|
+
} else {
|
|
2059
|
+
if (i === len - 1) {
|
|
2060
|
+
nIndex.push(-1);
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
return (!isCallBack && nIndex[0] === -1) ? [] : nIndex;
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
/**
|
|
2068
|
+
* This method is used to enable or disable the menu items in the Menu based on the items and enable argument.
|
|
2069
|
+
*
|
|
2070
|
+
* @param {string[]} items - Text items that needs to be enabled/disabled.
|
|
2071
|
+
* @param {boolean} enable - Set `true`/`false` to enable/disable the list items.
|
|
2072
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
2073
|
+
* @returns {void}
|
|
2074
|
+
*/
|
|
2075
|
+
public enableItems(items: string[], enable: boolean = true, isUniqueId?: boolean): void {
|
|
2076
|
+
let ul: Element;
|
|
2077
|
+
let idx: number;
|
|
2078
|
+
let navIdx: number[];
|
|
2079
|
+
const disabled: string = DISABLED; let skipItem: boolean;
|
|
2080
|
+
for (let i: number = 0; i < items.length; i++) {
|
|
2081
|
+
navIdx = this.getIndex(items[i], isUniqueId);
|
|
2082
|
+
if (this.navIdx.length) {
|
|
2083
|
+
if (navIdx.length !== 1) {
|
|
2084
|
+
skipItem = false;
|
|
2085
|
+
for (let i: number = 0, len: number = navIdx.length - 1; i < len; i++) {
|
|
2086
|
+
if (navIdx[i] !== this.navIdx[i]) {
|
|
2087
|
+
skipItem = true; break;
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
if (skipItem) { continue; }
|
|
2091
|
+
}
|
|
2092
|
+
} else {
|
|
2093
|
+
if (navIdx.length !== 1) { continue; }
|
|
2094
|
+
}
|
|
2095
|
+
idx = navIdx.pop();
|
|
2096
|
+
ul = this.getUlByNavIdx(navIdx.length);
|
|
2097
|
+
if (ul) {
|
|
2098
|
+
if (enable) {
|
|
2099
|
+
if (this.isMenu) {
|
|
2100
|
+
ul.children[idx].classList.remove(disabled);
|
|
2101
|
+
ul.children[idx].removeAttribute('aria-disabled');
|
|
2102
|
+
} else {
|
|
2103
|
+
if (Browser.isDevice && !ul.classList.contains('e-contextmenu')) {
|
|
2104
|
+
ul.children[idx + 1].classList.remove(disabled);
|
|
2105
|
+
} else {
|
|
2106
|
+
ul.children[idx].classList.remove(disabled);
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
} else {
|
|
2110
|
+
if (this.isMenu) {
|
|
2111
|
+
ul.children[idx].classList.add(disabled);
|
|
2112
|
+
ul.children[idx].setAttribute('aria-disabled', 'true');
|
|
2113
|
+
} else {
|
|
2114
|
+
if (Browser.isDevice && !ul.classList.contains('e-contextmenu')) {
|
|
2115
|
+
ul.children[idx + 1].classList.add(disabled);
|
|
2116
|
+
} else {
|
|
2117
|
+
ul.children[idx].classList.add(disabled);
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
/**
|
|
2126
|
+
* This method is used to show the menu items in the Menu based on the items text.
|
|
2127
|
+
*
|
|
2128
|
+
* @param {string[]} items - Text items that needs to be shown.
|
|
2129
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
2130
|
+
* @returns {void}
|
|
2131
|
+
*/
|
|
2132
|
+
public showItems(items: string[], isUniqueId?: boolean): void {
|
|
2133
|
+
this.showHideItems(items, false, isUniqueId);
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
/**
|
|
2137
|
+
* This method is used to hide the menu items in the Menu based on the items text.
|
|
2138
|
+
*
|
|
2139
|
+
* @param {string[]} items - Text items that needs to be hidden.
|
|
2140
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
2141
|
+
* @returns {void}
|
|
2142
|
+
*/
|
|
2143
|
+
public hideItems(items: string[], isUniqueId?: boolean): void {
|
|
2144
|
+
this.showHideItems(items, true, isUniqueId);
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
private showHideItems(items: string[], ishide: boolean, isUniqueId?: boolean): void {
|
|
2148
|
+
let ul: Element;
|
|
2149
|
+
let index: number;
|
|
2150
|
+
let navIdx: number[];
|
|
2151
|
+
for (let i: number = 0; i < items.length; i++) {
|
|
2152
|
+
navIdx = this.getIndex(items[i], isUniqueId);
|
|
2153
|
+
index = navIdx.pop();
|
|
2154
|
+
ul = this.getUlByNavIdx(navIdx.length);
|
|
2155
|
+
if (ul) {
|
|
2156
|
+
if (ishide) {
|
|
2157
|
+
if (Browser.isDevice && !ul.classList.contains('e-contextmenu')) {
|
|
2158
|
+
ul.children[index + 1].classList.add(HIDE);
|
|
2159
|
+
} else {
|
|
2160
|
+
ul.children[index].classList.add(HIDE);
|
|
2161
|
+
}
|
|
2162
|
+
} else {
|
|
2163
|
+
if (Browser.isDevice && !ul.classList.contains('e-contextmenu')) {
|
|
2164
|
+
ul.children[index + 1].classList.remove(HIDE);
|
|
2165
|
+
} else {
|
|
2166
|
+
ul.children[index].classList.remove(HIDE);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
/**
|
|
2174
|
+
* It is used to remove the menu items from the Menu based on the items text.
|
|
2175
|
+
*
|
|
2176
|
+
* @param {string[]} items Text items that needs to be removed.
|
|
2177
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
2178
|
+
* @returns {void}
|
|
2179
|
+
*/
|
|
2180
|
+
public removeItems(items: string[], isUniqueId?: boolean): void {
|
|
2181
|
+
let idx: number;
|
|
2182
|
+
let navIdx: number[];
|
|
2183
|
+
let iitems: MenuItemModel[];
|
|
2184
|
+
for (let i: number = 0; i < items.length; i++) {
|
|
2185
|
+
navIdx = this.getIndex(items[i], isUniqueId);
|
|
2186
|
+
idx = navIdx.pop();
|
|
2187
|
+
iitems = this.getItems(navIdx);
|
|
2188
|
+
this.removeItem(iitems, navIdx, idx);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
/**
|
|
2193
|
+
* It is used to insert the menu items after the specified menu item text.
|
|
2194
|
+
*
|
|
2195
|
+
* @param {MenuItemModel[]} items - Items that needs to be inserted.
|
|
2196
|
+
* @param {string} text - Text item after that the element to be inserted.
|
|
2197
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
2198
|
+
* @returns {void}
|
|
2199
|
+
*/
|
|
2200
|
+
public insertAfter(items: MenuItemModel[], text: string, isUniqueId?: boolean): void {
|
|
2201
|
+
this.insertItems(items, text, isUniqueId);
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
/**
|
|
2205
|
+
* It is used to insert the menu items before the specified menu item text.
|
|
2206
|
+
*
|
|
2207
|
+
* @param {MenuItemModel[]} items - Items that needs to be inserted.
|
|
2208
|
+
* @param {string} text - Text item before that the element to be inserted.
|
|
2209
|
+
* @param {boolean} isUniqueId - Set `true` if it is a unique id.
|
|
2210
|
+
* @returns {void}
|
|
2211
|
+
*/
|
|
2212
|
+
public insertBefore(items: MenuItemModel[], text: string, isUniqueId?: boolean): void {
|
|
2213
|
+
this.insertItems(items, text, isUniqueId, false);
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
private insertItems(items: MenuItemModel[] | objColl, text: string, isUniqueId?: boolean, isAfter: boolean = true): void {
|
|
2217
|
+
let li: Element;
|
|
2218
|
+
let idx: number;
|
|
2219
|
+
let navIdx: number[];
|
|
2220
|
+
let iitems: MenuItemModel[];
|
|
2221
|
+
let menuitem: MenuItem;
|
|
2222
|
+
for (let i: number = 0; i < items.length; i++) {
|
|
2223
|
+
navIdx = this.getIndex(text, isUniqueId);
|
|
2224
|
+
idx = navIdx.pop();
|
|
2225
|
+
iitems = this.getItems(navIdx);
|
|
2226
|
+
menuitem = new MenuItem(iitems[0] as MenuItem, 'items', items[i], true);
|
|
2227
|
+
iitems.splice(isAfter ? idx + 1 : idx, 0, menuitem);
|
|
2228
|
+
const uls: Element[] = this.isMenu ? [this.getWrapper()].concat(this.getPopups()) : [].slice.call(this.getWrapper().children);
|
|
2229
|
+
if (navIdx.length < uls.length) {
|
|
2230
|
+
idx = isAfter ? idx + 1 : idx;
|
|
2231
|
+
li = this.createItems(iitems).children[idx];
|
|
2232
|
+
const ul: Element = this.isMenu ? select('.e-menu-parent', uls[navIdx.length]) : uls[navIdx.length];
|
|
2233
|
+
ul.insertBefore(li, ul.children[idx]);
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
private removeAttributes(): void {
|
|
2239
|
+
['top', 'left', 'display', 'z-index'].forEach((key: string) => {
|
|
2240
|
+
this.element.style.removeProperty(key);
|
|
2241
|
+
});
|
|
2242
|
+
['role', 'tabindex', 'class', 'style'].forEach((key: string) => {
|
|
2243
|
+
if (key === 'class' && this.element.classList.contains('e-menu-parent')) {
|
|
2244
|
+
this.element.classList.remove('e-menu-parent');
|
|
2245
|
+
}
|
|
2246
|
+
if (['class', 'style'].indexOf(key) === -1 || !this.element.getAttribute(key)) {
|
|
2247
|
+
this.element.removeAttribute(key);
|
|
2248
|
+
}
|
|
2249
|
+
if (this.isMenu && key === 'class' && this.element.classList.contains('e-vertical')) {
|
|
2250
|
+
this.element.classList.remove('e-vertical');
|
|
2251
|
+
}
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
/**
|
|
2256
|
+
* Destroys the widget.
|
|
2257
|
+
*
|
|
2258
|
+
* @returns {void}
|
|
2259
|
+
*/
|
|
2260
|
+
|
|
2261
|
+
public destroy(): void {
|
|
2262
|
+
const wrapper: Element = this.getWrapper();
|
|
2263
|
+
if (wrapper) {
|
|
2264
|
+
this.unWireEvents();
|
|
2265
|
+
if (!this.isMenu) {
|
|
2266
|
+
this.clonedElement.style.display = '';
|
|
2267
|
+
if (this.clonedElement.tagName === 'EJS-CONTEXTMENU') {
|
|
2268
|
+
addClass([this.clonedElement], ['e-control', 'e-lib', 'e-' + this.getModuleName()]);
|
|
2269
|
+
this.element = this.clonedElement as HTMLUListElement;
|
|
2270
|
+
} else {
|
|
2271
|
+
if (this.refreshing && this.clonedElement.childElementCount && this.clonedElement.children[0].tagName === 'LI') {
|
|
2272
|
+
this.setProperties({ 'items': [] }, true);
|
|
2273
|
+
}
|
|
2274
|
+
if (document.getElementById(this.clonedElement.id)) {
|
|
2275
|
+
const refEle: Element = this.clonedElement.nextElementSibling;
|
|
2276
|
+
if (refEle && refEle !== wrapper) {
|
|
2277
|
+
this.clonedElement.parentElement.insertBefore(this.element, refEle);
|
|
2278
|
+
} else {
|
|
2279
|
+
this.clonedElement.parentElement.appendChild(this.element);
|
|
2280
|
+
}
|
|
2281
|
+
if (isBlazor() && !this.isMenu) {
|
|
2282
|
+
this.element = this.removeChildElement(this.element);
|
|
2283
|
+
} else {
|
|
2284
|
+
this.element.innerHTML = '';
|
|
2285
|
+
}
|
|
2286
|
+
append([].slice.call(this.clonedElement.children), this.element);
|
|
2287
|
+
detach(this.clonedElement);
|
|
2288
|
+
this.removeAttributes();
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
this.clonedElement = null;
|
|
2292
|
+
} else {
|
|
2293
|
+
this.closeMenu();
|
|
2294
|
+
if (isBlazor() && !this.isMenu) {
|
|
2295
|
+
this.element = this.removeChildElement(this.element);
|
|
2296
|
+
} else {
|
|
2297
|
+
this.element.innerHTML = '';
|
|
2298
|
+
}
|
|
2299
|
+
this.removeAttributes();
|
|
2300
|
+
wrapper.parentNode.insertBefore(this.element, wrapper);
|
|
2301
|
+
this.clonedElement = null;
|
|
2302
|
+
}
|
|
2303
|
+
if (this.isMenu && this.clonedElement) {
|
|
2304
|
+
detach(this.element);
|
|
2305
|
+
(wrapper as HTMLElement).style.display = '';
|
|
2306
|
+
wrapper.classList.remove('e-' + this.getModuleName() + '-wrapper');
|
|
2307
|
+
wrapper.removeAttribute('data-ripple');
|
|
2308
|
+
} else {
|
|
2309
|
+
detach(wrapper);
|
|
2310
|
+
}
|
|
2311
|
+
super.destroy();
|
|
2312
|
+
if (this.template) { this.clearTemplate(['template']); }
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
interface FieldsMap {
|
|
2318
|
+
id: string;
|
|
2319
|
+
iconCss: string;
|
|
2320
|
+
text: string;
|
|
2321
|
+
url: string;
|
|
2322
|
+
child: string;
|
|
2323
|
+
separator: string;
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
/**
|
|
2327
|
+
* Interface for before item render/select event.
|
|
2328
|
+
*/
|
|
2329
|
+
export interface MenuEventArgs extends BaseEventArgs {
|
|
2330
|
+
element: HTMLElement;
|
|
2331
|
+
item: MenuItemModel;
|
|
2332
|
+
event?: Event;
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
/**
|
|
2336
|
+
* Interface for before open/close event.
|
|
2337
|
+
*/
|
|
2338
|
+
export interface BeforeOpenCloseMenuEventArgs extends BaseEventArgs {
|
|
2339
|
+
element: HTMLElement;
|
|
2340
|
+
items: MenuItemModel[];
|
|
2341
|
+
parentItem: MenuItemModel;
|
|
2342
|
+
event: Event;
|
|
2343
|
+
cancel: boolean;
|
|
2344
|
+
top?: number;
|
|
2345
|
+
left?: number;
|
|
2346
|
+
isFocused?: boolean;
|
|
2347
|
+
showSubMenuOn?: MenuOpenType;
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
/**
|
|
2351
|
+
* Interface for open/close event.
|
|
2352
|
+
*/
|
|
2353
|
+
export interface OpenCloseMenuEventArgs extends BaseEventArgs {
|
|
2354
|
+
element: HTMLElement;
|
|
2355
|
+
items: MenuItemModel[] | { [key: string]: Object }[];
|
|
2356
|
+
parentItem: MenuItemModel;
|
|
2357
|
+
}
|