@componyx/ui 0.0.0-stage → 1.0.4

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 (169) hide show
  1. package/AppSkin/AppSkin.css +1268 -0
  2. package/AppSkin/AppSkin.js +2748 -0
  3. package/AppSkin/Themes/Default.css +241 -0
  4. package/Base/Base.js +3407 -0
  5. package/Base/ComponentIcons.css +66 -0
  6. package/Base/Font/ComponentIcons.woff +0 -0
  7. package/Base/Font/UI.woff +0 -0
  8. package/Base/Library.js +8432 -0
  9. package/Base/NavigationManager.js +462 -0
  10. package/Base/ResponsiveTemplates.js +371 -0
  11. package/Base/Sanitizer.js +288 -0
  12. package/Base/Themes/Default.css +255 -0
  13. package/Base/UI.css +618 -0
  14. package/Base/UIResourcePath.js +6 -0
  15. package/Bindary/Bindary.js +2011 -0
  16. package/Bindary/Modules/Connection.js +216 -0
  17. package/Bindary/Modules/Core.js +854 -0
  18. package/Bindary/Modules/DataUpdater.js +351 -0
  19. package/Bindary/Modules/ExpressionEngine.js +347 -0
  20. package/Bindary/Modules/ProxyManager.js +482 -0
  21. package/Bindary/Modules/Renderer.js +605 -0
  22. package/Bindary/Modules/Router.js +291 -0
  23. package/Bindary/Modules/Scroller.js +89 -0
  24. package/Bindary/Modules/Template.js +1273 -0
  25. package/BookmarkSpy/BookmarkSpy.js +430 -0
  26. package/Box/Box.css +36 -0
  27. package/Box/Box.js +1685 -0
  28. package/Button/Button.css +470 -0
  29. package/Button/Button.js +1398 -0
  30. package/Button/Themes/Default.css +200 -0
  31. package/Carousel/Carousel.css +273 -0
  32. package/Carousel/Carousel.js +607 -0
  33. package/ColorButton/ColorButton.css +39 -0
  34. package/ColorButton/ColorButton.js +336 -0
  35. package/ColorPicker/ColorPicker.css +359 -0
  36. package/ColorPicker/ColorPicker.js +972 -0
  37. package/ComboBox/ComboBox.css +357 -0
  38. package/ComboBox/ComboBox.js +2342 -0
  39. package/ComboBox/Themes/Default.css +23 -0
  40. package/DataPager/DataPager.css +72 -0
  41. package/DataPager/DataPager.js +674 -0
  42. package/DatePicker/DatePicker.css +227 -0
  43. package/DatePicker/DatePicker.js +1531 -0
  44. package/DatePicker/Themes/Default.css +26 -0
  45. package/Dialog/Dialog.css +106 -0
  46. package/Dialog/Dialog.js +572 -0
  47. package/Dialog/Themes/Default.css +10 -0
  48. package/Editor/Data/Emoji.json +8285 -0
  49. package/Editor/Data/Special.json +1042 -0
  50. package/Editor/Editor.css +1562 -0
  51. package/Editor/Editor.js +4058 -0
  52. package/Editor/Font/Editor.woff +0 -0
  53. package/Editor/Modules/ComponentFactory.js +565 -0
  54. package/Editor/Modules/ContentManager.js +748 -0
  55. package/Editor/Modules/DialogManager.js +1234 -0
  56. package/Editor/Modules/EventManager.js +458 -0
  57. package/Editor/Modules/Format.js +950 -0
  58. package/Editor/Modules/History.js +191 -0
  59. package/Editor/Modules/LayoutState.js +379 -0
  60. package/Editor/Modules/ListManager.js +296 -0
  61. package/Editor/Modules/MenuManager.js +388 -0
  62. package/Editor/Modules/NodeManager.js +681 -0
  63. package/Editor/Modules/ParagraphButtons.js +122 -0
  64. package/Editor/Modules/Resizer.js +176 -0
  65. package/Editor/Modules/SelectionRange.js +564 -0
  66. package/Editor/Modules/SourceViewBuilder.js +212 -0
  67. package/Editor/Modules/SymbolPicker.js +208 -0
  68. package/Editor/Modules/Table.js +2327 -0
  69. package/Editor/Modules/TableDialog.js +757 -0
  70. package/Editor/Modules/Toolbar.js +375 -0
  71. package/Editor/Modules/TooltipMenu.js +125 -0
  72. package/Editor/Modules/Utility.js +131 -0
  73. package/Editor/Themes/Default.css +204 -0
  74. package/FileUpload/FileUpload.css +156 -0
  75. package/FileUpload/FileUpload.js +898 -0
  76. package/FileUpload/Themes/Default.css +17 -0
  77. package/Form/Form.css +1934 -0
  78. package/Form/Form.js +4943 -0
  79. package/Form/Modules/ActionManager.js +368 -0
  80. package/Form/Modules/BuildPanelManager.js +319 -0
  81. package/Form/Modules/ComponentFactory.js +468 -0
  82. package/Form/Modules/ComponentPanel.js +265 -0
  83. package/Form/Modules/ConfigPanelManager.js +685 -0
  84. package/Form/Modules/DataBinder.js +602 -0
  85. package/Form/Modules/DataObserver.js +717 -0
  86. package/Form/Modules/Draggable.js +756 -0
  87. package/Form/Modules/OptionsPanel.js +342 -0
  88. package/Form/Modules/Renderer.js +1889 -0
  89. package/Form/Modules/RuleEngine.js +585 -0
  90. package/Form/Modules/RulesPanel.js +1158 -0
  91. package/Form/Modules/Types.js +1709 -0
  92. package/Form/Modules/ValidationManager.js +194 -0
  93. package/Form/Themes/Default.css +216 -0
  94. package/FormField/FormField.css +468 -0
  95. package/FormField/FormField.js +576 -0
  96. package/FormField/Themes/Default.css +99 -0
  97. package/Grid/Grid.css +544 -0
  98. package/Grid/Grid.js +3761 -0
  99. package/Grid/Themes/Default.css +43 -0
  100. package/LICENSE +126 -0
  101. package/MaskedTextBox/MaskedTextBox.css +28 -0
  102. package/MaskedTextBox/MaskedTextBox.js +642 -0
  103. package/MaskedTextBox/Themes/Default.css +6 -0
  104. package/Menu/Menu.css +328 -0
  105. package/Menu/Menu.js +2386 -0
  106. package/Menu/Themes/Default.css +24 -0
  107. package/NumericBox/NumericBox.css +120 -0
  108. package/NumericBox/NumericBox.js +984 -0
  109. package/PanelBar/PanelBar.css +123 -0
  110. package/PanelBar/PanelBar.js +505 -0
  111. package/PanelBar/Themes/Default.css +51 -0
  112. package/PieChart/PieChart.css +95 -0
  113. package/PieChart/PieChart.js +820 -0
  114. package/PieChart/Themes/Default.css +9 -0
  115. package/README.md +178 -3
  116. package/Slider/Slider.css +348 -0
  117. package/Slider/Slider.js +1306 -0
  118. package/Slider/Themes/Default.css +44 -0
  119. package/TabStrip/TabStrip.css +52 -0
  120. package/TabStrip/TabStrip.js +362 -0
  121. package/TabStrip/Themes/Default.css +35 -0
  122. package/TimePicker/Themes/Default.css +30 -0
  123. package/TimePicker/TimePicker.css +253 -0
  124. package/TimePicker/TimePicker.js +1485 -0
  125. package/TooltipManager/Themes/Default.css +21 -0
  126. package/TooltipManager/TooltipManager.css +227 -0
  127. package/TooltipManager/TooltipManager.js +791 -0
  128. package/Validator/Validator.css +54 -0
  129. package/Validator/Validator.js +2508 -0
  130. package/componyx.html-data.json +619 -0
  131. package/index.js +27 -0
  132. package/package.json +43 -4
  133. package/types/AppSkin.d.ts +842 -0
  134. package/types/Base.d.ts +1034 -0
  135. package/types/Bindary.d.ts +1196 -0
  136. package/types/BookmarkSpy.d.ts +112 -0
  137. package/types/Box.d.ts +374 -0
  138. package/types/Button.d.ts +455 -0
  139. package/types/Carousel.d.ts +136 -0
  140. package/types/ColorButton.d.ts +120 -0
  141. package/types/ColorPicker.d.ts +225 -0
  142. package/types/ComboBox.d.ts +507 -0
  143. package/types/DataPager.d.ts +152 -0
  144. package/types/DatePicker.d.ts +354 -0
  145. package/types/Dialog.d.ts +160 -0
  146. package/types/Editor.d.ts +1289 -0
  147. package/types/FileUpload.d.ts +206 -0
  148. package/types/Form.d.ts +3078 -0
  149. package/types/FormField.d.ts +204 -0
  150. package/types/Grid.d.ts +911 -0
  151. package/types/Library.d.ts +1899 -0
  152. package/types/MaskedTextBox.d.ts +91 -0
  153. package/types/Menu.d.ts +577 -0
  154. package/types/NumericBox.d.ts +310 -0
  155. package/types/PanelBar.d.ts +223 -0
  156. package/types/PieChart.d.ts +224 -0
  157. package/types/ResponsiveTemplates.d.ts +108 -0
  158. package/types/Slider.d.ts +227 -0
  159. package/types/TabStrip.d.ts +185 -0
  160. package/types/TimePicker.d.ts +265 -0
  161. package/types/TooltipManager.d.ts +178 -0
  162. package/types/UI.d.ts +29 -0
  163. package/types/Validator.d.ts +653 -0
  164. package/types/index.d.ts +59 -0
  165. package/ui.css +11783 -0
  166. package/ui.js +79477 -0
  167. package/ui.min.css +138 -0
  168. package/ui.min.js +264 -0
  169. package/ui.min.js.map +1 -0
