@syncfusion/ej2-navigations 17.2.55-1205479 → 17.3.14-96615

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.
Files changed (316) hide show
  1. package/.eslintrc.json +244 -0
  2. package/CHANGELOG.md +898 -786
  3. package/README.md +163 -163
  4. package/dist/ej2-navigations.umd.min.js +1 -10
  5. package/dist/ej2-navigations.umd.min.js.map +1 -1
  6. package/dist/es6/ej2-navigations.es2015.js +512 -255
  7. package/dist/es6/ej2-navigations.es2015.js.map +1 -1
  8. package/dist/es6/ej2-navigations.es5.js +642 -385
  9. package/dist/es6/ej2-navigations.es5.js.map +1 -1
  10. package/dist/global/ej2-navigations.min.js +1 -10
  11. package/dist/global/ej2-navigations.min.js.map +1 -1
  12. package/dist/global/index.d.ts +0 -9
  13. package/dist/ts/accordion/accordion.ts +1312 -0
  14. package/dist/ts/common/h-scroll.ts +459 -0
  15. package/dist/ts/common/menu-base.ts +2131 -0
  16. package/dist/ts/common/v-scroll.ts +430 -0
  17. package/dist/ts/context-menu/context-menu.ts +119 -0
  18. package/dist/ts/menu/menu.ts +270 -0
  19. package/dist/ts/sidebar/sidebar.ts +817 -0
  20. package/dist/ts/tab/tab.ts +1761 -0
  21. package/dist/ts/toolbar/toolbar.ts +2076 -0
  22. package/dist/ts/treeview/treeview.ts +5050 -0
  23. package/helpers/e2e/index.js +3 -3
  24. package/license +10 -10
  25. package/package.json +135 -145
  26. package/src/accordion/accordion-model.d.ts +162 -143
  27. package/src/accordion/accordion.d.ts +35 -6
  28. package/src/accordion/accordion.js +193 -71
  29. package/src/common/h-scroll-model.d.ts +5 -5
  30. package/src/common/h-scroll.js +19 -20
  31. package/src/common/index.d.ts +1 -0
  32. package/src/common/index.js +1 -0
  33. package/src/common/menu-base-model.d.ts +157 -157
  34. package/src/common/menu-base.d.ts +19 -0
  35. package/src/common/menu-base.js +97 -24
  36. package/src/common/v-scroll-model.d.ts +5 -5
  37. package/src/common/v-scroll.js +19 -19
  38. package/src/context-menu/context-menu-model.d.ts +15 -15
  39. package/src/context-menu/context-menu.js +19 -19
  40. package/src/menu/menu-model.d.ts +30 -30
  41. package/src/menu/menu.js +19 -19
  42. package/src/sidebar/sidebar-model.d.ts +136 -136
  43. package/src/sidebar/sidebar.js +19 -19
  44. package/src/tab/tab-model.d.ts +215 -215
  45. package/src/tab/tab.d.ts +3 -0
  46. package/src/tab/tab.js +120 -83
  47. package/src/toolbar/toolbar-model.d.ts +175 -175
  48. package/src/toolbar/toolbar.d.ts +2 -1
  49. package/src/toolbar/toolbar.js +30 -24
  50. package/src/treeview/treeview-model.d.ts +323 -323
  51. package/src/treeview/treeview.d.ts +3 -1
  52. package/src/treeview/treeview.js +107 -87
  53. package/styles/accordion/_all.scss +2 -2
  54. package/styles/accordion/_bootstrap-dark-definition.scss +69 -69
  55. package/styles/accordion/_bootstrap-definition.scss +76 -76
  56. package/styles/accordion/_bootstrap4-definition.scss +82 -82
  57. package/styles/accordion/_fabric-dark-definition.scss +74 -74
  58. package/styles/accordion/_fabric-definition.scss +78 -78
  59. package/styles/accordion/_highcontrast-definition.scss +106 -106
  60. package/styles/accordion/_highcontrast-light-definition.scss +104 -104
  61. package/styles/accordion/_layout.scss +447 -447
  62. package/styles/accordion/_material-dark-definition.scss +75 -75
  63. package/styles/accordion/_material-definition.scss +72 -72
  64. package/styles/accordion/_theme.scss +479 -479
  65. package/styles/accordion/icons/_bootstrap-dark.scss +17 -17
  66. package/styles/accordion/icons/_bootstrap.scss +17 -17
  67. package/styles/accordion/icons/_bootstrap4.scss +17 -17
  68. package/styles/accordion/icons/_fabric-dark.scss +17 -17
  69. package/styles/accordion/icons/_fabric.scss +17 -17
  70. package/styles/accordion/icons/_highcontrast-light.scss +17 -17
  71. package/styles/accordion/icons/_highcontrast.scss +17 -17
  72. package/styles/accordion/icons/_material-dark.scss +17 -17
  73. package/styles/accordion/icons/_material.scss +17 -17
  74. package/styles/accordion/material-dark.css +2 -2
  75. package/styles/bootstrap-dark.css +10 -9
  76. package/styles/bootstrap.css +10 -9
  77. package/styles/bootstrap4.css +10 -9
  78. package/styles/bootstrap5-dark.css +0 -0
  79. package/styles/bootstrap5-dark.scss +0 -0
  80. package/styles/bootstrap5.css +0 -0
  81. package/styles/bootstrap5.scss +0 -0
  82. package/styles/context-menu/_all.scss +2 -2
  83. package/styles/context-menu/_bootstrap-dark-definition.scss +54 -54
  84. package/styles/context-menu/_bootstrap-definition.scss +52 -52
  85. package/styles/context-menu/_bootstrap4-definition.scss +52 -52
  86. package/styles/context-menu/_fabric-dark-definition.scss +54 -54
  87. package/styles/context-menu/_fabric-definition.scss +52 -52
  88. package/styles/context-menu/_highcontrast-definition.scss +52 -52
  89. package/styles/context-menu/_highcontrast-light-definition.scss +54 -54
  90. package/styles/context-menu/_layout-mixin.scss +175 -174
  91. package/styles/context-menu/_layout.scss +70 -70
  92. package/styles/context-menu/_material-dark-definition.scss +54 -54
  93. package/styles/context-menu/_material-definition.scss +52 -52
  94. package/styles/context-menu/_theme-mixin.scss +59 -59
  95. package/styles/context-menu/_theme.scss +36 -36
  96. package/styles/context-menu/bootstrap-dark.css +1 -1
  97. package/styles/context-menu/bootstrap.css +1 -1
  98. package/styles/context-menu/bootstrap4.css +1 -1
  99. package/styles/context-menu/fabric-dark.css +1 -1
  100. package/styles/context-menu/fabric.css +1 -1
  101. package/styles/context-menu/highcontrast-light.css +1 -1
  102. package/styles/context-menu/highcontrast.css +1 -1
  103. package/styles/context-menu/icons/_bootstrap-dark.scss +30 -30
  104. package/styles/context-menu/icons/_bootstrap.scss +30 -30
  105. package/styles/context-menu/icons/_bootstrap4.scss +30 -30
  106. package/styles/context-menu/icons/_fabric-dark.scss +30 -30
  107. package/styles/context-menu/icons/_fabric.scss +30 -30
  108. package/styles/context-menu/icons/_highcontrast-light.scss +30 -30
  109. package/styles/context-menu/icons/_highcontrast.scss +30 -30
  110. package/styles/context-menu/icons/_material-dark.scss +30 -30
  111. package/styles/context-menu/icons/_material.scss +30 -30
  112. package/styles/context-menu/material-dark.css +1 -1
  113. package/styles/context-menu/material.css +4 -4
  114. package/styles/fabric-dark.css +10 -9
  115. package/styles/fabric.css +10 -9
  116. package/styles/h-scroll/_all.scss +2 -2
  117. package/styles/h-scroll/_bootstrap-dark-definition.scss +49 -49
  118. package/styles/h-scroll/_bootstrap-definition.scss +50 -50
  119. package/styles/h-scroll/_bootstrap4-definition.scss +49 -49
  120. package/styles/h-scroll/_fabric-dark-definition.scss +50 -50
  121. package/styles/h-scroll/_fabric-definition.scss +48 -48
  122. package/styles/h-scroll/_highcontrast-definition.scss +52 -52
  123. package/styles/h-scroll/_highcontrast-light-definition.scss +54 -54
  124. package/styles/h-scroll/_layout.scss +198 -198
  125. package/styles/h-scroll/_material-dark-definition.scss +77 -77
  126. package/styles/h-scroll/_material-definition.scss +77 -77
  127. package/styles/h-scroll/_theme.scss +157 -157
  128. package/styles/h-scroll/icons/_bootstrap-dark.scss +49 -49
  129. package/styles/h-scroll/icons/_bootstrap.scss +49 -49
  130. package/styles/h-scroll/icons/_bootstrap4.scss +49 -49
  131. package/styles/h-scroll/icons/_fabric-dark.scss +49 -49
  132. package/styles/h-scroll/icons/_fabric.scss +49 -49
  133. package/styles/h-scroll/icons/_highcontrast-light.scss +49 -49
  134. package/styles/h-scroll/icons/_highcontrast.scss +49 -49
  135. package/styles/h-scroll/icons/_material-dark.scss +49 -49
  136. package/styles/h-scroll/icons/_material.scss +49 -49
  137. package/styles/highcontrast-light.css +10 -9
  138. package/styles/highcontrast.css +10 -9
  139. package/styles/material-dark.css +12 -11
  140. package/styles/material.css +24 -14
  141. package/styles/menu/_all.scss +2 -2
  142. package/styles/menu/_bootstrap-dark-definition.scss +63 -63
  143. package/styles/menu/_bootstrap-definition.scss +65 -65
  144. package/styles/menu/_bootstrap4-definition.scss +64 -64
  145. package/styles/menu/_fabric-dark-definition.scss +63 -63
  146. package/styles/menu/_fabric-definition.scss +64 -64
  147. package/styles/menu/_highcontrast-definition.scss +65 -65
  148. package/styles/menu/_highcontrast-light-definition.scss +61 -61
  149. package/styles/menu/_layout.scss +638 -637
  150. package/styles/menu/_material-dark-definition.scss +63 -63
  151. package/styles/menu/_material-definition.scss +64 -64
  152. package/styles/menu/_theme.scss +243 -243
  153. package/styles/menu/bootstrap-dark.css +2 -1
  154. package/styles/menu/bootstrap.css +2 -1
  155. package/styles/menu/bootstrap.scss +1 -0
  156. package/styles/menu/bootstrap4.css +2 -1
  157. package/styles/menu/fabric-dark.css +2 -1
  158. package/styles/menu/fabric.css +2 -1
  159. package/styles/menu/fabric.scss +1 -0
  160. package/styles/menu/highcontrast-light.css +2 -1
  161. package/styles/menu/highcontrast.css +2 -1
  162. package/styles/menu/highcontrast.scss +1 -0
  163. package/styles/menu/icons/_bootstrap-dark.scss +127 -127
  164. package/styles/menu/icons/_bootstrap.scss +127 -127
  165. package/styles/menu/icons/_bootstrap4.scss +127 -127
  166. package/styles/menu/icons/_fabric-dark.scss +127 -127
  167. package/styles/menu/icons/_fabric.scss +127 -127
  168. package/styles/menu/icons/_highcontrast-light.scss +127 -127
  169. package/styles/menu/icons/_highcontrast.scss +127 -127
  170. package/styles/menu/icons/_material-dark.scss +127 -127
  171. package/styles/menu/icons/_material.scss +127 -127
  172. package/styles/menu/material-dark.css +2 -1
  173. package/styles/menu/material.css +4 -3
  174. package/styles/menu/material.scss +1 -0
  175. package/styles/sidebar/_all.scss +3 -3
  176. package/styles/sidebar/_bootstrap-dark-definition.scss +4 -4
  177. package/styles/sidebar/_bootstrap-definition.scss +4 -4
  178. package/styles/sidebar/_bootstrap4-definition.scss +4 -4
  179. package/styles/sidebar/_fabric-dark-definition.scss +4 -4
  180. package/styles/sidebar/_fabric-definition.scss +6 -6
  181. package/styles/sidebar/_highcontrast-definition.scss +4 -4
  182. package/styles/sidebar/_highcontrast-light-definition.scss +4 -4
  183. package/styles/sidebar/_icons.scss +1 -1
  184. package/styles/sidebar/_material-dark-definition.scss +4 -4
  185. package/styles/sidebar/_material-definition.scss +6 -6
  186. package/styles/sidebar/_theme.scss +168 -168
  187. package/styles/sidebar/bootstrap-dark.css +0 -1
  188. package/styles/sidebar/bootstrap.css +0 -1
  189. package/styles/sidebar/bootstrap4.css +0 -1
  190. package/styles/sidebar/fabric-dark.css +0 -1
  191. package/styles/sidebar/fabric.css +0 -1
  192. package/styles/sidebar/highcontrast-light.css +0 -1
  193. package/styles/sidebar/highcontrast.css +0 -1
  194. package/styles/sidebar/material-dark.css +0 -1
  195. package/styles/sidebar/material.css +0 -1
  196. package/styles/tab/_all.scss +2 -2
  197. package/styles/tab/_bootstrap-dark-definition.scss +386 -386
  198. package/styles/tab/_bootstrap-definition.scss +396 -396
  199. package/styles/tab/_bootstrap4-definition.scss +401 -401
  200. package/styles/tab/_fabric-dark-definition.scss +394 -394
  201. package/styles/tab/_fabric-definition.scss +410 -410
  202. package/styles/tab/_highcontrast-definition.scss +434 -434
  203. package/styles/tab/_highcontrast-light-definition.scss +423 -423
  204. package/styles/tab/_icons.scss +43 -43
  205. package/styles/tab/_layout.scss +3528 -3521
  206. package/styles/tab/_material-dark-definition.scss +407 -407
  207. package/styles/tab/_material-definition.scss +416 -416
  208. package/styles/tab/_theme.scss +1751 -1751
  209. package/styles/tab/bootstrap-dark.css +7 -2
  210. package/styles/tab/bootstrap.css +7 -2
  211. package/styles/tab/bootstrap4.css +7 -2
  212. package/styles/tab/fabric-dark.css +7 -2
  213. package/styles/tab/fabric.css +7 -2
  214. package/styles/tab/highcontrast-light.css +7 -2
  215. package/styles/tab/highcontrast.css +7 -2
  216. package/styles/tab/icons/_bootstrap-dark.scss +132 -132
  217. package/styles/tab/icons/_bootstrap.scss +132 -132
  218. package/styles/tab/icons/_bootstrap4.scss +132 -132
  219. package/styles/tab/icons/_fabric-dark.scss +132 -132
  220. package/styles/tab/icons/_fabric.scss +132 -132
  221. package/styles/tab/icons/_highcontrast-light.scss +132 -132
  222. package/styles/tab/icons/_highcontrast.scss +132 -132
  223. package/styles/tab/icons/_material-dark.scss +132 -132
  224. package/styles/tab/icons/_material.scss +132 -132
  225. package/styles/tab/material-dark.css +7 -2
  226. package/styles/tab/material.css +7 -2
  227. package/styles/tailwind-dark.css +0 -0
  228. package/styles/tailwind-dark.scss +0 -0
  229. package/styles/tailwind.css +0 -0
  230. package/styles/tailwind.scss +0 -0
  231. package/styles/toolbar/_all.scss +2 -2
  232. package/styles/toolbar/_bootstrap-dark-definition.scss +135 -135
  233. package/styles/toolbar/_bootstrap-definition.scss +134 -134
  234. package/styles/toolbar/_bootstrap4-definition.scss +139 -139
  235. package/styles/toolbar/_fabric-dark-definition.scss +155 -155
  236. package/styles/toolbar/_fabric-definition.scss +139 -139
  237. package/styles/toolbar/_highcontrast-definition.scss +149 -149
  238. package/styles/toolbar/_highcontrast-light-definition.scss +164 -164
  239. package/styles/toolbar/_layout.scss +1460 -1460
  240. package/styles/toolbar/_material-dark-definition.scss +180 -180
  241. package/styles/toolbar/_material-definition.scss +164 -164
  242. package/styles/toolbar/_theme.scss +451 -451
  243. package/styles/toolbar/bootstrap-dark.css +0 -1
  244. package/styles/toolbar/bootstrap.css +0 -1
  245. package/styles/toolbar/bootstrap.scss +1 -0
  246. package/styles/toolbar/bootstrap4.css +0 -1
  247. package/styles/toolbar/fabric-dark.css +0 -1
  248. package/styles/toolbar/fabric.css +0 -1
  249. package/styles/toolbar/fabric.scss +1 -0
  250. package/styles/toolbar/highcontrast-light.css +0 -1
  251. package/styles/toolbar/highcontrast.css +0 -1
  252. package/styles/toolbar/highcontrast.scss +1 -0
  253. package/styles/toolbar/icons/_bootstrap-dark.scss +16 -16
  254. package/styles/toolbar/icons/_bootstrap.scss +16 -16
  255. package/styles/toolbar/icons/_bootstrap4.scss +16 -16
  256. package/styles/toolbar/icons/_fabric-dark.scss +16 -16
  257. package/styles/toolbar/icons/_fabric.scss +16 -16
  258. package/styles/toolbar/icons/_highcontrast-light.scss +16 -16
  259. package/styles/toolbar/icons/_highcontrast.scss +16 -16
  260. package/styles/toolbar/icons/_material-dark.scss +16 -16
  261. package/styles/toolbar/icons/_material.scss +16 -16
  262. package/styles/toolbar/material-dark.css +0 -1
  263. package/styles/toolbar/material.css +0 -1
  264. package/styles/toolbar/material.scss +1 -0
  265. package/styles/treeview/_all.scss +2 -2
  266. package/styles/treeview/_bootstrap-dark-definition.scss +131 -131
  267. package/styles/treeview/_bootstrap-definition.scss +127 -127
  268. package/styles/treeview/_bootstrap4-definition.scss +153 -153
  269. package/styles/treeview/_fabric-dark-definition.scss +130 -130
  270. package/styles/treeview/_fabric-definition.scss +126 -126
  271. package/styles/treeview/_highcontrast-definition.scss +132 -132
  272. package/styles/treeview/_highcontrast-light-definition.scss +137 -137
  273. package/styles/treeview/_layout.scss +551 -551
  274. package/styles/treeview/_material-dark-definition.scss +126 -126
  275. package/styles/treeview/_material-definition.scss +126 -126
  276. package/styles/treeview/_theme.scss +331 -331
  277. package/styles/treeview/bootstrap-dark.css +0 -3
  278. package/styles/treeview/bootstrap.css +0 -3
  279. package/styles/treeview/bootstrap4.css +0 -3
  280. package/styles/treeview/fabric-dark.css +0 -3
  281. package/styles/treeview/fabric.css +0 -3
  282. package/styles/treeview/highcontrast-light.css +0 -3
  283. package/styles/treeview/highcontrast.css +0 -3
  284. package/styles/treeview/icons/_bootstrap-dark.scss +39 -39
  285. package/styles/treeview/icons/_bootstrap.scss +39 -39
  286. package/styles/treeview/icons/_bootstrap4.scss +39 -39
  287. package/styles/treeview/icons/_fabric-dark.scss +43 -43
  288. package/styles/treeview/icons/_fabric.scss +43 -43
  289. package/styles/treeview/icons/_highcontrast-light.scss +43 -43
  290. package/styles/treeview/icons/_highcontrast.scss +43 -43
  291. package/styles/treeview/icons/_material-dark.scss +43 -43
  292. package/styles/treeview/icons/_material.scss +43 -43
  293. package/styles/treeview/material-dark.css +0 -3
  294. package/styles/treeview/material.css +9 -3
  295. package/styles/v-scroll/_all.scss +2 -2
  296. package/styles/v-scroll/_bootstrap-dark-definition.scss +50 -50
  297. package/styles/v-scroll/_bootstrap-definition.scss +49 -49
  298. package/styles/v-scroll/_bootstrap4-definition.scss +49 -49
  299. package/styles/v-scroll/_fabric-dark-definition.scss +51 -51
  300. package/styles/v-scroll/_fabric-definition.scss +50 -50
  301. package/styles/v-scroll/_highcontrast-definition.scss +51 -51
  302. package/styles/v-scroll/_highcontrast-light-definition.scss +52 -52
  303. package/styles/v-scroll/_layout.scss +162 -162
  304. package/styles/v-scroll/_material-dark-definition.scss +78 -78
  305. package/styles/v-scroll/_material-definition.scss +77 -77
  306. package/styles/v-scroll/_theme.scss +133 -133
  307. package/styles/v-scroll/icons/_bootstrap-dark.scss +26 -26
  308. package/styles/v-scroll/icons/_bootstrap.scss +26 -26
  309. package/styles/v-scroll/icons/_bootstrap4.scss +26 -26
  310. package/styles/v-scroll/icons/_fabric-dark.scss +26 -26
  311. package/styles/v-scroll/icons/_fabric.scss +26 -26
  312. package/styles/v-scroll/icons/_highcontrast-light.scss +26 -26
  313. package/styles/v-scroll/icons/_highcontrast.scss +26 -26
  314. package/styles/v-scroll/icons/_material-dark.scss +26 -26
  315. package/styles/v-scroll/icons/_material.scss +26 -26
  316. package/tslint.json +111 -0
