@syncfusion/ej2-navigations 30.2.7 → 31.1.17
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/dist/ej2-navigations.min.js +1 -1
- package/dist/ej2-navigations.umd.min.js +1 -1
- package/dist/ej2-navigations.umd.min.js.map +1 -1
- package/dist/es6/ej2-navigations.es2015.js.map +1 -1
- package/dist/es6/ej2-navigations.es5.js.map +1 -1
- package/dist/global/ej2-navigations.min.js +1 -1
- package/dist/global/ej2-navigations.min.js.map +1 -1
- package/dist/global/index.d.ts +1 -1
- package/dist/ts/accordion/accordion-model.d.ts +285 -0
- package/dist/ts/accordion/accordion.d.ts +458 -0
- package/dist/ts/accordion/accordion.ts +1580 -0
- package/dist/ts/accordion/index.d.ts +5 -0
- package/dist/ts/accordion/index.ts +5 -0
- package/dist/ts/appbar/appbar-model.d.ts +76 -0
- package/dist/ts/appbar/appbar.d.ts +115 -0
- package/dist/ts/appbar/appbar.ts +281 -0
- package/dist/ts/appbar/index.d.ts +3 -0
- package/dist/ts/appbar/index.ts +3 -0
- package/dist/ts/breadcrumb/breadcrumb-model.d.ts +170 -0
- package/dist/ts/breadcrumb/breadcrumb.d.ts +297 -0
- package/dist/ts/breadcrumb/breadcrumb.ts +959 -0
- package/dist/ts/breadcrumb/index.d.ts +5 -0
- package/dist/ts/breadcrumb/index.ts +5 -0
- package/dist/ts/carousel/carousel-model.d.ts +282 -0
- package/dist/ts/carousel/carousel.d.ts +439 -0
- package/dist/ts/carousel/carousel.ts +1633 -0
- package/dist/ts/carousel/index.d.ts +3 -0
- package/dist/ts/carousel/index.ts +3 -0
- package/dist/ts/common/h-scroll-model.d.ts +16 -0
- package/dist/ts/common/h-scroll.d.ts +105 -0
- package/dist/ts/common/h-scroll.ts +481 -0
- package/dist/ts/common/index.d.ts +9 -0
- package/dist/ts/common/index.ts +10 -0
- package/dist/ts/common/menu-base-model.d.ts +308 -0
- package/dist/ts/common/menu-base.d.ts +558 -0
- package/dist/ts/common/menu-base.ts +2736 -0
- package/dist/ts/common/menu-scroll.d.ts +29 -0
- package/dist/ts/common/menu-scroll.ts +105 -0
- package/dist/ts/common/v-scroll-model.d.ts +16 -0
- package/dist/ts/common/v-scroll.d.ts +106 -0
- package/dist/ts/common/v-scroll.ts +454 -0
- package/dist/ts/context-menu/context-menu-model.d.ts +47 -0
- package/dist/ts/context-menu/context-menu.d.ts +102 -0
- package/dist/ts/context-menu/context-menu.ts +165 -0
- package/dist/ts/context-menu/index.d.ts +5 -0
- package/dist/ts/context-menu/index.ts +5 -0
- package/dist/ts/index.d.ts +16 -0
- package/dist/ts/index.ts +16 -0
- package/dist/ts/menu/index.d.ts +5 -0
- package/dist/ts/menu/index.ts +5 -0
- package/dist/ts/menu/menu-model.d.ts +70 -0
- package/dist/ts/menu/menu.d.ts +127 -0
- package/dist/ts/menu/menu.ts +313 -0
- package/dist/ts/sidebar/index.d.ts +5 -0
- package/dist/ts/sidebar/index.ts +5 -0
- package/dist/ts/sidebar/sidebar-model.d.ts +200 -0
- package/dist/ts/sidebar/sidebar.d.ts +336 -0
- package/dist/ts/sidebar/sidebar.ts +907 -0
- package/dist/ts/stepper/index.d.ts +3 -0
- package/dist/ts/stepper/index.ts +3 -0
- package/dist/ts/stepper/stepper-model.d.ts +159 -0
- package/dist/ts/stepper/stepper.d.ts +381 -0
- package/dist/ts/stepper/stepper.ts +1350 -0
- package/dist/ts/stepper-base/index.d.ts +5 -0
- package/dist/ts/stepper-base/index.ts +6 -0
- package/dist/ts/stepper-base/stepper-base-model.d.ts +124 -0
- package/dist/ts/stepper-base/stepper-base.d.ts +187 -0
- package/dist/ts/stepper-base/stepper-base.ts +290 -0
- package/dist/ts/tab/index.d.ts +5 -0
- package/dist/ts/tab/index.ts +5 -0
- package/dist/ts/tab/tab-model.d.ts +408 -0
- package/dist/ts/tab/tab.d.ts +715 -0
- package/dist/ts/tab/tab.ts +2842 -0
- package/dist/ts/toolbar/index.d.ts +5 -0
- package/dist/ts/toolbar/index.ts +5 -0
- package/dist/ts/toolbar/toolbar-model.d.ts +294 -0
- package/dist/ts/toolbar/toolbar.d.ts +541 -0
- package/dist/ts/toolbar/toolbar.ts +2646 -0
- package/dist/ts/treeview/index.d.ts +5 -0
- package/dist/ts/treeview/index.ts +5 -0
- package/dist/ts/treeview/treeview-model.d.ts +637 -0
- package/dist/ts/treeview/treeview.d.ts +1518 -0
- package/dist/ts/treeview/treeview.ts +6780 -0
- package/package.json +70 -17
- package/src/context-menu/context-menu-model.d.ts +1 -1
- package/src/context-menu/context-menu.js +1 -1
- package/styles/accordion/_bootstrap-dark-definition.scss +1 -1
- package/styles/accordion/_bootstrap-definition.scss +1 -1
- package/styles/accordion/bootstrap-dark.css +1 -1
- package/styles/accordion/bootstrap.css +1 -1
- package/styles/bds-lite.css +1 -1
- package/styles/bds.css +1 -1
- package/styles/bootstrap-dark-lite.css +2 -2
- package/styles/bootstrap-dark.css +2 -2
- package/styles/bootstrap-lite.css +2 -2
- package/styles/bootstrap.css +2 -2
- package/styles/bootstrap4-lite.css +1 -1
- package/styles/bootstrap4.css +1 -1
- package/styles/bootstrap5-dark-lite.css +1 -1
- package/styles/bootstrap5-dark.css +1 -1
- package/styles/bootstrap5-lite.css +1 -1
- package/styles/bootstrap5.3-lite.css +1 -1
- package/styles/bootstrap5.3.css +9 -1
- package/styles/bootstrap5.css +1 -1
- package/styles/fabric-dark-lite.css +1 -1
- package/styles/fabric-dark.css +1 -1
- package/styles/fabric-lite.css +1 -1
- package/styles/fabric.css +1 -1
- package/styles/fluent-dark-lite.css +1 -1
- package/styles/fluent-dark.css +1 -1
- package/styles/fluent-lite.css +1 -1
- package/styles/fluent.css +1 -1
- package/styles/fluent2-lite.css +4 -1
- package/styles/fluent2.css +4 -1
- package/styles/h-scroll/_layout.scss +1 -1
- package/styles/h-scroll/bds.css +1 -1
- package/styles/h-scroll/bootstrap-dark.css +1 -1
- package/styles/h-scroll/bootstrap.css +1 -1
- package/styles/h-scroll/bootstrap4.css +1 -1
- package/styles/h-scroll/bootstrap5-dark.css +1 -1
- package/styles/h-scroll/bootstrap5.3.css +1 -1
- package/styles/h-scroll/bootstrap5.css +1 -1
- package/styles/h-scroll/fabric-dark.css +1 -1
- package/styles/h-scroll/fabric.css +1 -1
- package/styles/h-scroll/fluent-dark.css +1 -1
- package/styles/h-scroll/fluent.css +1 -1
- package/styles/h-scroll/fluent2.css +1 -1
- package/styles/h-scroll/highcontrast-light.css +1 -1
- package/styles/h-scroll/highcontrast.css +1 -1
- package/styles/h-scroll/material-dark.css +1 -1
- package/styles/h-scroll/material.css +1 -1
- package/styles/h-scroll/material3-dark.css +1 -1
- package/styles/h-scroll/material3.css +1 -1
- package/styles/h-scroll/tailwind-dark.css +1 -1
- package/styles/h-scroll/tailwind.css +1 -1
- package/styles/h-scroll/tailwind3.css +1 -1
- package/styles/highcontrast-light-lite.css +1 -1
- package/styles/highcontrast-light.css +1 -1
- package/styles/highcontrast-lite.css +1 -1
- package/styles/highcontrast.css +1 -1
- package/styles/material-dark-lite.css +1 -1
- package/styles/material-dark.css +1 -1
- package/styles/material-lite.css +1 -1
- package/styles/material.css +1 -1
- package/styles/material3-dark-lite.css +1 -1
- package/styles/material3-dark.css +1 -7
- package/styles/material3-lite.css +1 -1
- package/styles/material3.css +1 -7
- package/styles/tailwind-dark-lite.css +1 -1
- package/styles/tailwind-dark.css +1 -1
- package/styles/tailwind-lite.css +1 -1
- package/styles/tailwind.css +1 -1
- package/styles/tailwind3-lite.css +1 -1
- package/styles/tailwind3.css +1 -1
- package/styles/toolbar/_layout.scss +1 -1
- package/styles/treeview/_bigger.scss +2 -2
- package/styles/treeview/_bootstrap5.3-definition.scss +1 -0
- package/styles/treeview/_layout.scss +3 -0
- package/styles/treeview/bootstrap5.3.css +8 -0
- package/styles/treeview/fluent2.css +3 -0
- package/styles/treeview/material3-dark.css +0 -6
- package/styles/treeview/material3.css +0 -6
|
@@ -0,0 +1,2842 @@
|
|
|
1
|
+
import { Component, Property, Event, EmitType, closest, Collection, Complex, attributes, detach, Instance, isNullOrUndefined, animationMode } from '@syncfusion/ej2-base';
|
|
2
|
+
import { INotifyPropertyChanged, NotifyPropertyChanges, ChildProperty, select, isVisible } from '@syncfusion/ej2-base';
|
|
3
|
+
import { KeyboardEvents, KeyboardEventArgs, MouseEventArgs, Effect, Browser, formatUnit, DomElements, L10n } from '@syncfusion/ej2-base';
|
|
4
|
+
import { setStyleAttribute as setStyle, isNullOrUndefined as isNOU, selectAll, addClass, removeClass, remove } from '@syncfusion/ej2-base';
|
|
5
|
+
import { EventHandler, rippleEffect, Touch, SwipeEventArgs, compile, Animation, AnimationModel, BaseEventArgs } from '@syncfusion/ej2-base';
|
|
6
|
+
import { getRandomId, SanitizeHtmlHelper, Draggable, DragEventArgs as DragArgs, DropEventArgs } from '@syncfusion/ej2-base';
|
|
7
|
+
import { Base } from '@syncfusion/ej2-base';
|
|
8
|
+
import { Popup, PopupModel } from '@syncfusion/ej2-popups';
|
|
9
|
+
import { Toolbar, OverflowMode, ClickEventArgs } from '../toolbar/toolbar';
|
|
10
|
+
import { TabModel, TabItemModel, HeaderModel, TabActionSettingsModel, TabAnimationSettingsModel } from './tab-model';
|
|
11
|
+
|
|
12
|
+
type HTEle = HTMLElement;
|
|
13
|
+
type Str = string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Specifies the orientation of the Tab header.
|
|
17
|
+
* ```props
|
|
18
|
+
* Top :- Places the Tab header on the top.
|
|
19
|
+
* Bottom :- Places the Tab header on the bottom.
|
|
20
|
+
* Left :- Places the Tab header on the left.
|
|
21
|
+
* Right :- Places the Tab header on the right.
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export type HeaderPosition = 'Top' | 'Bottom' | 'Left' | 'Right';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Options to set the content element height adjust modes.
|
|
28
|
+
* ```props
|
|
29
|
+
* None :- Based on the given height property, the content panel height is set.
|
|
30
|
+
* Auto :- Tallest panel height of a given Tab content is set to all the other panels.
|
|
31
|
+
* Content :- Based on the corresponding content height, the content panel height is set.
|
|
32
|
+
* Fill :- Content element take height based on the parent height.
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export type HeightStyles = 'None' | 'Auto' | 'Content' | 'Fill';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Enables or disables the tab swiping action through Touch and Mouse.
|
|
39
|
+
* - `Both`: Enables swiping for both touch and mouse input.
|
|
40
|
+
* - `Touch`: Enables swiping only for touch input.
|
|
41
|
+
* - `Mouse`: Enables swiping only for mouse input.
|
|
42
|
+
* - `None`: Disables swiping for both touch and mouse input.
|
|
43
|
+
*/
|
|
44
|
+
export type TabSwipeMode = 'Both' | 'Touch' | 'Mouse' | 'None'
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Specifies the options of Tab content display mode.
|
|
48
|
+
* ```props
|
|
49
|
+
* Demand :- The content of the selected tab alone is loaded initially. The content of the tabs which were loaded once will be maintained in the DOM.
|
|
50
|
+
* Dynamic :- Only the content of the selected tab is loaded and available in the DOM, and it will be replaced with the corresponding content if the tab is selected dynamically.
|
|
51
|
+
* Init :- The content of all the tabs are rendered on the initial load and maintained in the DOM.
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
export type ContentLoad = 'Dynamic' | 'Init' | 'Demand';
|
|
56
|
+
|
|
57
|
+
const CLS_TAB: string = 'e-tab';
|
|
58
|
+
const CLS_HEADER: string = 'e-tab-header';
|
|
59
|
+
const CLS_BLA_TEM: string = 'blazor-template';
|
|
60
|
+
const CLS_CONTENT: string = 'e-content';
|
|
61
|
+
const CLS_NEST: string = 'e-nested';
|
|
62
|
+
const CLS_ITEMS: string = 'e-items';
|
|
63
|
+
const CLS_ITEM: string = 'e-item';
|
|
64
|
+
const CLS_TEMPLATE: string = 'e-template';
|
|
65
|
+
const CLS_RTL: string = 'e-rtl';
|
|
66
|
+
const CLS_ACTIVE: string = 'e-active';
|
|
67
|
+
const CLS_DISABLE: string = 'e-disable';
|
|
68
|
+
const CLS_HIDDEN: string = 'e-hidden';
|
|
69
|
+
const CLS_FOCUS: string = 'e-focused';
|
|
70
|
+
const CLS_ICONS: string = 'e-icons';
|
|
71
|
+
const CLS_ICON: string = 'e-icon';
|
|
72
|
+
const CLS_ICON_TAB: string = 'e-icon-tab';
|
|
73
|
+
const CLS_ICON_CLOSE: string = 'e-close-icon';
|
|
74
|
+
const CLS_CLOSE_SHOW: string = 'e-close-show';
|
|
75
|
+
const CLS_TEXT: string = 'e-tab-text';
|
|
76
|
+
const CLS_INDICATOR: string = 'e-indicator';
|
|
77
|
+
const CLS_WRAP: string = 'e-tab-wrap';
|
|
78
|
+
const CLS_TEXT_WRAP: string = 'e-text-wrap';
|
|
79
|
+
const CLS_TAB_ICON: string = 'e-tab-icon';
|
|
80
|
+
const CLS_TB_ITEMS: string = 'e-toolbar-items';
|
|
81
|
+
const CLS_TB_ITEM: string = 'e-toolbar-item';
|
|
82
|
+
const CLS_TB_POP: string = 'e-toolbar-pop';
|
|
83
|
+
const CLS_TB_POPUP: string = 'e-toolbar-popup';
|
|
84
|
+
const CLS_HOR_NAV: string = 'e-hor-nav';
|
|
85
|
+
const CLS_POPUP_OPEN: string = 'e-popup-open';
|
|
86
|
+
const CLS_POPUP_CLOSE: string = 'e-popup-close';
|
|
87
|
+
const CLS_PROGRESS: string = 'e-progress';
|
|
88
|
+
const CLS_IGNORE: string = 'e-ignore';
|
|
89
|
+
const CLS_OVERLAY: string = 'e-overlay';
|
|
90
|
+
const CLS_HSCRCNT: string = 'e-hscroll-content';
|
|
91
|
+
const CLS_VSCRCNT: string = 'e-vscroll-content';
|
|
92
|
+
const CLS_VTAB: string = 'e-vertical-tab';
|
|
93
|
+
const CLS_VERTICAL: string = 'e-vertical';
|
|
94
|
+
const CLS_VLEFT: string = 'e-vertical-left';
|
|
95
|
+
const CLS_VRIGHT: string = 'e-vertical-right';
|
|
96
|
+
const CLS_HBOTTOM: string = 'e-horizontal-bottom';
|
|
97
|
+
const CLS_FILL: string = 'e-fill-mode';
|
|
98
|
+
const TABITEMPREFIX: string = 'tabitem_';
|
|
99
|
+
const CLS_REORDER_ACTIVE_ITEM: string = 'e-reorder-active-item';
|
|
100
|
+
|
|
101
|
+
/** An interface that holds options to control the selected item action. */
|
|
102
|
+
export interface SelectEventArgs extends BaseEventArgs {
|
|
103
|
+
/** Defines the previous Tab item element. */
|
|
104
|
+
previousItem: HTMLElement
|
|
105
|
+
/** Defines the previous Tab item index. */
|
|
106
|
+
previousIndex: number
|
|
107
|
+
/** Defines the selected Tab item element. */
|
|
108
|
+
selectedItem: HTMLElement
|
|
109
|
+
/** Defines the selected Tab item index. */
|
|
110
|
+
selectedIndex: number
|
|
111
|
+
/** Defines the content selection done through swiping. */
|
|
112
|
+
isSwiped: boolean
|
|
113
|
+
/** Defines the prevent action. */
|
|
114
|
+
cancel?: boolean
|
|
115
|
+
/** Defines the selected content. */
|
|
116
|
+
selectedContent: HTMLElement
|
|
117
|
+
/** Determines whether the event is triggered via user interaction or programmatic way. True, if the event is triggered by user interaction. */
|
|
118
|
+
isInteracted?: boolean
|
|
119
|
+
/** Determines whether the Tab item needs to focus or not after it is selected */
|
|
120
|
+
preventFocus?: boolean
|
|
121
|
+
}
|
|
122
|
+
/** An interface that holds options to control the selecting item action. */
|
|
123
|
+
export interface SelectingEventArgs extends SelectEventArgs {
|
|
124
|
+
/** Defines the selecting Tab item element. */
|
|
125
|
+
selectingItem: HTMLElement
|
|
126
|
+
/** Defines the selecting Tab item index. */
|
|
127
|
+
selectingIndex: number
|
|
128
|
+
/** Defines the selecting Tab item content. */
|
|
129
|
+
selectingContent: HTMLElement
|
|
130
|
+
/** Defines the type of the event. */
|
|
131
|
+
event?: Event
|
|
132
|
+
}
|
|
133
|
+
/** An interface that holds options to control the removing and removed item action. */
|
|
134
|
+
export interface RemoveEventArgs extends BaseEventArgs {
|
|
135
|
+
/** Defines the removed Tab item element. */
|
|
136
|
+
removedItem: HTMLElement
|
|
137
|
+
/** Defines the removed Tab item index. */
|
|
138
|
+
removedIndex: number
|
|
139
|
+
/** Defines the prevent action. */
|
|
140
|
+
cancel?: boolean
|
|
141
|
+
}
|
|
142
|
+
/** An interface that holds options to control the adding and added item action. */
|
|
143
|
+
export interface AddEventArgs extends BaseEventArgs {
|
|
144
|
+
/** Defines the added Tab item element */
|
|
145
|
+
addedItems: TabItemModel[]
|
|
146
|
+
/** Defines the prevent action. */
|
|
147
|
+
cancel?: boolean
|
|
148
|
+
}
|
|
149
|
+
/** An interface that holds option to control the dragging and dragged item action. */
|
|
150
|
+
export interface DragEventArgs extends BaseEventArgs {
|
|
151
|
+
/** Defines the current dragged Tab item. */
|
|
152
|
+
draggedItem: HTMLElement
|
|
153
|
+
/** Defines the dropped Tab item. */
|
|
154
|
+
droppedItem: HTMLElement
|
|
155
|
+
/** defines the Dragged Tab item index. */
|
|
156
|
+
index: number
|
|
157
|
+
/** Return the actual event. */
|
|
158
|
+
event: MouseEvent
|
|
159
|
+
/** Return the target element */
|
|
160
|
+
target: HTMLElement
|
|
161
|
+
/** Return the clone element */
|
|
162
|
+
clonedElement: HTMLElement
|
|
163
|
+
/** Defines the prevent action. */
|
|
164
|
+
cancel?: boolean
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Objects used for configuring the Tab selecting item action properties.
|
|
168
|
+
*/
|
|
169
|
+
export class TabActionSettings extends ChildProperty<TabActionSettings> {
|
|
170
|
+
/**
|
|
171
|
+
* Specifies the animation effect for displaying Tab content.
|
|
172
|
+
*
|
|
173
|
+
* @default 'SlideLeftIn'
|
|
174
|
+
* @aspType string
|
|
175
|
+
*/
|
|
176
|
+
@Property('SlideLeftIn')
|
|
177
|
+
public effect: 'None' | Effect;
|
|
178
|
+
/**
|
|
179
|
+
* Specifies the time duration to transform content.
|
|
180
|
+
*
|
|
181
|
+
* @default 600
|
|
182
|
+
*/
|
|
183
|
+
@Property(600)
|
|
184
|
+
public duration: number;
|
|
185
|
+
/**
|
|
186
|
+
* Specifies easing effect applied while transforming content.
|
|
187
|
+
*
|
|
188
|
+
* @default 'ease'
|
|
189
|
+
*/
|
|
190
|
+
@Property('ease')
|
|
191
|
+
public easing: string;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Objects used for configuring the Tab animation properties.
|
|
195
|
+
*/
|
|
196
|
+
export class TabAnimationSettings extends ChildProperty<TabAnimationSettings> {
|
|
197
|
+
/**
|
|
198
|
+
* Specifies the animation to appear while moving to previous Tab content.
|
|
199
|
+
*
|
|
200
|
+
* @default { effect: 'SlideLeftIn', duration: 600, easing: 'ease' }
|
|
201
|
+
*/
|
|
202
|
+
@Complex<TabActionSettingsModel>({ effect: 'SlideLeftIn', duration: 600, easing: 'ease' }, TabActionSettings)
|
|
203
|
+
public previous: TabActionSettingsModel;
|
|
204
|
+
/**
|
|
205
|
+
* Specifies the animation to appear while moving to next Tab content.
|
|
206
|
+
*
|
|
207
|
+
* @default { effect: 'SlideRightIn', duration: 600, easing: 'ease' }
|
|
208
|
+
*/
|
|
209
|
+
@Complex<TabActionSettingsModel>({ effect: 'SlideRightIn', duration: 600, easing: 'ease' }, TabActionSettings)
|
|
210
|
+
public next: TabActionSettingsModel;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Objects used for configuring the Tab item header properties.
|
|
214
|
+
*/
|
|
215
|
+
export class Header extends ChildProperty<Header> {
|
|
216
|
+
/**
|
|
217
|
+
* Specifies the display text of the Tab item header.
|
|
218
|
+
*
|
|
219
|
+
* @default ''
|
|
220
|
+
*/
|
|
221
|
+
@Property('')
|
|
222
|
+
public text: string | HTMLElement;
|
|
223
|
+
/**
|
|
224
|
+
* Specifies the icon class that is used to render an icon in the Tab header.
|
|
225
|
+
*
|
|
226
|
+
* @default ''
|
|
227
|
+
*/
|
|
228
|
+
@Property('')
|
|
229
|
+
public iconCss: string;
|
|
230
|
+
/**
|
|
231
|
+
* Options for positioning the icon in the Tab item header. This property depends on `iconCss` property.
|
|
232
|
+
* The possible values for this property as follows
|
|
233
|
+
* * `Left`: Places the icon to the left of the item.
|
|
234
|
+
* * `Top`: Places the icon on the top of the item.
|
|
235
|
+
* * `Right`: Places the icon to the right end of the item.
|
|
236
|
+
* * `Bottom`: Places the icon at the bottom of the item.
|
|
237
|
+
*
|
|
238
|
+
* @default 'left'
|
|
239
|
+
*/
|
|
240
|
+
@Property('left')
|
|
241
|
+
public iconPosition: string;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* An array of object that is used to configure the Tab.
|
|
245
|
+
*/
|
|
246
|
+
export class TabItem extends ChildProperty<TabItem> {
|
|
247
|
+
/**
|
|
248
|
+
* The object used for configuring the Tab item header properties.
|
|
249
|
+
*
|
|
250
|
+
* @default {}
|
|
251
|
+
*/
|
|
252
|
+
@Complex<HeaderModel>({}, Header)
|
|
253
|
+
public header: HeaderModel;
|
|
254
|
+
/**
|
|
255
|
+
* Specifies the header text of Tab item.
|
|
256
|
+
*
|
|
257
|
+
* @default null
|
|
258
|
+
* @angularType string | object
|
|
259
|
+
* @reactType string | function | JSX.Element
|
|
260
|
+
* @vueType string | function
|
|
261
|
+
* @aspType string
|
|
262
|
+
*/
|
|
263
|
+
@Property(null)
|
|
264
|
+
public headerTemplate: string | Function;
|
|
265
|
+
/**
|
|
266
|
+
* Specifies the content of Tab item, that is displayed when concern item header is selected.
|
|
267
|
+
*
|
|
268
|
+
* @default ''
|
|
269
|
+
* @angularType string | object
|
|
270
|
+
* @reactType string | function | JSX.Element
|
|
271
|
+
* @vueType string | function
|
|
272
|
+
* @aspType string
|
|
273
|
+
*/
|
|
274
|
+
@Property('')
|
|
275
|
+
public content: string | HTMLElement | Function;
|
|
276
|
+
/**
|
|
277
|
+
* Sets the CSS classes to the Tab item to customize its styles.
|
|
278
|
+
*
|
|
279
|
+
* @default ''
|
|
280
|
+
*/
|
|
281
|
+
@Property('')
|
|
282
|
+
public cssClass: string;
|
|
283
|
+
/**
|
|
284
|
+
* Sets true to disable user interactions of the Tab item.
|
|
285
|
+
*
|
|
286
|
+
* @default false
|
|
287
|
+
*/
|
|
288
|
+
@Property(false)
|
|
289
|
+
public disabled: boolean;
|
|
290
|
+
/**
|
|
291
|
+
* Sets false to hide the Tab item.
|
|
292
|
+
*
|
|
293
|
+
* @default true
|
|
294
|
+
*/
|
|
295
|
+
@Property(true)
|
|
296
|
+
public visible: boolean;
|
|
297
|
+
/**
|
|
298
|
+
* Sets unique ID to Tab item.
|
|
299
|
+
*
|
|
300
|
+
* @default null
|
|
301
|
+
*/
|
|
302
|
+
@Property()
|
|
303
|
+
public id: string;
|
|
304
|
+
/**
|
|
305
|
+
* Specifies the tab order of the Tabs items. When positive values assigned, it allows to switch focus to the next/previous tabs items with Tab/ShiftTab keys.
|
|
306
|
+
* By default, user can able to switch between items only via arrow keys.
|
|
307
|
+
* If the value is set to 0 for all tabs items, then tab switches based on element order.
|
|
308
|
+
*
|
|
309
|
+
* @default -1
|
|
310
|
+
*/
|
|
311
|
+
@Property(-1)
|
|
312
|
+
public tabIndex: number;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** @hidden */
|
|
316
|
+
interface EJ2Instance extends HTMLElement {
|
|
317
|
+
/* eslint-disable */
|
|
318
|
+
ej2_instances: Object[]
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Tab is a content panel to show multiple contents in a single space, one at a time.
|
|
323
|
+
* Each Tab item has an associated content, that will be displayed based on the active Tab header item.
|
|
324
|
+
* ```html
|
|
325
|
+
* <div id="tab"></div>
|
|
326
|
+
* <script>
|
|
327
|
+
* var tabObj = new Tab();
|
|
328
|
+
* tab.appendTo("#tab");
|
|
329
|
+
* </script>
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
@NotifyPropertyChanges
|
|
333
|
+
export class Tab extends Component<HTMLElement> implements INotifyPropertyChanged {
|
|
334
|
+
private hdrEle: HTEle;
|
|
335
|
+
private cntEle: HTEle;
|
|
336
|
+
private tbObj: Toolbar;
|
|
337
|
+
public tabId: string;
|
|
338
|
+
private tbItems: HTEle;
|
|
339
|
+
private tbItem: HTEle[];
|
|
340
|
+
private tbPop: HTEle;
|
|
341
|
+
private isTemplate: boolean;
|
|
342
|
+
private isPopup: boolean;
|
|
343
|
+
private isReplace: boolean;
|
|
344
|
+
private prevIndex: number;
|
|
345
|
+
private prevItem: HTEle;
|
|
346
|
+
private popEle: DomElements;
|
|
347
|
+
private actEleId: string;
|
|
348
|
+
private bdrLine: HTEle;
|
|
349
|
+
private popObj: Popup;
|
|
350
|
+
private btnCls: HTEle;
|
|
351
|
+
private cnt: string;
|
|
352
|
+
private show: object = {};
|
|
353
|
+
private hide: object = {};
|
|
354
|
+
private enableAnimation: boolean;
|
|
355
|
+
private keyModule: KeyboardEvents;
|
|
356
|
+
private tabKeyModule: KeyboardEvents;
|
|
357
|
+
private touchModule: Touch;
|
|
358
|
+
private maxHeight: number = 0;
|
|
359
|
+
private title: Str = 'Close';
|
|
360
|
+
private initRender: boolean;
|
|
361
|
+
private isInteracted: boolean = false;
|
|
362
|
+
private prevActiveEle: string;
|
|
363
|
+
private lastIndex: number = 0;
|
|
364
|
+
private isSwiped: boolean;
|
|
365
|
+
private isNested: boolean;
|
|
366
|
+
private itemIndexArray: string[];
|
|
367
|
+
private templateEle: string[];
|
|
368
|
+
private scrCntClass: string;
|
|
369
|
+
private isAdd: boolean = false;
|
|
370
|
+
private content: HTEle;
|
|
371
|
+
private selectedID: string;
|
|
372
|
+
private selectingID: string;
|
|
373
|
+
private isIconAlone: boolean = false;
|
|
374
|
+
private dragItem: HTMLElement;
|
|
375
|
+
private cloneElement: HTMLElement;
|
|
376
|
+
private droppedIndex: number;
|
|
377
|
+
private draggingItems: TabItemModel[];
|
|
378
|
+
private draggableItems: Draggable[] = [];
|
|
379
|
+
private tbId: string;
|
|
380
|
+
private resizeContext: EventListenerObject = this.refreshActiveTabBorder.bind(this);
|
|
381
|
+
/**
|
|
382
|
+
* Contains the keyboard configuration of the Tab.
|
|
383
|
+
*/
|
|
384
|
+
private keyConfigs: { [key: string]: Str } = {
|
|
385
|
+
tab: 'tab',
|
|
386
|
+
home: 'home',
|
|
387
|
+
end: 'end',
|
|
388
|
+
enter: 'enter',
|
|
389
|
+
space: 'space',
|
|
390
|
+
delete: 'delete',
|
|
391
|
+
moveLeft: 'leftarrow',
|
|
392
|
+
moveRight: 'rightarrow',
|
|
393
|
+
moveUp: 'uparrow',
|
|
394
|
+
moveDown: 'downarrow'
|
|
395
|
+
};
|
|
396
|
+
/**
|
|
397
|
+
* An array of object that is used to configure the Tab component.
|
|
398
|
+
*
|
|
399
|
+
* {% codeBlock src='tab/items/index.md' %}{% endcodeBlock %}
|
|
400
|
+
*
|
|
401
|
+
* @default []
|
|
402
|
+
*/
|
|
403
|
+
@Collection<TabItemModel>([], TabItem)
|
|
404
|
+
public items: TabItemModel[];
|
|
405
|
+
/**
|
|
406
|
+
* Specifies the width of the Tab component. Default, Tab width sets based on the width of its parent.
|
|
407
|
+
*
|
|
408
|
+
* @default '100%'
|
|
409
|
+
*/
|
|
410
|
+
@Property('100%')
|
|
411
|
+
public width: string | number;
|
|
412
|
+
/**
|
|
413
|
+
* Defines whether the tab transition should occur or not when performing Touch/Mouse swipe action.
|
|
414
|
+
*
|
|
415
|
+
* @remarks
|
|
416
|
+
* - `Both`: Enables swiping for both touch and mouse input.
|
|
417
|
+
* - `Touch`: Enables swiping only for touch input.
|
|
418
|
+
* - `Mouse`: Enables swiping only for mouse input.
|
|
419
|
+
* - `None`: Disables swiping for both touch and mouse input.
|
|
420
|
+
*
|
|
421
|
+
* @default "Both"
|
|
422
|
+
*/
|
|
423
|
+
@Property('Both')
|
|
424
|
+
public swipeMode: TabSwipeMode;
|
|
425
|
+
/**
|
|
426
|
+
* Specifies the height of the Tab component. By default, Tab height is set based on the height of its parent.
|
|
427
|
+
* To use height property, heightAdjustMode must be set to 'None'.
|
|
428
|
+
*
|
|
429
|
+
* @default 'auto'
|
|
430
|
+
*/
|
|
431
|
+
@Property('auto')
|
|
432
|
+
public height: string | number;
|
|
433
|
+
/**
|
|
434
|
+
* Sets the CSS classes to root element of the Tab that helps to customize component styles.
|
|
435
|
+
*
|
|
436
|
+
* @default ''
|
|
437
|
+
*/
|
|
438
|
+
@Property('')
|
|
439
|
+
public cssClass: string;
|
|
440
|
+
/**
|
|
441
|
+
* Specifies the index for activating the current Tab item.
|
|
442
|
+
*
|
|
443
|
+
* {% codeBlock src='tab/selectedItem/index.md' %}{% endcodeBlock %}
|
|
444
|
+
*
|
|
445
|
+
* @default 0
|
|
446
|
+
*/
|
|
447
|
+
@Property(0)
|
|
448
|
+
public selectedItem: number;
|
|
449
|
+
/**
|
|
450
|
+
* Specifies the orientation of Tab header.
|
|
451
|
+
* The possible values for this property as follows
|
|
452
|
+
* * `Top`: Places the Tab header on the top.
|
|
453
|
+
* * `Bottom`: Places the Tab header at the bottom.
|
|
454
|
+
* * `Left`: Places the Tab header on the left.
|
|
455
|
+
* * `Right`: Places the Tab header at the right.
|
|
456
|
+
*
|
|
457
|
+
* @default 'Top'
|
|
458
|
+
*/
|
|
459
|
+
@Property('Top')
|
|
460
|
+
public headerPlacement: HeaderPosition;
|
|
461
|
+
/**
|
|
462
|
+
* Specifies the height style for Tab content.
|
|
463
|
+
* The possible values for this property as follows
|
|
464
|
+
* * `None`: Based on the given height property, the content panel height is set.
|
|
465
|
+
* * `Auto`: Tallest panel height of a given Tab content is set to all the other panels.
|
|
466
|
+
* * `Content`: Based on the corresponding content height, the content panel height is set.
|
|
467
|
+
* * `Fill`: Based on the parent height, the content panel height is set.
|
|
468
|
+
*
|
|
469
|
+
* @default 'Content'
|
|
470
|
+
*/
|
|
471
|
+
@Property('Content')
|
|
472
|
+
public heightAdjustMode: HeightStyles;
|
|
473
|
+
/**
|
|
474
|
+
* Specifies the Tab display mode when Tab content exceeds the viewing area.
|
|
475
|
+
* The possible modes are:
|
|
476
|
+
* * `Scrollable`: All the elements are displayed in a single line with horizontal scrolling enabled.
|
|
477
|
+
* * `Popup`: Tab container holds the items that can be placed within the available space and rest of the items are moved to the popup.
|
|
478
|
+
* If the popup content overflows the height of the page, the rest of the elements can be viewed by scrolling the popup.
|
|
479
|
+
*
|
|
480
|
+
* @default 'Scrollable'
|
|
481
|
+
*/
|
|
482
|
+
@Property('Scrollable')
|
|
483
|
+
public overflowMode: OverflowMode;
|
|
484
|
+
/**
|
|
485
|
+
* Specifies the modes for Tab content.
|
|
486
|
+
* The possible modes are:
|
|
487
|
+
* * `Demand` - The content of the selected tab alone is loaded initially. The content of the tabs which were loaded once will be maintained in the DOM.
|
|
488
|
+
* * `Dynamic` - Only the content of the selected tab is loaded and available in the DOM, and it will be replaced with the corresponding content if the tab is selected dynamically.
|
|
489
|
+
* * `Init` - The content of all the tabs are rendered on the initial load and maintained in the DOM.
|
|
490
|
+
*
|
|
491
|
+
* @default 'Demand'
|
|
492
|
+
*/
|
|
493
|
+
@Property('Demand')
|
|
494
|
+
public loadOn: ContentLoad;
|
|
495
|
+
/**
|
|
496
|
+
* Enable or disable persisting component's state between page reloads.
|
|
497
|
+
* If enabled, following list of states will be persisted.
|
|
498
|
+
* 1. selectedItem
|
|
499
|
+
*
|
|
500
|
+
* @default false
|
|
501
|
+
*/
|
|
502
|
+
@Property(false)
|
|
503
|
+
public enablePersistence: boolean;
|
|
504
|
+
/**
|
|
505
|
+
* Specifies whether to enable the rendering of untrusted HTML values in the Tab component.
|
|
506
|
+
* When this property is enabled, the component will sanitize any suspected untrusted strings and scripts before rendering them.
|
|
507
|
+
*
|
|
508
|
+
* @default true
|
|
509
|
+
*/
|
|
510
|
+
@Property(true)
|
|
511
|
+
public enableHtmlSanitizer: boolean;
|
|
512
|
+
/**
|
|
513
|
+
* Specifies whether to show the close button for header items to remove the item from the Tab.
|
|
514
|
+
*
|
|
515
|
+
* @default false
|
|
516
|
+
*/
|
|
517
|
+
@Property(false)
|
|
518
|
+
public showCloseButton: boolean;
|
|
519
|
+
/**
|
|
520
|
+
* Determines whether to re-order tab items to show active tab item in the header area or popup when OverflowMode is Popup.
|
|
521
|
+
* True, if active tab item should be visible in header area instead of pop-up. The default value is true.
|
|
522
|
+
*
|
|
523
|
+
* @default true
|
|
524
|
+
*/
|
|
525
|
+
@Property(true)
|
|
526
|
+
public reorderActiveTab: boolean;
|
|
527
|
+
/**
|
|
528
|
+
* Specifies the scrolling distance in scroller.
|
|
529
|
+
*
|
|
530
|
+
* @default null
|
|
531
|
+
*/
|
|
532
|
+
@Property()
|
|
533
|
+
public scrollStep: number;
|
|
534
|
+
/**
|
|
535
|
+
* Defines the area in which the draggable element movement will be occurring. Outside that area will be restricted
|
|
536
|
+
* for the draggable element movement. By default, the draggable element movement occurs in the toolbar.
|
|
537
|
+
*
|
|
538
|
+
* @default null
|
|
539
|
+
*/
|
|
540
|
+
@Property()
|
|
541
|
+
public dragArea: string;
|
|
542
|
+
/**
|
|
543
|
+
* Sets true to allow drag and drop the Tab items
|
|
544
|
+
*
|
|
545
|
+
* @default false
|
|
546
|
+
*/
|
|
547
|
+
@Property(false)
|
|
548
|
+
public allowDragAndDrop: boolean;
|
|
549
|
+
/**
|
|
550
|
+
* Specifies whether the templates need to be cleared or not while changing the Tab items dynamically.
|
|
551
|
+
* @default true
|
|
552
|
+
*/
|
|
553
|
+
@Property(true)
|
|
554
|
+
public clearTemplates: boolean;
|
|
555
|
+
/**
|
|
556
|
+
* Specifies the animation configuration settings while showing the content of the Tab.
|
|
557
|
+
*
|
|
558
|
+
* @default
|
|
559
|
+
* { previous: { effect: 'SlideLeftIn', duration: 600, easing: 'ease' },
|
|
560
|
+
* next: { effect: 'SlideRightIn', duration: 600, easing: 'ease' } }
|
|
561
|
+
*/
|
|
562
|
+
@Complex<TabAnimationSettingsModel>({}, TabAnimationSettings)
|
|
563
|
+
public animation: TabAnimationSettingsModel;
|
|
564
|
+
/**
|
|
565
|
+
* The event will be fired once the component rendering is completed.
|
|
566
|
+
*
|
|
567
|
+
* @event
|
|
568
|
+
*/
|
|
569
|
+
@Event()
|
|
570
|
+
public created: EmitType<Event>;
|
|
571
|
+
/**
|
|
572
|
+
* The event will be fired before adding the item to the Tab.
|
|
573
|
+
*
|
|
574
|
+
* @event
|
|
575
|
+
*/
|
|
576
|
+
@Event()
|
|
577
|
+
public adding: EmitType<AddEventArgs>;
|
|
578
|
+
/**
|
|
579
|
+
* The event will be fired after adding the item to the Tab.
|
|
580
|
+
*
|
|
581
|
+
* @event
|
|
582
|
+
*/
|
|
583
|
+
@Event()
|
|
584
|
+
public added: EmitType<AddEventArgs>;
|
|
585
|
+
/**
|
|
586
|
+
* The event will be fired before the item gets selected.
|
|
587
|
+
*
|
|
588
|
+
* @event
|
|
589
|
+
*/
|
|
590
|
+
@Event()
|
|
591
|
+
public selecting: EmitType<SelectingEventArgs>;
|
|
592
|
+
/**
|
|
593
|
+
* The event will be fired after the item gets selected.
|
|
594
|
+
*
|
|
595
|
+
* @event
|
|
596
|
+
*/
|
|
597
|
+
@Event()
|
|
598
|
+
public selected: EmitType<SelectEventArgs>;
|
|
599
|
+
/**
|
|
600
|
+
* The event will be fired before removing the item from the Tab.
|
|
601
|
+
*
|
|
602
|
+
* @event
|
|
603
|
+
*/
|
|
604
|
+
@Event()
|
|
605
|
+
public removing: EmitType<RemoveEventArgs>;
|
|
606
|
+
/**
|
|
607
|
+
* The event will be fired after removing the item from the Tab.
|
|
608
|
+
*
|
|
609
|
+
* @event
|
|
610
|
+
*/
|
|
611
|
+
@Event()
|
|
612
|
+
public removed: EmitType<RemoveEventArgs>;
|
|
613
|
+
/**
|
|
614
|
+
* The event will be fired before dragging the item from Tab
|
|
615
|
+
* @event
|
|
616
|
+
*/
|
|
617
|
+
@Event()
|
|
618
|
+
public onDragStart: EmitType<DragEventArgs>;
|
|
619
|
+
/**
|
|
620
|
+
* The event will be fired while dragging the Tab item
|
|
621
|
+
* @event
|
|
622
|
+
*/
|
|
623
|
+
@Event()
|
|
624
|
+
public dragging: EmitType<DragEventArgs>;
|
|
625
|
+
/**
|
|
626
|
+
* The event will be fired after dropping the Tab item
|
|
627
|
+
* @event
|
|
628
|
+
*/
|
|
629
|
+
@Event()
|
|
630
|
+
public dragged: EmitType<DragEventArgs>;
|
|
631
|
+
/**
|
|
632
|
+
* The event will be fired when the component gets destroyed.
|
|
633
|
+
*
|
|
634
|
+
* @event
|
|
635
|
+
*/
|
|
636
|
+
@Event()
|
|
637
|
+
public destroyed: EmitType<Event>;
|
|
638
|
+
/**
|
|
639
|
+
* Removes the component from the DOM and detaches all its related event handlers, attributes and classes.
|
|
640
|
+
*
|
|
641
|
+
* @returns {void}
|
|
642
|
+
*/
|
|
643
|
+
public destroy(): void {
|
|
644
|
+
if (this.isReact || this.isAngular) {
|
|
645
|
+
this.clearTemplate();
|
|
646
|
+
}
|
|
647
|
+
if (!isNOU(this.tbObj)) {
|
|
648
|
+
this.tbObj.destroy();
|
|
649
|
+
this.tbObj = null;
|
|
650
|
+
}
|
|
651
|
+
this.unWireEvents();
|
|
652
|
+
this.element.removeAttribute('aria-disabled');
|
|
653
|
+
this.expTemplateContent();
|
|
654
|
+
if (!this.isTemplate) {
|
|
655
|
+
while (this.element.firstElementChild) {
|
|
656
|
+
remove(this.element.firstElementChild);
|
|
657
|
+
}
|
|
658
|
+
} else {
|
|
659
|
+
const cntEle: Element = select('.' + CLS_TAB + ' > .' + CLS_CONTENT, this.element);
|
|
660
|
+
this.element.classList.remove(CLS_TEMPLATE);
|
|
661
|
+
if (!isNOU(cntEle)) {
|
|
662
|
+
cntEle.innerHTML = this.cnt;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (this.btnCls) {
|
|
667
|
+
this.btnCls = null;
|
|
668
|
+
}
|
|
669
|
+
this.hdrEle = null;
|
|
670
|
+
this.cntEle = null;
|
|
671
|
+
this.tbItems = null;
|
|
672
|
+
this.tbItem = null;
|
|
673
|
+
this.tbPop = null;
|
|
674
|
+
this.prevItem = null;
|
|
675
|
+
this.popEle = null;
|
|
676
|
+
this.bdrLine = null;
|
|
677
|
+
this.content = null;
|
|
678
|
+
this.dragItem = null;
|
|
679
|
+
this.cloneElement = null;
|
|
680
|
+
this.draggingItems = [];
|
|
681
|
+
if (this.draggableItems && this.draggableItems.length > 0) {
|
|
682
|
+
for (let i: number = 0; i < this.draggableItems.length; i++) {
|
|
683
|
+
this.draggableItems[i].destroy();
|
|
684
|
+
this.draggableItems[i] = null;
|
|
685
|
+
}
|
|
686
|
+
this.draggableItems = [];
|
|
687
|
+
}
|
|
688
|
+
super.destroy();
|
|
689
|
+
this.trigger('destroyed');
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Refresh the tab component
|
|
694
|
+
*
|
|
695
|
+
* @returns {void}
|
|
696
|
+
*/
|
|
697
|
+
public refresh(): void {
|
|
698
|
+
if (this.isReact) {
|
|
699
|
+
this.clearTemplate();
|
|
700
|
+
}
|
|
701
|
+
super.refresh();
|
|
702
|
+
if (this.isReact) {
|
|
703
|
+
this.renderReactTemplates();
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Reorganizes and adjusts the Tab headers to fit the available width without re-rendering the entire Tab component.
|
|
709
|
+
*
|
|
710
|
+
* This method is useful for optimizing the layout when:
|
|
711
|
+
* - A hidden tab item becomes visible.
|
|
712
|
+
* - The number of tab items changes dynamically.
|
|
713
|
+
*
|
|
714
|
+
* @returns {void} This method does not return a value.
|
|
715
|
+
*/
|
|
716
|
+
public refreshOverflow(): void {
|
|
717
|
+
if (!isNOU(this.tbObj)) {
|
|
718
|
+
this.tbObj.refreshOverflow();
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Initialize component
|
|
724
|
+
*
|
|
725
|
+
* @private
|
|
726
|
+
* @returns {void}
|
|
727
|
+
*/
|
|
728
|
+
protected preRender(): void {
|
|
729
|
+
const nested: Element = closest(this.element, '.' + CLS_CONTENT);
|
|
730
|
+
this.prevIndex = 0;
|
|
731
|
+
this.isNested = false;
|
|
732
|
+
this.isPopup = false;
|
|
733
|
+
this.initRender = true;
|
|
734
|
+
this.isSwiped = false;
|
|
735
|
+
this.itemIndexArray = [];
|
|
736
|
+
this.templateEle = [];
|
|
737
|
+
if (this.allowDragAndDrop) {
|
|
738
|
+
this.dragArea = !isNOU(this.dragArea) ? this.dragArea : '#' + this.element.id + ' ' + ('.' + CLS_HEADER);
|
|
739
|
+
}
|
|
740
|
+
if (!isNOU(nested)) {
|
|
741
|
+
nested.parentElement.classList.add(CLS_NEST);
|
|
742
|
+
this.isNested = true;
|
|
743
|
+
}
|
|
744
|
+
const name: Str = Browser.info.name;
|
|
745
|
+
const css: Str = (name === 'msie') ? 'e-ie' : (name === 'edge') ? 'e-edge' : (name === 'safari') ? 'e-safari' : '';
|
|
746
|
+
setStyle(this.element, { 'width': formatUnit(this.width), 'height': formatUnit(this.height) });
|
|
747
|
+
this.setCssClass(this.element, this.cssClass, true);
|
|
748
|
+
attributes(this.element, { 'aria-disabled': 'false' });
|
|
749
|
+
this.setCssClass(this.element, css, true);
|
|
750
|
+
this.updatePopAnimationConfig();
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Initializes a new instance of the Tab class.
|
|
754
|
+
*
|
|
755
|
+
* @param {TabModel} options - Specifies Tab model properties as options.
|
|
756
|
+
* @param {string | HTMLElement} element - Specifies the element that is rendered as a Tab.
|
|
757
|
+
*/
|
|
758
|
+
public constructor(options?: TabModel, element?: string | HTMLElement) {
|
|
759
|
+
super(options, <HTEle | Str>element);
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Initialize the component rendering
|
|
763
|
+
*
|
|
764
|
+
* @private
|
|
765
|
+
* @returns {void}
|
|
766
|
+
*/
|
|
767
|
+
protected render(): void {
|
|
768
|
+
this.btnCls = this.createElement('span', { className: CLS_ICONS + ' ' + CLS_ICON_CLOSE, attrs: { title: this.title } });
|
|
769
|
+
this.tabId = this.element.id.length > 0 ? ('-' + this.element.id) : getRandomId();
|
|
770
|
+
this.renderContainer();
|
|
771
|
+
this.wireEvents();
|
|
772
|
+
this.initRender = false;
|
|
773
|
+
if (this.isReact && (this as Record<string, any>).portals && (this as Record<string, any>).portals.length > 0) {
|
|
774
|
+
this.renderReactTemplates(() => {
|
|
775
|
+
this.refreshOverflow();
|
|
776
|
+
this.selectingContent(this.selectedItem, this.isInteracted);
|
|
777
|
+
this.refreshActiveBorder();
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
private renderContainer(): void {
|
|
782
|
+
const ele: HTEle = this.element;
|
|
783
|
+
this.items.forEach((item: TabItemModel, index: number) => {
|
|
784
|
+
if (isNOU(item.id) && !isNOU((item as Base<HTMLElement>).setProperties)) {
|
|
785
|
+
(item as Base<HTMLElement>).setProperties({ id: TABITEMPREFIX + index.toString() }, true);
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
if (this.items.length > 0 && ele.children.length === 0) {
|
|
789
|
+
ele.appendChild(this.createElement('div', { className: CLS_CONTENT }));
|
|
790
|
+
this.setOrientation(this.headerPlacement, this.createElement('div', { className: CLS_HEADER }));
|
|
791
|
+
this.isTemplate = false;
|
|
792
|
+
} else if (this.element.children.length > 0) {
|
|
793
|
+
this.isTemplate = true;
|
|
794
|
+
ele.classList.add(CLS_TEMPLATE);
|
|
795
|
+
const header: HTEle = <HTEle>ele.querySelector('.' + CLS_HEADER);
|
|
796
|
+
if (header && this.headerPlacement === 'Bottom') {
|
|
797
|
+
this.setOrientation(this.headerPlacement, header);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if (!isNOU(select('.' + CLS_HEADER, this.element)) && !isNOU(select('.' + CLS_CONTENT, this.element))) {
|
|
801
|
+
this.renderHeader();
|
|
802
|
+
this.tbItems = <HTEle>select('.' + CLS_HEADER + ' .' + CLS_TB_ITEMS, this.element);
|
|
803
|
+
if (!isNOU(this.tbItems)) {
|
|
804
|
+
rippleEffect(this.tbItems, { selector: '.e-tab-wrap' });
|
|
805
|
+
}
|
|
806
|
+
this.renderContent();
|
|
807
|
+
if (selectAll('.' + CLS_TB_ITEM, this.element).length > 0) {
|
|
808
|
+
this.tbItems = <HTEle>select('.' + CLS_HEADER + ' .' + CLS_TB_ITEMS, this.element);
|
|
809
|
+
this.bdrLine = this.createElement('div', { className: CLS_INDICATOR + ' ' + CLS_HIDDEN + ' ' + CLS_IGNORE });
|
|
810
|
+
const scrCnt: HTEle = <HTEle>select('.' + this.scrCntClass, this.tbItems);
|
|
811
|
+
if (!isNOU(scrCnt)) {
|
|
812
|
+
scrCnt.insertBefore(this.bdrLine, scrCnt.firstChild);
|
|
813
|
+
} else {
|
|
814
|
+
this.tbItems.insertBefore(this.bdrLine, this.tbItems.firstChild);
|
|
815
|
+
}
|
|
816
|
+
this.setContentHeight(true);
|
|
817
|
+
this.select(this.selectedItem);
|
|
818
|
+
}
|
|
819
|
+
this.setRTL(this.enableRtl);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
private renderHeader(): void {
|
|
823
|
+
const hdrPlace: HeaderPosition = this.headerPlacement;
|
|
824
|
+
let tabItems: Object[] = [];
|
|
825
|
+
this.hdrEle = this.getTabHeader();
|
|
826
|
+
this.addVerticalClass();
|
|
827
|
+
if (!this.isTemplate) {
|
|
828
|
+
tabItems = this.parseObject(this.items, 0);
|
|
829
|
+
} else {
|
|
830
|
+
if (this.element.children.length > 1 && this.element.children[1].classList.contains(CLS_HEADER)) {
|
|
831
|
+
this.setProperties({ headerPlacement: 'Bottom' }, true);
|
|
832
|
+
}
|
|
833
|
+
const count: number = this.hdrEle.children.length;
|
|
834
|
+
const hdrItems: Element[] = [];
|
|
835
|
+
for (let i: number = 0; i < count; i++) {
|
|
836
|
+
hdrItems.push(this.hdrEle.children.item(i));
|
|
837
|
+
}
|
|
838
|
+
if (count > 0) {
|
|
839
|
+
const tabItems: HTMLElement = this.createElement('div', { className: CLS_ITEMS });
|
|
840
|
+
this.hdrEle.appendChild(tabItems);
|
|
841
|
+
hdrItems.forEach((item: Element, index: number) => {
|
|
842
|
+
this.lastIndex = index;
|
|
843
|
+
const attr: object = {
|
|
844
|
+
className: CLS_ITEM, id: CLS_ITEM + this.tabId + '_' + index
|
|
845
|
+
};
|
|
846
|
+
const txt: Str = this.createElement('span', {
|
|
847
|
+
className: CLS_TEXT, attrs: { 'role': 'presentation' }
|
|
848
|
+
}).outerHTML;
|
|
849
|
+
const cont: Str = this.createElement('div', {
|
|
850
|
+
className: CLS_TEXT_WRAP, innerHTML: txt + this.btnCls.outerHTML
|
|
851
|
+
}).outerHTML;
|
|
852
|
+
const wrap: HTEle = this.createElement('div', {
|
|
853
|
+
className: CLS_WRAP, innerHTML: cont,
|
|
854
|
+
attrs: { role: 'tab', tabIndex: '-1', 'aria-selected': 'false', 'aria-controls': CLS_CONTENT + this.tabId + '_' + index, 'aria-disabled': 'false' }
|
|
855
|
+
});
|
|
856
|
+
wrap.querySelector('.' + CLS_TEXT).appendChild(item);
|
|
857
|
+
tabItems.appendChild(this.createElement('div', attr));
|
|
858
|
+
selectAll('.' + CLS_ITEM, tabItems)[index].appendChild(wrap);
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
this.tbObj = new Toolbar({
|
|
863
|
+
width: (hdrPlace === 'Left' || hdrPlace === 'Right') ? 'auto' : '100%',
|
|
864
|
+
height: (hdrPlace === 'Left' || hdrPlace === 'Right') ? '100%' : 'auto',
|
|
865
|
+
overflowMode: this.overflowMode,
|
|
866
|
+
items: (tabItems.length !== 0) ? tabItems : [],
|
|
867
|
+
clicked: this.clickHandler.bind(this),
|
|
868
|
+
scrollStep: this.scrollStep,
|
|
869
|
+
enableHtmlSanitizer: this.enableHtmlSanitizer,
|
|
870
|
+
cssClass: this.cssClass
|
|
871
|
+
});
|
|
872
|
+
this.tbObj.isStringTemplate = true;
|
|
873
|
+
this.tbObj.createElement = this.createElement;
|
|
874
|
+
this.tbObj.appendTo(<HTEle>this.hdrEle);
|
|
875
|
+
attributes(this.hdrEle, { role: 'tablist' });
|
|
876
|
+
if (!isNOU(this.element.getAttribute('aria-label'))) {
|
|
877
|
+
this.hdrEle.setAttribute('aria-label', this.element.getAttribute('aria-label'));
|
|
878
|
+
this.element.removeAttribute('aria-label');
|
|
879
|
+
} else if (!isNOU(this.element.getAttribute('aria-labelledby'))) {
|
|
880
|
+
this.hdrEle.setAttribute('aria-labelledby', this.element.getAttribute('aria-labelledby'));
|
|
881
|
+
this.element.removeAttribute('aria-labelledby');
|
|
882
|
+
}
|
|
883
|
+
this.setCloseButton(this.showCloseButton);
|
|
884
|
+
const toolbarHeader: HTEle = this.tbObj.element.querySelector('.' + CLS_TB_ITEMS);
|
|
885
|
+
if (!isNOU(toolbarHeader)) {
|
|
886
|
+
if (isNOU(toolbarHeader.id) || toolbarHeader.id === '') {
|
|
887
|
+
toolbarHeader.id = this.element.id + '_' + 'tab_header_items';
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
private createContentElement(index: number): Node {
|
|
893
|
+
const contentElement = this.createElement('div', {
|
|
894
|
+
id: CLS_CONTENT + this.tabId + '_' + index, className: CLS_ITEM,
|
|
895
|
+
attrs: { 'role': 'tabpanel', 'aria-labelledby': CLS_ITEM + this.tabId + '_' + index }
|
|
896
|
+
});
|
|
897
|
+
if (['Dynamic', 'Demand'].indexOf(this.loadOn) !== -1 ||
|
|
898
|
+
(this.loadOn === 'Init' && index === this.selectedItem)) {
|
|
899
|
+
addClass([contentElement], CLS_ACTIVE);
|
|
900
|
+
}
|
|
901
|
+
return contentElement;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
private renderContent(): void {
|
|
905
|
+
this.cntEle = <HTEle>select('.' + CLS_CONTENT, this.element);
|
|
906
|
+
const hdrItem: HTEle[] = selectAll('.' + CLS_TB_ITEM, this.element);
|
|
907
|
+
if (this.isTemplate) {
|
|
908
|
+
this.cnt = (this.cntEle.children.length > 0) ? this.cntEle.innerHTML : '';
|
|
909
|
+
const contents: HTMLCollection = this.cntEle.children;
|
|
910
|
+
for (let i: number = 0; i < hdrItem.length; i++) {
|
|
911
|
+
if (contents.length - 1 >= i) {
|
|
912
|
+
addClass([contents.item(i)], CLS_ITEM);
|
|
913
|
+
attributes(contents.item(i), { 'role': 'tabpanel', 'aria-labelledby': CLS_ITEM + this.tabId + '_' + i });
|
|
914
|
+
contents.item(i).id = CLS_CONTENT + this.tabId + '_' + i;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
} else {
|
|
918
|
+
if (selectAll('.' + CLS_TB_ITEM, this.element).length > 0) {
|
|
919
|
+
if (this.loadOn === 'Init') {
|
|
920
|
+
for (let i = 0; i < this.itemIndexArray.length; i++) {
|
|
921
|
+
if (this.itemIndexArray[i]) {
|
|
922
|
+
this.cntEle.appendChild(this.createContentElement(Number(this.extIndex(this.itemIndexArray[i]))));
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
} else if (this.loadOn === 'Dynamic') {
|
|
926
|
+
this.cntEle.appendChild(this.createContentElement(this.selectedItem > 0 ?
|
|
927
|
+
this.selectedItem : Number(this.extIndex(this.itemIndexArray[0]))));
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
private reRenderItems(): void {
|
|
933
|
+
this.renderContainer();
|
|
934
|
+
if (!isNOU(this.cntEle)) {
|
|
935
|
+
this.bindSwipeEvents();
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
private parseObject(items: TabItemModel[], index: number): object[] {
|
|
939
|
+
const tbItems: HTMLElement[] = Array.prototype.slice.call(selectAll('.e-tab-header .' + CLS_TB_ITEM, this.element));
|
|
940
|
+
let maxId: number = this.lastIndex;
|
|
941
|
+
if (!this.isReplace && tbItems.length > 0) {
|
|
942
|
+
maxId = this.getMaxIndicesFromItems(tbItems);
|
|
943
|
+
}
|
|
944
|
+
const tItems: Object[] = [];
|
|
945
|
+
let txtWrapEle: HTEle;
|
|
946
|
+
const spliceArray: number[] = [];
|
|
947
|
+
const i: number = 0;
|
|
948
|
+
items.forEach((item: TabItemModel, i: number) => {
|
|
949
|
+
const pos: Str = (isNOU(item.header) || isNOU(item.header.iconPosition)) ? '' : item.header.iconPosition;
|
|
950
|
+
const css: Str = (isNOU(item.header) || isNOU(item.header.iconCss)) ? '' : item.header.iconCss;
|
|
951
|
+
if ((isNOU(item.headerTemplate)) && (isNOU(item.header) || isNOU(item.header.text) ||
|
|
952
|
+
(((<string>item.header.text).length === 0)) && (css === ''))) {
|
|
953
|
+
spliceArray.push(i);
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
let txt: Str | HTEle | Function = item.headerTemplate || item.header.text;
|
|
957
|
+
if (typeof txt === 'string' && this.enableHtmlSanitizer) {
|
|
958
|
+
txt = SanitizeHtmlHelper.sanitize(<Str>txt);
|
|
959
|
+
}
|
|
960
|
+
let itemIndex: number;
|
|
961
|
+
if (this.isReplace && !isNOU(this.tbId) && this.tbId !== '') {
|
|
962
|
+
itemIndex = parseInt(this.tbId.substring(this.tbId.lastIndexOf('_') + 1), 10);
|
|
963
|
+
this.tbId = '';
|
|
964
|
+
} else {
|
|
965
|
+
itemIndex = index + i;
|
|
966
|
+
}
|
|
967
|
+
this.lastIndex = ((tbItems.length === 0) ? i : ((this.isReplace) ? (itemIndex) : (maxId + 1 + i)));
|
|
968
|
+
const disabled: Str = (item.disabled) ? ' ' + CLS_DISABLE + ' ' + CLS_OVERLAY : '';
|
|
969
|
+
const hidden: Str = (item.visible === false) ? ' ' + CLS_HIDDEN : '';
|
|
970
|
+
txtWrapEle = this.createElement('div', { className: CLS_TEXT, attrs: { 'role': 'presentation' } });
|
|
971
|
+
const tHtml: Str = ((txt instanceof Object) ? (<HTEle>txt).outerHTML : txt);
|
|
972
|
+
const txtEmpty: boolean = (!isNOU(tHtml) && tHtml !== '');
|
|
973
|
+
if (!isNOU((<HTEle>txt).tagName)) {
|
|
974
|
+
txtWrapEle.appendChild(txt as HTEle);
|
|
975
|
+
} else {
|
|
976
|
+
this.headerTextCompile(txtWrapEle, txt as string, i);
|
|
977
|
+
}
|
|
978
|
+
let tEle: HTEle;
|
|
979
|
+
const icon: HTEle = this.createElement('span', {
|
|
980
|
+
className: CLS_ICONS + ' ' + CLS_TAB_ICON + ' ' + CLS_ICON + '-' + pos + ' ' + css
|
|
981
|
+
});
|
|
982
|
+
const tCont: HTEle = this.createElement('div', { className: CLS_TEXT_WRAP });
|
|
983
|
+
tCont.appendChild(txtWrapEle);
|
|
984
|
+
if ((txt !== '' && txt !== undefined) && css !== '') {
|
|
985
|
+
if ((pos === 'left' || pos === 'top')) {
|
|
986
|
+
tCont.insertBefore(icon, tCont.firstElementChild);
|
|
987
|
+
} else {
|
|
988
|
+
tCont.appendChild(icon);
|
|
989
|
+
}
|
|
990
|
+
tEle = txtWrapEle;
|
|
991
|
+
this.isIconAlone = false;
|
|
992
|
+
} else {
|
|
993
|
+
tEle = ((css === '') ? txtWrapEle : icon);
|
|
994
|
+
if (tEle === icon) {
|
|
995
|
+
detach(txtWrapEle);
|
|
996
|
+
tCont.appendChild(icon);
|
|
997
|
+
this.isIconAlone = true;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
const tabIndex : string = isNOU(item.tabIndex) ? '-1' : item.tabIndex.toString();
|
|
1001
|
+
const wrapAttrs: { [key: string]: string } = (item.disabled) ? { role: 'tab', 'aria-disabled': 'true'} : { tabIndex: tabIndex, 'data-tabindex': tabIndex , role: 'tab', 'aria-selected': 'false', 'aria-disabled': 'false' };
|
|
1002
|
+
tCont.appendChild(this.btnCls.cloneNode(true));
|
|
1003
|
+
const wrap: HTEle = this.createElement('div', { className: CLS_WRAP, attrs: wrapAttrs });
|
|
1004
|
+
wrap.appendChild(tCont);
|
|
1005
|
+
if (this.itemIndexArray instanceof Array) {
|
|
1006
|
+
this.itemIndexArray.splice((index + i), 0, CLS_ITEM + this.tabId + '_' + this.lastIndex);
|
|
1007
|
+
}
|
|
1008
|
+
const attrObj: Object = {
|
|
1009
|
+
id: CLS_ITEM + this.tabId + '_' + this.lastIndex, 'data-id': item.id
|
|
1010
|
+
};
|
|
1011
|
+
const tItem: { [key: string]: {} } = { htmlAttributes: attrObj, template: wrap };
|
|
1012
|
+
tItem.cssClass = ((item.cssClass !== undefined) ? item.cssClass : ' ') + ' ' + disabled + ' ' + hidden + ' '
|
|
1013
|
+
+ ((css !== '') ? 'e-i' + pos : '') + ' ' + ((!txtEmpty) ? CLS_ICON : '');
|
|
1014
|
+
if (pos === 'top' || pos === 'bottom') {
|
|
1015
|
+
this.element.classList.add('e-vertical-icon');
|
|
1016
|
+
}
|
|
1017
|
+
tItems.push(tItem);
|
|
1018
|
+
i++;
|
|
1019
|
+
});
|
|
1020
|
+
if (!this.isAdd) {
|
|
1021
|
+
spliceArray.forEach((spliceItemIndex: number) => {
|
|
1022
|
+
this.items.splice(spliceItemIndex, 1);
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
if (this.isIconAlone) {
|
|
1026
|
+
this.element.classList.add(CLS_ICON_TAB);
|
|
1027
|
+
} else {
|
|
1028
|
+
this.element.classList.remove(CLS_ICON_TAB);
|
|
1029
|
+
}
|
|
1030
|
+
return tItems;
|
|
1031
|
+
}
|
|
1032
|
+
private removeActiveClass(): void {
|
|
1033
|
+
const tabHeader: HTMLElement = this.getTabHeader();
|
|
1034
|
+
if (tabHeader) {
|
|
1035
|
+
const tabItems: HTMLElement[] = selectAll('.' + CLS_TB_ITEM + '.' + CLS_ACTIVE, tabHeader);
|
|
1036
|
+
[].slice.call(tabItems).forEach((node: HTMLElement) => node.classList.remove(CLS_ACTIVE));
|
|
1037
|
+
[].slice.call(tabItems).forEach((node: HTMLElement) => node.firstElementChild.setAttribute('aria-selected', 'false'));
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
private checkPopupOverflow(ele: HTEle): boolean {
|
|
1041
|
+
this.tbPop = <HTEle>select('.' + CLS_TB_POP, this.element);
|
|
1042
|
+
const popIcon: HTEle = (<HTEle>select('.e-hor-nav', this.element));
|
|
1043
|
+
const tbrItems: HTEle = (<HTEle>select('.' + CLS_TB_ITEMS, this.element));
|
|
1044
|
+
const lastChild: HTEle = <HTMLElement>tbrItems.lastChild;
|
|
1045
|
+
let isOverflow: boolean = false;
|
|
1046
|
+
if (!this.isVertical() && ((this.enableRtl && ((popIcon.offsetLeft + popIcon.offsetWidth) > tbrItems.offsetLeft))
|
|
1047
|
+
|| (!this.enableRtl && popIcon.offsetLeft < tbrItems.offsetWidth))) {
|
|
1048
|
+
isOverflow = true;
|
|
1049
|
+
} else if (this.isVertical() && (popIcon.offsetTop < lastChild.offsetTop + lastChild.offsetHeight)) {
|
|
1050
|
+
isOverflow = true;
|
|
1051
|
+
}
|
|
1052
|
+
if (isOverflow && !isNOU(ele)) {
|
|
1053
|
+
ele.classList.add(CLS_TB_POPUP);
|
|
1054
|
+
this.tbPop.insertBefore(<Node>ele, selectAll('.' + CLS_TB_POPUP, this.tbPop)[0]);
|
|
1055
|
+
}
|
|
1056
|
+
return isOverflow;
|
|
1057
|
+
}
|
|
1058
|
+
private popupHandler(target: HTEle): number {
|
|
1059
|
+
const ripEle: HTEle = <HTEle>target.querySelector('.e-ripple-element');
|
|
1060
|
+
if (!isNOU(ripEle)) {
|
|
1061
|
+
ripEle.outerHTML = '';
|
|
1062
|
+
target.querySelector('.' + CLS_WRAP).classList.remove('e-ripple');
|
|
1063
|
+
}
|
|
1064
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEMS + ' .' + CLS_TB_ITEM, this.hdrEle);
|
|
1065
|
+
const lastChild: HTEle = <HTEle>this.tbItem[this.tbItem.length - 1];
|
|
1066
|
+
if (this.tbItem.length >= 0) {
|
|
1067
|
+
target.classList.remove(CLS_TB_POPUP);
|
|
1068
|
+
target.removeAttribute('style');
|
|
1069
|
+
this.tbItems.appendChild(target);
|
|
1070
|
+
this.actEleId = target.id;
|
|
1071
|
+
if (this.checkPopupOverflow(lastChild)) {
|
|
1072
|
+
for (let i: number = 0; i < this.tbItems.children.length; i++) {
|
|
1073
|
+
let prevEle: HTEle = <HTEle>(<HTEle>this.tbItems.lastChild).previousElementSibling;
|
|
1074
|
+
prevEle = <HTEle>(prevEle && prevEle.classList.contains(CLS_INDICATOR) ? prevEle.previousElementSibling : prevEle);
|
|
1075
|
+
if (!this.checkPopupOverflow(prevEle ? prevEle : target)) {
|
|
1076
|
+
break;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
this.isPopup = true;
|
|
1081
|
+
}
|
|
1082
|
+
const tabItemsLength: number = selectAll('.' + CLS_TB_ITEM, this.tbItems).length;
|
|
1083
|
+
return tabItemsLength > 0 ? tabItemsLength - 1 : this.getEleIndex(target);
|
|
1084
|
+
}
|
|
1085
|
+
private setCloseButton(val: boolean): void {
|
|
1086
|
+
const trg: Element = select('.' + CLS_HEADER, this.element);
|
|
1087
|
+
if (val === true) {
|
|
1088
|
+
trg.classList.add(CLS_CLOSE_SHOW);
|
|
1089
|
+
} else {
|
|
1090
|
+
trg.classList.remove(CLS_CLOSE_SHOW);
|
|
1091
|
+
}
|
|
1092
|
+
this.refreshOverflow();
|
|
1093
|
+
this.refreshActiveTabBorder();
|
|
1094
|
+
}
|
|
1095
|
+
private prevCtnAnimation(prev: number, current: number): AnimationModel {
|
|
1096
|
+
let animation: AnimationModel;
|
|
1097
|
+
const checkRTL: boolean = this.enableRtl || this.element.classList.contains(CLS_RTL);
|
|
1098
|
+
if (this.isPopup || prev <= current) {
|
|
1099
|
+
if (this.animation.previous.effect === 'SlideLeftIn') {
|
|
1100
|
+
animation = {
|
|
1101
|
+
name: 'SlideLeftOut',
|
|
1102
|
+
duration: this.animation.previous.duration, timingFunction: this.animation.previous.easing
|
|
1103
|
+
};
|
|
1104
|
+
} else {
|
|
1105
|
+
animation = null;
|
|
1106
|
+
}
|
|
1107
|
+
} else {
|
|
1108
|
+
if (this.animation.next.effect === 'SlideRightIn') {
|
|
1109
|
+
animation = {
|
|
1110
|
+
name: 'SlideRightOut',
|
|
1111
|
+
duration: this.animation.next.duration, timingFunction: this.animation.next.easing
|
|
1112
|
+
};
|
|
1113
|
+
} else {
|
|
1114
|
+
animation = null;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
return animation;
|
|
1118
|
+
}
|
|
1119
|
+
private triggerPrevAnimation(oldCnt: HTEle, prevIndex: number): void {
|
|
1120
|
+
const animateObj: AnimationModel = this.prevCtnAnimation(prevIndex, this.selectedItem);
|
|
1121
|
+
if (!isNOU(animateObj)) {
|
|
1122
|
+
animateObj.begin = () => {
|
|
1123
|
+
setStyle(oldCnt, { 'position': 'absolute' });
|
|
1124
|
+
oldCnt.classList.add(CLS_PROGRESS);
|
|
1125
|
+
oldCnt.classList.add('e-view');
|
|
1126
|
+
};
|
|
1127
|
+
animateObj.end = () => {
|
|
1128
|
+
oldCnt.style.display = 'none';
|
|
1129
|
+
oldCnt.classList.remove(CLS_ACTIVE);
|
|
1130
|
+
oldCnt.classList.remove(CLS_PROGRESS);
|
|
1131
|
+
oldCnt.classList.remove('e-view');
|
|
1132
|
+
setStyle(oldCnt, { 'display': '', 'position': '' });
|
|
1133
|
+
if (oldCnt.childNodes.length === 0 && !this.isTemplate) {
|
|
1134
|
+
detach(oldCnt);
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
new Animation(animateObj).animate(oldCnt);
|
|
1138
|
+
} else {
|
|
1139
|
+
oldCnt.classList.remove(CLS_ACTIVE);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
private triggerAnimation(id: Str, value: boolean): void {
|
|
1143
|
+
const prevIndex: number = this.prevIndex;
|
|
1144
|
+
let oldCnt: HTEle;
|
|
1145
|
+
const itemCollection: HTMLElement[] = [].slice.call(this.element.querySelector('.' + CLS_CONTENT).children);
|
|
1146
|
+
itemCollection.forEach((item: HTEle) => {
|
|
1147
|
+
if (item.id === this.prevActiveEle) {
|
|
1148
|
+
oldCnt = item;
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
const prevEle: HTEle = this.tbItem[prevIndex];
|
|
1152
|
+
const newCnt: HTEle = this.getTrgContent(this.cntEle, this.extIndex(id));
|
|
1153
|
+
if (isNOU(oldCnt) && !isNOU(prevEle)) {
|
|
1154
|
+
const idNo: Str = this.extIndex(prevEle.id);
|
|
1155
|
+
oldCnt = this.getTrgContent(this.cntEle, idNo);
|
|
1156
|
+
}
|
|
1157
|
+
if (!isNOU(newCnt)) {
|
|
1158
|
+
this.prevActiveEle = newCnt.id;
|
|
1159
|
+
}
|
|
1160
|
+
const isPrevent: boolean = isNOU(this.animation) || isNOU(this.animation.next.effect) || isNOU(this.animation.previous.effect)
|
|
1161
|
+
|| this.animation.previous.effect === 'None' || this.animation.next.effect === 'None';
|
|
1162
|
+
if (this.initRender || value === false || isPrevent) {
|
|
1163
|
+
if (oldCnt && oldCnt !== newCnt) {
|
|
1164
|
+
oldCnt.classList.remove(CLS_ACTIVE);
|
|
1165
|
+
}
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
const cnt: HTEle = <HTEle>select('.' + CLS_CONTENT, this.element);
|
|
1169
|
+
let animateObj: AnimationModel;
|
|
1170
|
+
if (this.prevIndex > this.selectedItem && !this.isPopup) {
|
|
1171
|
+
const openEff: Effect = <Effect>this.animation.previous.effect;
|
|
1172
|
+
animateObj = {
|
|
1173
|
+
name: <Effect>((openEff === <Effect>'None') ? '' : ((openEff !== <Effect>'SlideLeftIn') ? openEff : 'SlideLeftIn')),
|
|
1174
|
+
duration: (this.animation.previous.duration === 0 && animationMode === 'Enable') ? 600: this.animation.previous.duration,
|
|
1175
|
+
timingFunction: this.animation.previous.easing
|
|
1176
|
+
};
|
|
1177
|
+
} else if (this.isPopup || this.prevIndex < this.selectedItem || this.prevIndex === this.selectedItem) {
|
|
1178
|
+
const clsEff: Effect = <Effect>this.animation.next.effect;
|
|
1179
|
+
animateObj = {
|
|
1180
|
+
name: <Effect>((clsEff === <Effect>'None') ? '' : ((clsEff !== <Effect>'SlideRightIn') ? clsEff : 'SlideRightIn')),
|
|
1181
|
+
duration: (this.animation.next.duration === 0 && animationMode === 'Enable') ? 600:this.animation.next.duration,
|
|
1182
|
+
timingFunction: this.animation.next.easing
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
animateObj.progress = () => {
|
|
1186
|
+
cnt.classList.add(CLS_PROGRESS); this.setActiveBorder();
|
|
1187
|
+
};
|
|
1188
|
+
animateObj.end = () => {
|
|
1189
|
+
cnt.classList.remove(CLS_PROGRESS);
|
|
1190
|
+
newCnt.classList.add(CLS_ACTIVE);
|
|
1191
|
+
};
|
|
1192
|
+
if (!this.initRender && !isNOU(oldCnt)) {
|
|
1193
|
+
this.triggerPrevAnimation(oldCnt, prevIndex);
|
|
1194
|
+
}
|
|
1195
|
+
this.isPopup = false;
|
|
1196
|
+
if (animateObj.name === <Effect>'') {
|
|
1197
|
+
newCnt.classList.add(CLS_ACTIVE);
|
|
1198
|
+
} else {
|
|
1199
|
+
new Animation(animateObj).animate(newCnt);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
private keyPressed(trg: HTEle): void {
|
|
1203
|
+
const trgParent: HTEle = <HTEle>closest(trg, '.' + CLS_HEADER + ' .' + CLS_TB_ITEM);
|
|
1204
|
+
const trgIndex: number = this.getEleIndex(trgParent);
|
|
1205
|
+
if (!isNOU(this.popEle) && trg.classList.contains('e-hor-nav')) {
|
|
1206
|
+
(this.popEle.classList.contains(CLS_POPUP_OPEN)) ? this.popObj.hide(this.hide) : this.popObj.show(this.show);
|
|
1207
|
+
} else if (trg.classList.contains('e-scroll-nav')) {
|
|
1208
|
+
trg.click();
|
|
1209
|
+
} else {
|
|
1210
|
+
if (!isNOU(trgParent) && trgParent.classList.contains(CLS_ACTIVE) === false) {
|
|
1211
|
+
this.selectTab(trgIndex, null, true);
|
|
1212
|
+
if (!isNOU(this.popEle)) {
|
|
1213
|
+
this.popObj.hide(this.hide);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
private getTabHeader(): HTMLElement {
|
|
1219
|
+
if (isNOU(this.element)) {
|
|
1220
|
+
return undefined;
|
|
1221
|
+
}
|
|
1222
|
+
const headers: HTMLElement[] = [].slice.call(this.element.children).filter((e: HTMLElement) => e.classList.contains(CLS_HEADER));
|
|
1223
|
+
if (headers.length > 0) {
|
|
1224
|
+
return headers[0];
|
|
1225
|
+
} else {
|
|
1226
|
+
const wrap: HTMLElement =
|
|
1227
|
+
[].slice.call(this.element.children).filter((e: HTMLElement) => !e.classList.contains(CLS_BLA_TEM))[0];
|
|
1228
|
+
if (!wrap) {
|
|
1229
|
+
return undefined;
|
|
1230
|
+
}
|
|
1231
|
+
return [].slice.call(wrap.children).filter((e: HTMLElement) => e.classList.contains(CLS_HEADER))[0];
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
private getEleIndex(item: HTEle): number {
|
|
1235
|
+
return Array.prototype.indexOf.call(selectAll('.' + CLS_TB_ITEM, this.getTabHeader()), item);
|
|
1236
|
+
}
|
|
1237
|
+
private extIndex(id: string): string {
|
|
1238
|
+
return id.replace(CLS_ITEM + this.tabId + '_', '');
|
|
1239
|
+
}
|
|
1240
|
+
private getMaxIndicesFromItems(tbItems: HTMLElement[]): number {
|
|
1241
|
+
const idList: number[] = [];
|
|
1242
|
+
tbItems.forEach((item: HTMLElement) => {
|
|
1243
|
+
idList.push(this.getIndexFromEle(item.id));
|
|
1244
|
+
});
|
|
1245
|
+
return Math.max(...idList);
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
private expTemplateContent(): void {
|
|
1249
|
+
this.templateEle.forEach((eleStr: Str): void => {
|
|
1250
|
+
if (!isNOU(this.element.querySelector(eleStr))) {
|
|
1251
|
+
(<HTEle>document.body.appendChild(this.element.querySelector(eleStr))).style.display = 'none';
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1255
|
+
private templateCompile(ele: HTEle, cnt: Str, index: number): void {
|
|
1256
|
+
const tempEle: HTEle = this.createElement('div');
|
|
1257
|
+
this.compileElement(tempEle, cnt, 'content', index);
|
|
1258
|
+
if (tempEle.childNodes.length !== 0) {
|
|
1259
|
+
ele.appendChild(tempEle);
|
|
1260
|
+
}
|
|
1261
|
+
if (this.isReact) {
|
|
1262
|
+
this.renderReactTemplates();
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
private compileElement(ele: HTEle, val: string, prop: string, index: number): void {
|
|
1266
|
+
let templateFn: Function;
|
|
1267
|
+
if (typeof val === 'string') {
|
|
1268
|
+
val = val.trim();
|
|
1269
|
+
if (this.isVue) {
|
|
1270
|
+
templateFn = compile(this.enableHtmlSanitizer ? SanitizeHtmlHelper.sanitize(val) : val);
|
|
1271
|
+
} else {
|
|
1272
|
+
ele.innerHTML = this.enableHtmlSanitizer ? SanitizeHtmlHelper.sanitize(val) : val;
|
|
1273
|
+
}
|
|
1274
|
+
} else {
|
|
1275
|
+
templateFn = compile(val);
|
|
1276
|
+
}
|
|
1277
|
+
let templateFUN: HTMLElement[];
|
|
1278
|
+
if (!isNOU(templateFn)) {
|
|
1279
|
+
templateFUN = templateFn({}, this, prop);
|
|
1280
|
+
}
|
|
1281
|
+
if (!isNOU(templateFn) && templateFUN.length > 0) {
|
|
1282
|
+
[].slice.call(templateFUN).forEach((el: HTEle): void => {
|
|
1283
|
+
ele.appendChild(el);
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
private headerTextCompile(element: HTEle, text: string, index: number): void {
|
|
1288
|
+
this.compileElement(element, text, 'headerTemplate', index);
|
|
1289
|
+
}
|
|
1290
|
+
private getContent(ele: HTEle, cnt: Str | HTEle | Function, callType: string, index: number): void {
|
|
1291
|
+
let eleStr: Str;
|
|
1292
|
+
cnt = isNOU(cnt) ? '' : cnt;
|
|
1293
|
+
if (typeof cnt === 'string' || isNOU((<HTEle>cnt).innerHTML)) {
|
|
1294
|
+
if (typeof cnt === 'string' && this.enableHtmlSanitizer) {
|
|
1295
|
+
cnt = SanitizeHtmlHelper.sanitize(<Str>cnt);
|
|
1296
|
+
}
|
|
1297
|
+
if ((<Str>cnt)[0] === '.' || (<Str>cnt)[0] === '#') {
|
|
1298
|
+
if (document.querySelectorAll(<string>cnt).length) {
|
|
1299
|
+
const eleVal: HTEle = <HTEle>document.querySelector(<string>cnt);
|
|
1300
|
+
eleStr = eleVal.outerHTML.trim();
|
|
1301
|
+
if (callType === 'clone') {
|
|
1302
|
+
ele.appendChild(eleVal.cloneNode(true));
|
|
1303
|
+
} else {
|
|
1304
|
+
ele.appendChild(eleVal);
|
|
1305
|
+
eleVal.style.display = '';
|
|
1306
|
+
}
|
|
1307
|
+
} else {
|
|
1308
|
+
this.templateCompile(ele, <Str>cnt, index);
|
|
1309
|
+
}
|
|
1310
|
+
} else {
|
|
1311
|
+
this.templateCompile(ele, <Str>cnt, index);
|
|
1312
|
+
}
|
|
1313
|
+
} else {
|
|
1314
|
+
ele.appendChild(cnt as HTMLElement);
|
|
1315
|
+
}
|
|
1316
|
+
if (!isNOU(eleStr)) {
|
|
1317
|
+
if (this.templateEle.indexOf(cnt.toString()) === -1) {
|
|
1318
|
+
this.templateEle.push(cnt.toString());
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
private getTrgContent(cntEle: HTEle, no: Str): HTEle {
|
|
1323
|
+
let ele: HTEle;
|
|
1324
|
+
if (this.element.classList.contains(CLS_NEST)) {
|
|
1325
|
+
ele = <HTEle>select('.' + CLS_NEST + '> .' + CLS_CONTENT + ' > #' + CLS_CONTENT + this.tabId + '_' + no, this.element);
|
|
1326
|
+
} else {
|
|
1327
|
+
ele = this.findEle(cntEle.children, CLS_CONTENT + this.tabId + '_' + no);
|
|
1328
|
+
}
|
|
1329
|
+
return ele;
|
|
1330
|
+
}
|
|
1331
|
+
private findEle(items: HTMLCollection, key: Str): HTEle {
|
|
1332
|
+
let ele: HTEle;
|
|
1333
|
+
for (let i: number = 0; i < items.length; i++) {
|
|
1334
|
+
if (items[i].id === key) {
|
|
1335
|
+
ele = <HTEle>items[i];
|
|
1336
|
+
break;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
return ele;
|
|
1340
|
+
}
|
|
1341
|
+
private isVertical(): boolean {
|
|
1342
|
+
const isVertical: boolean = (this.headerPlacement === 'Left' || this.headerPlacement === 'Right') ? true : false;
|
|
1343
|
+
this.scrCntClass = (isVertical) ? CLS_VSCRCNT : CLS_HSCRCNT;
|
|
1344
|
+
return isVertical;
|
|
1345
|
+
}
|
|
1346
|
+
private addVerticalClass(): void {
|
|
1347
|
+
if (this.isVertical()) {
|
|
1348
|
+
const tbPos: string = (this.headerPlacement === 'Left') ? CLS_VLEFT : CLS_VRIGHT;
|
|
1349
|
+
addClass([this.hdrEle], [CLS_VERTICAL, tbPos]);
|
|
1350
|
+
if (!this.element.classList.contains(CLS_NEST)) {
|
|
1351
|
+
addClass([this.element], [CLS_VTAB, tbPos]);
|
|
1352
|
+
} else {
|
|
1353
|
+
addClass([this.hdrEle], [CLS_VTAB, tbPos]);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
if (this.headerPlacement === 'Bottom') {
|
|
1357
|
+
addClass([this.hdrEle], [CLS_HBOTTOM]);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
private updatePopAnimationConfig(): void {
|
|
1361
|
+
this.show = { name: (this.isVertical() ? 'FadeIn' : 'SlideDown'), duration: 100 };
|
|
1362
|
+
this.hide = { name: (this.isVertical() ? 'FadeOut' : 'SlideUp'), duration: 100 };
|
|
1363
|
+
}
|
|
1364
|
+
private changeOrientation(place: Str): void {
|
|
1365
|
+
this.setOrientation(place, this.hdrEle);
|
|
1366
|
+
const activeTab: HTMLElement = this.hdrEle.querySelector('.' + CLS_ACTIVE);
|
|
1367
|
+
const isVertical: boolean = this.hdrEle.classList.contains(CLS_VERTICAL) ? true : false;
|
|
1368
|
+
removeClass([this.element], [CLS_VTAB]);
|
|
1369
|
+
removeClass([this.hdrEle], [CLS_VERTICAL, CLS_VLEFT, CLS_VRIGHT]);
|
|
1370
|
+
if (isVertical !== this.isVertical()) {
|
|
1371
|
+
this.changeToolbarOrientation();
|
|
1372
|
+
if (!isNOU(activeTab) && activeTab.classList.contains(CLS_TB_POPUP)) {
|
|
1373
|
+
this.popupHandler(activeTab);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
this.addVerticalClass();
|
|
1377
|
+
this.setActiveBorder();
|
|
1378
|
+
this.focusItem();
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
private focusItem(): void {
|
|
1382
|
+
const curActItem: HTEle = <HTEle>select(' #' + CLS_ITEM + this.tabId + '_' + this.selectedItem, this.hdrEle);
|
|
1383
|
+
if (!isNOU(curActItem)) {
|
|
1384
|
+
(<HTEle>curActItem.firstElementChild).focus();
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
private changeToolbarOrientation(): void {
|
|
1389
|
+
this.tbObj.setProperties({ height: (this.isVertical() ? '100%' : 'auto'), width: (this.isVertical() ? 'auto' : '100%') }, true);
|
|
1390
|
+
this.tbObj.changeOrientation();
|
|
1391
|
+
this.updatePopAnimationConfig();
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
private setOrientation(place: Str, ele: HTEle): void {
|
|
1395
|
+
const headerPos: number = Array.prototype.indexOf.call(this.element.children, ele);
|
|
1396
|
+
const contentPos: number = Array.prototype.indexOf.call(this.element.children, this.element.querySelector('.' + CLS_CONTENT));
|
|
1397
|
+
if (place === 'Bottom' && (contentPos > headerPos)) {
|
|
1398
|
+
this.element.appendChild(ele);
|
|
1399
|
+
} else {
|
|
1400
|
+
removeClass([ele], [CLS_HBOTTOM]);
|
|
1401
|
+
this.element.insertBefore(ele, select('.' + CLS_CONTENT, this.element));
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
private setCssClass(ele: HTEle, cls: Str, val: boolean): void {
|
|
1405
|
+
if (cls === '' || isNOU(cls)) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
const list: Str[] = cls.split(' ');
|
|
1409
|
+
for (let i: number = 0; i < list.length; i++) {
|
|
1410
|
+
if (val) {
|
|
1411
|
+
ele.classList.add(list[i]);
|
|
1412
|
+
} else {
|
|
1413
|
+
ele.classList.remove(list[i]);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
private loadContentInitMode(ele: HTEle): void {
|
|
1419
|
+
if (!ele) { return; }
|
|
1420
|
+
if (this.loadOn === 'Init') {
|
|
1421
|
+
for (let i = 0; i < this.items.length; i++) {
|
|
1422
|
+
if (<HTEle>this.cntEle.children.item(i)) {
|
|
1423
|
+
this.getContent(<HTEle>this.cntEle.children.item(i), this.items[i].content, 'render', i);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
private loadContentElement(): void {
|
|
1430
|
+
if (!this.isTemplate) {
|
|
1431
|
+
const ele: HTEle = <HTEle>this.cntEle.children.item(0);
|
|
1432
|
+
this.loadContentInitMode(ele);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
private setContentHeight(val: boolean): void {
|
|
1437
|
+
if (this.element.classList.contains(CLS_FILL)) {
|
|
1438
|
+
removeClass([this.element], [CLS_FILL]);
|
|
1439
|
+
}
|
|
1440
|
+
if (isNOU(this.cntEle)) {
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
const hdrEle: HTEle = this.getTabHeader();
|
|
1444
|
+
if (this.heightAdjustMode === 'None') {
|
|
1445
|
+
this.loadContentElement();
|
|
1446
|
+
if (this.height === 'auto') {
|
|
1447
|
+
return;
|
|
1448
|
+
} else {
|
|
1449
|
+
if (!this.isVertical()) {
|
|
1450
|
+
setStyle(this.cntEle, { 'height': (this.element.clientHeight - hdrEle.offsetHeight) + 'px' });
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
} else if (this.heightAdjustMode === 'Fill') {
|
|
1454
|
+
addClass([this.element], [CLS_FILL]);
|
|
1455
|
+
setStyle(this.element, { 'height': '100%' });
|
|
1456
|
+
this.loadContentElement();
|
|
1457
|
+
this.cntEle.style.height = 'calc(100% - ' + this.hdrEle.offsetHeight + 'px)';
|
|
1458
|
+
} else if (this.heightAdjustMode === 'Auto') {
|
|
1459
|
+
if (this.isTemplate === true) {
|
|
1460
|
+
const cnt: HTEle[] = selectAll('.' + CLS_CONTENT + ' > .' + CLS_ITEM, this.element);
|
|
1461
|
+
for (let i: number = 0; i < cnt.length; i++) {
|
|
1462
|
+
cnt[i].style.display = 'block';
|
|
1463
|
+
cnt[i].style.visibility = 'visible';
|
|
1464
|
+
this.maxHeight = Math.max(this.maxHeight, this.getHeight(cnt[i]));
|
|
1465
|
+
cnt[i].style.removeProperty('display');
|
|
1466
|
+
cnt[i].style.removeProperty('visibility');
|
|
1467
|
+
}
|
|
1468
|
+
} else {
|
|
1469
|
+
this.cntEle = <HTEle>select('.' + CLS_CONTENT, this.element);
|
|
1470
|
+
if (val === true && this.loadOn === 'Demand') {
|
|
1471
|
+
this.cntEle.appendChild(this.createContentElement(Number(this.extIndex(this.itemIndexArray[0]))));
|
|
1472
|
+
}
|
|
1473
|
+
const ele: HTEle = <HTEle>this.cntEle.children.item(0);
|
|
1474
|
+
for (let i: number = 0; i < this.items.length; i++) {
|
|
1475
|
+
this.getContent(ele, this.items[i].content, 'clone', i);
|
|
1476
|
+
this.maxHeight = Math.max(this.maxHeight, this.getHeight(ele));
|
|
1477
|
+
while (ele.firstChild) {
|
|
1478
|
+
ele.removeChild(ele.firstChild);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
if (this.isReact || this.isAngular || this.isVue) {
|
|
1482
|
+
this.clearTemplate(['content']);
|
|
1483
|
+
}
|
|
1484
|
+
this.templateEle = [];
|
|
1485
|
+
if (this.loadOn === 'Demand') {
|
|
1486
|
+
this.getContent(ele, this.items[0].content, 'render', 0);
|
|
1487
|
+
}
|
|
1488
|
+
this.loadContentInitMode(ele);
|
|
1489
|
+
if (this.prevIndex !== this.selectedItem) {
|
|
1490
|
+
ele.classList.remove(CLS_ACTIVE);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
setStyle(this.cntEle, { 'height': this.maxHeight + 'px' });
|
|
1494
|
+
} else {
|
|
1495
|
+
this.loadContentElement();
|
|
1496
|
+
setStyle(this.cntEle, { 'height': 'auto' });
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
private getHeight(ele: HTEle): number {
|
|
1500
|
+
const cs: CSSStyleDeclaration = window.getComputedStyle(ele);
|
|
1501
|
+
return ele.offsetHeight + parseFloat(cs.getPropertyValue('padding-top')) + parseFloat(cs.getPropertyValue('padding-bottom')) +
|
|
1502
|
+
parseFloat(cs.getPropertyValue('margin-top')) + parseFloat(cs.getPropertyValue('margin-bottom'));
|
|
1503
|
+
}
|
|
1504
|
+
private setActiveBorder(): void {
|
|
1505
|
+
const trgHdrEle: Element = this.getTabHeader();
|
|
1506
|
+
const trg: HTEle = <HTEle>select('.' + CLS_TB_ITEM + '.' + CLS_ACTIVE, trgHdrEle);
|
|
1507
|
+
if (isNOU(trg)) {
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
if (!this.reorderActiveTab) {
|
|
1511
|
+
if (trg.classList.contains(CLS_TB_POPUP) && !this.bdrLine.classList.contains(CLS_HIDDEN)) {
|
|
1512
|
+
this.bdrLine.classList.add(CLS_HIDDEN);
|
|
1513
|
+
}
|
|
1514
|
+
if (trgHdrEle && !trgHdrEle.classList.contains(CLS_REORDER_ACTIVE_ITEM)) {
|
|
1515
|
+
trgHdrEle.classList.add(CLS_REORDER_ACTIVE_ITEM);
|
|
1516
|
+
}
|
|
1517
|
+
} else if (trgHdrEle) {
|
|
1518
|
+
trgHdrEle.classList.remove(CLS_REORDER_ACTIVE_ITEM);
|
|
1519
|
+
}
|
|
1520
|
+
const root: HTEle = <HTEle>closest(trg, '.' + CLS_TAB);
|
|
1521
|
+
if (this.element !== root) {
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
this.tbItems = <HTEle>select('.' + CLS_TB_ITEMS, trgHdrEle);
|
|
1525
|
+
const bar: HTEle = <HTEle>select('.' + CLS_INDICATOR, trgHdrEle);
|
|
1526
|
+
const scrollCnt: HTEle = <HTEle>select('.' + CLS_TB_ITEMS + ' .' + this.scrCntClass, trgHdrEle);
|
|
1527
|
+
if (this.isVertical()) {
|
|
1528
|
+
setStyle(bar, { 'left': '', 'right': '' });
|
|
1529
|
+
const tbHeight: number = (isNOU(scrollCnt)) ? this.tbItems.offsetHeight : scrollCnt.offsetHeight;
|
|
1530
|
+
if (tbHeight !== 0) {
|
|
1531
|
+
setStyle(bar, { 'top': trg.offsetTop + 'px', 'height': trg.offsetHeight + 'px' });
|
|
1532
|
+
} else {
|
|
1533
|
+
setStyle(bar, { 'top': 0, 'height': 0 });
|
|
1534
|
+
}
|
|
1535
|
+
} else {
|
|
1536
|
+
if (this.overflowMode === 'MultiRow') {
|
|
1537
|
+
const top: number = this.headerPlacement === 'Bottom' ? trg.offsetTop : trg.offsetHeight + trg.offsetTop;
|
|
1538
|
+
setStyle(bar, { 'top': top + 'px', 'height': '' });
|
|
1539
|
+
} else {
|
|
1540
|
+
setStyle(bar, { 'top': '', 'height': '' });
|
|
1541
|
+
}
|
|
1542
|
+
let tbWidth: number = (isNOU(scrollCnt)) ? this.tbItems.offsetWidth : scrollCnt.offsetWidth;
|
|
1543
|
+
if (tbWidth !== 0) {
|
|
1544
|
+
setStyle(bar, { 'left': trg.offsetLeft + 'px', 'right': tbWidth - (trg.offsetLeft + trg.offsetWidth) + 'px' });
|
|
1545
|
+
} else {
|
|
1546
|
+
setStyle(bar, { 'left': 'auto', 'right': 'auto' });
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
if (!isNOU(this.bdrLine) && !trg.classList.contains(CLS_TB_POPUP)) {
|
|
1550
|
+
this.bdrLine.classList.remove(CLS_HIDDEN);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
private setActive(value: number, skipDataBind: boolean = false, isInteracted: boolean = false): void {
|
|
1554
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEM, this.getTabHeader());
|
|
1555
|
+
const trg: HTEle = this.tbItem[value];
|
|
1556
|
+
if (value < 0 || isNaN(value) || this.tbItem.length === 0 || !isNOU(trg) && trg.classList.contains(CLS_DISABLE)) {
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
if (value >= 0 && !skipDataBind) {
|
|
1560
|
+
this.allowServerDataBinding = false;
|
|
1561
|
+
this.setProperties({ selectedItem: value }, true);
|
|
1562
|
+
this.allowServerDataBinding = true;
|
|
1563
|
+
if (!this.initRender) {
|
|
1564
|
+
this.serverDataBind();
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
if (trg.classList.contains(CLS_ACTIVE)) {
|
|
1568
|
+
this.setActiveBorder();
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
if (!this.isTemplate) {
|
|
1572
|
+
attributes(trg.firstElementChild, { 'aria-controls': CLS_CONTENT + this.tabId + '_' + this.extIndex(trg.id) });
|
|
1573
|
+
}
|
|
1574
|
+
const id: Str = trg.id;
|
|
1575
|
+
this.removeActiveClass();
|
|
1576
|
+
trg.classList.add(CLS_ACTIVE);
|
|
1577
|
+
trg.firstElementChild.setAttribute('aria-selected', 'true');
|
|
1578
|
+
const no: number = Number(this.extIndex(id));
|
|
1579
|
+
if (isNOU(this.prevActiveEle)) {
|
|
1580
|
+
this.prevActiveEle = CLS_CONTENT + this.tabId + '_' + no;
|
|
1581
|
+
}
|
|
1582
|
+
if (this.isTemplate) {
|
|
1583
|
+
if (select('.' + CLS_CONTENT, this.element).children.length > 0) {
|
|
1584
|
+
const trg: HTEle = this.findEle(select('.' + CLS_CONTENT, this.element).children, CLS_CONTENT + this.tabId + '_' + no);
|
|
1585
|
+
if (!isNOU(trg)) {
|
|
1586
|
+
trg.classList.add(CLS_ACTIVE);
|
|
1587
|
+
}
|
|
1588
|
+
this.triggerAnimation(id, this.enableAnimation);
|
|
1589
|
+
}
|
|
1590
|
+
} else {
|
|
1591
|
+
this.cntEle = <HTEle>select('.' + CLS_TAB + ' > .' + CLS_CONTENT, this.element);
|
|
1592
|
+
while (this.loadOn === 'Dynamic' && this.cntEle.firstElementChild) {
|
|
1593
|
+
this.cntEle.removeChild(this.cntEle.firstElementChild);
|
|
1594
|
+
}
|
|
1595
|
+
const item: HTEle = this.getTrgContent(this.cntEle, this.extIndex(id));
|
|
1596
|
+
if (isNOU(item)) {
|
|
1597
|
+
this.cntEle.appendChild(this.createElement('div', {
|
|
1598
|
+
id: CLS_CONTENT + this.tabId + '_' + this.extIndex(id), className: CLS_ITEM + ' ' + CLS_ACTIVE,
|
|
1599
|
+
attrs: { role: 'tabpanel', 'aria-labelledby': CLS_ITEM + this.tabId + '_' + this.extIndex(id) }
|
|
1600
|
+
}));
|
|
1601
|
+
const eleTrg: HTEle = this.getTrgContent(this.cntEle, this.extIndex(id));
|
|
1602
|
+
const itemIndex: number = Array.prototype.indexOf.call(this.itemIndexArray, id);
|
|
1603
|
+
this.getContent(eleTrg, this.items[itemIndex].content, 'render', itemIndex);
|
|
1604
|
+
} else {
|
|
1605
|
+
item.classList.add(CLS_ACTIVE);
|
|
1606
|
+
}
|
|
1607
|
+
this.triggerAnimation(id, this.enableAnimation);
|
|
1608
|
+
}
|
|
1609
|
+
this.setActiveBorder();
|
|
1610
|
+
this.refreshItemVisibility(trg);
|
|
1611
|
+
if (!this.initRender && !skipDataBind) {
|
|
1612
|
+
const eventArg: SelectEventArgs = {
|
|
1613
|
+
previousItem: this.prevItem,
|
|
1614
|
+
previousIndex: this.prevIndex,
|
|
1615
|
+
selectedItem: trg,
|
|
1616
|
+
selectedIndex: value,
|
|
1617
|
+
selectedContent: <HTEle>select('#' + CLS_CONTENT + this.tabId + '_' + this.selectingID, this.content),
|
|
1618
|
+
isSwiped: this.isSwiped,
|
|
1619
|
+
isInteracted: isInteracted,
|
|
1620
|
+
preventFocus: false
|
|
1621
|
+
};
|
|
1622
|
+
this.trigger('selected', eventArg, (selectEventArgs: SelectEventArgs) => {
|
|
1623
|
+
if (!selectEventArgs.preventFocus) {
|
|
1624
|
+
(<HTEle>trg.firstElementChild).focus();
|
|
1625
|
+
}
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
private setItems(items: object[]): void {
|
|
1630
|
+
this.isReplace = true;
|
|
1631
|
+
this.tbItems = <HTEle>select('.' + CLS_TB_ITEMS, this.getTabHeader());
|
|
1632
|
+
this.tbObj.items = this.parseObject(items, 0);
|
|
1633
|
+
this.tbObj.dataBind();
|
|
1634
|
+
this.isReplace = false;
|
|
1635
|
+
}
|
|
1636
|
+
private setRTL(value: boolean): void {
|
|
1637
|
+
this.tbObj.enableRtl = value;
|
|
1638
|
+
this.tbObj.dataBind();
|
|
1639
|
+
this.setCssClass(this.element, CLS_RTL, value);
|
|
1640
|
+
this.refreshActiveBorder();
|
|
1641
|
+
}
|
|
1642
|
+
private refreshActiveBorder(): void {
|
|
1643
|
+
if (!isNOU(this.bdrLine)) {
|
|
1644
|
+
this.bdrLine.classList.add(CLS_HIDDEN);
|
|
1645
|
+
}
|
|
1646
|
+
this.setActiveBorder();
|
|
1647
|
+
}
|
|
1648
|
+
private showPopup(config: object): void {
|
|
1649
|
+
const tbPop: HTEle = <HTEle>select('.e-popup.e-toolbar-pop', this.hdrEle);
|
|
1650
|
+
if (tbPop && tbPop.classList.contains('e-popup-close')) {
|
|
1651
|
+
const tbPopObj: Popup = (<PopupModel>(tbPop && (<Instance>tbPop).ej2_instances[0])) as Popup;
|
|
1652
|
+
tbPopObj.position.X = (this.headerPlacement === 'Left' || this.element.classList.contains(CLS_RTL)) ? 'left' : 'right';
|
|
1653
|
+
tbPopObj.dataBind();
|
|
1654
|
+
tbPopObj.show(config);
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
private bindDraggable(): void {
|
|
1658
|
+
if (this.allowDragAndDrop) {
|
|
1659
|
+
const tabHeader: Element = this.element.querySelector('.' + CLS_HEADER);
|
|
1660
|
+
if (tabHeader){
|
|
1661
|
+
const items: NodeList = Array.prototype.slice.call(tabHeader.querySelectorAll('.' + CLS_TB_ITEM));
|
|
1662
|
+
items.forEach((element: HTMLElement) => {
|
|
1663
|
+
this.initializeDrag(element as HTMLElement);
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
private bindSwipeEvents(): void {
|
|
1669
|
+
if (this.swipeMode !== 'None') {
|
|
1670
|
+
this.touchModule = new Touch(this.cntEle, { swipe: this.swipeHandler.bind(this) });
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
private wireEvents(): void {
|
|
1674
|
+
this.bindDraggable();
|
|
1675
|
+
window.addEventListener('resize', this.resizeContext);
|
|
1676
|
+
EventHandler.add(this.element, 'mouseover', this.hoverHandler, this);
|
|
1677
|
+
EventHandler.add(this.element, 'keydown', this.spaceKeyDown, this);
|
|
1678
|
+
if (!isNOU(this.cntEle)) {
|
|
1679
|
+
this.bindSwipeEvents();
|
|
1680
|
+
}
|
|
1681
|
+
this.keyModule = new KeyboardEvents(this.element, { keyAction: this.keyHandler.bind(this), keyConfigs: this.keyConfigs });
|
|
1682
|
+
this.tabKeyModule = new KeyboardEvents(this.element, {
|
|
1683
|
+
keyAction: this.keyHandler.bind(this),
|
|
1684
|
+
keyConfigs: { openPopup: 'shift+f10', tab: 'tab', shiftTab: 'shift+tab' },
|
|
1685
|
+
eventName: 'keydown'
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
private unWireEvents(): void {
|
|
1689
|
+
if (!isNOU(this.keyModule)) {
|
|
1690
|
+
this.keyModule.destroy();
|
|
1691
|
+
}
|
|
1692
|
+
if (!isNOU(this.tabKeyModule)) {
|
|
1693
|
+
this.tabKeyModule.destroy();
|
|
1694
|
+
}
|
|
1695
|
+
if (!isNOU(this.cntEle) && !isNOU(this.touchModule)) {
|
|
1696
|
+
this.touchModule.destroy();
|
|
1697
|
+
this.touchModule = null;
|
|
1698
|
+
}
|
|
1699
|
+
window.removeEventListener('resize', this.resizeContext);
|
|
1700
|
+
EventHandler.remove(this.element, 'mouseover', this.hoverHandler);
|
|
1701
|
+
EventHandler.remove(this.element, 'keydown', this.spaceKeyDown);
|
|
1702
|
+
this.element.classList.remove(CLS_RTL);
|
|
1703
|
+
this.element.classList.remove(CLS_FOCUS);
|
|
1704
|
+
}
|
|
1705
|
+
private clickHandler(args: ClickEventArgs): void {
|
|
1706
|
+
this.element.classList.remove(CLS_FOCUS);
|
|
1707
|
+
const trg: HTEle = <HTEle>args.originalEvent.target;
|
|
1708
|
+
const trgParent: HTEle = <HTEle>closest(trg, '.' + CLS_TB_ITEM);
|
|
1709
|
+
const trgIndex: number = this.getEleIndex(trgParent);
|
|
1710
|
+
if (trg.classList.contains(CLS_ICON_CLOSE)) {
|
|
1711
|
+
this.removeTab(trgIndex);
|
|
1712
|
+
} else if (this.isVertical() && closest(trg, '.' + CLS_HOR_NAV)) {
|
|
1713
|
+
this.showPopup(this.show);
|
|
1714
|
+
} else {
|
|
1715
|
+
this.isPopup = false;
|
|
1716
|
+
if (!isNOU(trgParent) && (trgIndex !== this.selectedItem)) {
|
|
1717
|
+
this.selectTab(trgIndex, args.originalEvent, true);
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
private swipeHandler(e: SwipeEventArgs): void {
|
|
1722
|
+
if ((e.velocity < 3 && isNullOrUndefined(e.originalEvent.changedTouches)) ||
|
|
1723
|
+
(this.swipeMode === 'Touch' && ((e.originalEvent.type === 'mouseup') || e.originalEvent.type === 'mouseleave')) ||
|
|
1724
|
+
(this.swipeMode === 'Mouse' && e.originalEvent.type === 'touchend') || (this.swipeMode === 'None')) {
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
if (this.isNested) {
|
|
1728
|
+
this.element.setAttribute('data-swipe', 'true');
|
|
1729
|
+
}
|
|
1730
|
+
const nestedTab: HTMLElement = this.element.querySelector('[data-swipe="true"]');
|
|
1731
|
+
if (nestedTab) {
|
|
1732
|
+
nestedTab.removeAttribute('data-swipe');
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
this.isSwiped = true;
|
|
1736
|
+
if (e.swipeDirection === 'Right' && this.selectedItem !== 0) {
|
|
1737
|
+
for (let k: number = this.selectedItem - 1; k >= 0; k--) {
|
|
1738
|
+
if (!this.tbItem[k].classList.contains(CLS_HIDDEN)) {
|
|
1739
|
+
this.selectTab(k, null, true);
|
|
1740
|
+
break;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
} else if (e.swipeDirection === 'Left' && (this.selectedItem !== selectAll('.' + CLS_TB_ITEM, this.element).length - 1)) {
|
|
1744
|
+
for (let i: number = this.selectedItem + 1; i < this.tbItem.length; i++) {
|
|
1745
|
+
if (!this.tbItem[i].classList.contains(CLS_HIDDEN)) {
|
|
1746
|
+
this.selectTab(i, null, true);
|
|
1747
|
+
break;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
this.isSwiped = false;
|
|
1752
|
+
}
|
|
1753
|
+
private spaceKeyDown(e: KeyboardEvent): void {
|
|
1754
|
+
if ((e.keyCode === 32 && e.which === 32) || (e.keyCode === 35 && e.which === 35)) {
|
|
1755
|
+
const clstHead: HTEle = <HTEle>closest(<Element>e.target, '.' + CLS_HEADER);
|
|
1756
|
+
if (!isNOU(clstHead)) {
|
|
1757
|
+
e.preventDefault();
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
private keyHandler(e: KeyboardEventArgs): void {
|
|
1762
|
+
if (this.element.classList.contains(CLS_DISABLE)) {
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
this.element.classList.add(CLS_FOCUS);
|
|
1766
|
+
const trg: HTEle = <HTEle>e.target;
|
|
1767
|
+
const tabHeader: HTMLElement = this.getTabHeader();
|
|
1768
|
+
const actEle: HTEle = <HTEle>select('.' + CLS_ACTIVE, tabHeader);
|
|
1769
|
+
this.popEle = <DomElements>select('.' + CLS_TB_POP, tabHeader);
|
|
1770
|
+
if (!isNOU(this.popEle)) {
|
|
1771
|
+
this.popObj = <Popup>this.popEle.ej2_instances[0];
|
|
1772
|
+
}
|
|
1773
|
+
const item: HTEle = <HTEle>closest(document.activeElement, '.' + CLS_TB_ITEM);
|
|
1774
|
+
const trgParent: HTEle = <HTEle>closest(trg, '.' + CLS_TB_ITEM);
|
|
1775
|
+
switch (e.action) {
|
|
1776
|
+
case 'space':
|
|
1777
|
+
case 'enter':
|
|
1778
|
+
if (trg.parentElement.classList.contains(CLS_DISABLE)) {
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
if (e.action === 'enter' && trg.classList.contains('e-hor-nav')) {
|
|
1782
|
+
this.showPopup(this.show);
|
|
1783
|
+
break;
|
|
1784
|
+
}
|
|
1785
|
+
this.keyPressed(trg);
|
|
1786
|
+
break;
|
|
1787
|
+
case 'tab':
|
|
1788
|
+
case 'shiftTab':
|
|
1789
|
+
if (trg.classList.contains(CLS_WRAP)
|
|
1790
|
+
&& (<HTEle>closest(trg, '.' + CLS_TB_ITEM)).classList.contains(CLS_ACTIVE) === false) {
|
|
1791
|
+
trg.setAttribute('tabindex', trg.getAttribute('data-tabindex'));
|
|
1792
|
+
}
|
|
1793
|
+
if (this.popObj && isVisible(this.popObj.element)) {
|
|
1794
|
+
this.popObj.hide(this.hide);
|
|
1795
|
+
}
|
|
1796
|
+
if (!isNOU(actEle) && actEle.children.item(0).getAttribute('tabindex') === '-1') {
|
|
1797
|
+
actEle.children.item(0).setAttribute('tabindex', '0');
|
|
1798
|
+
}
|
|
1799
|
+
break;
|
|
1800
|
+
case 'moveLeft':
|
|
1801
|
+
case 'moveRight':
|
|
1802
|
+
if (!isNOU(item)) {
|
|
1803
|
+
this.refreshItemVisibility(item);
|
|
1804
|
+
}
|
|
1805
|
+
break;
|
|
1806
|
+
case 'openPopup':
|
|
1807
|
+
if (!isNOU(e.target) && ((e.target as HTMLElement).classList.contains(CLS_WRAP))) {
|
|
1808
|
+
e.preventDefault();
|
|
1809
|
+
}
|
|
1810
|
+
if (!isNOU(this.popEle) && this.popEle.classList.contains(CLS_POPUP_CLOSE)) {
|
|
1811
|
+
this.popObj.show(this.show);
|
|
1812
|
+
}
|
|
1813
|
+
break;
|
|
1814
|
+
case 'delete':
|
|
1815
|
+
if (this.showCloseButton === true && !isNOU(trgParent)) {
|
|
1816
|
+
const nxtSib: HTEle = <HTEle>trgParent.nextSibling;
|
|
1817
|
+
if (!isNOU(nxtSib) && nxtSib.classList.contains(CLS_TB_ITEM)) {
|
|
1818
|
+
(<HTEle>nxtSib.firstElementChild).focus();
|
|
1819
|
+
}
|
|
1820
|
+
this.removeTab(this.getEleIndex(trgParent));
|
|
1821
|
+
}
|
|
1822
|
+
this.setActiveBorder();
|
|
1823
|
+
break;
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
private refreshItemVisibility(target: HTEle): void {
|
|
1827
|
+
const scrCnt: HTEle = <HTEle>select('.' + this.scrCntClass, this.tbItems);
|
|
1828
|
+
if (!this.isVertical() && !isNOU(scrCnt)) {
|
|
1829
|
+
const scrBar: HTEle = <HTEle>select('.e-hscroll-bar', this.tbItems);
|
|
1830
|
+
const scrStart: number = scrBar.scrollLeft;
|
|
1831
|
+
const scrEnd: number = scrStart + scrBar.offsetWidth;
|
|
1832
|
+
const eleStart: number = target.offsetLeft;
|
|
1833
|
+
const eleWidth: number = target.offsetWidth;
|
|
1834
|
+
const eleEnd: number = target.offsetLeft + target.offsetWidth;
|
|
1835
|
+
if ((scrStart < eleStart) && (scrEnd < eleEnd)) {
|
|
1836
|
+
const eleViewRange: number = scrEnd - eleStart;
|
|
1837
|
+
scrBar.scrollLeft = scrStart + (eleWidth - eleViewRange);
|
|
1838
|
+
} else {
|
|
1839
|
+
if ((scrStart > eleStart) && (scrEnd > eleEnd)) {
|
|
1840
|
+
const eleViewRange: number = eleEnd - scrStart;
|
|
1841
|
+
scrBar.scrollLeft = scrStart - (eleWidth - eleViewRange);
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
} else {
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
private getIndexFromEle (id: string): number {
|
|
1849
|
+
return parseInt(id.substring(id.lastIndexOf('_') + 1), 10);
|
|
1850
|
+
}
|
|
1851
|
+
private hoverHandler(e: MouseEventArgs): void {
|
|
1852
|
+
const trg: HTEle = <HTEle>e.target;
|
|
1853
|
+
if (!isNOU(trg.classList) && trg.classList.contains(CLS_ICON_CLOSE)) {
|
|
1854
|
+
trg.setAttribute('title', new L10n('tab', { closeButtonTitle: this.title }, this.locale).getConstant('closeButtonTitle'));
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
private evalOnPropertyChangeItems(newProp: TabModel, oldProp: TabModel): void {
|
|
1858
|
+
if (!(newProp.items instanceof Array && oldProp.items instanceof Array)) {
|
|
1859
|
+
const changedProp: Object[] = Object.keys(newProp.items);
|
|
1860
|
+
for (let i: number = 0; i < changedProp.length; i++) {
|
|
1861
|
+
const index: number = parseInt(Object.keys(newProp.items)[i], 10);
|
|
1862
|
+
const properties: string[] = Object.keys(newProp.items[index]);
|
|
1863
|
+
for (let j: number = 0; j < properties.length; j++) {
|
|
1864
|
+
const oldVal: Str = Object(oldProp.items[index])[properties[j]];
|
|
1865
|
+
const newVal: Str | Object = Object(newProp.items[index])[properties[j]];
|
|
1866
|
+
const hdr: HTEle = <HTEle>this.element.querySelectorAll('.' + CLS_TB_ITEM)[index];
|
|
1867
|
+
let itemIndex: number;
|
|
1868
|
+
if (hdr && !isNOU(hdr.id) && hdr.id !== '') {
|
|
1869
|
+
itemIndex = this.getIndexFromEle(hdr.id);
|
|
1870
|
+
} else {
|
|
1871
|
+
itemIndex = index;
|
|
1872
|
+
}
|
|
1873
|
+
const hdrItem: HTEle = <HTEle>select('.' + CLS_TB_ITEMS + ' #' + CLS_ITEM + this.tabId + '_' + itemIndex, this.element);
|
|
1874
|
+
const cntItem: HTEle = <HTEle>select('.' + CLS_CONTENT + ' #' + CLS_CONTENT + this.tabId + '_' + itemIndex, this.element);
|
|
1875
|
+
if (properties[j] === 'header' || properties[j] === 'headerTemplate') {
|
|
1876
|
+
const icon: Str | Object = (isNOU(this.items[index].header) ||
|
|
1877
|
+
isNOU(this.items[index].header.iconCss)) ? '' : this.items[index].header.iconCss;
|
|
1878
|
+
const textVal: Str | Object = this.items[index].headerTemplate || this.items[index].header.text;
|
|
1879
|
+
if (properties[j] === 'headerTemplate') {
|
|
1880
|
+
this.clearTabTemplate(hdrItem, properties[j], CLS_TB_ITEM);
|
|
1881
|
+
}
|
|
1882
|
+
if ((textVal === '') && (icon === '')) {
|
|
1883
|
+
this.removeTab(index);
|
|
1884
|
+
} else {
|
|
1885
|
+
this.tbId = hdr.id;
|
|
1886
|
+
const arr: Object[] = [];
|
|
1887
|
+
arr.push(<TabItemModel>this.items[index]);
|
|
1888
|
+
this.items.splice(index, 1);
|
|
1889
|
+
this.itemIndexArray.splice(index, 1);
|
|
1890
|
+
this.tbObj.items.splice(index, 1);
|
|
1891
|
+
const isHiddenEle: boolean = hdrItem.classList.contains(CLS_HIDDEN);
|
|
1892
|
+
detach(hdrItem);
|
|
1893
|
+
this.isReplace = true;
|
|
1894
|
+
this.addTab(arr, index);
|
|
1895
|
+
if (isHiddenEle) {
|
|
1896
|
+
this.hideTab(index);
|
|
1897
|
+
}
|
|
1898
|
+
this.isReplace = false;
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
if (properties[j] === 'content' && !isNOU(cntItem)) {
|
|
1902
|
+
const strVal: boolean = typeof newVal === 'string' || isNOU((<HTEle>newVal).innerHTML);
|
|
1903
|
+
if (strVal && ((<Str>newVal)[0] === '.' || (<Str>newVal)[0] === '#') && (<Str>newVal).length) {
|
|
1904
|
+
const eleVal: HTEle = <HTEle>document.querySelector(<Str>newVal);
|
|
1905
|
+
cntItem.appendChild(eleVal);
|
|
1906
|
+
eleVal.style.display = '';
|
|
1907
|
+
} else if (newVal === '' && oldVal[0] === '#') {
|
|
1908
|
+
(<HTEle>document.body.appendChild(this.element.querySelector(oldVal))).style.display = 'none';
|
|
1909
|
+
cntItem.innerHTML = <Str>newVal;
|
|
1910
|
+
} else if (this.isAngular || this.isReact) {
|
|
1911
|
+
this.clearTabTemplate(cntItem, properties[j], CLS_ITEM);
|
|
1912
|
+
cntItem.innerHTML = '';
|
|
1913
|
+
this.templateCompile(cntItem, <Str>newVal, index);
|
|
1914
|
+
} else if (typeof newVal !== 'function') {
|
|
1915
|
+
cntItem.innerHTML = <Str>newVal;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
if (properties[j] === 'cssClass') {
|
|
1919
|
+
if (!isNOU(hdrItem)) {
|
|
1920
|
+
hdrItem.classList.remove(oldVal);
|
|
1921
|
+
hdrItem.classList.add(<Str>newVal);
|
|
1922
|
+
}
|
|
1923
|
+
if (!isNOU(cntItem)) {
|
|
1924
|
+
cntItem.classList.remove(oldVal);
|
|
1925
|
+
cntItem.classList.add(<Str>newVal);
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
if (properties[j] === 'disabled') {
|
|
1929
|
+
this.enableTab(index, ((newVal === true) ? false : true));
|
|
1930
|
+
}
|
|
1931
|
+
if (properties[j] === 'visible') {
|
|
1932
|
+
this.hideTab(index, ((newVal === true) ? false : true));
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
if (this.isReact && (this as Record<string, any>).portals && (this as Record<string, any>).portals.length > 0) {
|
|
1937
|
+
this.renderReactTemplates(() => {
|
|
1938
|
+
this.refreshActiveTabBorder();
|
|
1939
|
+
});
|
|
1940
|
+
}
|
|
1941
|
+
} else {
|
|
1942
|
+
this.lastIndex = 0;
|
|
1943
|
+
if (isNOU(this.tbObj)) {
|
|
1944
|
+
this.reRenderItems();
|
|
1945
|
+
} else {
|
|
1946
|
+
if (this.isReact || this.isAngular) {
|
|
1947
|
+
this.clearTemplate();
|
|
1948
|
+
}
|
|
1949
|
+
this.setItems(<TabItemModel[]>newProp.items);
|
|
1950
|
+
if (this.templateEle.length > 0) {
|
|
1951
|
+
this.expTemplateContent();
|
|
1952
|
+
}
|
|
1953
|
+
this.templateEle = [];
|
|
1954
|
+
const selectElement: HTEle = <HTEle>select('.' + CLS_TAB + ' > .' + CLS_CONTENT, this.element);
|
|
1955
|
+
while (selectElement.firstElementChild) {
|
|
1956
|
+
detach(selectElement.firstElementChild);
|
|
1957
|
+
}
|
|
1958
|
+
this.select(this.selectedItem);
|
|
1959
|
+
this.draggableItems = [];
|
|
1960
|
+
this.bindDraggable();
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
private clearTabTemplate(templateEle: HTMLElement, templateName: string, className: string): void {
|
|
1966
|
+
if(!this.clearTemplates) {
|
|
1967
|
+
return;
|
|
1968
|
+
}
|
|
1969
|
+
if ((this as Record<string, any>).registeredTemplate && (this as Record<string, any>).registeredTemplate[templateName]) {
|
|
1970
|
+
const registeredTemplates: Record<string, any> = (this as Record<string, any>).registeredTemplate;
|
|
1971
|
+
for (let index = 0; index < registeredTemplates[templateName].length; index++) {
|
|
1972
|
+
const registeredItem = registeredTemplates[templateName][index].rootNodes[0];
|
|
1973
|
+
const closestItem = closest(registeredItem, '.' + className);
|
|
1974
|
+
if (!isNullOrUndefined(closestItem) && closestItem === templateEle) {
|
|
1975
|
+
this.clearTemplate([templateName], [registeredTemplates[templateName][index]]);
|
|
1976
|
+
break;
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
} else if ((this as Record<string, any>).portals && (this as Record<string, any>).portals.length > 0) {
|
|
1980
|
+
const portals: Record<string, any>[] = (this as Record<string, any>).portals;
|
|
1981
|
+
for (let index = 0; index < portals.length; index++) {
|
|
1982
|
+
const portalItem: Record<string, any> = portals[index];
|
|
1983
|
+
const closestItem: Element = closest(portalItem.containerInfo, '.' + className);
|
|
1984
|
+
if (!isNullOrUndefined(closestItem) && closestItem === templateEle) {
|
|
1985
|
+
this.clearTemplate([templateName], index);
|
|
1986
|
+
break;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
private initializeDrag(target: HTEle): void {
|
|
1993
|
+
let dragObj: Draggable = new Draggable(target, {
|
|
1994
|
+
dragArea: this.dragArea,
|
|
1995
|
+
dragTarget: '.' + CLS_TB_ITEM,
|
|
1996
|
+
clone: true,
|
|
1997
|
+
helper: this.helper.bind(this),
|
|
1998
|
+
dragStart: this.itemDragStart.bind(this),
|
|
1999
|
+
drag: (e: DragArgs) => {
|
|
2000
|
+
let dragIndex: number = this.getEleIndex(this.dragItem);
|
|
2001
|
+
let dropIndex: number;
|
|
2002
|
+
let dropItem: HTMLElement;
|
|
2003
|
+
let dragArgs: DragEventArgs = {
|
|
2004
|
+
draggedItem: <HTMLElement>this.dragItem,
|
|
2005
|
+
event: e.event,
|
|
2006
|
+
target: e.target,
|
|
2007
|
+
droppedItem: <HTMLElement>e.target.closest('.' + CLS_TB_ITEM),
|
|
2008
|
+
clonedElement: this.cloneElement,
|
|
2009
|
+
index: dragIndex
|
|
2010
|
+
};
|
|
2011
|
+
if (!isNOU(e.target.closest('.' + CLS_TAB)) && !e.target.closest('.' + CLS_TAB).isEqualNode(this.element) &&
|
|
2012
|
+
this.dragArea !== '.' + CLS_HEADER) {
|
|
2013
|
+
this.trigger('dragging', dragArgs);
|
|
2014
|
+
} else {
|
|
2015
|
+
if (!(e.target.closest(this.dragArea)) && this.overflowMode !== 'Popup') {
|
|
2016
|
+
document.body.style.cursor = 'not-allowed';
|
|
2017
|
+
addClass([this.cloneElement], CLS_HIDDEN);
|
|
2018
|
+
if (this.dragItem.classList.contains(CLS_HIDDEN)) {
|
|
2019
|
+
removeClass([this.dragItem], CLS_HIDDEN);
|
|
2020
|
+
}
|
|
2021
|
+
(<HTEle>this.dragItem.querySelector('.' + CLS_WRAP)).style.visibility = 'visible';
|
|
2022
|
+
} else {
|
|
2023
|
+
document.body.style.cursor = '';
|
|
2024
|
+
(<HTEle>this.dragItem.querySelector('.' + CLS_WRAP)).style.visibility = 'hidden';
|
|
2025
|
+
if (this.cloneElement.classList.contains(CLS_HIDDEN)) {
|
|
2026
|
+
removeClass([this.cloneElement], CLS_HIDDEN);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
if (this.overflowMode === 'Scrollable' && !isNOU(this.element.querySelector('.e-hscroll'))) {
|
|
2030
|
+
let scrollRightNavEle: HTMLElement = this.element.querySelector('.e-scroll-right-nav');
|
|
2031
|
+
let scrollLeftNavEle: HTMLElement = this.element.querySelector('.e-scroll-left-nav');
|
|
2032
|
+
let hscrollBar: HTMLElement = this.element.querySelector('.e-hscroll-bar');
|
|
2033
|
+
if (!isNOU(scrollRightNavEle) && Math.abs((scrollRightNavEle.offsetWidth / 2) +
|
|
2034
|
+
scrollRightNavEle.offsetLeft) > this.cloneElement.offsetLeft + this.cloneElement.offsetWidth) {
|
|
2035
|
+
hscrollBar.scrollLeft -= 10;
|
|
2036
|
+
}
|
|
2037
|
+
if (!isNOU(scrollLeftNavEle) && Math.abs((scrollLeftNavEle.offsetLeft + scrollLeftNavEle.offsetWidth) -
|
|
2038
|
+
this.cloneElement.offsetLeft) > (scrollLeftNavEle.offsetWidth / 2)) {
|
|
2039
|
+
hscrollBar.scrollLeft += 10;
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
this.cloneElement.style.pointerEvents = 'none';
|
|
2043
|
+
dropItem = <HTMLElement>closest(e.target, '.' + CLS_TB_ITEM + '.e-draggable');
|
|
2044
|
+
let scrollContentWidth: number = 0;
|
|
2045
|
+
if (this.overflowMode === 'Scrollable' && !isNOU(this.element.querySelector('.e-hscroll'))) {
|
|
2046
|
+
scrollContentWidth = (<HTMLElement>this.element.querySelector('.e-hscroll-content')).offsetWidth;
|
|
2047
|
+
}
|
|
2048
|
+
if (dropItem != null && !dropItem.isSameNode(this.dragItem) &&
|
|
2049
|
+
dropItem.closest('.' + CLS_TAB).isSameNode(this.dragItem.closest('.' + CLS_TAB))) {
|
|
2050
|
+
dropIndex = this.getEleIndex(dropItem);
|
|
2051
|
+
if (dropIndex < dragIndex &&
|
|
2052
|
+
(Math.abs((dropItem.offsetLeft + dropItem.offsetWidth) -
|
|
2053
|
+
this.cloneElement.offsetLeft) > (dropItem.offsetWidth / 2))) {
|
|
2054
|
+
this.dragAction(dropItem, dragIndex, dropIndex);
|
|
2055
|
+
}
|
|
2056
|
+
if (dropIndex > dragIndex &&
|
|
2057
|
+
(Math.abs(dropItem.offsetWidth / 2) + dropItem.offsetLeft -
|
|
2058
|
+
scrollContentWidth) < this.cloneElement.offsetLeft + this.cloneElement.offsetWidth) {
|
|
2059
|
+
this.dragAction(dropItem, dragIndex, dropIndex);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
this.droppedIndex = this.getEleIndex(this.dragItem);
|
|
2063
|
+
this.trigger('dragging', dragArgs);
|
|
2064
|
+
}
|
|
2065
|
+
},
|
|
2066
|
+
dragStop: this.itemDragStop.bind(this)
|
|
2067
|
+
});
|
|
2068
|
+
this.draggableItems.push(dragObj);
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
private helper(e: { sender: MouseEvent & TouchEvent, element: HTMLElement }): HTMLElement {
|
|
2072
|
+
this.cloneElement = this.createElement('div');
|
|
2073
|
+
if (e.element) {
|
|
2074
|
+
this.cloneElement = <HTMLElement>(e.element.cloneNode(true));
|
|
2075
|
+
addClass([this.cloneElement], 'e-tab-clone-element');
|
|
2076
|
+
if (this.element.querySelector('.' + CLS_HEADER).classList.contains(CLS_CLOSE_SHOW)) {
|
|
2077
|
+
addClass([this.cloneElement], CLS_CLOSE_SHOW);
|
|
2078
|
+
}
|
|
2079
|
+
removeClass([this.cloneElement.querySelector('.' + CLS_WRAP)], 'e-ripple');
|
|
2080
|
+
if (!isNOU(this.cloneElement.querySelector('.e-ripple-element'))) {
|
|
2081
|
+
remove(this.cloneElement.querySelector('.e-ripple-element'));
|
|
2082
|
+
}
|
|
2083
|
+
document.body.appendChild(this.cloneElement);
|
|
2084
|
+
}
|
|
2085
|
+
return this.cloneElement;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
private itemDragStart(e: DragArgs): void {
|
|
2089
|
+
this.draggingItems = this.items.map((x: TabItemModel) => x);
|
|
2090
|
+
this.dragItem = e.element;
|
|
2091
|
+
let dragArgs: DragEventArgs = {
|
|
2092
|
+
draggedItem: e.element,
|
|
2093
|
+
event: e.event,
|
|
2094
|
+
target: e.target,
|
|
2095
|
+
droppedItem: null,
|
|
2096
|
+
index: this.getEleIndex(this.dragItem),
|
|
2097
|
+
clonedElement: this.cloneElement,
|
|
2098
|
+
cancel: false
|
|
2099
|
+
};
|
|
2100
|
+
this.trigger('onDragStart', dragArgs, (tabItemDragArgs: DragEventArgs) => {
|
|
2101
|
+
if (tabItemDragArgs.cancel) {
|
|
2102
|
+
const dragObj: Draggable = (e.element as EJ2Instance).ej2_instances[0] as Draggable;
|
|
2103
|
+
if (!isNullOrUndefined(dragObj)) {
|
|
2104
|
+
dragObj.intDestroy(e.event);
|
|
2105
|
+
}
|
|
2106
|
+
detach(this.cloneElement);
|
|
2107
|
+
} else {
|
|
2108
|
+
this.removeActiveClass();
|
|
2109
|
+
addClass([this.tbItems.querySelector('.' + CLS_INDICATOR)], CLS_HIDDEN);
|
|
2110
|
+
(<HTEle>this.dragItem.querySelector('.' + CLS_WRAP)).style.visibility = 'hidden';
|
|
2111
|
+
}
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
private dragAction(dropItem: HTMLElement, dragsIndex: number, dropIndex: number): void {
|
|
2116
|
+
if (this.items.length > 0) {
|
|
2117
|
+
let item: TabItemModel = this.draggingItems[dragsIndex];
|
|
2118
|
+
this.draggingItems.splice(dragsIndex, 1);
|
|
2119
|
+
this.draggingItems.splice(dropIndex, 0, item);
|
|
2120
|
+
}
|
|
2121
|
+
if (this.overflowMode === 'MultiRow') {
|
|
2122
|
+
dropItem.parentNode.insertBefore(this.dragItem, dropItem.nextElementSibling);
|
|
2123
|
+
}
|
|
2124
|
+
if (dragsIndex > dropIndex) {
|
|
2125
|
+
if (!(this.dragItem.parentElement).isSameNode(dropItem.parentElement)) {
|
|
2126
|
+
if (this.overflowMode === 'Extended') {
|
|
2127
|
+
if (dropItem.isSameNode(dropItem.parentElement.lastChild)) {
|
|
2128
|
+
let popupContainer: Node = this.dragItem.parentNode;
|
|
2129
|
+
dropItem.parentNode.insertBefore(this.dragItem, dropItem);
|
|
2130
|
+
popupContainer.insertBefore(dropItem.parentElement.lastChild, popupContainer.childNodes[0]);
|
|
2131
|
+
} else {
|
|
2132
|
+
this.dragItem.parentNode.insertBefore(
|
|
2133
|
+
(dropItem.parentElement.lastChild), this.dragItem.parentElement.childNodes[0]);
|
|
2134
|
+
dropItem.parentNode.insertBefore(this.dragItem, dropItem);
|
|
2135
|
+
}
|
|
2136
|
+
} else {
|
|
2137
|
+
let lastEle: HTMLElement = <HTEle>(dropItem.parentElement).lastChild;
|
|
2138
|
+
if (dropItem.isSameNode(lastEle)) {
|
|
2139
|
+
let popupContainer: Node = <HTEle>this.dragItem.parentNode;
|
|
2140
|
+
dropItem.parentNode.insertBefore(this.dragItem, dropItem);
|
|
2141
|
+
popupContainer.insertBefore(lastEle, popupContainer.childNodes[0]);
|
|
2142
|
+
} else {
|
|
2143
|
+
this.dragItem.parentNode.insertBefore(
|
|
2144
|
+
(dropItem.parentElement).lastChild, this.dragItem.parentElement.childNodes[0]);
|
|
2145
|
+
dropItem.parentNode.insertBefore(this.dragItem, dropItem);
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
} else {
|
|
2149
|
+
this.dragItem.parentNode.insertBefore(this.dragItem, dropItem);
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
if (dragsIndex < dropIndex) {
|
|
2153
|
+
if (!(this.dragItem.parentElement).isSameNode(dropItem.parentElement)) {
|
|
2154
|
+
if (this.overflowMode === 'Extended') {
|
|
2155
|
+
this.dragItem.parentElement.appendChild(dropItem.parentElement.firstElementChild);
|
|
2156
|
+
dropItem.parentNode.insertBefore(this.dragItem, dropItem.nextSibling);
|
|
2157
|
+
} else {
|
|
2158
|
+
this.dragItem.parentNode.insertBefore(
|
|
2159
|
+
(dropItem.parentElement).lastChild, this.dragItem.parentElement.childNodes[0]);
|
|
2160
|
+
dropItem.parentNode.insertBefore(this.dragItem, dropItem);
|
|
2161
|
+
}
|
|
2162
|
+
} else {
|
|
2163
|
+
this.dragItem.parentNode.insertBefore(this.dragItem, dropItem.nextElementSibling);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
private itemDragStop(e: DropEventArgs): void {
|
|
2169
|
+
detach(this.cloneElement);
|
|
2170
|
+
this.cloneElement = null;
|
|
2171
|
+
(<HTEle>this.dragItem.querySelector('.' + CLS_WRAP)).style.visibility = 'visible';
|
|
2172
|
+
document.body.style.cursor = '';
|
|
2173
|
+
let dragStopArgs: DragEventArgs = {
|
|
2174
|
+
draggedItem: <HTEle>this.dragItem,
|
|
2175
|
+
event: e.event,
|
|
2176
|
+
target: e.target,
|
|
2177
|
+
droppedItem: this.tbItem[this.droppedIndex],
|
|
2178
|
+
clonedElement: null,
|
|
2179
|
+
index: this.droppedIndex,
|
|
2180
|
+
cancel: false
|
|
2181
|
+
};
|
|
2182
|
+
this.trigger('dragged', dragStopArgs, (tabItemDropArgs: DragEventArgs) => {
|
|
2183
|
+
if (tabItemDropArgs.cancel) {
|
|
2184
|
+
this.refresh();
|
|
2185
|
+
} else {
|
|
2186
|
+
if (this.items.length > 0 && this.draggingItems.length > 0) {
|
|
2187
|
+
this.items = this.draggingItems;
|
|
2188
|
+
this.selectedItem = isNOU(this.droppedIndex) ? this.getEleIndex(this.dragItem) : this.droppedIndex;
|
|
2189
|
+
this.refresh();
|
|
2190
|
+
} else {
|
|
2191
|
+
(<HTEle>this.dragItem.querySelector('.' + CLS_WRAP)).style.visibility = '';
|
|
2192
|
+
removeClass([<HTEle>this.tbItems.querySelector('.' + CLS_INDICATOR)], CLS_HIDDEN);
|
|
2193
|
+
this.droppedIndex = isNOU(this.droppedIndex) ? this.getEleIndex(this.dragItem) : this.droppedIndex;
|
|
2194
|
+
this.selectTab(this.droppedIndex, null, true);
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
});
|
|
2198
|
+
this.dragItem = null;
|
|
2199
|
+
this.droppedIndex = null;
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
/**
|
|
2203
|
+
* Enables or disables the specified Tab item. On passing value as `false`, the item will be disabled.
|
|
2204
|
+
*
|
|
2205
|
+
* @param {number} index - Index value of target Tab item.
|
|
2206
|
+
* @param {boolean} value - Boolean value that determines whether the command should be enabled or disabled.
|
|
2207
|
+
* By default, isEnable is true.
|
|
2208
|
+
* @returns {void}.
|
|
2209
|
+
*/
|
|
2210
|
+
public enableTab(index: number, value: boolean): void {
|
|
2211
|
+
const tbItems: HTEle = selectAll('.' + CLS_TB_ITEM, this.element)[index];
|
|
2212
|
+
if (isNOU(tbItems)) {
|
|
2213
|
+
return;
|
|
2214
|
+
}
|
|
2215
|
+
if (value === true) {
|
|
2216
|
+
tbItems.classList.remove(CLS_DISABLE, CLS_OVERLAY);
|
|
2217
|
+
(<HTEle>tbItems.firstElementChild).setAttribute('tabindex',(<HTEle>tbItems.firstElementChild).getAttribute('data-tabindex'));
|
|
2218
|
+
} else {
|
|
2219
|
+
tbItems.classList.add(CLS_DISABLE, CLS_OVERLAY);
|
|
2220
|
+
(<HTEle>tbItems.firstElementChild).removeAttribute('tabindex');
|
|
2221
|
+
if (tbItems.classList.contains(CLS_ACTIVE)) {
|
|
2222
|
+
this.select(index + 1);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
if (!isNOU(this.items[index])) {
|
|
2226
|
+
this.items[index].disabled = !value;
|
|
2227
|
+
this.dataBind();
|
|
2228
|
+
}
|
|
2229
|
+
tbItems.firstElementChild.setAttribute('aria-disabled', (value === true) ? 'false' : 'true');
|
|
2230
|
+
}
|
|
2231
|
+
/**
|
|
2232
|
+
* Adds new items to the Tab that accepts an array as Tab items.
|
|
2233
|
+
*
|
|
2234
|
+
* @param {TabItemModel[]} items - An array of item that is added to the Tab.
|
|
2235
|
+
* @param {number} index - Number value that determines where the items to be added. By default, index is 0.
|
|
2236
|
+
* @returns {void}.
|
|
2237
|
+
*/
|
|
2238
|
+
public addTab(items: TabItemModel[], index?: number): void {
|
|
2239
|
+
const addArgs: AddEventArgs = { addedItems: items, cancel: false };
|
|
2240
|
+
if (!this.isReplace) {
|
|
2241
|
+
for (const item of items) {
|
|
2242
|
+
item.disabled = item.disabled || false;
|
|
2243
|
+
item.visible = item.visible || true;
|
|
2244
|
+
}
|
|
2245
|
+
if (items && items.length !== 0 && this.element && this.element.classList.contains(CLS_HIDDEN)) {
|
|
2246
|
+
this.element.classList.remove(CLS_HIDDEN);
|
|
2247
|
+
}
|
|
2248
|
+
this.trigger('adding', addArgs, (tabAddingArgs: AddEventArgs) => {
|
|
2249
|
+
if (!tabAddingArgs.cancel) {
|
|
2250
|
+
this.addingTabContent(items, index);
|
|
2251
|
+
}
|
|
2252
|
+
});
|
|
2253
|
+
} else {
|
|
2254
|
+
this.addingTabContent(items, index);
|
|
2255
|
+
}
|
|
2256
|
+
if (this.isReact) {
|
|
2257
|
+
this.renderReactTemplates();
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
private addingTabContent(items: TabItemModel[], index?: number): void {
|
|
2261
|
+
let lastEleIndex: number = 0;
|
|
2262
|
+
this.hdrEle = <HTEle>select('.' + CLS_HEADER, this.element);
|
|
2263
|
+
if (isNOU(this.hdrEle)) {
|
|
2264
|
+
this.items = items;
|
|
2265
|
+
this.reRenderItems();
|
|
2266
|
+
this.bindDraggable();
|
|
2267
|
+
} else {
|
|
2268
|
+
const tbItems: HTMLElement[] = Array.from(selectAll('.e-tab-header .' + CLS_TB_ITEM, this.element));
|
|
2269
|
+
const itemsCount: number = tbItems.length;
|
|
2270
|
+
if (itemsCount !== 0) {
|
|
2271
|
+
lastEleIndex = this.getMaxIndicesFromItems(tbItems) + 1;
|
|
2272
|
+
}
|
|
2273
|
+
if (isNOU(index)) {
|
|
2274
|
+
index = itemsCount - 1;
|
|
2275
|
+
}
|
|
2276
|
+
if (itemsCount < index || index < 0 || isNaN(index)) {
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
if (itemsCount === 0 && !isNOU(this.hdrEle)) {
|
|
2280
|
+
this.hdrEle.style.display = '';
|
|
2281
|
+
}
|
|
2282
|
+
if (!isNOU(this.bdrLine)) {
|
|
2283
|
+
this.bdrLine.classList.add(CLS_HIDDEN);
|
|
2284
|
+
}
|
|
2285
|
+
this.tbItems = <HTEle>select('.' + CLS_TB_ITEMS, this.getTabHeader());
|
|
2286
|
+
this.isAdd = true;
|
|
2287
|
+
const tabItems: object[] = this.parseObject(items, index);
|
|
2288
|
+
this.isAdd = false;
|
|
2289
|
+
let i: number = 0;
|
|
2290
|
+
let textValue: string | HTEle | Function;
|
|
2291
|
+
items.forEach((item: TabItemModel, place: number) => {
|
|
2292
|
+
textValue = item.headerTemplate || item.header.text;
|
|
2293
|
+
if (!(isNOU(item.headerTemplate || item.header) || isNOU(textValue) ||
|
|
2294
|
+
((<string>textValue).length === 0) && !isNOU(item.header) && isNOU(item.header.iconCss))) {
|
|
2295
|
+
if (tabItems[place]) {
|
|
2296
|
+
if (isNOU(item.id)) {
|
|
2297
|
+
item.id = CLS_ITEM + this.tabId + '_' + TABITEMPREFIX + (lastEleIndex + place).toString();
|
|
2298
|
+
}
|
|
2299
|
+
(tabItems[place] as Record<string, any>).htmlAttributes['data-id'] = item.id;
|
|
2300
|
+
}
|
|
2301
|
+
this.items.splice((index + i), 0, item);
|
|
2302
|
+
i++;
|
|
2303
|
+
}
|
|
2304
|
+
if (!isNOU(item.header) && !isNOU(item.header.text) && (this.isTemplate || this.loadOn === 'Init')) {
|
|
2305
|
+
const no: number = lastEleIndex + place;
|
|
2306
|
+
const ele: HTEle = this.createElement('div', {
|
|
2307
|
+
id: CLS_CONTENT + this.tabId + '_' + no, className: CLS_ITEM,
|
|
2308
|
+
attrs: { role: 'tabpanel', 'aria-labelledby': CLS_ITEM + '_' + no }
|
|
2309
|
+
});
|
|
2310
|
+
this.cntEle.insertBefore(ele, this.cntEle.children[(index + place)]);
|
|
2311
|
+
const eleTrg: HTEle = this.getTrgContent(this.cntEle, no.toString());
|
|
2312
|
+
this.getContent(eleTrg, item.content, 'render', index);
|
|
2313
|
+
}
|
|
2314
|
+
});
|
|
2315
|
+
this.tbObj.addItems(tabItems, index);
|
|
2316
|
+
if (!this.isReplace) {
|
|
2317
|
+
this.trigger('added', { addedItems: items });
|
|
2318
|
+
}
|
|
2319
|
+
if (this.selectedItem === index) {
|
|
2320
|
+
this.select(index);
|
|
2321
|
+
} else {
|
|
2322
|
+
this.setActiveBorder();
|
|
2323
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEM, this.getTabHeader());
|
|
2324
|
+
}
|
|
2325
|
+
this.bindDraggable();
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
/**
|
|
2329
|
+
* Removes the items in the Tab from the specified index.
|
|
2330
|
+
*
|
|
2331
|
+
* @param {number} index - Index of target item that is going to be removed.
|
|
2332
|
+
* @returns {void}.
|
|
2333
|
+
*/
|
|
2334
|
+
public removeTab(index: number): void {
|
|
2335
|
+
const trg: HTEle = selectAll('.' + CLS_TB_ITEM, this.hdrEle)[index];
|
|
2336
|
+
if (isNOU(trg)) {
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
const removeArgs: RemoveEventArgs = { removedItem: trg, removedIndex: index, cancel: false };
|
|
2340
|
+
this.trigger('removing', removeArgs, (tabRemovingArgs: RemoveEventArgs) => {
|
|
2341
|
+
if (!tabRemovingArgs.cancel) {
|
|
2342
|
+
const header: HTEle =
|
|
2343
|
+
select('#' + CLS_ITEM + this.tabId + '_' + this.extIndex(trg.id), select('.' + CLS_TB_ITEMS, this.hdrEle));
|
|
2344
|
+
if (!isNOU(header)) {
|
|
2345
|
+
this.clearTabTemplate(header, 'headerTemplate', CLS_TB_ITEM);
|
|
2346
|
+
}
|
|
2347
|
+
this.tbObj.removeItems(index);
|
|
2348
|
+
if (this.allowDragAndDrop && (index !== Array.prototype.indexOf.call(this.itemIndexArray, trg.id))) {
|
|
2349
|
+
index = Array.prototype.indexOf.call(this.itemIndexArray, trg.id);
|
|
2350
|
+
}
|
|
2351
|
+
const targetEleIndex: number = this.itemIndexArray.indexOf(trg.id);
|
|
2352
|
+
this.items.splice(targetEleIndex, 1);
|
|
2353
|
+
this.itemIndexArray.splice(targetEleIndex, 1);
|
|
2354
|
+
this.refreshActiveBorder();
|
|
2355
|
+
const cntTrg: HTEle =
|
|
2356
|
+
<HTEle>select('#' + CLS_CONTENT + this.tabId + '_' + this.extIndex(trg.id), select('.' + CLS_CONTENT, this.element));
|
|
2357
|
+
if (!isNOU(cntTrg)) {
|
|
2358
|
+
this.clearTabTemplate(cntTrg, 'content', CLS_ITEM);
|
|
2359
|
+
detach(cntTrg);
|
|
2360
|
+
}
|
|
2361
|
+
this.trigger('removed', tabRemovingArgs);
|
|
2362
|
+
if (this.draggableItems && this.draggableItems.length > 0) {
|
|
2363
|
+
this.draggableItems[index].destroy();
|
|
2364
|
+
this.draggableItems[index] = null;
|
|
2365
|
+
this.draggableItems.splice(index, 1);
|
|
2366
|
+
}
|
|
2367
|
+
if (trg.classList.contains(CLS_ACTIVE)) {
|
|
2368
|
+
index = (index > selectAll('.' + CLS_TB_ITEM + ':not(.' + CLS_TB_POPUP + ')', this.element).length - 1) ? index - 1 : index;
|
|
2369
|
+
this.enableAnimation = false;
|
|
2370
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEM, this.getTabHeader());
|
|
2371
|
+
index = this.getSelectingTabIndex(index);
|
|
2372
|
+
index = !isNaN(index) && index >= 0 && this.tbItem.length > index ? index : 0;
|
|
2373
|
+
const tabItem = this.tbItem[index];
|
|
2374
|
+
if (tabItem) {
|
|
2375
|
+
if (tabItem.classList.contains(CLS_HIDDEN)) {
|
|
2376
|
+
tabItem.classList.remove(CLS_HIDDEN);
|
|
2377
|
+
}
|
|
2378
|
+
const firstChild = tabItem.firstElementChild;
|
|
2379
|
+
if (firstChild && firstChild.hasAttribute('aria-hidden')) {
|
|
2380
|
+
firstChild.removeAttribute('aria-hidden');
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
this.selectedItem = index;
|
|
2384
|
+
this.select(index);
|
|
2385
|
+
} else if (index !== this.selectedItem) {
|
|
2386
|
+
if (index < this.selectedItem) {
|
|
2387
|
+
index = this.itemIndexArray.indexOf(this.tbItem[this.selectedItem].id);
|
|
2388
|
+
this.setProperties({ selectedItem: index > -1 ? index : this.selectedItem }, true);
|
|
2389
|
+
this.prevIndex = this.selectedItem;
|
|
2390
|
+
}
|
|
2391
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEM, this.getTabHeader());
|
|
2392
|
+
}
|
|
2393
|
+
if (selectAll('.' + CLS_TB_ITEM, this.element).length === 0) {
|
|
2394
|
+
const cnt: HTEle = <HTEle>select('.' + CLS_CONTENT, this.element);
|
|
2395
|
+
detach(this.hdrEle);
|
|
2396
|
+
detach(cnt);
|
|
2397
|
+
}
|
|
2398
|
+
this.enableAnimation = true;
|
|
2399
|
+
}
|
|
2400
|
+
});
|
|
2401
|
+
}
|
|
2402
|
+
/**
|
|
2403
|
+
* Shows or hides the Tab that is in the specified index.
|
|
2404
|
+
*
|
|
2405
|
+
* @param {number} index - Index value of target item.
|
|
2406
|
+
* @param {boolean} value - Based on this Boolean value, item will be hide (true) or show (false). By default, value is true.
|
|
2407
|
+
* @returns {void}.
|
|
2408
|
+
*/
|
|
2409
|
+
public hideTab(index: number, value?: boolean): void {
|
|
2410
|
+
let items: HTMLElement[];
|
|
2411
|
+
let tabId: string;
|
|
2412
|
+
if (index >= 0 && index < this.tbItem.length) {
|
|
2413
|
+
tabId = this.tbItem[index].getAttribute('id');
|
|
2414
|
+
}
|
|
2415
|
+
const item: HTEle = this.element.querySelector(`[id="${tabId}"]`);
|
|
2416
|
+
if (isNOU(item)) {
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
if (isNOU(value)) {
|
|
2420
|
+
value = true;
|
|
2421
|
+
}
|
|
2422
|
+
this.bdrLine.classList.add(CLS_HIDDEN);
|
|
2423
|
+
if (value === true) {
|
|
2424
|
+
item.classList.add(CLS_HIDDEN);
|
|
2425
|
+
items = selectAll('.' + CLS_TB_ITEM + ':not(.' + CLS_HIDDEN + ')', this.tbItems);
|
|
2426
|
+
if (items.length !== 0 && item.classList.contains(CLS_ACTIVE)) {
|
|
2427
|
+
if (index !== 0) {
|
|
2428
|
+
for (let i: number = index - 1; i >= 0; i--) {
|
|
2429
|
+
if (!this.tbItem[i].classList.contains(CLS_HIDDEN)) {
|
|
2430
|
+
this.select(i);
|
|
2431
|
+
break;
|
|
2432
|
+
} else if (i === 0) {
|
|
2433
|
+
for (let k: number = index + 1; k < this.tbItem.length; k++) {
|
|
2434
|
+
if (!this.tbItem[k].classList.contains(CLS_HIDDEN)) {
|
|
2435
|
+
this.select(k);
|
|
2436
|
+
break;
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
} else {
|
|
2442
|
+
for (let k: number = index + 1; k < this.tbItem.length; k++) {
|
|
2443
|
+
if (!this.tbItem[k].classList.contains(CLS_HIDDEN)) {
|
|
2444
|
+
this.select(k);
|
|
2445
|
+
break;
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
} else if (items.length === 0) {
|
|
2450
|
+
this.element.classList.add(CLS_HIDDEN);
|
|
2451
|
+
}
|
|
2452
|
+
} else {
|
|
2453
|
+
this.element.classList.remove(CLS_HIDDEN);
|
|
2454
|
+
items = selectAll('.' + CLS_TB_ITEM + ':not(.' + CLS_HIDDEN + ')', this.tbItems);
|
|
2455
|
+
item.classList.remove(CLS_HIDDEN);
|
|
2456
|
+
if (items.length === 0) {
|
|
2457
|
+
this.select(index);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
this.setActiveBorder();
|
|
2461
|
+
if (!isNOU(this.items[index])) {
|
|
2462
|
+
this.items[index].visible = !value;
|
|
2463
|
+
this.dataBind();
|
|
2464
|
+
}
|
|
2465
|
+
if (!isNullOrUndefined(item.firstElementChild)) {
|
|
2466
|
+
item.firstElementChild.setAttribute('aria-hidden', '' + value);
|
|
2467
|
+
}
|
|
2468
|
+
if (this.overflowMode === 'Popup') {
|
|
2469
|
+
this.refreshOverflow();
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
private selectTab(args: number | HTEle, event: Event = null, isInteracted: boolean = false): void {
|
|
2474
|
+
this.isInteracted = isInteracted;
|
|
2475
|
+
this.select(args, event);
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
/**
|
|
2479
|
+
* Specifies the index or HTMLElement to select an item from the Tab.
|
|
2480
|
+
*
|
|
2481
|
+
* @param {number | HTMLElement} args - Index or DOM element is used for selecting an item from the Tab.
|
|
2482
|
+
* @param {Event} event - An event which takes place in DOM.
|
|
2483
|
+
* @returns {void}
|
|
2484
|
+
*/
|
|
2485
|
+
|
|
2486
|
+
public select(args: number | HTEle, event?: Event): void {
|
|
2487
|
+
const tabHeader: HTMLElement = this.getTabHeader();
|
|
2488
|
+
this.tbItems = <HTEle>select('.' + CLS_TB_ITEMS, tabHeader);
|
|
2489
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEM, tabHeader);
|
|
2490
|
+
this.content = <HTEle>select('.' + CLS_CONTENT, this.element);
|
|
2491
|
+
this.prevItem = this.tbItem[this.prevIndex];
|
|
2492
|
+
if (isNOU(this.selectedItem) || (this.selectedItem < 0) || (this.tbItem.length <= this.selectedItem) || isNaN(this.selectedItem)) {
|
|
2493
|
+
this.selectedItem = 0;
|
|
2494
|
+
} else {
|
|
2495
|
+
this.selectedID = this.extIndex(this.tbItem[this.selectedItem].id);
|
|
2496
|
+
}
|
|
2497
|
+
const trg: HTEle = this.tbItem[args as number];
|
|
2498
|
+
if (isNOU(trg)) {
|
|
2499
|
+
this.selectedID = '0';
|
|
2500
|
+
} else {
|
|
2501
|
+
this.selectingID = this.extIndex(trg.id);
|
|
2502
|
+
}
|
|
2503
|
+
if (!isNOU(this.prevItem) && !this.prevItem.classList.contains(CLS_DISABLE)) {
|
|
2504
|
+
this.prevItem.children.item(0).setAttribute('tabindex', this.prevItem.firstElementChild.getAttribute('tabindex'));
|
|
2505
|
+
}
|
|
2506
|
+
const eventArg: SelectingEventArgs = {
|
|
2507
|
+
event: event,
|
|
2508
|
+
previousItem: this.prevItem,
|
|
2509
|
+
previousIndex: this.prevIndex,
|
|
2510
|
+
selectedItem: this.tbItem[this.selectedItem],
|
|
2511
|
+
selectedIndex: this.selectedItem,
|
|
2512
|
+
selectedContent: !isNOU(this.content) ?
|
|
2513
|
+
<HTEle>select('#' + CLS_CONTENT + this.tabId + '_' + this.selectedID, this.content) : null,
|
|
2514
|
+
selectingItem: trg,
|
|
2515
|
+
selectingIndex: args as number,
|
|
2516
|
+
selectingContent: !isNOU(this.content) ?
|
|
2517
|
+
<HTEle>select('#' + CLS_CONTENT + this.tabId + '_' + this.selectingID, this.content) : null,
|
|
2518
|
+
isSwiped: this.isSwiped,
|
|
2519
|
+
isInteracted: this.isInteracted,
|
|
2520
|
+
cancel: false
|
|
2521
|
+
};
|
|
2522
|
+
if (!this.initRender) {
|
|
2523
|
+
this.trigger('selecting', eventArg, (selectArgs: SelectingEventArgs) => {
|
|
2524
|
+
if (!selectArgs.cancel) {
|
|
2525
|
+
this.selectingContent(args, this.isInteracted);
|
|
2526
|
+
}
|
|
2527
|
+
});
|
|
2528
|
+
} else {
|
|
2529
|
+
this.selectingContent(args, this.isInteracted);
|
|
2530
|
+
}
|
|
2531
|
+
this.isInteracted = false;
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
private getSelectingTabIndex(args: number): number {
|
|
2535
|
+
if (!isNOU(this.tbItem[args]) && (this.tbItem[<number>args].classList.contains(CLS_DISABLE) ||
|
|
2536
|
+
this.tbItem[<number>args].classList.contains(CLS_HIDDEN))) {
|
|
2537
|
+
for (let i: number = <number>args + 1; i < this.items.length; i++) {
|
|
2538
|
+
if (this.items[i].disabled === false && this.items[i].visible === true) {
|
|
2539
|
+
args = i; break;
|
|
2540
|
+
} else {
|
|
2541
|
+
args = 0;
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
return args;
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
private selectingContent(args: number | HTEle, isInteracted?: boolean): void {
|
|
2549
|
+
if (typeof args === 'number') {
|
|
2550
|
+
args = this.getSelectingTabIndex(args);
|
|
2551
|
+
if (this.tbItem.length > args && args >= 0 && !isNaN(args)) {
|
|
2552
|
+
this.prevIndex = this.selectedItem;
|
|
2553
|
+
this.prevItem = this.tbItem[this.prevIndex];
|
|
2554
|
+
if (this.tbItem[args].classList.contains(CLS_TB_POPUP) && this.reorderActiveTab) {
|
|
2555
|
+
this.setActive(this.popupHandler(this.tbItem[args]), null, isInteracted);
|
|
2556
|
+
if ((!isNOU(this.items) && this.items.length > 0) && this.allowDragAndDrop) {
|
|
2557
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEMS + ' .' + CLS_TB_ITEM, this.hdrEle);
|
|
2558
|
+
let item: TabItemModel = this.items[args];
|
|
2559
|
+
this.items.splice(args, 1);
|
|
2560
|
+
this.items.splice(this.tbItem.length - 1, 0, item);
|
|
2561
|
+
let itemId: string = this.itemIndexArray[args];
|
|
2562
|
+
this.itemIndexArray.splice(args, 1);
|
|
2563
|
+
this.itemIndexArray.splice(this.tbItem.length - 1, 0, itemId);
|
|
2564
|
+
}
|
|
2565
|
+
} else {
|
|
2566
|
+
this.setActive(args, null, isInteracted);
|
|
2567
|
+
}
|
|
2568
|
+
} else {
|
|
2569
|
+
this.setActive(0, null, isInteracted);
|
|
2570
|
+
}
|
|
2571
|
+
} else if (args instanceof (HTMLElement)) {
|
|
2572
|
+
this.setActive(this.getEleIndex(args), null, isInteracted);
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* Gets the item index from the Tab.
|
|
2577
|
+
*
|
|
2578
|
+
* @param {string} tabItemId - Item ID is used for getting index from the Tab.
|
|
2579
|
+
* @returns {number} - It returns item index.
|
|
2580
|
+
*/
|
|
2581
|
+
public getItemIndex(tabItemId: string): number {
|
|
2582
|
+
let tabIndex: number;
|
|
2583
|
+
this.tbItem = selectAll('.' + CLS_TB_ITEM, this.getTabHeader());
|
|
2584
|
+
for (let i: number = 0; i < this.tbItem.length; i++) {
|
|
2585
|
+
const value: string = this.tbItem[i].getAttribute('data-id');
|
|
2586
|
+
if (tabItemId === value) {
|
|
2587
|
+
tabIndex = i;
|
|
2588
|
+
break;
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
return tabIndex;
|
|
2592
|
+
}
|
|
2593
|
+
/**
|
|
2594
|
+
* Specifies the value to disable/enable the Tab component.
|
|
2595
|
+
* When set to `true`, the component will be disabled.
|
|
2596
|
+
*
|
|
2597
|
+
* @param {boolean} value - Based on this Boolean value, Tab will be enabled (false) or disabled (true).
|
|
2598
|
+
* @returns {void}.
|
|
2599
|
+
*/
|
|
2600
|
+
public disable(value: boolean): void {
|
|
2601
|
+
this.setCssClass(this.element, CLS_DISABLE, value);
|
|
2602
|
+
this.element.setAttribute('aria-disabled', '' + value);
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* Get the properties to be maintained in the persisted state.
|
|
2606
|
+
*
|
|
2607
|
+
* @returns {string} - It returns the persisted state.
|
|
2608
|
+
*/
|
|
2609
|
+
protected getPersistData(): string {
|
|
2610
|
+
return this.addOnPersist(['selectedItem', 'actEleId']);
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Returns the current module name.
|
|
2614
|
+
*
|
|
2615
|
+
* @returns {string} - It returns the current module name.
|
|
2616
|
+
* @private
|
|
2617
|
+
*/
|
|
2618
|
+
protected getModuleName(): string {
|
|
2619
|
+
return 'tab';
|
|
2620
|
+
}
|
|
2621
|
+
/**
|
|
2622
|
+
* Gets called when the model property changes.The data that describes the old and new values of the property that changed.
|
|
2623
|
+
*
|
|
2624
|
+
* @param {TabModel} newProp - It contains the new value of data.
|
|
2625
|
+
* @param {TabModel} oldProp - It contains the old value of data.
|
|
2626
|
+
* @returns {void}
|
|
2627
|
+
* @private
|
|
2628
|
+
*/
|
|
2629
|
+
public onPropertyChanged(newProp: TabModel, oldProp: TabModel): void {
|
|
2630
|
+
let sortedKeys = Object.keys(newProp).sort(function (a, b) {
|
|
2631
|
+
if (a === 'items') return -1;
|
|
2632
|
+
if (b === 'items') return 1;
|
|
2633
|
+
return 0;
|
|
2634
|
+
});
|
|
2635
|
+
for (const prop of sortedKeys) {
|
|
2636
|
+
switch (prop) {
|
|
2637
|
+
case 'width':
|
|
2638
|
+
setStyle(this.element, { width: formatUnit(newProp.width) });
|
|
2639
|
+
break;
|
|
2640
|
+
case 'height':
|
|
2641
|
+
setStyle(this.element, { height: formatUnit(newProp.height) });
|
|
2642
|
+
this.setContentHeight(false);
|
|
2643
|
+
break;
|
|
2644
|
+
case 'cssClass':
|
|
2645
|
+
const headerEle: HTMLElement = this.element.querySelector('.' + CLS_HEADER);
|
|
2646
|
+
if (oldProp.cssClass !== '' && !isNullOrUndefined(oldProp.cssClass)) {
|
|
2647
|
+
this.setCssClass(this.element, oldProp.cssClass, false);
|
|
2648
|
+
this.setCssClass(this.element, newProp.cssClass, true);
|
|
2649
|
+
if (!isNullOrUndefined(headerEle)) {
|
|
2650
|
+
this.setCssClass(headerEle, oldProp.cssClass, false);
|
|
2651
|
+
this.setCssClass(headerEle, newProp.cssClass, true);
|
|
2652
|
+
}
|
|
2653
|
+
} else {
|
|
2654
|
+
this.setCssClass(this.element, newProp.cssClass, true);
|
|
2655
|
+
if (!isNullOrUndefined(headerEle)) {
|
|
2656
|
+
this.setCssClass(headerEle, newProp.cssClass, true);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
break;
|
|
2660
|
+
case 'items':
|
|
2661
|
+
this.evalOnPropertyChangeItems(newProp, oldProp);
|
|
2662
|
+
break;
|
|
2663
|
+
case 'showCloseButton':
|
|
2664
|
+
this.setCloseButton(newProp.showCloseButton);
|
|
2665
|
+
break;
|
|
2666
|
+
case 'reorderActiveTab':
|
|
2667
|
+
this.refreshActiveTabBorder();
|
|
2668
|
+
break;
|
|
2669
|
+
case 'selectedItem':
|
|
2670
|
+
this.selectedItem = oldProp.selectedItem;
|
|
2671
|
+
this.select(newProp.selectedItem);
|
|
2672
|
+
break;
|
|
2673
|
+
case 'headerPlacement':
|
|
2674
|
+
this.changeOrientation(newProp.headerPlacement);
|
|
2675
|
+
break;
|
|
2676
|
+
case 'enableRtl':
|
|
2677
|
+
this.setRTL(newProp.enableRtl);
|
|
2678
|
+
break;
|
|
2679
|
+
case 'overflowMode':
|
|
2680
|
+
this.tbObj.overflowMode = newProp.overflowMode;
|
|
2681
|
+
this.tbObj.dataBind();
|
|
2682
|
+
this.refreshActiveTabBorder();
|
|
2683
|
+
break;
|
|
2684
|
+
case 'heightAdjustMode':
|
|
2685
|
+
this.setContentHeight(false);
|
|
2686
|
+
this.select(this.selectedItem);
|
|
2687
|
+
break;
|
|
2688
|
+
case 'scrollStep':
|
|
2689
|
+
if (this.tbObj) {
|
|
2690
|
+
this.tbObj.scrollStep = this.scrollStep;
|
|
2691
|
+
}
|
|
2692
|
+
break;
|
|
2693
|
+
case 'allowDragAndDrop':
|
|
2694
|
+
this.bindDraggable();
|
|
2695
|
+
break;
|
|
2696
|
+
case 'swipeMode':
|
|
2697
|
+
if (this.touchModule) {
|
|
2698
|
+
this.touchModule.destroy();
|
|
2699
|
+
this.touchModule = null;
|
|
2700
|
+
}
|
|
2701
|
+
this.bindSwipeEvents();
|
|
2702
|
+
break;
|
|
2703
|
+
case 'dragArea':
|
|
2704
|
+
if (this.allowDragAndDrop) {
|
|
2705
|
+
this.draggableItems.forEach((item: Draggable) => {
|
|
2706
|
+
item.dragArea = this.dragArea;
|
|
2707
|
+
});
|
|
2708
|
+
this.refresh();
|
|
2709
|
+
}
|
|
2710
|
+
break;
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
/**
|
|
2715
|
+
* To refresh the active tab contents.
|
|
2716
|
+
*
|
|
2717
|
+
* @returns {void}
|
|
2718
|
+
*/
|
|
2719
|
+
public refreshActiveTab(): void {
|
|
2720
|
+
if (this.isReact && this.isTemplate) {
|
|
2721
|
+
this.clearTemplate();
|
|
2722
|
+
}
|
|
2723
|
+
if (!this.isTemplate) {
|
|
2724
|
+
if (this.element.querySelector('.' + CLS_TB_ITEM + '.' + CLS_ACTIVE)) {
|
|
2725
|
+
detach(this.element.querySelector('.' + CLS_TB_ITEM + '.' + CLS_ACTIVE).children[0]);
|
|
2726
|
+
detach(this.element.querySelector('.' + CLS_CONTENT).querySelector('.' + CLS_ACTIVE).children[0]);
|
|
2727
|
+
const item: TabItemModel = this.items[this.selectedItem];
|
|
2728
|
+
const pos: Str = (isNOU(item.header) || isNOU(item.header.iconPosition)) ? '' : item.header.iconPosition;
|
|
2729
|
+
const css: Str = (isNOU(item.header) || isNOU(item.header.iconCss)) ? '' : item.header.iconCss;
|
|
2730
|
+
const text: Str | HTEle | Function = item.headerTemplate || item.header.text;
|
|
2731
|
+
const txtWrap: HTEle = this.createElement('div', { className: CLS_TEXT, attrs: { 'role': 'presentation' } });
|
|
2732
|
+
if (!isNOU((<HTEle>text).tagName)) {
|
|
2733
|
+
txtWrap.appendChild(text as HTEle);
|
|
2734
|
+
} else {
|
|
2735
|
+
this.headerTextCompile(txtWrap, text as string, this.selectedItem);
|
|
2736
|
+
}
|
|
2737
|
+
let tEle: HTEle;
|
|
2738
|
+
const icon: HTEle = this.createElement('span', {
|
|
2739
|
+
className: CLS_ICONS + ' ' + CLS_TAB_ICON + ' ' + CLS_ICON + '-' + pos + ' ' + css
|
|
2740
|
+
});
|
|
2741
|
+
const tConts: HTEle = this.createElement('div', { className: CLS_TEXT_WRAP });
|
|
2742
|
+
tConts.appendChild(txtWrap);
|
|
2743
|
+
if ((text !== '' && text !== undefined) && css !== '') {
|
|
2744
|
+
if ((pos === 'left' || pos === 'top')) {
|
|
2745
|
+
tConts.insertBefore(icon, tConts.firstElementChild);
|
|
2746
|
+
} else {
|
|
2747
|
+
tConts.appendChild(icon);
|
|
2748
|
+
}
|
|
2749
|
+
tEle = txtWrap;
|
|
2750
|
+
this.isIconAlone = false;
|
|
2751
|
+
} else {
|
|
2752
|
+
tEle = ((css === '') ? txtWrap : icon);
|
|
2753
|
+
if (tEle === icon) {
|
|
2754
|
+
detach(txtWrap); tConts.appendChild(icon); this.isIconAlone = true;
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
const tabIndex: string = isNOU(item.tabIndex) ? '-1' : item.tabIndex.toString();
|
|
2758
|
+
const wrapAtt: { [key: string]: string } = (item.disabled) ? {} : { tabIndex: tabIndex, 'data-tabindex': tabIndex, role: 'tab', 'aria-selected': 'true', 'aria-disabled': 'false' };
|
|
2759
|
+
tConts.appendChild(this.btnCls.cloneNode(true));
|
|
2760
|
+
const wraper: HTEle = this.createElement('div', { className: CLS_WRAP, attrs: wrapAtt });
|
|
2761
|
+
wraper.appendChild(tConts);
|
|
2762
|
+
if (pos === 'top' || pos === 'bottom') {
|
|
2763
|
+
this.element.classList.add('e-vertical-icon');
|
|
2764
|
+
}
|
|
2765
|
+
this.element.querySelector('.' + CLS_TB_ITEM + '.' + CLS_ACTIVE).appendChild(wraper);
|
|
2766
|
+
const crElem: HTEle = this.createElement('div');
|
|
2767
|
+
let cnt: string | HTMLElement | Function = item.content; let eleStr: string;
|
|
2768
|
+
if (typeof cnt === 'string' || isNOU((<HTEle>cnt).innerHTML)) {
|
|
2769
|
+
if (typeof cnt === 'string' && this.enableHtmlSanitizer) {
|
|
2770
|
+
cnt = SanitizeHtmlHelper.sanitize(<Str>cnt);
|
|
2771
|
+
}
|
|
2772
|
+
if ((<Str>cnt)[0] === '.' || (<Str>cnt)[0] === '#') {
|
|
2773
|
+
if (document.querySelectorAll(<string>cnt).length) {
|
|
2774
|
+
const eleVal: HTEle = <HTEle>document.querySelector(<string>cnt);
|
|
2775
|
+
eleStr = eleVal.outerHTML.trim();
|
|
2776
|
+
crElem.appendChild(eleVal);
|
|
2777
|
+
eleVal.style.display = '';
|
|
2778
|
+
} else {
|
|
2779
|
+
this.compileElement(crElem, <Str>cnt, 'content', this.selectedItem);
|
|
2780
|
+
}
|
|
2781
|
+
} else {
|
|
2782
|
+
this.compileElement(crElem, <Str>cnt, 'content', this.selectedItem);
|
|
2783
|
+
}
|
|
2784
|
+
} else {
|
|
2785
|
+
crElem.appendChild(cnt as HTEle);
|
|
2786
|
+
}
|
|
2787
|
+
if (!isNOU(eleStr)) {
|
|
2788
|
+
if (this.templateEle.indexOf(cnt.toString()) === -1) {
|
|
2789
|
+
this.templateEle.push(cnt.toString());
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
this.element.querySelector('.' + CLS_ITEM + '.' + CLS_ACTIVE).appendChild(crElem);
|
|
2793
|
+
}
|
|
2794
|
+
} else {
|
|
2795
|
+
const tabItems: HTMLElement = this.element.querySelector('.' + CLS_TB_ITEMS);
|
|
2796
|
+
const element: HTMLElement = this.element.querySelector('.' + CLS_TB_ITEM + '.' + CLS_ACTIVE);
|
|
2797
|
+
const index: number = this.getIndexFromEle(element.id);
|
|
2798
|
+
const header: string = element.innerText;
|
|
2799
|
+
const detachContent: Element = this.element.querySelector('.' + CLS_CONTENT).querySelector('.' + CLS_ACTIVE).children[0];
|
|
2800
|
+
const mainContents: string = detachContent.innerHTML;
|
|
2801
|
+
detach(element);
|
|
2802
|
+
detach(detachContent);
|
|
2803
|
+
const attr: object = {
|
|
2804
|
+
className: CLS_TB_ITEM + ' ' + CLS_TEMPLATE + ' ' + CLS_ACTIVE, id: CLS_ITEM + this.tabId + '_' + index
|
|
2805
|
+
};
|
|
2806
|
+
const txtString: Str = this.createElement('span', {
|
|
2807
|
+
className: CLS_TEXT, innerHTML: header, attrs: { 'role': 'presentation' }
|
|
2808
|
+
}).outerHTML;
|
|
2809
|
+
const conte: Str = this.createElement('div', {
|
|
2810
|
+
className: CLS_TEXT_WRAP, innerHTML: txtString + this.btnCls.outerHTML
|
|
2811
|
+
}).outerHTML;
|
|
2812
|
+
const tabIndex: string = element.firstElementChild.getAttribute('data-tabindex');
|
|
2813
|
+
const wrap: HTEle = this.createElement('div', {
|
|
2814
|
+
className: CLS_WRAP, innerHTML: conte,
|
|
2815
|
+
attrs: { tabIndex: tabIndex, 'data-tabindex': tabIndex, role: 'tab', 'aria-controls': CLS_CONTENT + this.tabId + '_' + index, 'aria-selected': 'true', 'aria-disabled': 'false' }
|
|
2816
|
+
});
|
|
2817
|
+
tabItems.insertBefore(this.createElement('div', attr), tabItems.children[index + 1]);
|
|
2818
|
+
this.element.querySelector('.' + CLS_TB_ITEM + '.' + CLS_ACTIVE).appendChild(wrap);
|
|
2819
|
+
const crElem: HTEle = this.createElement('div', { innerHTML: mainContents });
|
|
2820
|
+
this.element.querySelector('.' + CLS_CONTENT).querySelector('.' + CLS_ACTIVE).appendChild(crElem);
|
|
2821
|
+
}
|
|
2822
|
+
if (this.isReact) {
|
|
2823
|
+
this.renderReactTemplates();
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
/**
|
|
2827
|
+
* To refresh the active tab indicator.
|
|
2828
|
+
*
|
|
2829
|
+
* @returns {void}
|
|
2830
|
+
*/
|
|
2831
|
+
public refreshActiveTabBorder(): void {
|
|
2832
|
+
if (this.heightAdjustMode === 'None' && this.height !== 'auto' && this.cntEle && !this.isVertical()) {
|
|
2833
|
+
const hdrEle: HTEle = this.getTabHeader();
|
|
2834
|
+
setStyle(this.cntEle, { 'height': (this.element.clientHeight - hdrEle.offsetHeight) + 'px' });
|
|
2835
|
+
}
|
|
2836
|
+
const activeEle: Element = select('.' + CLS_TB_ITEM + '.' + CLS_TB_POPUP + '.' + CLS_ACTIVE, this.element);
|
|
2837
|
+
if (!isNOU(activeEle) && this.reorderActiveTab) {
|
|
2838
|
+
this.select(this.getEleIndex(<HTEle>activeEle));
|
|
2839
|
+
}
|
|
2840
|
+
this.refreshActiveBorder();
|
|
2841
|
+
}
|
|
2842
|
+
}
|