package/Box/Box.js ADDED
@@ -0,0 +1,1685 @@
1
+ /*! Componyx.UI | (c) E.H. Daanen / Componyx | BUSL-1.1 | componyx.com/license */
2
+ import '../Base/Base.js';
3
+ import '../Base/Library.js';
4
+
5
+ (function (window)
6
+ {
7
+ /**
8
+ * Box class.
9
+ * @class
10
+ * @memberof componyx.UI
11
+ * @augments componyx.UI.base.Component
12
+ * @mixes componyx.UI.base.methods
13
+ * @param {String} id The id of the component.
14
+ * @param {Object|HTMLElement} properties The properties used to initialize the component or the container element.
15
+ * @property {componyx.UI.base.AjaxMethod} ajax.load - AJAX method used to load box content data on demand.
16
+ * @returns {Object} An instance of the component.
17
+ */
18
+ componyx.UI.Box = function Box(id, properties)
19
+ {
20
+ var _instance = this,
21
+ _contentElement,
22
+ _draggable,
23
+ _focusable = [],
24
+ _timerId = null,
25
+ _showTimerId, _hideTimerId,
26
+ _styleCache = {},
27
+ _animation = null,
28
+ _invertedX = false,
29
+ _invertedY = false,
30
+ _resizedX = false,
31
+ _resizedY = false,
32
+ _resizeObserver = null,
33
+ _invertMarginX = 0,
34
+ _invertMarginY = 0,
35
+ _rendered = false,
36
+ _allowHide = true,
37
+ _expander = null, _modal,
38
+ _pointerCoordinates,
39
+ _modalStyle = 'position:fixed; left:0px; top:0px; width:100%; height:100%;';
40
+ $base.static.ThemeOption;
41
+ var _autoPositionOption = componyx.UI.Box.AutoPositionOption,
42
+ _expandDirectionOption = componyx.UI.Box.ExpandDirectionOption,
43
+ _alignXOption = componyx.UI.Box.AlignXOption,
44
+ _alignYOption = componyx.UI.Box.AlignYOption,
45
+ _animationTypeOption = componyx.UI.Box.AnimationTypeOption,
46
+ _classOption =
47
+ {
48
+ CONTENT: 'content',
49
+ MODAL: 'modal',
50
+ EXPANDED: 'expanded',
51
+ HORIZONTALINVERTED: 'inverted',
52
+ VERTICALINVERTED: 'inverted',
53
+ SHOW: 'show',
54
+ SHOWANIMATION: 'show-animation',
55
+ HIDEANIMATION: 'hide-animation'
56
+ };
57
+
58
+ // define public properties
59
+ /**
60
+ * Gets or sets the css class of the box content.
61
+ * @type {String}
62
+ */
63
+ this.cssClassContent = '';
64
+
65
+ /**
66
+ * Gets or sets the css class of the box modal overlay.
67
+ * @type {String}
68
+ */
69
+ this.cssClassModal = '';
70
+
71
+ /**
72
+ * Gets or sets the css class of the box when AutoInvertFit is true and the box is inverted horizontally.
73
+ * @type {String}
74
+ */
75
+ this.cssClassHorizontalInverted = '';
76
+
77
+ /**
78
+ * Gets or sets the css class of the box when AutoInvertFit is true and the box is inverted vertically.
79
+ * @type {String}
80
+ */
81
+ this.cssClassVerticalInverted = '';
82
+
83
+ /**
84
+ * Gets or sets the top position of the box. Overwrites the property if already defined through Style.
85
+ * @type {String}
86
+ */
87
+ this.top = '';
88
+
89
+ /**
90
+ * Gets or sets the right position of the box. Overwrites the property if already defined through Style.
91
+ * @type {String}
92
+ */
93
+ this.right = '';
94
+
95
+ /**
96
+ * Gets or sets the bottom position of the box. Overwrites the property if already defined through Style.
97
+ * @type {String}
98
+ */
99
+ this.bottom = '';
100
+
101
+ /**
102
+ * Gets or sets the left position of the box. Overwrites the property if already defined through Style.
103
+ * @type {String}
104
+ */
105
+ this.left = '';
106
+
107
+ /**
108
+ * Gets or sets the width of the box. Overwrites the property if already defined through Style.
109
+ * @type {String}
110
+ */
111
+ this.width = '';
112
+
113
+ /**
114
+ * Gets or sets the height of the box. Overwrites the property if already defined through Style.
115
+ * @type {String}
116
+ */
117
+ this.height = '';
118
+
119
+ /**
120
+ * Gets or sets a value indicating if the box element must stretch to the size of the expander element. The content width has priority over the expander width when stretchToContent is enabled and the content exceeds the expander width.
121
+ * @type {Boolean}
122
+ */
123
+ this.stretchToExpander = false;
124
+
125
+ /**
126
+ * Gets or sets a value indicating if the box element must stretch to the size of the content element. This setting is useful when the box is positioned absolute/fixed and the content element is a flex-box (display:flex).
127
+ * @type {Boolean}
128
+ */
129
+ this.stretchToContent = false;
130
+
131
+ /**
132
+ * Gets or sets a value indicating whether the box should handle focus events for focusable child elements. Only applies when modal is false.
133
+ * @type {Boolean}
134
+ */
135
+ this.handleFocus = false;
136
+
137
+ /**
138
+ * Gets or sets a value indicating whether the first element of the focusable list should get focus when the box is shown.
139
+ * @type {Boolean}
140
+ */
141
+ this.autoFocus = true;
142
+
143
+ /**
144
+ * Gets or sets a value indicating whether the focusable list is ordered by tabindex (requires all elements to have a tabindex set).
145
+ * @type {Boolean}
146
+ */
147
+ this.tabIndexFocus = false;
148
+
149
+ /**
150
+ * Gets or sets the auto position of the box.
151
+ * @type {componyx.UI.Box.AutoPositionOption}
152
+ */
153
+ this.autoPosition = _autoPositionOption.NONE;
154
+
155
+ /**
156
+ * Gets or sets a value indicating whether the box should try to fit when the window is too small.
157
+ * @type {Boolean}
158
+ */
159
+ this.autoFit = true;
160
+
161
+ /**
162
+ * Gets or sets a value indicating whether the box should try to fit inverted when the window is too small.
163
+ * @type {Boolean}
164
+ */
165
+ this.autoInvertFit = false;
166
+
167
+ /**
168
+ * Gets or sets a value indicating whether the box should be resized when the window is too small.
169
+ * @type {Boolean}
170
+ */
171
+ this.autoResizeFit = false;
172
+
173
+ /**
174
+ * Gets or sets a value indicating whether the animation direction should be auto inverted when the box is inverted.
175
+ * @type {Boolean}
176
+ */
177
+ this.autoInvertAnimation = true;
178
+
179
+ /**
180
+ * Gets or sets a value indicating whether the box is either resized to the window width or available (inverted) space when auto resized.
181
+ * @type {Boolean}
182
+ */
183
+ this.resizeToMaxWidth = true;
184
+
185
+ /**
186
+ * Gets or sets a value indicating whether the box is either resized to the window height or available (inverted) space when auto resized.
187
+ * @type {Boolean}
188
+ */
189
+ this.resizeToMaxHeight = true;
190
+
191
+ /**
192
+ * Gets or sets a value indicating whether the box is displayed as modal popup.
193
+ * @type {Boolean}
194
+ */
195
+ this.modal = false;
196
+
197
+ /**
198
+ * Gets or sets a value indicating whether the box is draggable.
199
+ * @type {Boolean}
200
+ */
201
+ this.draggable = false;
202
+
203
+ /**
204
+ * Gets or sets a value indicating whether the box is hidden when the user clicks outside the box.
205
+ * @type {Boolean}
206
+ */
207
+ this.hideOnOutsideClick = false;
208
+
209
+ /**
210
+ * Gets or sets a value indicating whether the box position tracks the pointer when AutoPosition is set to Pointer.
211
+ * @type {Boolean}
212
+ */
213
+ this.trackPointer = false;
214
+
215
+ /**
216
+ * Gets or sets a value indicating whether the box's horizontal position is aligned to the left, center or right of the expander element or pointer.
217
+ * @type {componyx.UI.Box.AlignXOption|null}
218
+ */
219
+ this.alignX = null;
220
+
221
+ /**
222
+ * Gets or sets a value indicating whether the box's vertical position is aligned to the top, center or bottom of the expander element or pointer.
223
+ * @type {componyx.UI.Box.AlignYOption|null}
224
+ */
225
+ this.alignY = null;
226
+
227
+ /**
228
+ * Gets the tag name of the content element.
229
+ * @type {String}
230
+ */
231
+ this.contentTag = 'div';
232
+
233
+ /**
234
+ * Gets or sets the expand direction.
235
+ * @type {componyx.UI.Box.ExpandDirectionOption}
236
+ */
237
+ this.expandDirection = _expandDirectionOption.RIGHT;
238
+
239
+ /**
240
+ * Gets or sets the expander element or element-id.
241
+ * @type {HTMLElement|String|null}
242
+ */
243
+ this.expander = null;
244
+
245
+ /**
246
+ * Gets or sets the submitter element or element-id on which to fire a click event when the enter-key is pressed within a field inside the box element.
247
+ * @type {HTMLElement|String|null}
248
+ */
249
+ this.enterKeySubmitter = null;
250
+
251
+ /**
252
+ * Gets the element which contains the box content.
253
+ * @type {HTMLElement}
254
+ */
255
+ Object.defineProperty(this, 'contentElement',
256
+ {
257
+ get: function () { return _contentElement; }
258
+ });
259
+
260
+
261
+ /**
262
+ * Box animation.
263
+ * @type animation
264
+ * @property {componyx.UI.Box.AnimationTypeOption} showType - Gets or sets the animation type used when showing the box.
265
+ * @property {String} showClass - Gets or sets the CSS class applied when showing the box.
266
+ * @property {String} showDirection - Gets or sets the animation direction (down, right, up, left) used when showing the box.
267
+ * @property {Boolean} showFade - Gets or sets a value indicating if fading is used when showing the box.
268
+ * @property {componyx.UI.Box.AnimationTypeOption} hideType - Gets or sets the animation type used when hiding the box.
269
+ * @property {String} hideClass - Gets or sets the CSS class applied when hiding the box.
270
+ * @property {String} hideDirection - Gets or sets the animation direction (top, right, bottom, left) used when hiding the box.
271
+ * @property {Boolean} hideFade - Gets or sets a value indicating if fading is used when hiding the box.
272
+ */
273
+ this.animation =
274
+ {
275
+ showType: null,
276
+ showClass: null,
277
+ showDirection: null,
278
+ showFade: null,
279
+ hideType: null,
280
+ hideClass: null,
281
+ hideDirection: null,
282
+ hideFade: null
283
+ };
284
+
285
+ /**
286
+ * @type {componyx.library.DraggableSettings}
287
+ * @see {@link componyx.library.DraggableSettings}
288
+ */
289
+ this.dragSettings = {};
290
+
291
+ /**
292
+ * @class
293
+ * @augments componyx.UI.base.Events
294
+ * @memberof componyx.UI.Box
295
+ * @property {componyx.UI.base.Event} onPrePosition - Event which fires before the box is positioned.
296
+ * @property {componyx.UI.base.Event} onPostPosition - Event which fires after the box is positioned.
297
+ * @property {componyx.UI.base.Event} onAutoFit - Event which fires when the window is too small and the box performs an auto fit. @see {@link componyx.UI.Box.AutoFitEventArgs}
298
+ * @property {componyx.UI.base.Event} onShowComplete - Event which fires when the show animation has completed, or immediately if animation type is 'none'.
299
+ * @property {componyx.UI.base.Event} onHideComplete - Event which fires when the hide animation has completed, or immediately if animation type is 'none'.
300
+ * @property {componyx.UI.base.Event} onHide - Event which fires when the box is hidden (overrides the base event arguments). Set cancel to true to keep the box visible. @see {@link componyx.UI.Box.HideEventArgs}
301
+ * @see {@link componyx.UI.base.Events}
302
+ */
303
+ function BoxEvents(events)
304
+ {
305
+ Object.assign(this, events);
306
+ this.onPrePosition = $base.static.createEvent('onPrePosition');
307
+ this.onPostPosition = $base.static.createEvent('onPostPosition');
308
+ this.onAutoFit = $base.static.createEvent('onAutoFit');
309
+ this.onShowComplete = $base.static.createEvent('onShowComplete');
310
+ this.onHideComplete = $base.static.createEvent('onHideComplete');
311
+ }
312
+ /**
313
+ * Box events
314
+ * @type {componyx.UI.Box.BoxEvents}
315
+ */
316
+ this.events = new BoxEvents(this.events);
317
+
318
+ /**
319
+ * Box hide event arguments.
320
+ * @typedef {Object} HideEventArgs
321
+ * @memberof componyx.UI.Box
322
+ * @property {Event} event - The original event object.
323
+ * @property {Boolean} cancel - Set to true to cancel hiding the box.
324
+ */
325
+
326
+ /**
327
+ * Box auto fit event arguments.
328
+ * @typedef {Object} AutoFitEventArgs
329
+ * @memberof componyx.UI.Box
330
+ * @property {Boolean} fitX - A value indicating if the box was fitted horizontally.
331
+ * @property {Boolean} fitY - A value indicating if the box was fitted vertically.
332
+ * @property {Boolean} invertedX - A value indicating if the box position was inverted horizontally.
333
+ * @property {Boolean} invertedY - A value indicating if the box position was inverted vertically.
334
+ * @property {Boolean} resizedX - A value indicating if the box was resized horizontally.
335
+ * @property {Boolean} resizedY - A value indicating if the box was resized vertically.
336
+ */
337
+
338
+ // inherit base instance members
339
+ $base.Component.apply(this, [id, properties]);
340
+
341
+ /**
342
+ * Adds the content template.
343
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The content template.
344
+ */
345
+ this.setContentTemplate = function (content)
346
+ {
347
+ _instance.addTemplate('Content', content, false);
348
+ };
349
+
350
+ /**
351
+ * Updates the box view to stretch and position with the updated content.
352
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} [content] A new content template.
353
+ * @param {Boolean} [show=true] A value indicating if the box should be displayed when hidden.
354
+ */
355
+ this.update = function (content, show)
356
+ {
357
+ stopAnimation();
358
+
359
+ if (content)
360
+ {
361
+ _instance.addTemplate('Content', content, false);
362
+ _instance.applyTemplate(_instance.contentElement, 'Content');
363
+ }
364
+
365
+ if (_instance.modal || _instance.handleFocus)
366
+ createFocusableList();
367
+
368
+ if (_instance.autoPosition == _autoPositionOption.EXPAND)
369
+ getExpander();
370
+
371
+ if (_instance.showing || !show)
372
+ {
373
+ if (_instance.showing && _instance.autoPosition == _autoPositionOption.EXPAND && _instance.expander != _expander)
374
+ {
375
+ setExpanded(_expander, true);
376
+ setExpanded(_instance.expander);
377
+ _expander = _instance.expander;
378
+ }
379
+
380
+ activate();
381
+ }
382
+ else
383
+ this.show();
384
+ };
385
+
386
+ /**
387
+ * Stops the animation.
388
+ */
389
+ this.stopAnimation = function ()
390
+ {
391
+ stopAnimation();
392
+ };
393
+
394
+ /**
395
+ * Shows or hides the component.
396
+ */
397
+ this.toggle = function ()
398
+ {
399
+ checkExpander();
400
+ $base.methods.toggle.call(_instance);
401
+ };
402
+
403
+ /**
404
+ * Shows the component.
405
+ * @param {boolean} [instant] A value indicating if the box should be shown instantly without animation.
406
+ * @param {{clientX: number, clientY: number}} [pointerCoordinates] Optional pointer coordinates for POINTER auto-positioning. Pass these when the show is deferred (e.g. via setTimeout), as the original pointer event may no longer be available by then.
407
+ */
408
+ this.show = function (instant, pointerCoordinates)
409
+ {
410
+ show(instant, pointerCoordinates);
411
+ };
412
+
413
+ /**
414
+ * Hides the component.
415
+ * @param {Boolean} [instant] A value indicating if the box should be hidden instantly without animation.
416
+ */
417
+ this.hide = function (instant)
418
+ {
419
+ hide(instant);
420
+ };
421
+
422
+ /**
423
+ * Renders the component.
424
+ */
425
+ this.render = function ()
426
+ {
427
+ if (_instance.renderState != $base.static.RenderState.RENDERING)
428
+ {
429
+ // call base render and return
430
+ $base.methods.render.call(_instance, preRender, 'box', false);
431
+ return;
432
+ }
433
+
434
+ // render logic after loading resources
435
+ if (_instance.ajax.load && _instance.ajax.load.isDefined())
436
+ load();
437
+ else
438
+ draw();
439
+ };
440
+
441
+ /**
442
+ * Destroys the component.
443
+ * @see {@link componyx.UI.base.methods#destroy}
444
+ */
445
+ this.destroy = function (...args)
446
+ {
447
+ stopAnimation();
448
+ dispose();
449
+ $base.methods.destroy.call(this, ...args);
450
+ };
451
+
452
+ function show(instant, pointerCoordinates)
453
+ {
454
+ var a = _instance.animation; _instance.element;
455
+ var type = (a.showType != null) ? a.showType : _animationTypeOption.SLIDE;
456
+
457
+ checkExpander();
458
+
459
+ if (_instance.showing && _rendered)
460
+ {
461
+ _allowHide = true;
462
+ clearTimers();
463
+
464
+ if (instant)
465
+ stopAnimation();
466
+
467
+ return;
468
+ }
469
+
470
+ _rendered = true;
471
+ _allowHide = false;
472
+ _expander = _instance.expander;
473
+
474
+ if (_instance.renderState != $base.static.RenderState.RENDERED)
475
+ {
476
+ _rendered = false;
477
+
478
+ if (_instance.renderState == $base.static.RenderState.NONE)
479
+ $base.methods.show.call(_instance);
480
+
481
+ return;
482
+ }
483
+
484
+ clearTimers();
485
+ stopAnimation();
486
+ addDirectionClass();
487
+ removeOutsideClickHandler();
488
+
489
+ if (_instance.autoPosition == _autoPositionOption.POINTER)
490
+ {
491
+ _pointerCoordinates = pointerCoordinates ?? { clientX: ($lib.event) ? $lib.clientX($lib.event) : 0, clientY: ($lib.event) ? $lib.clientY($lib.event) : 0 };
492
+ }
493
+
494
+ if (instant || !type)
495
+ execShow(instant);
496
+ else if (!_showTimerId)
497
+ _showTimerId = setTimeout(execShow.bind(_instance, instant), 0); // animate when device is ready
498
+ }
499
+
500
+ function execShow(instant)
501
+ {
502
+ var a = _instance.animation, el = _instance.element,
503
+ type = (a.showType != null) ? a.showType : _animationTypeOption.SLIDE,
504
+ direction = getShowDirection(),
505
+ fade = (a.showFade != null) ? a.showFade : false;
506
+
507
+ $base.methods.show.call(_instance);
508
+ el.style.display = '';
509
+ activate();
510
+ setExpanded(_instance.expander);
511
+ bindOutsideClickHandler();
512
+
513
+ _instance.showing = true;
514
+
515
+ if (_instance.trackPointer)
516
+ {
517
+ $lib.on(document, 'pointermove', trackPointer, null, _instance);
518
+ $lib.on(document, 'pointerup', stopPointerTracking, _instance.hideOnOutsideClick);
519
+ }
520
+
521
+ _modal.style.display = 'none';
522
+
523
+ if (_instance.autoInvertAnimation && _invertedX)
524
+ direction = (direction.indexOf('right') > -1) ? direction.replace('right', 'left') : direction.replace('left', 'right');
525
+
526
+ if (_instance.autoInvertAnimation && _invertedY)
527
+ direction = (direction.indexOf('down') > -1) ? direction.replace('down', 'up') : direction.replace('up', 'down');
528
+
529
+ if (!instant && type > 0)
530
+ {
531
+ if (type == _animationTypeOption.SLIDE)
532
+ _animation = $lib.slide(el, false, 'slide', direction, fade, showComplete);
533
+ else if (type == _animationTypeOption.REVEAL)
534
+ _animation = $lib.slide(el, false, 'reveal', direction, fade, showComplete);
535
+ else if (type == _animationTypeOption.CSS)
536
+ {
537
+ _animation = $lib.cssAnimation(el, a.showClass || _classOption.SHOWANIMATION, [], { onComplete: showComplete });
538
+ }
539
+ else
540
+ showComplete();
541
+ }
542
+ else
543
+ showComplete();
544
+
545
+ _allowHide = true;
546
+ }
547
+
548
+ function hide(instant)
549
+ {
550
+ if (!_instance.showing)
551
+ {
552
+ clearTimers();
553
+
554
+ if (instant)
555
+ stopAnimation();
556
+
557
+ return;
558
+ }
559
+
560
+ if (_instance.renderState != $base.static.RenderState.RENDERED)
561
+ return;
562
+
563
+ var a = _instance.animation,
564
+ type = (a.hideType != null) ? a.hideType : _animationTypeOption.SLIDE;
565
+
566
+ clearTimers();
567
+ stopAnimation();
568
+ _allowHide = false;
569
+
570
+ if (instant || !type) // synchronous
571
+ execHide(instant);
572
+ else if (!_hideTimerId)
573
+ _hideTimerId = setTimeout(execHide.bind(_instance, instant), 0); // animate when device is ready
574
+ }
575
+
576
+ function execHide(instant)
577
+ {
578
+ var a = _instance.animation, el = _instance.element,
579
+ type = (a.hideType != null) ? a.hideType : _animationTypeOption.SLIDE,
580
+ direction = getHideDirection(),
581
+ fade = (a.hideFade != null) ? a.hideFade : false,
582
+ args = { event: $lib.event, cancel: false };
583
+
584
+ _instance.showing = false;
585
+ _instance.events.onHide.fire(_instance, args);
586
+
587
+ if (args.cancel)
588
+ {
589
+ _instance.showing = _allowHide = true;
590
+ return;
591
+ }
592
+
593
+ removeOutsideClickHandler();
594
+ stopPointerTracking();
595
+ el.style.display = '';
596
+ _modal.style.display = 'none';
597
+
598
+ if (!instant && type > 0)
599
+ {
600
+ if (_instance.autoInvertAnimation && _invertedX)
601
+ direction = (direction.indexOf('right') > -1) ? direction.replace('right', 'left') : direction.replace('left', 'right');
602
+
603
+ if (_instance.autoInvertAnimation && _invertedY)
604
+ direction = (direction.indexOf('down') > -1) ? direction.replace('down', 'up') : direction.replace('up', 'down');
605
+
606
+ if (type == _animationTypeOption.SLIDE)
607
+ _animation = $lib.slide(el, true, 'slide', direction, fade, hideComplete);
608
+ else if (type == _animationTypeOption.REVEAL)
609
+ _animation = $lib.slide(el, true, 'reveal', direction, fade, hideComplete);
610
+ else if (type == _animationTypeOption.CSS)
611
+ {
612
+ _animation = $lib.cssAnimation(el, a.hideClass || _classOption.HIDEANIMATION, [], { onComplete: hideComplete });
613
+ }
614
+ else
615
+ hideComplete();
616
+ }
617
+ else
618
+ hideComplete();
619
+
620
+ _allowHide = true;
621
+ }
622
+
623
+ function showComplete()
624
+ {
625
+ if (arguments[0] && arguments[0] instanceof Event && arguments[0].target !== _instance.element)
626
+ return;
627
+
628
+ var el = _instance.element;
629
+
630
+ _showTimerId = null;
631
+
632
+ $lib.addClass(el, _classOption.SHOW);
633
+ el.style.display = '';
634
+
635
+ if (_instance.modal)
636
+ _modal.style.display = '';
637
+
638
+ if (_instance.modal || _instance.handleFocus)
639
+ {
640
+ createFocusableList();
641
+ blurAll();
642
+ $lib.on(el, 'keydown', setFocus);
643
+
644
+ if (_instance.autoFocus && _focusable.length > 0)
645
+ setTimeout(function () { setFocus(); }, 1);
646
+ }
647
+
648
+ if (_animation)
649
+ {
650
+ _animation = null;
651
+ position();
652
+ }
653
+
654
+ _instance.events.onShowComplete.fire(_instance);
655
+ }
656
+
657
+ function hideComplete()
658
+ {
659
+ if (arguments[0] && arguments[0] instanceof Event && arguments[0].target !== _instance.element)
660
+ return;
661
+
662
+ var el = _instance.element;
663
+
664
+ _hideTimerId = null;
665
+
666
+ if (_instance.modal || _instance.handleFocus)
667
+ $lib.off(el, 'keydown', setFocus);
668
+
669
+ $lib.removeClass(el, _classOption.SHOW);
670
+ setExpanded(_instance.expander, true);
671
+ _instance.showing = false;
672
+ _animation = null;
673
+ _pointerCoordinates = null;
674
+ $base.methods.hide.call(_instance, false);
675
+ _instance.events.onHideComplete.fire(_instance);
676
+ }
677
+
678
+ function clearTimers()
679
+ {
680
+ clearTimeout(_showTimerId);
681
+ clearTimeout(_hideTimerId);
682
+ _showTimerId = _hideTimerId = null;
683
+ }
684
+
685
+ function trackPointer(e)
686
+ {
687
+ const pointerType = e.pointerType;
688
+
689
+ if (pointerType === "mouse" || pointerType === "pen")
690
+ {
691
+ position();
692
+ }
693
+ }
694
+
695
+ function stopPointerTracking(hide)
696
+ {
697
+ $lib.off(document, 'pointermove', trackPointer);
698
+ $lib.off(document, 'pointerup', stopPointerTracking);
699
+
700
+ if (hide)
701
+ {
702
+ _allowHide = true;
703
+ checkHide();
704
+ }
705
+ }
706
+
707
+ function checkExpander()
708
+ {
709
+ getExpander();
710
+
711
+ if (_instance.expander != _expander && _instance.autoPosition == _autoPositionOption.EXPAND)
712
+ {
713
+ _instance.hide(true); // instant hide when previous expander element is different
714
+ setExpanded(_expander, true);
715
+ }
716
+ }
717
+
718
+ function getExpander()
719
+ {
720
+ if (!$lib.isEmpty(_instance.expander) && (typeof _instance.expander === 'string') && $lib('#' + _instance.expander))
721
+ _instance.expander = $lib('#' + _instance.expander);
722
+ }
723
+
724
+ function addDirectionClass()
725
+ {
726
+ var direction = _instance.animation.showDirection || 'right',
727
+ vertical = (_instance.expandDirection == _expandDirectionOption.DOWN || _instance.expandDirection == _expandDirectionOption.UP);
728
+
729
+ clearDirectionClasses();
730
+
731
+ if (_instance.expandDirection != null)
732
+ $lib.addClass(_instance.element, _expandDirectionOption.getName(_instance.expandDirection));
733
+ else
734
+ $lib.addClass(_instance.element, direction);
735
+
736
+ if (vertical && _instance.alignX > 0)
737
+ $lib.addClass(_instance.element, $lib.format('align-{0}', _alignXOption.getName(_instance.alignX)));
738
+ else if (!vertical && _instance.alignY > 0)
739
+ $lib.addClass(_instance.element, $lib.format('align-{0}', _alignYOption.getName(_instance.alignY)));
740
+ }
741
+
742
+ function clearDirectionClasses()
743
+ {
744
+ $lib.removeClass(_instance.element, 'down right up left align-left align-center align-right align-top align-bottom');
745
+ }
746
+
747
+ function setExpanded(expander, remove)
748
+ {
749
+ if ($lib.isEmpty(expander) || _instance.autoPosition != _autoPositionOption.EXPAND)
750
+ return;
751
+
752
+ if (remove)
753
+ $lib.removeClass(expander, _classOption.EXPANDED);
754
+ else
755
+ $lib.addClass(expander, _classOption.EXPANDED);
756
+ }
757
+
758
+ function checkHide()
759
+ {
760
+ if (_allowHide)
761
+ _instance.hide();
762
+
763
+ _allowHide = true;
764
+ }
765
+
766
+ function blurAll()
767
+ {
768
+ $lib(function (el)
769
+ {
770
+ if (el.blur)
771
+ el.blur();
772
+
773
+ }, document.body);
774
+ }
775
+
776
+ function createFocusableList()
777
+ {
778
+ _focusable = [];
779
+
780
+ $lib(function (el)
781
+ {
782
+ if ($lib.focusable(el))
783
+ _focusable.push(el);
784
+
785
+ }, _instance.element);
786
+
787
+ if (_instance.tabIndexFocus)
788
+ {
789
+ _focusable = _focusable.sort(function (a, b)
790
+ {
791
+ return (a.tabIndex - b.tabIndex);
792
+ });
793
+ }
794
+ }
795
+
796
+ function setFocus(e)
797
+ {
798
+ let keyCode = (e) ? e.key : null,
799
+ shift = (e) ? e.shiftKey : false,
800
+ startIndex, element, index, focusable,
801
+ doc = _instance.element.ownerDocument || document;
802
+
803
+ if (!_focusable.length)
804
+ return;
805
+
806
+ if (!e || keyCode == 'Tab')
807
+ {
808
+ if (e)
809
+ {
810
+ element = $lib.eventSource(e);
811
+ startIndex = index = $lib.indexOf(_focusable, element);
812
+
813
+ if (index == -1)
814
+ return;
815
+
816
+ if (index == _focusable.length - 1)
817
+ index = (shift) ? index - 1 : 0;
818
+ else if (shift)
819
+ index--;
820
+ else
821
+ index++;
822
+
823
+ if (index < 0)
824
+ index = 0;
825
+
826
+ e.returnValue = false;
827
+ }
828
+ else
829
+ {
830
+ startIndex = _focusable.length;
831
+ index = 0;
832
+ }
833
+
834
+ // loop until next visible focusable element is found or when we are back on the current element
835
+ while (!focusable && (startIndex != index))
836
+ {
837
+ _focusable[index].focus();
838
+ focusable = (_focusable[index] === doc.activeElement);
839
+
840
+ if (!focusable)
841
+ {
842
+ if (shift)
843
+ index--;
844
+ else
845
+ index++;
846
+
847
+ if (index < 0)
848
+ index = _focusable.length - 1;
849
+
850
+ if (index != startIndex && index == _focusable.length)
851
+ index = 0;
852
+ }
853
+ }
854
+
855
+ return false;
856
+ }
857
+ }
858
+
859
+ function getShowDirection()
860
+ {
861
+ var a = _instance.animation;
862
+
863
+ if (a.showDirection)
864
+ return a.showDirection;
865
+
866
+ if (_instance.expandDirection != null)
867
+ return _expandDirectionOption.getName(_instance.expandDirection);
868
+ else
869
+ return 'right';
870
+ }
871
+
872
+ function getHideDirection()
873
+ {
874
+ var a = _instance.animation;
875
+ return (a.hideDirection != null) ? a.hideDirection : getShowDirection();
876
+ }
877
+
878
+ function stopAnimation()
879
+ {
880
+ if (_animation)
881
+ _animation.complete();
882
+
883
+ _animation = null;
884
+ }
885
+
886
+ function preRender()
887
+ {
888
+ // initialize script and css
889
+ return ['Box'];
890
+ }
891
+
892
+ function load(parentItem, initialLoad)
893
+ {
894
+ _instance.ajaxCall('load', null, { onSuccess: dataLoaded });
895
+ }
896
+
897
+ function dataLoaded(ajaxArgs)
898
+ {
899
+ draw(ajaxArgs.data);
900
+ }
901
+
902
+ function draw(data)
903
+ {
904
+ var divBox = _instance.element,
905
+ content = document.createElement(_instance.contentTag || 'div');
906
+
907
+ _modal = document.createElement('div');
908
+ _modal.className = _instance.cssClassModal || _classOption.MODAL;
909
+ $lib.updateStyle(_modal.style, _modalStyle);
910
+ divBox.appendChild(_modal);
911
+
912
+ content.className = _instance.cssClassContent || _classOption.CONTENT;
913
+ divBox.appendChild(content);
914
+
915
+ if (data)
916
+ {
917
+ content.innerHTML = data;
918
+ }
919
+ else
920
+ {
921
+ _instance.applyTemplate(content, 'Content');
922
+ }
923
+
924
+ _contentElement = content;
925
+ _resizeObserver = new ResizeObserver(positionDelayed);
926
+ _resizeObserver.observe(_contentElement);
927
+
928
+ bindGlobalEvents();
929
+
930
+ if (_instance.draggable)
931
+ {
932
+ _draggable = $lib.draggable(_instance.element, $base.static.initDragSettings(_instance.dragSettings));
933
+ }
934
+
935
+ _instance.postRender();
936
+ }
937
+
938
+ function activate()
939
+ {
940
+ _styleCache = {};
941
+ $lib.setStyle(_instance.element, '');
942
+
943
+ getExpander();
944
+ stretch();
945
+ setStyle();
946
+ position();
947
+ }
948
+
949
+ function stretch()
950
+ {
951
+ if (!_instance.showing || _animation || (!_instance.stretchToExpander && !_instance.stretchToContent))
952
+ return;
953
+
954
+ var divBox = _instance.element, contentSize, expanderSize;
955
+
956
+ if (_instance.stretchToContent)
957
+ {
958
+ contentSize = $lib.size(_instance.contentElement);
959
+ divBox.style.minWidth = $lib.unit(contentSize.width);
960
+ divBox.style.minHeight = $lib.unit(contentSize.height);
961
+ }
962
+
963
+ if (_instance.stretchToExpander && _instance.expander)
964
+ {
965
+ expanderSize = $lib.size(_instance.expander);
966
+
967
+ if (!contentSize)
968
+ contentSize = $lib.size(_instance.contentElement);
969
+
970
+ if (expanderSize.width > contentSize.width)
971
+ divBox.style.minWidth = $lib.unit(expanderSize.width);
972
+ }
973
+ }
974
+
975
+ function setStyle()
976
+ {
977
+ var divBox = _instance.element,
978
+ content = _instance.contentElement,
979
+ style = [];
980
+
981
+ $lib.updateStyle(divBox.style, _instance.style);
982
+ content.style.width = content.style.height = '';
983
+
984
+ if (_instance.top)
985
+ style.push('top: ' + $lib.unit(_instance.top));
986
+ if (_instance.right)
987
+ style.push('right: ' + $lib.unit(_instance.right));
988
+ if (_instance.bottom)
989
+ style.push('bottom: ' + $lib.unit(_instance.bottom));
990
+ if (_instance.left)
991
+ style.push('left: ' + $lib.unit(_instance.left));
992
+ if (_instance.width)
993
+ style.push('width: ' + $lib.unit(_instance.width));
994
+ if (_instance.height)
995
+ style.push('height: ' + $lib.unit(_instance.height));
996
+
997
+ // add styles
998
+ if (style.length > 0)
999
+ $lib.updateStyle(divBox.style, style.join(';'));
1000
+ }
1001
+
1002
+ function position()
1003
+ {
1004
+ clearTimeout(_timerId);
1005
+ _timerId = null;
1006
+
1007
+ if (!_instance.showing || _animation || (_instance.autoPosition == _autoPositionOption.NONE && !_instance.autoFit))
1008
+ return;
1009
+
1010
+ var divBox = _instance.element;
1011
+
1012
+ _invertMarginX = _invertMarginY = 0;
1013
+ _instance.events.onPrePosition.fire(_instance, null);
1014
+
1015
+ if (_instance.autoInvertFit)
1016
+ {
1017
+ $lib.removeClass(divBox, _instance.cssClassHorizontalInverted || _classOption.HORIZONTALINVERTED);
1018
+ $lib.removeClass(divBox, _instance.cssClassVerticalInverted || _classOption.VERTICALINVERTED);
1019
+ }
1020
+
1021
+ if (_instance.autoPosition != _autoPositionOption.NONE)
1022
+ {
1023
+ var stylePos = _styleCache.position || $lib.styleValue(divBox, 'position');
1024
+
1025
+ if (stylePos != 'absolute' && stylePos != 'fixed')
1026
+ {
1027
+ divBox.style.position = 'fixed';
1028
+ stylePos = 'fixed';
1029
+ _styleCache.position = stylePos;
1030
+ }
1031
+
1032
+ divBox.style.position = stylePos;
1033
+
1034
+ if (_instance.autoPosition == _autoPositionOption.EXPAND)
1035
+ positionExpand(stylePos);
1036
+ else if (_instance.autoPosition == _autoPositionOption.POINTER && _pointerCoordinates)
1037
+ positionAtPointer(stylePos, _pointerCoordinates.clientX, _pointerCoordinates.clientY);
1038
+ else
1039
+ positionAuto(stylePos);
1040
+ }
1041
+
1042
+ _instance.events.onPostPosition.fire(_instance, null);
1043
+
1044
+ if (_instance.autoFit)
1045
+ fit();
1046
+ }
1047
+
1048
+ function clearPosition()
1049
+ {
1050
+ $lib.updateStyle(_instance.element.style, 'left: $; right: $; top: $; bottom: $; width: $; height: $;'.replace(/\$/g, 'auto'));
1051
+ }
1052
+
1053
+ function positionExpand(stylePos)
1054
+ {
1055
+ clearPosition();
1056
+
1057
+ var coords = {},
1058
+ vertical = (_instance.expandDirection == _expandDirectionOption.DOWN || _instance.expandDirection == _expandDirectionOption.UP),
1059
+ divBox = _instance.element,
1060
+ expander = _instance.expander,
1061
+ position = $lib.getPos(expander, null, stylePos == 'fixed'),
1062
+ boxWidth = _styleCache.width = _styleCache.width || divBox.offsetWidth,
1063
+ boxHeight = _styleCache.height = _styleCache.height || divBox.offsetHeight,
1064
+ expanderWidth = (vertical && _instance.alignX > 0) ? expander.offsetWidth : 0,
1065
+ expanderHeight = (!vertical && _instance.alignY > 0) ? expander.offsetHeight : 0;
1066
+
1067
+ _invertMarginX = position.width;
1068
+ _invertMarginY = position.height;
1069
+
1070
+ switch (_instance.expandDirection)
1071
+ {
1072
+ case (_expandDirectionOption.DOWN):
1073
+ coords.left = position.left;
1074
+ coords.top = position.bottom;
1075
+ break;
1076
+
1077
+ case (_expandDirectionOption.UP):
1078
+ coords.left = position.left;
1079
+ coords.top = position.top - boxHeight;
1080
+ break;
1081
+
1082
+ case (_expandDirectionOption.RIGHT):
1083
+ coords.left = position.right;
1084
+ coords.top = position.top;
1085
+ break;
1086
+
1087
+ case (_expandDirectionOption.LEFT):
1088
+ coords.left = position.left - boxWidth;
1089
+ coords.top = position.top;
1090
+ break;
1091
+ }
1092
+
1093
+ if (vertical && _instance.alignX > 0)
1094
+ {
1095
+ if (_instance.alignX == _alignXOption.CENTER)
1096
+ coords.left += (expanderWidth / 2) - (boxWidth / 2);
1097
+ else
1098
+ coords.left = position.right - boxWidth;
1099
+ }
1100
+ else if (!vertical && _instance.alignY > 0)
1101
+ {
1102
+ if (_instance.alignY == _alignYOption.CENTER)
1103
+ coords.top += (expanderHeight / 2) - (boxHeight / 2);
1104
+ else
1105
+ coords.top = position.bottom - boxHeight;
1106
+ }
1107
+
1108
+ $lib.setPos(divBox, coords, true);
1109
+ }
1110
+
1111
+ function positionAtPointer(stylePos, clientX, clientY)
1112
+ {
1113
+ var coords = {},
1114
+ direction = _instance.animation.showDirection || 'right',
1115
+ divBox = _instance.element,
1116
+ boxWidth = _styleCache.width = _styleCache.width || divBox.offsetWidth,
1117
+ boxHeight = _styleCache.height = _styleCache.height || divBox.offsetHeight,
1118
+ scroll = $lib.getScrollPosition(),
1119
+ y = (stylePos != 'fixed') ? clientY + scroll.scrollTop : clientY,
1120
+ x = (stylePos != 'fixed') ? clientX + scroll.scrollLeft : clientX;
1121
+
1122
+ clearPosition();
1123
+
1124
+ if (_instance.expandDirection != null)
1125
+ direction = _expandDirectionOption.getName(_instance.expandDirection); // expand direction has precedence over animation direction
1126
+
1127
+ if (direction.indexOf('left') > -1)
1128
+ coords.left = x - boxWidth;
1129
+ else
1130
+ coords.left = x;
1131
+
1132
+ if (direction.indexOf('up') > -1)
1133
+ coords.top = y - boxHeight;
1134
+ else
1135
+ coords.top = y;
1136
+
1137
+ // unlike the auto position setting 'expand', the auto postion setting 'pointer' allows both horizontal and vertical alignment.
1138
+
1139
+ if (_instance.alignX == _alignXOption.CENTER)
1140
+ coords.left = x - (boxWidth / 2);
1141
+ else if (_instance.alignX > 0)
1142
+ coords.left = x - boxWidth;
1143
+
1144
+ if (_instance.alignY == _alignYOption.CENTER)
1145
+ coords.top = y - (boxHeight / 2);
1146
+ else if (_instance.alignY > 0)
1147
+ coords.top = y - boxHeight;
1148
+
1149
+ $lib.setPos(divBox, coords, true);
1150
+ }
1151
+
1152
+ function positionAuto(stylePos)
1153
+ {
1154
+ var divBox = _instance.element, position;
1155
+
1156
+ clearPosition();
1157
+ position = $lib.getPos(divBox, $lib.positionedParent(divBox), stylePos == 'fixed');
1158
+
1159
+ if (_instance.autoPosition <= _autoPositionOption.TOPRIGHT)
1160
+ {
1161
+ divBox.style.top = '0%';
1162
+ }
1163
+ else if (_instance.autoPosition <= _autoPositionOption.RIGHT)
1164
+ {
1165
+ divBox.style.top = '50%';
1166
+ divBox.style.marginTop = $lib.unit((position.height / 2) * -1);
1167
+ }
1168
+ else
1169
+ {
1170
+ divBox.style.bottom = '0%';
1171
+ }
1172
+
1173
+ if (_instance.autoPosition == _autoPositionOption.TOPLEFT || _instance.autoPosition == _autoPositionOption.LEFT || _instance.autoPosition == _autoPositionOption.BOTTOMLEFT)
1174
+ {
1175
+ divBox.style.left = '0%';
1176
+ }
1177
+ else if (_instance.autoPosition == _autoPositionOption.TOPCENTER || _instance.autoPosition == _autoPositionOption.CENTER || _instance.autoPosition == _autoPositionOption.BOTTOMCENTER)
1178
+ {
1179
+ divBox.style.left = '50%';
1180
+ divBox.style.marginLeft = $lib.unit((position.width / 2) * -1);
1181
+ }
1182
+ else
1183
+ {
1184
+ divBox.style.right = '0%';
1185
+ }
1186
+ }
1187
+
1188
+ function fit()
1189
+ {
1190
+ var divBox = _instance.element,
1191
+ winSize = $lib.getWindowSize(),
1192
+ rect = $lib.getPos(divBox, null, true),
1193
+ autoPos = (_instance.autoPosition == _autoPositionOption.NONE || _instance.autoPosition == _autoPositionOption.EXPAND || _instance.autoPosition == _autoPositionOption.POINTER),
1194
+ fitX = (autoPos && (rect.left < 0 || rect.right > winSize.width)) ? true : false,
1195
+ fitY = (autoPos && (rect.top < 0 || rect.bottom > winSize.height)) ? true : false,
1196
+ vertical = (_instance.expandDirection == _expandDirectionOption.DOWN || _instance.expandDirection == _expandDirectionOption.UP);
1197
+
1198
+ _invertedX = _invertedY = _resizedX = _resizedY = false;
1199
+ divBox.style.removeProperty('--expander-offset');
1200
+
1201
+ if (fitX)
1202
+ {
1203
+ fitHorizontal(rect, winSize);
1204
+
1205
+ if (vertical)
1206
+ {
1207
+ $lib.removeClass(_instance.element, 'align-left align-center align-right');
1208
+
1209
+ if (divBox.style.left && divBox.style.left != 'auto')
1210
+ $lib.addClass(_instance.element, 'align-left');
1211
+ else
1212
+ $lib.addClass(_instance.element, 'align-right');
1213
+ }
1214
+
1215
+ if (!fitY)
1216
+ divBox.style.top = $lib.unit(rect.top - parseFloat($.styleValue(divBox, 'margin-top', true))); // must be changed to match fixed position
1217
+ }
1218
+
1219
+ if (fitY)
1220
+ {
1221
+ fitVertical(rect, winSize);
1222
+
1223
+ if (!vertical)
1224
+ {
1225
+ $lib.removeClass(_instance.element, 'align-top align-center align-bottom');
1226
+
1227
+ if (divBox.style.top && divBox.style.top != 'auto')
1228
+ $lib.addClass(_instance.element, 'align-top');
1229
+ else
1230
+ $lib.addClass(_instance.element, 'align-bottom');
1231
+ }
1232
+
1233
+ if (!fitX)
1234
+ divBox.style.left = $lib.unit(rect.left - parseFloat($.styleValue(divBox, 'margin-left', true))); // must be changed to match fixed position
1235
+ }
1236
+
1237
+ if (fitX || fitY)
1238
+ {
1239
+ divBox.style.position = 'fixed';
1240
+ setExpanderOffset(divBox, vertical);
1241
+ _instance.events.onAutoFit.fire(_instance, { fitX: fitX, fitY: fitY, invertedX: _invertedX, invertedY: _invertedY, resizedX: _resizedX, resizedY: _resizedY });
1242
+ }
1243
+ }
1244
+
1245
+ function fitVertical(rect, winSize)
1246
+ {
1247
+ var divBox = _instance.element,
1248
+ invertRect = getInvertRect(divBox, true),
1249
+ space = 0, invertPos = 0, invertSpace = 0, fits = (rect.height <= winSize.height),
1250
+ resize = function ()
1251
+ {
1252
+ if (fits || !_instance.autoResizeFit) return;
1253
+
1254
+ const cs = window.getComputedStyle(divBox),
1255
+ boxSizing = (cs.boxSizing || cs.getPropertyValue('box-sizing') || 'content-box').toLowerCase();
1256
+
1257
+ let baseSpace;
1258
+ if (_instance.resizeToMaxHeight)
1259
+ {
1260
+ baseSpace = winSize.height;
1261
+ divBox.style.top = $lib.unit(0);
1262
+ }
1263
+ else
1264
+ {
1265
+ baseSpace = (_invertedY) ? invertSpace : space;
1266
+ }
1267
+
1268
+ let finalHeight = baseSpace;
1269
+
1270
+ if (boxSizing === 'content-box') // subtract border+padding because style.height sets the content box
1271
+ {
1272
+ const devSize = $lib.borderAndPadding(divBox);
1273
+ finalHeight = baseSpace - devSize.height;
1274
+ }
1275
+
1276
+ divBox.style.height = (finalHeight > 0) ? $lib.unit(finalHeight) : '0px';
1277
+ _styleCache.height = null;
1278
+ _resizedY = true;
1279
+ };
1280
+
1281
+ // clear position and margin
1282
+ $lib.updateStyle(divBox.style, 'top:auto;bottom:auto;margin-top:0px !important;margin-bottom:0px !important;');
1283
+
1284
+ if (_instance.autoPosition != _autoPositionOption.EXPAND || !_instance.autoInvertFit
1285
+ || (_instance.expandDirection != _expandDirectionOption.DOWN && _instance.expandDirection != _expandDirectionOption.UP))
1286
+ {
1287
+ if (rect.top < 0)
1288
+ divBox.style.top = $lib.unit(0);
1289
+ else
1290
+ divBox.style.bottom = $lib.unit(0);
1291
+
1292
+ return resize();
1293
+ }
1294
+ else if (_instance.expandDirection == _expandDirectionOption.DOWN)
1295
+ {
1296
+ if (rect.top < 0)
1297
+ {
1298
+ divBox.style.top = $lib.unit(0);
1299
+ return resize();
1300
+ }
1301
+ else if ((rect.top - _invertMarginY) > winSize.height)
1302
+ {
1303
+ divBox.style.bottom = $lib.unit(0);
1304
+ return resize();
1305
+ }
1306
+
1307
+ space = winSize.height - rect.top;
1308
+ invertPos = invertRect.top - (invertRect.height + _invertMarginY);
1309
+ invertSpace = (invertPos < 0) ? invertRect.bottom - invertRect.height - _invertMarginY : invertRect.height;
1310
+ }
1311
+ else
1312
+ {
1313
+ if (rect.bottom > winSize.height)
1314
+ {
1315
+ divBox.style.bottom = $lib.unit(0);
1316
+ return resize();
1317
+ }
1318
+ else if ((rect.bottom + _invertMarginY) < 0)
1319
+ {
1320
+ divBox.style.top = $lib.unit(0);
1321
+ return resize();
1322
+ }
1323
+
1324
+ space = (winSize.height < rect.bottom) ? winSize.height : rect.bottom;
1325
+ invertPos = invertRect.bottom + _invertMarginY;
1326
+ invertSpace = (invertPos < 0) ? 0 : winSize.height - invertPos;
1327
+ }
1328
+
1329
+ if (rect.height <= invertSpace)
1330
+ {
1331
+ // box fits inverted
1332
+ $lib.addClass(divBox, _instance.cssClassVerticalInverted || _classOption.VERTICALINVERTED);
1333
+ divBox.style.top = $lib.unit(invertPos);
1334
+ _invertedY = true;
1335
+ return;
1336
+ }
1337
+ else
1338
+ {
1339
+ // when invert space is larger, utilize that space
1340
+ if (space >= invertSpace)
1341
+ {
1342
+ if (fits && rect.top >= 0)
1343
+ divBox.style.bottom = $lib.unit(0);
1344
+ else
1345
+ divBox.style.top = (rect.top >= 0) ? $lib.unit(rect.top) : $lib.unit(0);
1346
+ }
1347
+ else
1348
+ divBox.style.top = (invertPos >= 0) ? $lib.unit(invertPos) : $lib.unit(0);
1349
+
1350
+ if (invertSpace > space)
1351
+ {
1352
+ $lib.addClass(divBox, _instance.cssClassVerticalInverted || _classOption.VERTICALINVERTED);
1353
+ _invertedY = true;
1354
+ }
1355
+
1356
+ if (!_instance.resizeToMaxHeight)
1357
+ fits = (space >= invertSpace) ? (rect.height <= space) : (rect.height <= invertSpace);
1358
+
1359
+ return resize();
1360
+ }
1361
+ }
1362
+
1363
+ function fitHorizontal(rect, winSize)
1364
+ {
1365
+ var divBox = _instance.element,
1366
+ invertRect = getInvertRect(divBox),
1367
+ space = 0, invertPos = 0, invertSpace = 0, fits = (rect.width <= winSize.width),
1368
+ resize = function ()
1369
+ {
1370
+ if (fits || !_instance.autoResizeFit) return;
1371
+
1372
+ const cs = window.getComputedStyle(divBox),
1373
+ boxSizing = (cs.boxSizing || cs.getPropertyValue('box-sizing') || 'content-box').toLowerCase();
1374
+
1375
+ let baseSpace;
1376
+ if (_instance.resizeToMaxWidth)
1377
+ {
1378
+ baseSpace = winSize.width;
1379
+ divBox.style.left = $lib.unit(0);
1380
+ }
1381
+ else
1382
+ {
1383
+ baseSpace = (_invertedX) ? invertSpace : space;
1384
+ }
1385
+
1386
+ let finalWidth = baseSpace;
1387
+
1388
+ if (boxSizing === 'content-box') // subtract border+padding because style.width sets the content box
1389
+ {
1390
+ const devSize = $lib.borderAndPadding(divBox);
1391
+ finalWidth = baseSpace - devSize.width;
1392
+ }
1393
+
1394
+ divBox.style.width = (finalWidth > 0) ? $lib.unit(finalWidth) : '0px';
1395
+ _styleCache.width = null;
1396
+ _resizedX = true;
1397
+ };
1398
+
1399
+ // clear position and margin
1400
+ $lib.updateStyle(divBox.style, 'left:auto;right:auto;margin-left:0px !important;margin-right:0px !important;');
1401
+
1402
+ if ((_instance.autoPosition != _autoPositionOption.EXPAND || !_instance.autoInvertFit)
1403
+ || (_instance.expandDirection != _expandDirectionOption.RIGHT && _instance.expandDirection != _expandDirectionOption.LEFT))
1404
+ {
1405
+ if (rect.left < 0)
1406
+ divBox.style.left = $lib.unit(0);
1407
+ else
1408
+ divBox.style.right = $lib.unit(0);
1409
+
1410
+ return resize();
1411
+ }
1412
+ else if (_instance.expandDirection == _expandDirectionOption.RIGHT)
1413
+ {
1414
+ if (rect.left < 0)
1415
+ {
1416
+ divBox.style.left = $lib.unit(0);
1417
+ return resize();
1418
+ }
1419
+ else if ((rect.left - _invertMarginX) > winSize.width)
1420
+ {
1421
+ divBox.style.right = $lib.unit(0);
1422
+ return resize();
1423
+ }
1424
+
1425
+ space = winSize.width - rect.left;
1426
+ invertPos = invertRect.left - (invertRect.width + _invertMarginX);
1427
+ invertSpace = (invertPos < 0) ? invertRect.right - invertRect.width - _invertMarginX : invertRect.width;
1428
+ }
1429
+ else
1430
+ {
1431
+ if (rect.right > winSize.width)
1432
+ {
1433
+ divBox.style.right = $lib.unit(0);
1434
+ return resize();
1435
+ }
1436
+ else if ((rect.right + _invertMarginX) < 0)
1437
+ {
1438
+ divBox.style.left = $lib.unit(0);
1439
+ return resize();
1440
+ }
1441
+
1442
+ space = (winSize.width < rect.right) ? winSize.width : rect.right;
1443
+ invertPos = invertRect.right + _invertMarginX;
1444
+ invertSpace = (invertPos < 0) ? 0 : winSize.width - invertPos;
1445
+ }
1446
+
1447
+ if (rect.width <= invertSpace)
1448
+ {
1449
+ // box fits inverted
1450
+ $lib.addClass(divBox, _instance.cssClassHorizontalInverted || _classOption.HORIZONTALINVERTED);
1451
+ divBox.style.left = $lib.unit(invertPos);
1452
+ _invertedX = true;
1453
+ return;
1454
+ }
1455
+ else
1456
+ {
1457
+ // when invert space is larger, utilize that space
1458
+ if (space >= invertSpace)
1459
+ {
1460
+ if (fits && rect.left >= 0)
1461
+ divBox.style.right = $lib.unit(0);
1462
+ else
1463
+ divBox.style.left = (rect.left >= 0) ? $lib.unit(rect.left) : $lib.unit(0);
1464
+ }
1465
+ else
1466
+ divBox.style.left = (invertPos >= 0) ? $lib.unit(invertPos) : $lib.unit(0);
1467
+
1468
+ if (invertSpace > space)
1469
+ {
1470
+ $lib.addClass(divBox, _instance.cssClassHorizontalInverted || _classOption.HORIZONTALINVERTED);
1471
+ _invertedX = true;
1472
+ }
1473
+
1474
+ if (!_instance.resizeToMaxWidth)
1475
+ fits = (space >= invertSpace) ? (rect.width <= space) : (rect.width <= invertSpace);
1476
+
1477
+ return resize();
1478
+ }
1479
+ }
1480
+
1481
+ function setExpanderOffset(divBox, vertical)
1482
+ {
1483
+ if (!_instance.expander) return;
1484
+
1485
+ const boxRect = divBox.getBoundingClientRect(),
1486
+ expRect = _instance.expander.getBoundingClientRect(),
1487
+ expCenterX = expRect.left + expRect.width / 2,
1488
+ expCenterY = expRect.top + expRect.height / 2;
1489
+
1490
+ if (vertical)
1491
+ {
1492
+ if (divBox.classList.contains('align-left'))
1493
+ {
1494
+ const offsetX = Math.floor(expCenterX - boxRect.left);
1495
+ divBox.style.setProperty('--expander-offset', offsetX + 'px');
1496
+ } else if (divBox.classList.contains('align-right'))
1497
+ {
1498
+ const offsetX = Math.floor(boxRect.right - expCenterX);
1499
+ divBox.style.setProperty('--expander-offset', offsetX + 'px');
1500
+ }
1501
+ }
1502
+ else
1503
+ {
1504
+ if (divBox.classList.contains('align-top'))
1505
+ {
1506
+ const offsetY = Math.floor(expCenterY - boxRect.top);
1507
+ divBox.style.setProperty('--expander-offset', offsetY + 'px');
1508
+ } else if (divBox.classList.contains('align-bottom'))
1509
+ {
1510
+ const offsetY = Math.floor(boxRect.bottom - expCenterY);
1511
+ divBox.style.setProperty('--expander-offset', offsetY + 'px');
1512
+ }
1513
+ }
1514
+ }
1515
+
1516
+ function getInvertRect(divBox, vertical)
1517
+ {
1518
+ var cssClass = (vertical) ? _instance.cssClassVerticalInverted || _classOption.VERTICALINVERTED : _instance.cssClassHorizontalInverted || _classOption.HORIZONTALINVERTED;
1519
+ var rect;
1520
+
1521
+ if (!$lib.hasClass(divBox, cssClass))
1522
+ {
1523
+ $lib.addClass(divBox, cssClass);
1524
+ rect = $lib.getPos(divBox, null, true);
1525
+ $lib.removeClass(divBox, cssClass);
1526
+ }
1527
+ else
1528
+ rect = $lib.getPos(divBox, null, true);
1529
+
1530
+ return rect;
1531
+ }
1532
+
1533
+ function bindGlobalEvents()
1534
+ {
1535
+ $lib.on(window, 'resize', positionDelayed, null, _instance);
1536
+ $lib.on(window, 'scroll', positionDelayed, null, _instance);
1537
+ $lib.on(_instance.element, 'pointerdown pointerup', function () { _allowHide = false; }, null, _instance);
1538
+ $lib.on(_instance.element, 'pointercancel', function () { _allowHide = true; }, null, _instance); // touch scroll/long-press ends without pointerup
1539
+ $lib.on(_instance.element, 'keydown', function (e)
1540
+ {
1541
+ const doc = _instance.element.ownerDocument || document,
1542
+ activeElement = doc.activeElement;
1543
+
1544
+ if (e.defaultPrevented) // canceled by other handler, do not process enter key submission
1545
+ return;
1546
+
1547
+ if (_instance.enterKeySubmitter && e.key?.toLowerCase() == 'enter' && !e.shiftKey && activeElement && _instance.element.contains(activeElement))
1548
+ {
1549
+ let element = _instance.enterKeySubmitter;
1550
+
1551
+ element = (typeof element === 'string') ? $lib('#' + element) : element;
1552
+ $lib.fireEvent(element, 'click', true, true);
1553
+ }
1554
+ });
1555
+ }
1556
+
1557
+ function bindOutsideClickHandler()
1558
+ {
1559
+ if (_instance.hideOnOutsideClick && !$lib.has(document, 'pointerup', checkHide))
1560
+ $lib.on(document, 'pointerup', checkHide);
1561
+ }
1562
+
1563
+ function removeOutsideClickHandler()
1564
+ {
1565
+ $lib.off(document, 'pointerup', checkHide);
1566
+ }
1567
+
1568
+ function positionDelayed()
1569
+ {
1570
+ clearTimeout(_timerId);
1571
+ _timerId = setTimeout(position, 0);
1572
+ }
1573
+
1574
+ function dispose()
1575
+ {
1576
+ $lib.off(window, 'resize', positionDelayed);
1577
+ $lib.off(window, 'scroll', positionDelayed);
1578
+ $lib.off(document, 'pointermove', trackPointer);
1579
+ $lib.off(document, 'pointerup', stopPointerTracking);
1580
+
1581
+ if (_resizeObserver)
1582
+ {
1583
+ _resizeObserver.disconnect();
1584
+ _resizeObserver = null;
1585
+ }
1586
+
1587
+ clearTimers();
1588
+ removeOutsideClickHandler();
1589
+
1590
+ if (_draggable)
1591
+ _draggable.disable();
1592
+
1593
+ _draggable = null;
1594
+ _pointerCoordinates = null;
1595
+ _styleCache = {};
1596
+ }
1597
+ };
1598
+
1599
+ /**
1600
+ * @see {@link componyx.UI.base.methods}
1601
+ */
1602
+ componyx.UI.Box.prototype = Object.create($base.methods);
1603
+ componyx.UI.Box.prototype.constructor = componyx.UI.Box;
1604
+
1605
+ /**
1606
+ * AutoPositionOption
1607
+ * @readonly
1608
+ * @enum {number}
1609
+ */
1610
+ componyx.UI.Box.AutoPositionOption =
1611
+ {
1612
+ NONE: 0,
1613
+ TOPLEFT: 1,
1614
+ TOPCENTER: 2,
1615
+ TOPRIGHT: 3,
1616
+ LEFT: 4,
1617
+ CENTER: 5,
1618
+ RIGHT: 6,
1619
+ BOTTOMLEFT: 7,
1620
+ BOTTOMCENTER: 8,
1621
+ BOTTOMRIGHT: 9,
1622
+ POINTER: 10,
1623
+ EXPAND: 11
1624
+ };
1625
+
1626
+ /**
1627
+ * ExpandDirectionOption
1628
+ * @readonly
1629
+ * @enum {number}
1630
+ */
1631
+ componyx.UI.Box.ExpandDirectionOption =
1632
+ {
1633
+ DOWN: 0,
1634
+ RIGHT: 1,
1635
+ UP: 2,
1636
+ LEFT: 3,
1637
+
1638
+ getName: function (value) { return $base.static.getKeyByValue(this, value).toLowerCase(); }
1639
+ };
1640
+
1641
+ /**
1642
+ * AlignXOption
1643
+ * @readonly
1644
+ * @enum {number}
1645
+ */
1646
+ componyx.UI.Box.AlignXOption =
1647
+ {
1648
+ LEFT: 0,
1649
+ CENTER: 1,
1650
+ RIGHT: 2,
1651
+
1652
+ getName: function (value) { return $base.static.getKeyByValue(this, value).toLowerCase(); }
1653
+ };
1654
+
1655
+ /**
1656
+ * AlignYOption
1657
+ * @readonly
1658
+ * @enum {number}
1659
+ */
1660
+ componyx.UI.Box.AlignYOption =
1661
+ {
1662
+ TOP: 0,
1663
+ CENTER: 1,
1664
+ BOTTOM: 2,
1665
+
1666
+ getName: function (value) { return $base.static.getKeyByValue(this, value).toLowerCase(); }
1667
+ };
1668
+
1669
+ /**
1670
+ * AnimationTypeOption
1671
+ * @readonly
1672
+ * @enum {number}
1673
+ */
1674
+ componyx.UI.Box.AnimationTypeOption =
1675
+ {
1676
+ NONE: 0,
1677
+ SLIDE: 1,
1678
+ REVEAL: 2,
1679
+ CSS: 3
1680
+ };
1681
+ })(window);
1682
+
1683
+ const Box = componyx.UI.Box;
1684
+
1685
+ export { Box };