@@ -0,0 +1,1312 @@
1
+ import { Component, EventHandler, Property, Event, EmitType, AnimationModel, KeyboardEvents, rippleEffect } from '@syncfusion/ej2-base';
2
+ import { KeyboardEventArgs, BaseEventArgs, Effect, getUniqueID, compile as templateCompiler } from '@syncfusion/ej2-base';
3
+ import { isVisible, closest, attributes, detach, select, isBlazor, addClass, append } from '@syncfusion/ej2-base';
4
+ import { INotifyPropertyChanged, NotifyPropertyChanges, ChildProperty, Collection, Animation } from '@syncfusion/ej2-base';
5
+ import { setStyleAttribute as setStyle, Complex, updateBlazorTemplate } from '@syncfusion/ej2-base';
6
+ import { isNullOrUndefined as isNOU, formatUnit, selectAll } from '@syncfusion/ej2-base';
7
+ import { AccordionModel, AccordionItemModel, AccordionAnimationSettingsModel, AccordionActionSettingsModel } from './accordion-model';
8
+
9
+ /**
10
+ * Specifies the option to expand single or multiple panel at a time.
11
+ */
12
+ export type ExpandMode = 'Single' | 'Multiple';
13
+
14
+ type HTEle = HTMLElement;
15
+ type Str = string;
16
+
17
+ const CLS_ACRDN_ROOT: Str = 'e-acrdn-root';
18
+ const CLS_ROOT: Str = 'e-accordion';
19
+ const CLS_ITEM: Str = 'e-acrdn-item';
20
+ const CLS_ITEMFOCUS: Str = 'e-item-focus';
21
+ const CLS_ITEMHIDE: Str = 'e-hide';
22
+ const CLS_HEADER: Str = 'e-acrdn-header';
23
+ const CLS_HEADERICN: Str = 'e-acrdn-header-icon';
24
+ const CLS_HEADERCTN: Str = 'e-acrdn-header-content';
25
+ const CLS_CONTENT: Str = 'e-acrdn-panel';
26
+ const CLS_CTENT: Str = 'e-acrdn-content';
27
+ const CLS_TOOGLEICN: Str = 'e-toggle-icon';
28
+ const CLS_COLLAPSEICN: Str = 'e-tgl-collapse-icon e-icons';
29
+ const CLS_EXPANDICN: Str = 'e-expand-icon';
30
+ const CLS_RTL: Str = 'e-rtl';
31
+ const CLS_CTNHIDE: Str = 'e-content-hide';
32
+ const CLS_SLCT: Str = 'e-select';
33
+ const CLS_SLCTED: Str = 'e-selected';
34
+ const CLS_ACTIVE: Str = 'e-active';
35
+ const CLS_ANIMATE: Str = 'e-animate';
36
+ const CLS_DISABLE: Str = 'e-overlay';
37
+ const CLS_TOGANIMATE: Str = 'e-toggle-animation';
38
+ const CLS_NEST: Str = 'e-nested';
39
+ const CLS_EXPANDSTATE: Str = 'e-expand-state';
40
+ const CLS_CONTAINER: Str = 'e-accordion-container';
41
+
42
+ interface AcrdnTemplateRef {
43
+ elementRef: AcrdnElementRef;
44
+ }
45
+
46
+ interface AcrdnElementRef {
47
+ nativeElement: AcrdnElementComment;
48
+ }
49
+
50
+ interface AcrdnElementComment {
51
+ childNodes?: NodeList;
52
+ firstChild?: HTMLElement;
53
+ lastChild?: HTMLElement;
54
+ nextElementSibling?: HTMLElement;
55
+ parentElement?: HTMLElement;
56
+ propName?: HTMLElement;
57
+ data?: string;
58
+ }
59
+
60
+ export interface AccordionClickArgs extends BaseEventArgs {
61
+ /** Defines the current Accordion Item Object. */
62
+ item?: AccordionItemModel;
63
+ /**
64
+ * Defines the current Event arguments.
65
+ * @blazorType MouseEventArgs
66
+ */
67
+ originalEvent?: Event;
68
+ }
69
+ export interface ExpandEventArgs extends BaseEventArgs {
70
+ /** Defines the current Accordion Item Object. */
71
+ item?: AccordionItemModel;
72
+ /** Defines the current Accordion Item Element. */
73
+ element?: HTMLElement;
74
+ /** Defines the expand/collapse state. */
75
+ isExpanded?: boolean;
76
+ /** Defines the prevent action. */
77
+ cancel?: boolean;
78
+ /** Defines the Accordion Item Index */
79
+ index?: number;
80
+ /** Defines the Accordion Item Content */
81
+ content?: HTMLElement;
82
+ }
83
+
84
+ export interface ExpandedEventArgs extends BaseEventArgs {
85
+ /** Defines the current Accordion Item Object. */
86
+ item?: AccordionItemModel;
87
+ /** Defines the current Accordion Item Element. */
88
+ element?: HTMLElement;
89
+ /** Defines the expand/collapse state. */
90
+ isExpanded?: boolean;
91
+ /** Defines the Accordion Item Index */
92
+ index?: number;
93
+ /** Defines the Accordion Item Content */
94
+ content?: HTMLElement;
95
+ }
96
+
97
+ export class AccordionActionSettings extends ChildProperty<AccordionActionSettings> {
98
+ /**
99
+ * Specifies the type of animation.
100
+ * @default 'SlideDown'
101
+ * @aspType string
102
+ * @blazorType string
103
+ */
104
+ @Property('SlideDown')
105
+ public effect: 'None' | Effect;
106
+ /**
107
+ * Specifies the duration to animate.
108
+ * @default 400
109
+ */
110
+ @Property(400)
111
+ public duration: number;
112
+ /**
113
+ * Specifies the animation timing function.
114
+ * @default 'linear'
115
+ */
116
+ @Property('linear')
117
+ public easing: string;
118
+ }
119
+
120
+ export class AccordionAnimationSettings extends ChildProperty<AccordionAnimationSettings> {
121
+ /**
122
+ * Specifies the animation to appear while collapsing the Accordion item.
123
+ * @default { effect: 'SlideDown', duration: 400, easing: 'linear' }
124
+ */
125
+ @Complex<AccordionActionSettingsModel>({ effect: 'SlideUp', duration: 400, easing: 'linear' }, AccordionActionSettings)
126
+ public collapse: AccordionActionSettingsModel;
127
+ /**
128
+ * Specifies the animation to appear while expanding the Accordion item.
129
+ * @default { effect: 'SlideDown', duration: 400, easing: 'linear' }
130
+ */
131
+ @Complex<AccordionActionSettingsModel>({ effect: 'SlideDown', duration: 400, easing: 'linear' }, AccordionActionSettings)
132
+ public expand: AccordionActionSettingsModel;
133
+ }
134
+ /**
135
+ * An item object that is used to configure Accordion items.
136
+ */
137
+ export class AccordionItem extends ChildProperty<AccordionItem> {
138
+ /**
139
+ * Sets the text content to be displayed for the Accordion item.
140
+ * You can set the content of the Accordion item using `content` property.
141
+ * It also supports to include the title as `HTML element`, `string`, or `query selector`.
142
+ * ```typescript
143
+ * let accordionObj: Accordion = new Accordion( {
144
+ * items: [
145
+ * { header: 'Accordion Header', content: 'Accordion Content' },
146
+ * { header: '<div>Accordion Header</div>', content: '<div>Accordion Content</div' },
147
+ * { header: '#headerContent', content: '#panelContent' }]
148
+ * });
149
+ * accordionObj.appendTo('#accordion');
150
+ * ```
151
+ * @default null
152
+ */
153
+ @Property(null)
154
+ public content: string;
155
+ /**
156
+ * Sets the header text to be displayed for the Accordion item.
157
+ * You can set the title of the Accordion item using `header` property.
158
+ * It also supports to include the title as `HTML element`, `string`, or `query selector`.
159
+ * ```typescript
160
+ * let accordionObj: Accordion = new Accordion( {
161
+ * items: [
162
+ * { header: 'Accordion Header', content: 'Accordion Content' },
163
+ * { header: '<div>Accordion Header</div>', content: '<div>Accordion Content</div' },
164
+ * { header: '#headerContent', content: '#panelContent' }]
165
+ * });
166
+ * accordionObj.appendTo('#accordion');
167
+ * ```
168
+ * @default null
169
+ */
170
+ @Property(null)
171
+ public header: string;
172
+ /**
173
+ * Defines single/multiple classes (separated by a space) are to be used for Accordion item customization.
174
+ * @default null
175
+ */
176
+ @Property(null)
177
+ public cssClass: string;
178
+ /**
179
+ * Defines an icon with the given custom CSS class that is to be rendered before the header text.
180
+ * Add the css classes to the `iconCss` property and write the css styles to the defined class to set images/icons.
181
+ * Adding icon is applicable only to the header.
182
+ * ```typescript
183
+ * let accordionObj: Accordion = new Accordion( {
184
+ * items: [
185
+ * { header: 'Accordion Header', iconCss: 'e-app-icon' }]
186
+ * });
187
+ * accordionObj.appendTo('#accordion');
188
+ * ```
189
+ * ```css
190
+ * .e-app-icon::before {
191
+ * content: "\e710";
192
+ * }
193
+ * ```
194
+ * @default null
195
+ */
196
+ @Property(null)
197
+ public iconCss: string;
198
+ /**
199
+ * Sets the expand (true) or collapse (false) state of the Accordion item. By default, all the items are in a collapsed state.
200
+ * @default false
201
+ */
202
+ @Property(false)
203
+ public expanded: Boolean;
204
+ }
205
+
206
+ /**
207
+ * The Accordion is a vertically collapsible content panel that displays one or more panels at a time within the available space.
208
+ * ```html
209
+ * <div id='accordion'/>
210
+ * <script>
211
+ * var accordionObj = new Accordion();
212
+ * accordionObj.appendTo('#accordion');
213
+ * </script>
214
+ * ```
215
+ */
216
+ @NotifyPropertyChanges
217
+ export class Accordion extends Component<HTMLElement> implements INotifyPropertyChanged {
218
+ private lastActiveItemId: string;
219
+ private trgtEle: HTEle;
220
+ private ctrlTem: HTEle;
221
+ private keyModule: KeyboardEvents;
222
+ private expandedItems: number[];
223
+ private initExpand: number[];
224
+ private isNested: Boolean;
225
+ private isDestroy: Boolean;
226
+ private templateEle: string[];
227
+ private isAngular: boolean;
228
+ private headerTemplateFn: Function;
229
+ private itemTemplateFn: Function;
230
+ /**
231
+ * Contains the keyboard configuration of the Accordion.
232
+ */
233
+ private keyConfigs: { [key: string]: Str } = {
234
+ moveUp: 'uparrow',
235
+ moveDown: 'downarrow',
236
+ enter: 'enter',
237
+ space: 'space',
238
+ home: 'home',
239
+ end: 'end',
240
+ };
241
+
242
+ /**
243
+ * An array of item that is used to specify Accordion items.
244
+ * ```typescript
245
+ * let accordionObj: Accordion = new Accordion( {
246
+ * items: [
247
+ * { header: 'Accordion Header', content: 'Accordion Content' }]
248
+ * });
249
+ * accordionObj.appendTo('#accordion');
250
+ * ```
251
+ * @default []
252
+ */
253
+ @Collection<AccordionItemModel>([], AccordionItem)
254
+ public items: AccordionItemModel[];
255
+ /**
256
+ * Specifies the datasource for the accordion items.
257
+ * @isdatamanager false
258
+ * @default []
259
+ */
260
+ @Property([])
261
+ public dataSource: Object[];
262
+ /**
263
+ * Specifies the template option for accordion items.
264
+ * @default null
265
+ */
266
+ @Property()
267
+ public itemTemplate: string;
268
+ /**
269
+ * Specifies the header title template option for accordion items.
270
+ * @default null
271
+ */
272
+ @Property()
273
+ public headerTemplate: string;
274
+ /**
275
+ * Specifies the width of the Accordion in pixels/number/percentage. Number value is considered as pixels.
276
+ * @default '100%'
277
+ */
278
+ @Property('100%')
279
+ public width: string | number;
280
+ /**
281
+ * Specifies the height of the Accordion in pixels/number/percentage. Number value is considered as pixels.
282
+ * @default 'auto'
283
+ */
284
+ @Property('auto')
285
+ public height: string | number;
286
+ /**
287
+ * Specifies the options to expand single or multiple panel at a time.
288
+ * The possible values are:
289
+ * - Single: Sets to expand only one Accordion item at a time.
290
+ * - Multiple: Sets to expand more than one Accordion item at a time.
291
+ * @default 'Multiple'
292
+ */
293
+ @Property('Multiple')
294
+ public expandMode: ExpandMode;
295
+ /**
296
+ * Specifies the animation configuration settings for expanding and collapsing the panel.
297
+ * @default { expand: { effect: 'SlideDown', duration: 400, easing: 'linear' },
298
+ * collapse: { effect: 'SlideUp', duration: 400, easing: 'linear' }}
299
+ */
300
+ @Complex<AccordionAnimationSettingsModel>({}, AccordionAnimationSettings)
301
+ public animation: AccordionAnimationSettingsModel;
302
+ /**
303
+ * The event will be fired while clicking anywhere within the Accordion.
304
+ * @event
305
+ * @blazorProperty 'Clicked'
306
+ */
307
+ @Event()
308
+ public clicked: EmitType<AccordionClickArgs>;
309
+ /**
310
+ * The event will be fired before the item gets collapsed/expanded.
311
+ * @event
312
+ * @blazorProperty 'Expanding'
313
+ */
314
+ @Event()
315
+ public expanding: EmitType<ExpandEventArgs>;
316
+ /**
317
+ * The event will be fired after the item gets collapsed/expanded.
318
+ * @event
319
+ * @blazorProperty 'Expanded'
320
+ */
321
+ @Event()
322
+ public expanded: EmitType<ExpandedEventArgs>;
323
+ /**
324
+ * The event will be fired once the control rendering is completed.
325
+ * @event
326
+ * @blazorProperty 'Created'
327
+ */
328
+ @Event()
329
+ public created: EmitType<Event>;
330
+ /**
331
+ * The event will be fired when the control gets destroyed.
332
+ * @event
333
+ * @blazorProperty 'Destroyed'
334
+ */
335
+ @Event()
336
+ public destroyed: EmitType<Event>;
337
+
338
+ /**
339
+ * Initializes a new instance of the Accordion class.
340
+ * @param options - Specifies Accordion model properties as options.
341
+ * @param element - Specifies the element that is rendered as an Accordion.
342
+ */
343
+ constructor(options?: AccordionModel, element?: string | HTMLElement) {
344
+ super(options, <HTEle | Str>element);
345
+ }
346
+ /**
347
+ * Removes the control from the DOM and also removes all its related events.
348
+ * @returns void
349
+ */
350
+ public destroy(): void {
351
+ let ele: HTEle = this.element;
352
+ super.destroy();
353
+ this.unwireEvents();
354
+ this.isDestroy = true;
355
+ this.restoreContent(null);
356
+ while (ele.firstElementChild) {
357
+ ele.removeChild(ele.firstElementChild); }
358
+ if (this.trgtEle) {
359
+ while (this.ctrlTem.firstElementChild) {
360
+ ele.appendChild(this.ctrlTem.firstElementChild); } }
361
+ ele.classList.remove(CLS_ACRDN_ROOT);
362
+ ele.removeAttribute('style');
363
+ ['aria-disabled', 'aria-multiselectable', 'role', 'data-ripple'].forEach((attrb: string): void => {
364
+ this.element.removeAttribute(attrb);
365
+ });
366
+ }
367
+ protected preRender(): void {
368
+ let nested: Element = closest(this.element, '.' + CLS_CONTENT);
369
+ this.isNested = false;
370
+ this.templateEle = [];
371
+ if (!this.isDestroy) {
372
+ this.isDestroy = false; }
373
+ if (!isNOU(nested)) {
374
+ nested.classList.add(CLS_NEST);
375
+ this.isNested = true;
376
+ } else {
377
+ this.element.classList.add(CLS_ACRDN_ROOT);
378
+ }
379
+ if (this.enableRtl) {
380
+ this.add(this.element, CLS_RTL);
381
+ }
382
+ if (!this.enablePersistence || isNOU(this.expandedItems)) {
383
+ this.expandedItems = []; }
384
+ }
385
+ private add(ele: HTEle, val: Str): void {
386
+ ele.classList.add(val);
387
+ }
388
+ private remove(ele: HTEle, val: Str): void {
389
+ ele.classList.remove(val);
390
+ }
391
+ /**
392
+ * To initialize the control rendering
393
+ * @private
394
+ */
395
+ protected render(): void {
396
+ this.initializeheaderTemplate();
397
+ this.initializeItemTemplate();
398
+ this.initialize();
399
+ this.renderControl();
400
+ this.wireEvents();
401
+ this.renderComplete();
402
+ }
403
+ private initialize(): void {
404
+ let width: Str = formatUnit(this.width);
405
+ let height: Str = formatUnit(this.height);
406
+ setStyle(this.element, {'width': width, 'height': height});
407
+ let ariaAttr: { [key: string]: Str } = {
408
+ 'aria-disabled': 'false', 'role': 'presentation', 'aria-multiselectable' : 'true'
409
+ };
410
+ if (this.expandedItems.length > 0 ) {
411
+ this.initExpand = this.expandedItems;
412
+ }
413
+ attributes(this.element, ariaAttr);
414
+ if (this.expandMode === 'Single') {
415
+ this.element.setAttribute('aria-multiselectable', 'false');
416
+ }
417
+ }
418
+ private renderControl(): void {
419
+ this.trgtEle = (this.element.children.length > 0) ? <HTEle>select('div', this.element) : null;
420
+ this.renderItems();
421
+ this.initItemExpand();
422
+ }
423
+ private unwireEvents(): void {
424
+ EventHandler.remove(this.element, 'click', this.clickHandler);
425
+ if (!isNOU(this.keyModule)) {
426
+ this.keyModule.destroy(); }
427
+ }
428
+ private wireEvents(): void {
429
+ EventHandler.add(this.element, 'click', this.clickHandler, this);
430
+ if (!this.isNested && !this.isDestroy) {
431
+ rippleEffect(this.element, { selector: '.' + CLS_HEADER}); }
432
+ if (!this.isNested) {
433
+ this.keyModule = new KeyboardEvents(
434
+ this.element,
435
+ {
436
+ keyAction: this.keyActionHandler.bind(this),
437
+ keyConfigs: this.keyConfigs,
438
+ eventName: 'keydown'
439
+ }); }
440
+ }
441
+ private templateParser(template: string): Function {
442
+ if (template) {
443
+ try {
444
+ if (document.querySelectorAll(template).length) {
445
+ return templateCompiler(document.querySelector(template).innerHTML.trim());
446
+ }
447
+ } catch (error) {
448
+ return templateCompiler(template);
449
+ }
450
+ }
451
+ return undefined;
452
+ }
453
+ private initializeheaderTemplate(): void {
454
+ if (this.headerTemplate) {
455
+ this.headerTemplateFn = this.templateParser(this.headerTemplate);
456
+ }
457
+ }
458
+ private initializeItemTemplate(): void {
459
+ if (this.itemTemplate) {
460
+ this.itemTemplateFn = this.templateParser(this.itemTemplate);
461
+ }
462
+ }
463
+ private getheaderTemplate(): Function {
464
+ return this.headerTemplateFn;
465
+ }
466
+ private getItemTemplate(): Function {
467
+ return this.itemTemplateFn;
468
+ }
469
+ private updateContentBlazorTemplate(item?: AccordionItemModel, index?: number): void {
470
+ if (this.itemTemplate && isBlazor() && !this.isStringTemplate) {
471
+ updateBlazorTemplate(this.element.id + '_itemTemplate', 'ItemTemplate', this, false);
472
+ }
473
+ if (item && item.content && isBlazor() && !this.isStringTemplate && item.content.indexOf('<div>Blazor') === 0) {
474
+ updateBlazorTemplate(this.element.id + index + '_content', 'ContentTemplate', item);
475
+ }
476
+ }
477
+ private updateHeaderBlazorTemplate(item?: AccordionItemModel, index?: number): void {
478
+ if (this.headerTemplate && isBlazor() && !this.isStringTemplate) {
479
+ updateBlazorTemplate(this.element.id + '_headerTemplate', 'HeaderTemplate', this, false);
480
+ }
481
+ if (item && item.header && isBlazor() && !this.isStringTemplate && item.header.indexOf('<div>Blazor') === 0) {
482
+ updateBlazorTemplate(this.element.id + index + '_header', 'HeaderTemplate', item);
483
+ }
484
+ }
485
+ private focusIn(e: FocusEvent): void {
486
+ (<HTEle>e.target).parentElement.classList.add(CLS_ITEMFOCUS);
487
+ }
488
+ private focusOut(e: FocusEvent): void {
489
+ (<HTEle>e.target).parentElement.classList.remove(CLS_ITEMFOCUS);
490
+ }
491
+ private ctrlTemplate(): void {
492
+ this.ctrlTem = <HTEle>this.element.cloneNode(true);
493
+ let innerEles: HTMLCollection;
494
+ let rootEle: HTMLElement = <HTMLElement>select('.' + CLS_CONTAINER, this.element);
495
+ if (rootEle) {
496
+ innerEles = rootEle.children as HTMLCollection;
497
+ } else {
498
+ innerEles = this.element.children as HTMLCollection;
499
+ }
500
+ let items: AccordionItemModel[] = [];
501
+ /* tslint:disable */
502
+ [].slice.call(innerEles).forEach((el: HTEle) => {
503
+ items.push({
504
+ header: (el.childElementCount > 0 && el.children[0]) ? (el.children[0]) as any : '' ,
505
+ content: (el.childElementCount > 1 && el.children[1]) ? (el.children[1]) as any : ''
506
+ });
507
+ el.parentNode.removeChild(el);
508
+ });
509
+ /* tslint:enable */
510
+ if (rootEle) {
511
+ this.element.removeChild(rootEle);
512
+ }
513
+ this.setProperties({ items: items }, true);
514
+ }
515
+ private toggleIconGenerate(): HTEle {
516
+ let tglIcon: HTEle = this.createElement('div', {className: CLS_TOOGLEICN});
517
+ let hdrColIcon: HTEle = this.createElement('span', {className: CLS_COLLAPSEICN });
518
+ tglIcon.appendChild(hdrColIcon);
519
+ return tglIcon;
520
+ }
521
+ private initItemExpand(): void {
522
+ let len: number = this.initExpand.length;
523
+ if (len === 0 ) {
524
+ return; }
525
+ if (this.expandMode === 'Single') {
526
+ this.expandItem(true, this.initExpand[len - 1]);
527
+ } else {
528
+ for (let i: number = 0; i < len; i++) {
529
+ this.expandItem(true, this.initExpand[i]); } }
530
+ }
531
+ private renderItems(): void {
532
+ let ele: HTEle = this.element;
533
+ let innerItem: HTEle;
534
+ let innerDataSourceItem: HTEle;
535
+ if (isNOU(this.initExpand)) {
536
+ this.initExpand = [];
537
+ }
538
+ if (!isNOU(this.trgtEle)) {
539
+ this.ctrlTemplate();
540
+ }
541
+ if (this.dataSource.length > 0) {
542
+ this.dataSource.forEach((item: object, index: number) => {
543
+ innerDataSourceItem = this.renderInnerItem(item, index);
544
+ ele.appendChild(innerDataSourceItem);
545
+ if (innerDataSourceItem.childElementCount > 0) {
546
+ EventHandler.add(innerDataSourceItem.querySelector('.' + CLS_HEADER), 'focus', this.focusIn, this);
547
+ EventHandler.add(innerDataSourceItem.querySelector('.' + CLS_HEADER), 'blur', this.focusOut, this);
548
+ }
549
+ });
550
+ this.updateHeaderBlazorTemplate();
551
+ } else {
552
+ let items: AccordionItem[] = <AccordionItem[]>this.items;
553
+ if (ele && items.length > 0) {
554
+ items.forEach((item: AccordionItem, index: number) => {
555
+ innerItem = this.renderInnerItem(item, index);
556
+ ele.appendChild(innerItem);
557
+ this.updateHeaderBlazorTemplate(item, index);
558
+ if (innerItem.childElementCount > 0) {
559
+ EventHandler.add(innerItem.querySelector('.' + CLS_HEADER), 'focus', this.focusIn, this);
560
+ EventHandler.add(innerItem.querySelector('.' + CLS_HEADER), 'blur', this.focusOut, this);
561
+ }
562
+ });
563
+ }
564
+ }
565
+ }
566
+ private clickHandler(e: Event): void {
567
+ let trgt: HTEle = <HTEle>e.target;
568
+ let items: Object[] = this.getItems();
569
+ let eventArgs: AccordionClickArgs = { };
570
+ let index: number;
571
+ let tglIcon: HTEle;
572
+ let acrdEle: HTEle = <HTEle>closest(trgt, '.' + CLS_ROOT);
573
+ if (acrdEle !== this.element) {
574
+ return; }
575
+ trgt.classList.add('e-target');
576
+ let acrdnItem: HTEle = <HTEle>closest(trgt, '.' + CLS_ITEM);
577
+ let acrdnHdr: HTEle = <HTEle>closest(trgt, '.' + CLS_HEADER);
578
+ let acrdnCtn: HTEle = <HTEle>closest(trgt, '.' + CLS_CONTENT);
579
+ if (acrdnItem && (isNOU(acrdnHdr) || isNOU(acrdnCtn))) {
580
+ acrdnHdr = <HTEle>acrdnItem.children[0];
581
+ acrdnCtn = <HTEle>acrdnItem.children[1]; }
582
+ if (acrdnHdr) {
583
+ tglIcon = <HTEle> select('.' + CLS_TOOGLEICN, acrdnHdr); }
584
+ let acrdnCtnItem: HTEle;
585
+ if (acrdnHdr) {
586
+ acrdnCtnItem = <HTEle>closest(acrdnHdr, '.' + CLS_ITEM); } else if (acrdnCtn) {
587
+ acrdnCtnItem = <HTEle>closest(acrdnCtn, '.' + CLS_ITEM); }
588
+ let acrdActive: HTEle[] = [];
589
+ index = this.getIndexByItem(acrdnItem);
590
+ if (acrdnCtnItem) {
591
+ eventArgs.item = items[this.getIndexByItem(acrdnCtnItem)]; }
592
+ eventArgs.originalEvent = e;
593
+ let ctnCheck: Boolean = !isNOU(tglIcon) && acrdnItem.childElementCount <= 1;
594
+ if (ctnCheck && (isNOU(acrdnCtn) || !isNOU(select('.' + CLS_HEADER + ' .' + CLS_TOOGLEICN, acrdnCtnItem )))) {
595
+ acrdnItem.appendChild(this.contentRendering(index));
596
+ this.updateContentBlazorTemplate(eventArgs.item, index);
597
+ this.ariaAttrUpdate(acrdnItem);
598
+ }
599
+ this.trigger('clicked', eventArgs);
600
+ let cntclkCheck: boolean = (acrdnCtn && !isNOU(select('.e-target', acrdnCtn)));
601
+ let inlineAcrdnSel: string = '.' + CLS_CONTENT + ' .' + CLS_ROOT;
602
+ let inlineEleAcrdn: boolean = acrdnCtn && !isNOU(select('.' + CLS_ROOT, acrdnCtn)) && isNOU(closest(trgt , inlineAcrdnSel )) ;
603
+ let nestContCheck: boolean = acrdnCtn && isNOU(select('.' + CLS_ROOT, acrdnCtn)) || !(closest(trgt , '.' + CLS_ROOT) === this.element);
604
+ cntclkCheck = cntclkCheck && (inlineEleAcrdn || nestContCheck);
605
+ trgt.classList.remove('e-target');
606
+ if (trgt.classList.contains(CLS_CONTENT) || trgt.classList.contains(CLS_CTENT) || cntclkCheck) {
607
+ return; }
608
+ let acrdcontainer: HTMLElement = <HTMLElement>this.element.querySelector('.' + CLS_CONTAINER);
609
+ let acrdnchild: HTMLCollection = (acrdcontainer) ? acrdcontainer.children : this.element.children;
610
+ [].slice.call(acrdnchild).forEach((el: HTEle) => {
611
+ if (el.classList.contains(CLS_ACTIVE)) { acrdActive.push(el); }
612
+ });
613
+ let acrdAniEle: HTEle[] = [].slice.call(this.element.querySelectorAll('.' + CLS_ITEM + ' [' + CLS_ANIMATE + ']'));
614
+ if (acrdAniEle.length > 0) {
615
+ for (let el of acrdAniEle) {
616
+ acrdActive.push(el.parentElement);
617
+ }
618
+ }
619
+ let sameContentCheck: boolean = acrdActive.indexOf(acrdnCtnItem) !== -1 && acrdnCtn.getAttribute('e-animate') === 'true';
620
+ let sameHeader: boolean = false;
621
+ if (!isNOU(acrdnItem) && !isNOU(acrdnHdr) ) {
622
+ let acrdnCtn: HTEle = <HTEle>select('.' + CLS_CONTENT, acrdnItem);
623
+ let acrdnRoot: HTEle = <HTEle>closest(acrdnItem, '.' + CLS_ACRDN_ROOT);
624
+ let expandState: HTEle = <HTEle>acrdnRoot.querySelector('.' + CLS_EXPANDSTATE);
625
+ if (isNOU(acrdnCtn) ) {
626
+ return; }
627
+ sameHeader = (expandState === acrdnItem);
628
+ if (isVisible(acrdnCtn) && (!sameContentCheck || acrdnCtnItem.classList.contains(CLS_SLCTED))) {
629
+ this.collapse(acrdnCtn);
630
+ } else {
631
+ if ((acrdActive.length > 0) && this.expandMode === 'Single' && !sameContentCheck) {
632
+ acrdActive.forEach( (el: HTEle) => {
633
+ this.collapse(<HTEle>select('.' + CLS_CONTENT, el));
634
+ el.classList.remove(CLS_EXPANDSTATE);
635
+ });
636
+ }
637
+ this.expand(acrdnCtn);
638
+ }
639
+ if (!isNOU(expandState) && !sameHeader ) {
640
+ expandState.classList.remove(CLS_EXPANDSTATE); }
641
+ }
642
+ }
643
+ private eleMoveFocus(action: Str, root: HTEle, trgt: HTEle): void {
644
+ let clst: HTEle;
645
+ let clstItem: HTEle = <HTEle>closest(trgt, '.' + CLS_ITEM);
646
+ if (trgt === root) {
647
+ clst = <HTEle>((action === 'moveUp' ? trgt.lastElementChild : trgt).querySelector('.' + CLS_HEADER));
648
+ } else if (trgt.classList.contains(CLS_HEADER)) {
649
+ clstItem = <HTEle>(action === 'moveUp' ? clstItem.previousElementSibling : clstItem.nextElementSibling );
650
+ if (clstItem) {
651
+ clst = <HTEle>select('.' + CLS_HEADER, clstItem);
652
+ }
653
+ }
654
+ if (clst) {
655
+ clst.focus();
656
+ }
657
+ }
658
+ private keyActionHandler(e: KeyboardEventArgs): void {
659
+ let trgt: HTEle = <HTEle>e.target;
660
+ let header: HTEle = <HTEle>closest(e.target as HTEle, CLS_HEADER);
661
+ if (isNOU(header) && !trgt.classList.contains(CLS_ROOT) && !trgt.classList.contains(CLS_HEADER)) {
662
+ return; }
663
+ let clst: HTEle;
664
+ let root: HTEle = this.element;
665
+ let content: HTEle;
666
+ switch (e.action) {
667
+ case 'moveUp':
668
+ this.eleMoveFocus(e.action, root, trgt);
669
+ break;
670
+ case 'moveDown':
671
+ this.eleMoveFocus(e.action, root, trgt);
672
+ break;
673
+ case 'space':
674
+ case 'enter':
675
+ content = trgt.nextElementSibling as HTEle;
676
+ if (!isNOU(content) && content.classList.contains(CLS_CONTENT)) {
677
+ if (content.getAttribute('e-animate') !== 'true') {
678
+ trgt.click(); }} else {
679
+ trgt.click();
680
+ }
681
+ break;
682
+ case 'home':
683
+ case 'end':
684
+ clst = e.action === 'home' ? <HTEle>root.firstElementChild.children[0] : <HTEle>root.lastElementChild.children[0];
685
+ clst.focus();
686
+ break;
687
+ }
688
+ }
689
+ private headerEleGenerate(): HTEle {
690
+ let header: HTEle = this.createElement('div', { className: CLS_HEADER, id: getUniqueID('acrdn_header') });
691
+ let items: Object[] = this.getItems();
692
+ let ariaAttr: { [key: string]: Str } = {
693
+ 'tabindex': '0', 'role': 'heading', 'aria-selected': 'false',
694
+ 'aria-disabled': 'false', 'aria-level': items.length.toString()
695
+ };
696
+ attributes(header, ariaAttr);
697
+ return header;
698
+ }
699
+ private renderInnerItem(item: AccordionItemModel, index: number): HTEle {
700
+ let innerEle: HTEle;
701
+ innerEle = this.createElement('div', { className: CLS_ITEM });
702
+ innerEle.id = getUniqueID('acrdn_item');
703
+ attributes(innerEle, { 'aria-expanded': 'false' });
704
+ if (this.headerTemplate) {
705
+ let ctnEle: HTEle = this.headerEleGenerate();
706
+ let hdrEle: HTEle = this.createElement('div', { className: CLS_HEADERCTN });
707
+ ctnEle.appendChild(hdrEle);
708
+ append(this.getheaderTemplate()(item, this, 'headerTemplate', this.element.id + '_headerTemplate', false), hdrEle);
709
+ innerEle.appendChild(ctnEle);
710
+ ctnEle.appendChild(this.toggleIconGenerate());
711
+ this.add(innerEle, CLS_SLCT);
712
+ return innerEle;
713
+ }
714
+ if (item.header && this.angularnativeCondiCheck(item, 'header')) {
715
+ let ctnEle: HTEle = this.headerEleGenerate();
716
+ let hdrEle: HTEle = this.createElement('div', { className: CLS_HEADERCTN});
717
+ ctnEle.appendChild(hdrEle);
718
+ ctnEle.appendChild(this.fetchElement(hdrEle, item.header, index, true));
719
+ innerEle.appendChild(ctnEle);
720
+ }
721
+ let hdr: HTEle = <HTEle>select('.' + CLS_HEADER, innerEle);
722
+ if (item.expanded && !isNOU(index) && (!this.enablePersistence)) {
723
+ if (this.initExpand.indexOf(index) === -1) {
724
+ this.initExpand.push(index); }
725
+ }
726
+ if (item.cssClass) {
727
+ let acrdnClass: string = item.cssClass;
728
+ let arcdnClassList: string[] = [];
729
+ arcdnClassList = acrdnClass.split(' ');
730
+ arcdnClassList.forEach((el: string): void => {
731
+ addClass([innerEle], el);
732
+ });
733
+ }
734
+ if (item.iconCss) {
735
+ let hdrIcnEle: HTEle = this.createElement('div', { className: CLS_HEADERICN });
736
+ let icon: HTEle = this.createElement('span', { className: item.iconCss + ' e-icons' });
737
+ hdrIcnEle.appendChild(icon);
738
+ if (isNOU(hdr)) {
739
+ hdr = this.headerEleGenerate();
740
+ hdr.appendChild(hdrIcnEle);
741
+ innerEle.appendChild(hdr);
742
+ } else {
743
+ hdr.insertBefore(hdrIcnEle, hdr.childNodes[0]); }
744
+ }
745
+ if (item.content && this.angularnativeCondiCheck(item, 'content')) {
746
+ let hdrIcon: HTEle = this.toggleIconGenerate();
747
+ if (isNOU(hdr)) {
748
+ hdr = this.headerEleGenerate();
749
+ innerEle.appendChild(hdr);
750
+ }
751
+ hdr.appendChild(hdrIcon);
752
+ this.add(innerEle, CLS_SLCT);
753
+ }
754
+ return innerEle;
755
+ }
756
+
757
+ private angularnativeCondiCheck(item: AccordionItemModel, prop: string): boolean {
758
+ let property: string = prop === 'content' ? item.content : item.header;
759
+ let content: AcrdnTemplateRef = (property as Object) as AcrdnTemplateRef;
760
+ if (this.isAngular && !isNOU(content.elementRef) ) {
761
+ let data: string = content.elementRef.nativeElement.data;
762
+ if (isNOU(data) || data === '' || (data.indexOf('bindings=') === -1) ) {
763
+ return true;
764
+ }
765
+ let parseddata: { [key: string]: string } = JSON.parse(content.elementRef.nativeElement.data.replace('bindings=', ''));
766
+ if (!isNOU(parseddata) && parseddata['ng-reflect-ng-if'] === 'false' ) {
767
+ return false;
768
+ } else {
769
+ return true;
770
+ }
771
+ } else {
772
+ return true;
773
+ }
774
+ }
775
+
776
+ private fetchElement(ele: HTEle, value: Str, index: number, isHeader: boolean): HTEle {
777
+ let templateFn: Function;
778
+ let temString: Str;
779
+ try {
780
+ if (document.querySelectorAll(value).length) {
781
+ let eleVal: HTEle = <HTEle>document.querySelector(value);
782
+ temString = eleVal.outerHTML.trim();
783
+ ele.appendChild(eleVal);
784
+ eleVal.style.display = '';
785
+ }
786
+ } catch (e) {
787
+ if (typeof (value) === 'string' && isBlazor() && value.indexOf('<div>Blazor') !== 0) {
788
+ ele.innerHTML = value;
789
+ /* tslint:disable */
790
+ } else if (!isNOU(this.trgtEle) && ((value as any) instanceof (HTMLElement))) {
791
+ ele.appendChild(value as any);
792
+ (<HTMLElement>ele.firstElementChild).style.display = '';
793
+ /* tslint:enable */
794
+ } else {
795
+ templateFn = templateCompiler(value);
796
+ }
797
+ }
798
+ let tempArray: HTEle[];
799
+ if (!isNOU(templateFn)) {
800
+ let templateProps: string;
801
+ if (ele.classList.contains(CLS_HEADERCTN)) {
802
+ templateProps = this.element.id + index + '_header';
803
+ } else if (ele.classList.contains(CLS_CTENT)) {
804
+ templateProps = this.element.id + index + '_content';
805
+ }
806
+ tempArray = templateFn({}, null, null, templateProps, this.isStringTemplate);
807
+ }
808
+ if (!isNOU(tempArray) && tempArray.length > 0 && !(isNOU(tempArray[0].tagName) && tempArray.length === 1) ) {
809
+ [].slice.call(tempArray).forEach((el: HTEle): void => {
810
+ if (!isNOU(el.tagName)) {
811
+ el.style.display = '';
812
+ }
813
+ ele.appendChild(el);
814
+ });
815
+ } else if (ele.childElementCount === 0) {
816
+ ele.innerHTML = value;
817
+ }
818
+ if (!isNOU(temString)) {
819
+ if (this.templateEle.indexOf(value) === -1) {
820
+ this.templateEle.push(value);
821
+ }
822
+ }
823
+ return ele;
824
+ }
825
+ private ariaAttrUpdate(itemEle: HTEle): void {
826
+ let header: Element = select('.' + CLS_HEADER, itemEle);
827
+ let content: Element = select('.' + CLS_CONTENT, itemEle);
828
+ header.setAttribute('aria-controls', content.id);
829
+ content.setAttribute('aria-labelledby', header.id);
830
+ content.setAttribute('role', 'definition');
831
+ }
832
+ private contentRendering(index: number): HTEle {
833
+ let itemcnt: HTEle = this.createElement('div', { className: CLS_CONTENT + ' ' + CLS_CTNHIDE, id: getUniqueID('acrdn_panel') });
834
+ attributes(itemcnt, { 'aria-hidden': 'true' });
835
+ let ctn: HTEle = this.createElement('div', { className: CLS_CTENT });
836
+ if (this.dataSource.length > 0) {
837
+ append(this.getItemTemplate()(this.dataSource[index], this, 'itemTemplate', this.element.id + '_itemTemplate', false), ctn);
838
+ itemcnt.appendChild(ctn);
839
+ } else {
840
+ itemcnt.appendChild(this.fetchElement(ctn, this.items[index].content, index, false));
841
+ }
842
+ return itemcnt;
843
+ }
844
+ private expand(trgt: HTEle): void {
845
+ let eventArgs: ExpandEventArgs;
846
+ let items: Object[] = this.getItems();
847
+ let trgtItemEle: HTEle = <HTEle>closest(trgt, '.' + CLS_ITEM);
848
+ if (isNOU(trgt) || (isVisible(trgt) && trgt.getAttribute('e-animate') !== 'true' ) || trgtItemEle.classList.contains(CLS_DISABLE)) {
849
+ return; }
850
+ let acrdnRoot: HTEle = <HTEle>closest(trgtItemEle, '.' + CLS_ACRDN_ROOT);
851
+ let expandState: HTEle = <HTEle>acrdnRoot.querySelector('.' + CLS_EXPANDSTATE);
852
+ let animation: AnimationModel = {
853
+ name: <Effect>this.animation.expand.effect,
854
+ duration: this.animation.expand.duration,
855
+ timingFunction: this.animation.expand.easing
856
+ };
857
+ let icon: HTEle = <HTEle>select('.' + CLS_TOOGLEICN, trgtItemEle).firstElementChild;
858
+ eventArgs = { element: trgtItemEle,
859
+ item: items[this.getIndexByItem(trgtItemEle)],
860
+ index: this.getIndexByItem(trgtItemEle),
861
+ content: trgtItemEle.querySelector('.' + CLS_CONTENT),
862
+ isExpanded: true };
863
+ let eff: string = animation.name;
864
+ this.trigger('expanding', eventArgs, (expandArgs: ExpandEventArgs) => {
865
+ if (!expandArgs.cancel) {
866
+ icon.classList.add(CLS_TOGANIMATE);
867
+ this.expandedItemsPush(trgtItemEle);
868
+ if (!isNOU(expandState)) {
869
+ expandState.classList.remove(CLS_EXPANDSTATE); }
870
+ trgtItemEle.classList.add(CLS_EXPANDSTATE);
871
+ if ((animation.name === <Effect>'None')) {
872
+ this.expandProgress('begin', icon, trgt, trgtItemEle, expandArgs);
873
+ this.expandProgress('end', icon, trgt, trgtItemEle, expandArgs);
874
+ } else {
875
+ this.expandAnimation(eff, icon, trgt, trgtItemEle, animation, expandArgs);
876
+ }
877
+ }
878
+ });
879
+ }
880
+ private expandAnimation (ef: Str, icn: HTEle, trgt: HTEle, trgtItemEle: HTEle, animate: AnimationModel, args: ExpandEventArgs ): void {
881
+ let height: number;
882
+ let trgtHgt: number;
883
+ this.lastActiveItemId = trgtItemEle.id;
884
+ if (ef === 'SlideDown') {
885
+ animate.begin = () => {
886
+ this.expandProgress('begin', icn, trgt, trgtItemEle, args);
887
+ trgt.style.position = 'absolute';
888
+ height = trgtItemEle.offsetHeight;
889
+ trgtHgt = trgt.offsetHeight;
890
+ trgt.style.maxHeight = (trgt.offsetHeight) + 'px';
891
+ trgtItemEle.style.maxHeight = '';
892
+ };
893
+ animate.progress = () => {
894
+ trgtItemEle.style.minHeight = (height + trgt.offsetHeight) + 'px';
895
+ };
896
+ animate.end = () => {
897
+ setStyle(trgt, { 'position': '', 'maxHeight': '' });
898
+ trgtItemEle.style.minHeight = '';
899
+ this.expandProgress('end', icn, trgt, trgtItemEle, args);
900
+ };
901
+ } else {
902
+ animate.begin = () => {
903
+ this.expandProgress('begin', icn, trgt, trgtItemEle, args); };
904
+ animate.end = () => {
905
+ this.expandProgress('end', icn, trgt, trgtItemEle, args); };
906
+ }
907
+ new Animation(animate).animate(trgt);
908
+ }
909
+ private expandProgress(progress: string, icon: HTEle, trgt: HTEle, trgtItemEle: HTEle, eventArgs: ExpandEventArgs ): void {
910
+ this.remove(trgt, CLS_CTNHIDE);
911
+ this.add(trgtItemEle, CLS_SLCTED);
912
+ this.add(icon , CLS_EXPANDICN);
913
+ if (progress === 'end') {
914
+ this.add(trgtItemEle, CLS_ACTIVE);
915
+ trgt.setAttribute('aria-hidden', 'false');
916
+ attributes (trgtItemEle, {'aria-expanded': 'true' });
917
+ attributes (trgt.previousElementSibling, { 'aria-selected': 'true'});
918
+ icon.classList.remove(CLS_TOGANIMATE);
919
+ this.trigger('expanded' , eventArgs);
920
+ }
921
+ }
922
+ private expandedItemsPush(item: HTEle): void {
923
+ let index: number = this.getIndexByItem(item);
924
+ if (this.expandedItems.indexOf(index) === -1) {
925
+ this.expandedItems.push (index); }
926
+ }
927
+ private getIndexByItem(item: HTEle): number {
928
+ let itemEle: HTEle[] = this.getItemElements();
929
+ return [].slice.call(itemEle).indexOf(item);
930
+ }
931
+ private getItemElements(): HTEle[] {
932
+ let itemEle: HTEle[] = [];
933
+ let itemCollection: HTMLCollection = this.element.children;
934
+ [].slice.call(itemCollection).forEach((el: HTEle) => {
935
+ if (el.classList.contains(CLS_ITEM)) { itemEle.push(el); }
936
+ });
937
+ return itemEle;
938
+ }
939
+ private expandedItemsPop(item: HTEle): void {
940
+ let index: number = this.getIndexByItem(item);
941
+ this.expandedItems.splice(this.expandedItems.indexOf(index), 1);
942
+ }
943
+ private collapse(trgt: HTEle): void {
944
+ let eventArgs: ExpandEventArgs;
945
+ let items: Object[] = this.getItems();
946
+ let trgtItemEle: HTEle = <HTEle>closest(trgt, '.' + CLS_ITEM);
947
+ if (isNOU(trgt) || !isVisible(trgt) || trgtItemEle.classList.contains(CLS_DISABLE)) { return; }
948
+ let animation: AnimationModel = {
949
+ name: <Effect>this.animation.collapse.effect,
950
+ duration: this.animation.collapse.duration,
951
+ timingFunction: this.animation.collapse.easing,
952
+ };
953
+ let icon: HTEle = <HTEle>select('.' + CLS_TOOGLEICN, trgtItemEle).firstElementChild;
954
+ eventArgs = { element: trgtItemEle,
955
+ item: items[this.getIndexByItem(trgtItemEle)],
956
+ index: this.getIndexByItem(trgtItemEle),
957
+ content: trgtItemEle.querySelector('.' + CLS_CONTENT),
958
+ isExpanded: false };
959
+ let eff: string = animation.name;
960
+ this.trigger('expanding', eventArgs, (expandArgs: ExpandEventArgs) => {
961
+ if (!expandArgs.cancel) {
962
+ this.expandedItemsPop(trgtItemEle);
963
+ trgtItemEle.classList.add(CLS_EXPANDSTATE);
964
+ icon.classList.add(CLS_TOGANIMATE);
965
+ if ((animation.name === <Effect>'None')) {
966
+ this.collapseProgress('begin', icon, trgt, trgtItemEle, expandArgs);
967
+ this.collapseProgress('end', icon, trgt, trgtItemEle, expandArgs);
968
+ } else {
969
+ this.collapseAnimation(eff, trgt, trgtItemEle, icon, animation, expandArgs);
970
+ }
971
+ }
972
+ });
973
+ }
974
+ private collapseAnimation (ef: Str, trgt: HTEle, trgtItEl: HTEle, icn: HTEle, animate: AnimationModel, args: ExpandEventArgs ): void {
975
+ let height: number;
976
+ let trgtHeight: number;
977
+ let itemHeight: number;
978
+ let remain: number;
979
+ this.lastActiveItemId = trgtItEl.id;
980
+ if (ef === 'SlideUp') {
981
+ animate.begin = () => {
982
+ itemHeight = trgtItEl.offsetHeight;
983
+ trgtItEl.style.minHeight = itemHeight + 'px';
984
+ trgt.style.position = 'absolute';
985
+ height = trgtItEl.offsetHeight;
986
+ trgtHeight = trgt.offsetHeight;
987
+ trgt.style.maxHeight = trgtHeight + 'px';
988
+ this.collapseProgress('begin', icn, trgt, trgtItEl, args);
989
+ };
990
+ animate.progress = () => {
991
+ remain = ((height - (trgtHeight - trgt.offsetHeight)));
992
+ if (remain < itemHeight) {
993
+ trgtItEl.style.minHeight = remain + 'px'; }
994
+ };
995
+ animate.end = () => {
996
+ trgt.style.display = 'none';
997
+ this.collapseProgress('end', icn, trgt, trgtItEl, args);
998
+ trgtItEl.style.minHeight = '';
999
+ setStyle(trgt, { 'position': '', 'maxHeight': '', 'display': '' });
1000
+ };
1001
+ } else {
1002
+ animate.begin = () => {
1003
+ this.collapseProgress('begin', icn, trgt, trgtItEl, args); };
1004
+ animate.end = () => {
1005
+ this.collapseProgress('end', icn, trgt, trgtItEl, args); };
1006
+ }
1007
+ new Animation(animate).animate(trgt);
1008
+ }
1009
+ private collapseProgress(progress: string, icon: HTEle, trgt: HTEle, trgtItemEle: HTEle, eventArgs: ExpandEventArgs ): void {
1010
+ this.remove(icon , CLS_EXPANDICN);
1011
+ this.remove(trgtItemEle, CLS_SLCTED);
1012
+ if (progress === 'end') {
1013
+ this.add(trgt, CLS_CTNHIDE);
1014
+ icon.classList.remove(CLS_TOGANIMATE);
1015
+ this.remove(trgtItemEle, CLS_ACTIVE);
1016
+ trgt.setAttribute('aria-hidden', 'true');
1017
+ attributes (trgtItemEle, {'aria-expanded': 'false' });
1018
+ attributes (trgt.previousElementSibling, { 'aria-selected': 'false'});
1019
+ this.trigger('expanded' , eventArgs);
1020
+ }
1021
+ }
1022
+ /**
1023
+ * Returns the current module name.
1024
+ * @returns string
1025
+ * @private
1026
+ */
1027
+ protected getModuleName(): string {
1028
+ return 'accordion';
1029
+ }
1030
+ private itemAttribUpdate(): void {
1031
+ let items: Object[] = this.getItems();
1032
+ let itemEle: HTEle[] = this.getItemElements();
1033
+ let itemLen: number = items.length;
1034
+ itemEle.forEach((ele: HTEle): void => {
1035
+ select('.' + CLS_HEADER, ele).setAttribute('aria-level', '' + itemLen);
1036
+ });
1037
+ }
1038
+ private getItems(): Object[] {
1039
+ let items: AccordionItemModel[] | Object[];
1040
+ if (this.itemTemplate && this.headerTemplate) {
1041
+ items = this.dataSource;
1042
+ } else {
1043
+ items = this.items;
1044
+ }
1045
+ return items;
1046
+ }
1047
+ /**
1048
+ * Adds new item to the Accordion with the specified index of the Accordion.
1049
+ * @param {AccordionItemModel | Object} item - Item array that is to be added to the Accordion.
1050
+ * @param {number} index - Number value that determines where the item should be added.
1051
+ * By default, item is added at the last index if the index is not specified.
1052
+ * @returns void
1053
+ */
1054
+ public addItem (item: AccordionItemModel | Object, index?: number): void {
1055
+ let ele: HTEle = this.element;
1056
+ let itemEle: HTEle[] = this.getItemElements();
1057
+ let items: Object[] = this.getItems();
1058
+ if (isNOU(index)) {
1059
+ index = items.length; }
1060
+ if (ele.childElementCount >= index) {
1061
+ items.splice(index, 0, item);
1062
+ let innerItemEle: HTEle = this.renderInnerItem(item, index);
1063
+ if (ele.childElementCount === index) {
1064
+ ele.appendChild(innerItemEle);
1065
+ } else {
1066
+ ele.insertBefore(innerItemEle, itemEle[index]);
1067
+ }
1068
+ this.updateHeaderBlazorTemplate();
1069
+ EventHandler.add(innerItemEle.querySelector('.' + CLS_HEADER), 'focus', this.focusIn, this);
1070
+ EventHandler.add(innerItemEle.querySelector('.' + CLS_HEADER), 'blur', this.focusOut, this);
1071
+ this.itemAttribUpdate();
1072
+ }
1073
+ this.expandedItems = [];
1074
+ this.expandedItemRefresh(ele);
1075
+ if (item && (item as AccordionItemModel).expanded) {
1076
+ this.expandItem(true, index);
1077
+ }
1078
+ }
1079
+ private expandedItemRefresh(ele: HTEle): void {
1080
+ let itemEle: HTEle[] = this.getItemElements();
1081
+ [].slice.call(itemEle).forEach( (el: HTEle) => {
1082
+ if (el.classList.contains(CLS_SLCTED)) {
1083
+ this.expandedItemsPush(el);
1084
+ }
1085
+ });
1086
+ }
1087
+ /**
1088
+ * Dynamically removes item from Accordion.
1089
+ * @param {number} index - Number value that determines which item should be removed.
1090
+ * @returns void.
1091
+ */
1092
+ public removeItem(index: number): void {
1093
+ let itemEle: HTEle[] = this.getItemElements();
1094
+ let ele: HTEle = <HTEle>itemEle[index];
1095
+ let items: Object[] = this.getItems();
1096
+ if (isNOU(ele)) { return; }
1097
+ this.restoreContent(index);
1098
+ detach(ele);
1099
+ items.splice(index, 1);
1100
+ this.itemAttribUpdate();
1101
+ this.expandedItems = [];
1102
+ this.expandedItemRefresh(this.element);
1103
+ }
1104
+ /**
1105
+ * Sets focus to the specified index item header in Accordion.
1106
+ * @param {number} index - Number value that determines which item should be focused.
1107
+ * @returns void.
1108
+ */
1109
+ public select(index: number): void {
1110
+ let itemEle: HTEle[] = this.getItemElements();
1111
+ let ele: HTEle = <HTEle>itemEle[index];
1112
+ if (isNOU(ele) || isNOU(select('.' + CLS_HEADER, ele))) {
1113
+ return; }
1114
+ (<HTEle>ele.children[0]).focus();
1115
+ }
1116
+ /**
1117
+ * Shows or hides the specified item from Accordion.
1118
+ * @param {number} index - Number value that determines which item should be hidden/shown.
1119
+ * @param {Boolean} isHidden - Boolean value that determines the action either hide (true) or show (false). Default value is false.
1120
+ * If the `isHidden` value is false, the item is shown or else item it is hidden.
1121
+ * @returns void.
1122
+ */
1123
+ public hideItem(index: number, isHidden?: Boolean): void {
1124
+ let itemEle: HTEle[] = this.getItemElements();
1125
+ let ele: HTEle = <HTEle>itemEle[index];
1126
+ if (isNOU(ele)) {
1127
+ return; }
1128
+ if (isNOU(isHidden)) {
1129
+ isHidden = true; }
1130
+ isHidden ? this.add(ele, CLS_ITEMHIDE ) : this.remove(ele, CLS_ITEMHIDE );
1131
+ }
1132
+ /**
1133
+ * Enables/Disables the specified Accordion item.
1134
+ * @param {number} index - Number value that determines which item should be enabled/disabled.
1135
+ * @param {boolean} isEnable - Boolean value that determines the action as enable (true) or disable (false).
1136
+ * If the `isEnable` value is true, the item is enabled or else it is disabled.
1137
+ * @returns void.
1138
+ */
1139
+ public enableItem(index: number, isEnable: boolean): void {
1140
+ let itemEle: HTEle[] = this.getItemElements();
1141
+ let ele: HTEle = <HTEle>itemEle[index];
1142
+ if (isNOU(ele)) {
1143
+ return; }
1144
+ let eleHeader: HTEle = <HTEle>ele.firstElementChild;
1145
+ if (isEnable) {
1146
+ this.remove(ele, CLS_DISABLE );
1147
+ attributes(eleHeader, {'tabindex': '0', 'aria-disabled': 'false'});
1148
+ eleHeader.focus();
1149
+ } else {
1150
+ if (ele.classList.contains(CLS_ACTIVE)) {
1151
+ this.expandItem(false, index);
1152
+ this.eleMoveFocus('movedown', this.element, eleHeader); }
1153
+ this.add(ele, CLS_DISABLE );
1154
+ eleHeader.setAttribute('aria-disabled', 'true');
1155
+ eleHeader.removeAttribute('tabindex');
1156
+ }
1157
+ }
1158
+ /**
1159
+ * Expands/Collapses the specified Accordion item.
1160
+ * @param {boolean} isExpand - Boolean value that determines the action as expand or collapse.
1161
+ * @param {number} index - Number value that determines which item should be expanded/collapsed.`index` is optional parameter.
1162
+ * Without Specifying index, based on the `isExpand` value all Accordion item can be expanded or collapsed.
1163
+ * @returns void.
1164
+ */
1165
+ public expandItem(isExpand: boolean, index?: number): void {
1166
+ let root: HTEle = this.element;
1167
+ let itemEle: HTEle[] = this.getItemElements();
1168
+ if (isNOU(index)) {
1169
+ if (this.expandMode === 'Single' && isExpand) {
1170
+ let ele: HTEle = <HTEle>itemEle[itemEle.length - 1];
1171
+ this.itemExpand(isExpand, ele, this.getIndexByItem(ele));
1172
+ } else {
1173
+ let item: HTMLElement = <HTMLElement>select('#' + this.lastActiveItemId, this.element);
1174
+ [].slice.call(itemEle).forEach( (el: HTEle) => {
1175
+ this.itemExpand(isExpand, el, this.getIndexByItem(el));
1176
+ el.classList.remove(CLS_EXPANDSTATE);
1177
+ });
1178
+ let expandedItem: Element = select('.' + CLS_EXPANDSTATE, this.element);
1179
+ if (expandedItem) { expandedItem.classList.remove(CLS_EXPANDSTATE); }
1180
+ if (item) { item.classList.add(CLS_EXPANDSTATE); }
1181
+ }
1182
+ } else {
1183
+ let ele: HTEle = <HTEle>itemEle[index];
1184
+ if (isNOU(ele) || !ele.classList.contains(CLS_SLCT) || (ele.classList.contains(CLS_ACTIVE) && isExpand)) {
1185
+ return; } else {
1186
+ if (this.expandMode === 'Single') {
1187
+ this.expandItem(false); }
1188
+ this.itemExpand(isExpand, ele, index);
1189
+ }
1190
+ }
1191
+ }
1192
+ private itemExpand(isExpand: Boolean , ele: HTEle, index: number): void {
1193
+ let ctn: HTEle = <HTEle>ele.children[1];
1194
+ let items: Object[] = this.getItems();
1195
+ if (ele.classList.contains(CLS_DISABLE)) {
1196
+ return; }
1197
+ if (isNOU(ctn) && isExpand) {
1198
+ ctn = this.contentRendering(index);
1199
+ ele.appendChild(ctn);
1200
+ this.updateContentBlazorTemplate(items[index], index);
1201
+ this.ariaAttrUpdate(ele);
1202
+ } else if (isNOU(ctn)) {
1203
+ return;
1204
+ }
1205
+ isExpand ? this.expand(ctn) : this.collapse(ctn);
1206
+ }
1207
+ private destroyItems(): void {
1208
+ this.restoreContent(null);
1209
+ [].slice.call(this.element.querySelectorAll('.' + CLS_ITEM)).forEach ((el: HTEle) => {
1210
+ detach(el); });
1211
+ }
1212
+ private restoreContent(index: number): void {
1213
+ let ctnElePos: HTMLElement;
1214
+ if (isNOU(index)) { ctnElePos = this.element;
1215
+ } else {
1216
+ ctnElePos = <HTMLElement> this.element.querySelectorAll('.' + CLS_ITEM)[index];
1217
+ }
1218
+ this.templateEle.forEach((eleStr: Str): void => {
1219
+ if (!isNOU(ctnElePos.querySelector(eleStr))) {
1220
+ (<HTEle>document.body.appendChild(ctnElePos.querySelector(eleStr))).style.display = 'none'; }
1221
+ });
1222
+ }
1223
+ private updateItem(item: HTEle, index: number): void {
1224
+ if (!isNOU(item)) {
1225
+ let items: Object[] = this.getItems();
1226
+ let itemObj: Object = items[index];
1227
+ items.splice(index, 1);
1228
+ this.restoreContent(index);
1229
+ detach(item);
1230
+ this.addItem(itemObj, index);
1231
+ }
1232
+ }
1233
+ protected getPersistData(): string {
1234
+ let keyEntity: string[] = ['expandedItems'];
1235
+ return this.addOnPersist(keyEntity);
1236
+ }
1237
+ /**
1238
+ * Gets called when the model property changes.The data that describes the old and new values of the property that changed.
1239
+ * @param {AccordionModel} newProp
1240
+ * @param {AccordionModel} oldProp
1241
+ * @returns void
1242
+ * @private
1243
+ */
1244
+ public onPropertyChanged(newProp: AccordionModel, oldProp: AccordionModel): void {
1245
+ let acrdn: HTEle = this.element;
1246
+ let isRefresh: boolean = false;
1247
+ for (let prop of Object.keys(newProp)) {
1248
+ switch (prop) {
1249
+ case 'items':
1250
+ if (!(newProp.items instanceof Array && oldProp.items instanceof Array)) {
1251
+ let changedProp: Object[] = Object.keys(newProp.items);
1252
+ for (let j: number = 0; j < changedProp.length; j++) {
1253
+ let index: number = parseInt(Object.keys(newProp.items)[j], 10);
1254
+ let property: Str = Object.keys(newProp.items[index])[0];
1255
+ let item: HTEle = <HTEle> selectAll('.' + CLS_ITEM, this.element)[index];
1256
+ let oldVal: Str = Object(oldProp.items[index])[property];
1257
+ let newVal: Str = Object(newProp.items[index])[property];
1258
+ let temp: Str = property;
1259
+ if (temp === 'header' || temp === 'iconCss' || temp === 'expanded' || ((temp === 'content') && (oldVal === ''))) {
1260
+ this.updateItem(item, index);
1261
+ }
1262
+ if (property === 'cssClass' && !isNOU(item)) {
1263
+ item.classList.remove(oldVal);
1264
+ item.classList.add(newVal);
1265
+ }
1266
+ if (property === 'content' && !isNOU(item) && item.children.length === 2) {
1267
+ if (item.classList.contains(CLS_SLCTED)) { this.expandItem(false, index); }
1268
+ detach(item.querySelector('.' + CLS_CONTENT));
1269
+ }
1270
+ }
1271
+ } else {
1272
+ isRefresh = true;
1273
+ }
1274
+ break;
1275
+ case 'dataSource':
1276
+ isRefresh = true;
1277
+ break;
1278
+ case 'headerTemplate':
1279
+ this.initializeheaderTemplate();
1280
+ isRefresh = true;
1281
+ break;
1282
+ case 'itemTemplate':
1283
+ this.initializeItemTemplate();
1284
+ isRefresh = true;
1285
+ break;
1286
+ case 'enableRtl':
1287
+ newProp.enableRtl ? this.add(acrdn, CLS_RTL) : this.remove(acrdn, CLS_RTL);
1288
+ break;
1289
+ case 'height':
1290
+ setStyle(this.element, { 'height': formatUnit(newProp.height) });
1291
+ break;
1292
+ case 'width':
1293
+ setStyle(this.element, { 'width': formatUnit(newProp.width) });
1294
+ break;
1295
+ case 'expandMode':
1296
+ if (newProp.expandMode === 'Single') {
1297
+ this.element.setAttribute('aria-multiselectable', 'false');
1298
+ if (this.expandedItems.length > 1) {
1299
+ this.expandItem(false); }
1300
+ } else {
1301
+ this.element.setAttribute('aria-multiselectable', 'true');
1302
+ }
1303
+ break;
1304
+ }
1305
+ }
1306
+ if (isRefresh) {
1307
+ this.destroyItems();
1308
+ this.renderItems();
1309
+ this.initItemExpand();
1310
+ }
1311
+ }
1312
+ }