@componyx/ui 0.0.0-stage → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AppSkin/AppSkin.css +1268 -0
- package/AppSkin/AppSkin.js +2748 -0
- package/AppSkin/Themes/Default.css +241 -0
- package/Base/Base.js +3407 -0
- package/Base/ComponentIcons.css +66 -0
- package/Base/Font/ComponentIcons.woff +0 -0
- package/Base/Font/UI.woff +0 -0
- package/Base/Library.js +8432 -0
- package/Base/NavigationManager.js +462 -0
- package/Base/ResponsiveTemplates.js +371 -0
- package/Base/Sanitizer.js +288 -0
- package/Base/Themes/Default.css +255 -0
- package/Base/UI.css +618 -0
- package/Base/UIResourcePath.js +6 -0
- package/Bindary/Bindary.js +2011 -0
- package/Bindary/Modules/Connection.js +216 -0
- package/Bindary/Modules/Core.js +854 -0
- package/Bindary/Modules/DataUpdater.js +351 -0
- package/Bindary/Modules/ExpressionEngine.js +347 -0
- package/Bindary/Modules/ProxyManager.js +482 -0
- package/Bindary/Modules/Renderer.js +605 -0
- package/Bindary/Modules/Router.js +291 -0
- package/Bindary/Modules/Scroller.js +89 -0
- package/Bindary/Modules/Template.js +1273 -0
- package/BookmarkSpy/BookmarkSpy.js +430 -0
- package/Box/Box.css +36 -0
- package/Box/Box.js +1685 -0
- package/Button/Button.css +470 -0
- package/Button/Button.js +1398 -0
- package/Button/Themes/Default.css +200 -0
- package/Carousel/Carousel.css +273 -0
- package/Carousel/Carousel.js +607 -0
- package/ColorButton/ColorButton.css +39 -0
- package/ColorButton/ColorButton.js +336 -0
- package/ColorPicker/ColorPicker.css +359 -0
- package/ColorPicker/ColorPicker.js +972 -0
- package/ComboBox/ComboBox.css +357 -0
- package/ComboBox/ComboBox.js +2342 -0
- package/ComboBox/Themes/Default.css +23 -0
- package/DataPager/DataPager.css +72 -0
- package/DataPager/DataPager.js +674 -0
- package/DatePicker/DatePicker.css +227 -0
- package/DatePicker/DatePicker.js +1531 -0
- package/DatePicker/Themes/Default.css +26 -0
- package/Dialog/Dialog.css +106 -0
- package/Dialog/Dialog.js +572 -0
- package/Dialog/Themes/Default.css +10 -0
- package/Editor/Data/Emoji.json +8285 -0
- package/Editor/Data/Special.json +1042 -0
- package/Editor/Editor.css +1562 -0
- package/Editor/Editor.js +4058 -0
- package/Editor/Font/Editor.woff +0 -0
- package/Editor/Modules/ComponentFactory.js +565 -0
- package/Editor/Modules/ContentManager.js +748 -0
- package/Editor/Modules/DialogManager.js +1234 -0
- package/Editor/Modules/EventManager.js +458 -0
- package/Editor/Modules/Format.js +950 -0
- package/Editor/Modules/History.js +191 -0
- package/Editor/Modules/LayoutState.js +379 -0
- package/Editor/Modules/ListManager.js +296 -0
- package/Editor/Modules/MenuManager.js +388 -0
- package/Editor/Modules/NodeManager.js +681 -0
- package/Editor/Modules/ParagraphButtons.js +122 -0
- package/Editor/Modules/Resizer.js +176 -0
- package/Editor/Modules/SelectionRange.js +564 -0
- package/Editor/Modules/SourceViewBuilder.js +212 -0
- package/Editor/Modules/SymbolPicker.js +208 -0
- package/Editor/Modules/Table.js +2327 -0
- package/Editor/Modules/TableDialog.js +757 -0
- package/Editor/Modules/Toolbar.js +375 -0
- package/Editor/Modules/TooltipMenu.js +125 -0
- package/Editor/Modules/Utility.js +131 -0
- package/Editor/Themes/Default.css +204 -0
- package/FileUpload/FileUpload.css +156 -0
- package/FileUpload/FileUpload.js +898 -0
- package/FileUpload/Themes/Default.css +17 -0
- package/Form/Form.css +1934 -0
- package/Form/Form.js +4943 -0
- package/Form/Modules/ActionManager.js +368 -0
- package/Form/Modules/BuildPanelManager.js +319 -0
- package/Form/Modules/ComponentFactory.js +468 -0
- package/Form/Modules/ComponentPanel.js +265 -0
- package/Form/Modules/ConfigPanelManager.js +685 -0
- package/Form/Modules/DataObserver.js +717 -0
- package/Form/Modules/Databinder.js +602 -0
- package/Form/Modules/Draggable.js +756 -0
- package/Form/Modules/OptionsPanel.js +342 -0
- package/Form/Modules/Renderer.js +1889 -0
- package/Form/Modules/RuleEngine.js +585 -0
- package/Form/Modules/RulesPanel.js +1158 -0
- package/Form/Modules/Types.js +1709 -0
- package/Form/Modules/ValidationManager.js +194 -0
- package/Form/Themes/Default.css +216 -0
- package/FormField/FormField.css +468 -0
- package/FormField/FormField.js +576 -0
- package/FormField/Themes/Default.css +99 -0
- package/Grid/Grid.css +544 -0
- package/Grid/Grid.js +3761 -0
- package/Grid/Themes/Default.css +43 -0
- package/LICENSE +126 -0
- package/MaskedTextBox/MaskedTextBox.css +28 -0
- package/MaskedTextBox/MaskedTextBox.js +642 -0
- package/MaskedTextBox/Themes/Default.css +6 -0
- package/Menu/Menu.css +328 -0
- package/Menu/Menu.js +2386 -0
- package/Menu/Themes/Default.css +24 -0
- package/NumericBox/NumericBox.css +120 -0
- package/NumericBox/NumericBox.js +984 -0
- package/PanelBar/PanelBar.css +123 -0
- package/PanelBar/PanelBar.js +505 -0
- package/PanelBar/Themes/Default.css +51 -0
- package/PieChart/PieChart.css +95 -0
- package/PieChart/PieChart.js +820 -0
- package/PieChart/Themes/Default.css +9 -0
- package/README.md +178 -3
- package/Slider/Slider.css +348 -0
- package/Slider/Slider.js +1306 -0
- package/Slider/Themes/Default.css +44 -0
- package/TabStrip/TabStrip.css +52 -0
- package/TabStrip/TabStrip.js +362 -0
- package/TabStrip/Themes/Default.css +35 -0
- package/TimePicker/Themes/Default.css +30 -0
- package/TimePicker/TimePicker.css +253 -0
- package/TimePicker/TimePicker.js +1485 -0
- package/TooltipManager/Themes/Default.css +21 -0
- package/TooltipManager/TooltipManager.css +227 -0
- package/TooltipManager/TooltipManager.js +791 -0
- package/Validator/Validator.css +54 -0
- package/Validator/Validator.js +2508 -0
- package/componyx.html-data.json +619 -0
- package/index.js +27 -0
- package/package.json +43 -4
- package/types/AppSkin.d.ts +842 -0
- package/types/Base.d.ts +1034 -0
- package/types/Bindary.d.ts +1196 -0
- package/types/BookmarkSpy.d.ts +112 -0
- package/types/Box.d.ts +374 -0
- package/types/Button.d.ts +455 -0
- package/types/Carousel.d.ts +136 -0
- package/types/ColorButton.d.ts +120 -0
- package/types/ColorPicker.d.ts +225 -0
- package/types/ComboBox.d.ts +507 -0
- package/types/DataPager.d.ts +152 -0
- package/types/DatePicker.d.ts +354 -0
- package/types/Dialog.d.ts +160 -0
- package/types/Editor.d.ts +1289 -0
- package/types/FileUpload.d.ts +206 -0
- package/types/Form.d.ts +3078 -0
- package/types/FormField.d.ts +204 -0
- package/types/Grid.d.ts +911 -0
- package/types/Library.d.ts +1899 -0
- package/types/MaskedTextBox.d.ts +91 -0
- package/types/Menu.d.ts +577 -0
- package/types/NumericBox.d.ts +310 -0
- package/types/PanelBar.d.ts +223 -0
- package/types/PieChart.d.ts +224 -0
- package/types/ResponsiveTemplates.d.ts +108 -0
- package/types/Slider.d.ts +227 -0
- package/types/TabStrip.d.ts +185 -0
- package/types/TimePicker.d.ts +265 -0
- package/types/TooltipManager.d.ts +178 -0
- package/types/UI.d.ts +29 -0
- package/types/Validator.d.ts +653 -0
- package/types/index.d.ts +59 -0
- package/ui.css +11783 -0
- package/ui.js +79477 -0
- package/ui.min.css +138 -0
- package/ui.min.js +264 -0
- package/ui.min.js.map +1 -0
|
@@ -0,0 +1,2748 @@
|
|
|
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
|
+
import '../Button/Button.js';
|
|
5
|
+
import '../FormField/FormField.js';
|
|
6
|
+
import '../Box/Box.js';
|
|
7
|
+
import '../Menu/Menu.js';
|
|
8
|
+
|
|
9
|
+
(function (window)
|
|
10
|
+
{
|
|
11
|
+
/**
|
|
12
|
+
* AppSkin class.
|
|
13
|
+
* @class
|
|
14
|
+
* @memberof componyx.UI
|
|
15
|
+
* @augments componyx.UI.base.Component
|
|
16
|
+
* @mixes componyx.UI.base.methods
|
|
17
|
+
* @param {String} id The id of the component.
|
|
18
|
+
* @param {Object|HTMLElement} properties The properties used to initialize the component or the container element.
|
|
19
|
+
* @property {componyx.UI.base.AjaxMethod} ajax.authenticate - AJAX method used to authenticate.
|
|
20
|
+
* @property {componyx.UI.base.AjaxMethod} ajax.search - AJAX method used to load search results.
|
|
21
|
+
* @returns {componyx.UI.AppSkin} An instance of the component.
|
|
22
|
+
*/
|
|
23
|
+
componyx.UI.AppSkin = function AppSkin(id, properties)
|
|
24
|
+
{
|
|
25
|
+
window.$appskin = this;
|
|
26
|
+
|
|
27
|
+
// define private properties
|
|
28
|
+
let _instance = this,
|
|
29
|
+
_screenOption = componyx.UI.AppSkin.ScreenOption,
|
|
30
|
+
_menuTypeOption = componyx.UI.AppSkin.MenuTypeOption,
|
|
31
|
+
_footerDisplayOption = componyx.UI.AppSkin.FooterDisplayOption,
|
|
32
|
+
_menuSectionOption = componyx.UI.AppSkin.MenuSectionOption,
|
|
33
|
+
_routePathMatchingOption = componyx.UI.AppSkin.RoutePathMatchingOption,
|
|
34
|
+
_failureReasonOption = componyx.UI.AppSkin.FailureReasonOption,
|
|
35
|
+
_tileSizeOption = componyx.UI.AppSkin.TileSizeOption,
|
|
36
|
+
_menuButton, _login, _loginVerification, _topbar, _page, _header, _footer, _sideMenuBox, _mainMenu, _headerMenu, _footerMenu, _quickLaunchMenu, _searchBox, _searchResult,
|
|
37
|
+
_user, _pass, _remember, _loginFailedMessage, _verificationFailedMessage, _verificationCode, _activeScreen, _view, _error, _overlay, _allInHeader = true, _errorData,
|
|
38
|
+
_preloader, _launch = true, _resizeTimerId, _headerOverflowTimerId, _searchTimerId, _windowWidth, _classOption;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Internal CSS class name constants.
|
|
42
|
+
* You can override any of these classes on the Component instance by defining a property named
|
|
43
|
+
* `cssClass<Key>` where <Key> is the PascalCase key from this object.
|
|
44
|
+
* Example:
|
|
45
|
+
* 'SEARCH_RESULT' -> 'cssClassSearchResult'
|
|
46
|
+
* Be cautious: overriding these classes without including the default names may break styling and functionality.
|
|
47
|
+
* @constant
|
|
48
|
+
* @type {Readonly<Object<string, string>>}
|
|
49
|
+
*/
|
|
50
|
+
this.classOption = Object.freeze(
|
|
51
|
+
{
|
|
52
|
+
FULL: 'full',
|
|
53
|
+
ERROR: 'error',
|
|
54
|
+
TOPBAR: 'topbar',
|
|
55
|
+
FOOTER: 'footer',
|
|
56
|
+
REQUIRED: 'required',
|
|
57
|
+
MENU_LEFT: 'menu-left',
|
|
58
|
+
AUTHENTICATED: 'authenticated',
|
|
59
|
+
SEARCH_ACTIVE: 'search-active',
|
|
60
|
+
PORTAL_MENU: 'portal-menu',
|
|
61
|
+
SIDE_MENU: 'side-menu',
|
|
62
|
+
LOGIN: 'login',
|
|
63
|
+
VERIFICATION: 'verification',
|
|
64
|
+
HEADER_ALL: 'header-all',
|
|
65
|
+
HEADER_MENU_HIDDEN: 'header-menu-hidden',
|
|
66
|
+
HEADER_OVERFLOW: 'header-overflow',
|
|
67
|
+
BODY: 'body',
|
|
68
|
+
PAGE: 'page',
|
|
69
|
+
VIEW: 'view',
|
|
70
|
+
OVERLAY: 'overlay',
|
|
71
|
+
SIDEBAR: 'sidebar',
|
|
72
|
+
APP_CONTENT: 'app-content',
|
|
73
|
+
SEARCH: 'search',
|
|
74
|
+
SEARCH_RESULT: 'search-result',
|
|
75
|
+
SPINNER: 'spinner',
|
|
76
|
+
BOX: 'box',
|
|
77
|
+
PRELOADER: 'preloader',
|
|
78
|
+
MENU: 'menu',
|
|
79
|
+
MAIN: 'main',
|
|
80
|
+
SIDE: 'side',
|
|
81
|
+
PORTAL: 'portal',
|
|
82
|
+
HEADER_MENU: 'header-menu',
|
|
83
|
+
QUICK_LAUNCH: 'quick-launch',
|
|
84
|
+
FOOTER_MENU: 'footer-menu',
|
|
85
|
+
BUTTON: 'button',
|
|
86
|
+
MENU_BUTTON: 'menu-button',
|
|
87
|
+
ACCOUNT: 'account',
|
|
88
|
+
ACCOUNT_AVATAR: 'account-avatar',
|
|
89
|
+
NO_ACTION: 'no-action',
|
|
90
|
+
SUB_GROUP: 'sub-group',
|
|
91
|
+
ROW_START: 'row-start',
|
|
92
|
+
SHADE: 'shade',
|
|
93
|
+
LOGIN_SCREEN: 'login-screen',
|
|
94
|
+
LOGIN_VERIFICATION: 'login-verification',
|
|
95
|
+
CONTENT: 'content',
|
|
96
|
+
USER: 'user',
|
|
97
|
+
PASS: 'pass',
|
|
98
|
+
REMEMBER: 'remember',
|
|
99
|
+
CODE: 'code',
|
|
100
|
+
MESSAGE: 'message',
|
|
101
|
+
ICON_MENU: 'ico-menu ico-m',
|
|
102
|
+
ICON_USER: 'ico-user',
|
|
103
|
+
ICON_LOCK: 'ico-lock',
|
|
104
|
+
ICON_KEY: 'ico-key',
|
|
105
|
+
ICON_EYE: 'ico-eye',
|
|
106
|
+
ICON_EYE_BLOCKED: 'ico-eye-blocked'
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Gets the css class if it exists and otherwise the default css class.
|
|
111
|
+
* @param {String} cssClassValue The default css class (a value of the classOption object).
|
|
112
|
+
* @returns {String} The css class.
|
|
113
|
+
*/
|
|
114
|
+
this.getCssClass = function (cssClassValue)
|
|
115
|
+
{
|
|
116
|
+
return $base.methods.getCssClass.call(_instance, _instance.classOption, cssClassValue);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// define public properties
|
|
120
|
+
/**
|
|
121
|
+
* Gets or sets a value indicating if authentication is required.
|
|
122
|
+
* @type {Boolean}
|
|
123
|
+
*/
|
|
124
|
+
this.authenticationRequired = true;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Gets a value indicating if the user is authenticated.
|
|
128
|
+
* @type {Boolean}
|
|
129
|
+
*/
|
|
130
|
+
this.authenticated = false;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Gets a value indicating if the menu is displayed on app launch.
|
|
134
|
+
* @type {Boolean}
|
|
135
|
+
*/
|
|
136
|
+
this.launchMenu = true;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Gets a value indicating if the menu button is displayed when the app-skin login page is active.
|
|
140
|
+
* @type { Boolean }
|
|
141
|
+
*/
|
|
142
|
+
this.hideMenuButtonOnLogin = false;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Gets or sets a value indicating if the contents of the app skin will utilize the full-screen width.
|
|
146
|
+
* @type {Boolean}
|
|
147
|
+
*/
|
|
148
|
+
this.fullscreen = false;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Gets or sets a value indicating if the page content utilizes the full-screen width when not in full-screen mode.
|
|
152
|
+
* @type {Boolean}
|
|
153
|
+
*/
|
|
154
|
+
this.fullpage = false;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Gets or sets a value indicating if the rememeber me option is available for manual login.
|
|
158
|
+
* @type {Boolean}
|
|
159
|
+
*/
|
|
160
|
+
this.showRememberMe = false;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Gets or sets a value indicating if the top-bar in the header is always visible (true) or is hidden when the portal-menu is active (false).
|
|
164
|
+
* @type {Boolean}
|
|
165
|
+
*/
|
|
166
|
+
this.persistentTopBar = false;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Gets or sets a value indicating if the menu button is always visible (true) or is hidden when the all menu-items are visible in the header-menu.
|
|
170
|
+
* @type {Boolean}
|
|
171
|
+
*/
|
|
172
|
+
this.persistentMenuButton = false;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Gets or sets a value indicating if the side-menu displays at the right side (false) or the left side (true) of the screen.
|
|
176
|
+
* @type {Boolean}
|
|
177
|
+
*/
|
|
178
|
+
this.menuLeft = false;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Gets or sets a value indicating if the account button is displayed as avatar when the user is authenticated.
|
|
182
|
+
* @type {Boolean}
|
|
183
|
+
*/
|
|
184
|
+
this.accountButtonAvatar = false;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Gets or sets a value indicating if the login template is created when rendering the app skin.
|
|
188
|
+
* @type {Boolean}
|
|
189
|
+
*/
|
|
190
|
+
this.useLoginTemplate = true;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Gets or sets a value indicating if the Bindary framework is used for loading routes.
|
|
194
|
+
* @type {Boolean}
|
|
195
|
+
*/
|
|
196
|
+
this.useBindary = true;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Gets or sets the menu navigation type (portal-menu or side-menu).
|
|
200
|
+
* @type {componyx.UI.AppSkin.MenuTypeOption}
|
|
201
|
+
*/
|
|
202
|
+
this.menuType = _menuTypeOption.PORTALMENU;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Gets or sets a value indicating if menu-items are automatically selected if the item's route-path (partially) matches the current URL route-path.
|
|
206
|
+
* @type {componyx.UI.AppSkin.RoutePathMatchingOption}
|
|
207
|
+
*/
|
|
208
|
+
this.menuRoutePathMatching = _routePathMatchingOption.PARTIAL;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Gets or sets a value indicating when the footer is displayed.
|
|
212
|
+
* @type {componyx.UI.AppSkin.FooterDisplayOption}
|
|
213
|
+
*/
|
|
214
|
+
this.footerDisplay = _footerDisplayOption.MENU;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Gets or sets the delay in milliseconds before the typed letter(s) in the search-box are sent to the server.
|
|
218
|
+
* @type {Number}
|
|
219
|
+
*/
|
|
220
|
+
this.searchDelay = 100;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Gets or sets the search-box placeholder label.
|
|
224
|
+
* @type {String}
|
|
225
|
+
*/
|
|
226
|
+
this.searchLabel = 'Search';
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Gets or sets the label when no search results are found.
|
|
230
|
+
* @type {String}
|
|
231
|
+
*/
|
|
232
|
+
this.searchNoResultLabel = 'No results found.';
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Gets or sets the category labels for the search-results. Use empty string key for root label.
|
|
236
|
+
* @type {Object}
|
|
237
|
+
*/
|
|
238
|
+
this.searchCategoryLabels = {};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Gets or sets the action of the account button.
|
|
242
|
+
* @type {Function|String}
|
|
243
|
+
*/
|
|
244
|
+
this.accountAction = null;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Gets or sets the account button avatar initials.
|
|
248
|
+
* @type {String}
|
|
249
|
+
*/
|
|
250
|
+
this.avatarInitials = '';
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Gets or sets the account button avatar image path.
|
|
254
|
+
* @type {String}
|
|
255
|
+
*/
|
|
256
|
+
this.avatarImagePath = '';
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Gets or sets the Loading text label.
|
|
260
|
+
* @type {String}
|
|
261
|
+
*/
|
|
262
|
+
this.loadingLabel = 'Loading...';
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Gets or sets the text label of the main category.
|
|
266
|
+
* @type {String}
|
|
267
|
+
*/
|
|
268
|
+
this.mainCategoryLabel = '';
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Gets or sets the username of the authenticated user.
|
|
272
|
+
* @type {String}
|
|
273
|
+
*/
|
|
274
|
+
this.username = 'Not logged in';
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Gets or sets the Username text label.
|
|
278
|
+
* @type {String}
|
|
279
|
+
*/
|
|
280
|
+
this.usernameLabel = 'USERNAME';
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Gets or sets the Password text label.
|
|
284
|
+
* @type {String}
|
|
285
|
+
*/
|
|
286
|
+
this.passwordLabel = 'PASSWORD';
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Gets or sets the RememberMe text label.
|
|
290
|
+
* @type {String}
|
|
291
|
+
*/
|
|
292
|
+
this.rememberMeLabel = 'Remember me';
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Gets or sets the text label of the login button.
|
|
296
|
+
* @type {String}
|
|
297
|
+
*/
|
|
298
|
+
this.loginButtonLabel = 'LOGIN';
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Gets or sets the default label for an authentication failure.
|
|
302
|
+
* @type {String}
|
|
303
|
+
*/
|
|
304
|
+
this.authenticationFailureLabel = 'Authentication failed';
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Gets or sets the labels for the authentication failure reasons.
|
|
308
|
+
* @type {String[]}
|
|
309
|
+
*/
|
|
310
|
+
this.authenticationFailureReasonLabels = [
|
|
311
|
+
'CRSF-Token mismatch.',
|
|
312
|
+
'Maximum sign-in attempts exceeded.',
|
|
313
|
+
'Username and/or parssword is incorrect.',
|
|
314
|
+
'Verification code is incorrect.',
|
|
315
|
+
'The verification code has expired.',
|
|
316
|
+
'Maximum verification attempts exceeded.',
|
|
317
|
+
'Authentication failed.'
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Gets or sets the text label of the login-verification button.
|
|
322
|
+
* @type {String}
|
|
323
|
+
*/
|
|
324
|
+
this.verificationButtonLabel = 'VERIFY';
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Gets or sets the text label of the login verification code.
|
|
328
|
+
* @type {String}
|
|
329
|
+
*/
|
|
330
|
+
this.verificationCodeLabel = 'Verification Code';
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Gets or sets the input field length of the login verification code.
|
|
334
|
+
* @type {Number}
|
|
335
|
+
*/
|
|
336
|
+
this.verificationCodeLength = 6;
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Gets or sets the delay in milliseconds before the app is reloaded when the login verification failed.
|
|
340
|
+
* @type {Number}
|
|
341
|
+
*/
|
|
342
|
+
this.verificationFailedReloadDelay = 5000;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Gets or sets the CRSF Token to send with autorisation POST actions.
|
|
346
|
+
* @type {String|null}
|
|
347
|
+
*/
|
|
348
|
+
this.crsfToken = null;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Gets or sets the list of menu-items.
|
|
352
|
+
* @type {componyx.UI.AppSkin.MenuItem[]}
|
|
353
|
+
*/
|
|
354
|
+
this.menu = [];
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Gets or sets the id of the menu component used as base for the main menu.
|
|
358
|
+
* @type {String|null}
|
|
359
|
+
*/
|
|
360
|
+
this.mainMenuId = null;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Gets or sets the id of the menu component used as base for the header menu.
|
|
364
|
+
* @type {String|null}
|
|
365
|
+
*/
|
|
366
|
+
this.headerMenuId = null;
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Gets or sets the id of the menu component used as base for the footer menu.
|
|
370
|
+
* @type {String|null}
|
|
371
|
+
*/
|
|
372
|
+
this.footerMenuId = null;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Gets or sets the id of the menu component used as base for the quick launch menu.
|
|
376
|
+
* @type {String|null}
|
|
377
|
+
*/
|
|
378
|
+
this.quickLaunchMenuId = null;
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Gets or sets the id of the button component used as base for the menu button.
|
|
382
|
+
* @type {String|null}
|
|
383
|
+
*/
|
|
384
|
+
this.menuButtonId = null;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Gets or sets the id of the button component used as base for the login button.
|
|
388
|
+
* @type {String|null}
|
|
389
|
+
*/
|
|
390
|
+
this.loginButtonId = null;
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Gets or sets the id of the button component used as base for the login-verification button.
|
|
394
|
+
* @type {String|null}
|
|
395
|
+
*/
|
|
396
|
+
this.verificationButtonId = null;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Gets or sets the id of the button component used as base for the account button.
|
|
400
|
+
* @type {String|null}
|
|
401
|
+
*/
|
|
402
|
+
this.accountButtonId = null;
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Gets or sets the id of the form-field component used as base for the username form field.
|
|
406
|
+
* @type {String|null}
|
|
407
|
+
*/
|
|
408
|
+
this.usernameFormFieldId = null;
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Gets or sets the id of the form-field component used as base for the password form field.
|
|
412
|
+
* @type {String|null}
|
|
413
|
+
*/
|
|
414
|
+
this.passwordFormFieldId = null;
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Gets or sets the id of the form-field component used as base for the remember-me form field.
|
|
418
|
+
* @type {String|null}
|
|
419
|
+
*/
|
|
420
|
+
this.rememberMeFormFieldId = null;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Gets or sets the id of the form-field component used as base for the verification code form field.
|
|
424
|
+
* @type {String|null}
|
|
425
|
+
*/
|
|
426
|
+
this.verificationCodeFormFieldId = null;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* @typedef {Object} AuthenticationResponseEventArgs
|
|
430
|
+
* @memberof componyx.UI.AppSkin
|
|
431
|
+
* @property {AuthenticationStateOption} authenticationState - The authentication state.
|
|
432
|
+
* @property {FailureReasonOption} failureReason - The reason why the authentication attempt failed.
|
|
433
|
+
* @property {String} failureMessage - The failure message.
|
|
434
|
+
* @property {Boolean} [cancel=false] - A value indicating if the default action of the AppSkin component should be canceled.
|
|
435
|
+
*/
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @typedef {Object} ResizeActionEventArgs
|
|
439
|
+
* @memberof componyx.UI.AppSkin
|
|
440
|
+
* @property {Boolean} headerOverflow - A value indicating if the content in the header caused an overflow.
|
|
441
|
+
* @property {Boolean} [cancel=false] - A value indicating if the default action of the AppSkin component should be canceled.
|
|
442
|
+
*/
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* @typedef {Object} SearchResultsEventArgs
|
|
446
|
+
* @memberof componyx.UI.AppSkin
|
|
447
|
+
* @property {Array<Object>} data - The search results.
|
|
448
|
+
* @property {HTMLElement} container - The search results container element.
|
|
449
|
+
* @property {Boolean} [cancel=false] - A value indicating if the default action of the AppSkin component should be canceled.
|
|
450
|
+
*/
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* @typedef {Object} SearchResultEventArgs
|
|
454
|
+
* @memberof componyx.UI.AppSkin
|
|
455
|
+
* @property {Array<Object>} data - The search results.
|
|
456
|
+
* @property {HTMLElement} container - The search results container element.
|
|
457
|
+
* @property {HTMLElement} [anchor] - The seach result element.
|
|
458
|
+
* @property {Object} [item] - The seach result item.
|
|
459
|
+
*/
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* @class
|
|
463
|
+
* @augments componyx.UI.base.Events
|
|
464
|
+
* @memberof componyx.UI.AppSkin
|
|
465
|
+
* @property {componyx.UI.base.Event} onShowLogin - Event which fires when the login-screen is shown.
|
|
466
|
+
* @property {componyx.UI.base.Event} onShowLoginVerification - Event which fires when the login-verification-screen is shown.
|
|
467
|
+
* @property {componyx.UI.base.Event} onShowPage - Event which fires when the page-screen is shown.
|
|
468
|
+
* @property {componyx.UI.base.Event} onShowError - Event which fires when the error-screen is shown.
|
|
469
|
+
* @property {componyx.UI.base.Event} onShowMenu - Event which fires when the menu is shown.
|
|
470
|
+
* @property {componyx.UI.base.Event} onHideMenu - Event which fires when the menu is hidden.
|
|
471
|
+
* @property {componyx.UI.base.Event} onLoginAttempt - Event which fires when a login attempt is made. @see {@link componyx.UI.AppSkin.AuthenticationResponseEventArgs}
|
|
472
|
+
* @property {componyx.UI.base.Event} onLoginVerificationAttempt - Event which fires when a login verification attempt is made. @see {@link componyx.UI.AppSkin.AuthenticationResponseEventArgs}
|
|
473
|
+
* @property {componyx.UI.base.Event} onLogout - Event which fires when the user logged out. @see {@link componyx.UI.AppSkin.AuthenticationResponseEventArgs}
|
|
474
|
+
* @property {componyx.UI.base.Event} onPreSearchResults - Event which fires before the search results are rendered. @see {@link componyx.UI.AppSkin.SearchResultsEventArgs}
|
|
475
|
+
* @property {componyx.UI.base.Event} onRenderSearchResult - Event which fires when a search result link is rendered. @see {@link componyx.UI.AppSkin.SearchResultEventArgs}
|
|
476
|
+
* @property {componyx.UI.base.Event} onPostSearchResults - Event which fires after the search results are rendered. @see {@link componyx.UI.AppSkin.SearchResultsEventArgs}
|
|
477
|
+
* @property {componyx.UI.base.Event} onResize - Event which fires when the window is resized. @see {@link componyx.UI.AppSkin.ResizeActionEventArgs}
|
|
478
|
+
* @see {@link componyx.UI.base.Events}
|
|
479
|
+
*/
|
|
480
|
+
function AppSkinEvents(events)
|
|
481
|
+
{
|
|
482
|
+
Object.assign(this, events);
|
|
483
|
+
|
|
484
|
+
this.onShowLogin = $base.static.createEvent('onShowLogin');
|
|
485
|
+
this.onShowLoginVerification = $base.static.createEvent('onShowLoginVerification');
|
|
486
|
+
this.onShowPage = $base.static.createEvent('onShowPage');
|
|
487
|
+
this.onShowError = $base.static.createEvent('onShowError');
|
|
488
|
+
this.onShowMenu = $base.static.createEvent('onShowMenu');
|
|
489
|
+
this.onHideMenu = $base.static.createEvent('onHideMenu');
|
|
490
|
+
this.onLoginAttempt = $base.static.createEvent('onLoginAttempt');
|
|
491
|
+
this.onLoginVerificationAttempt = $base.static.createEvent('onLoginVerificationAttempt');
|
|
492
|
+
this.onLogout = $base.static.createEvent('onLogout');
|
|
493
|
+
this.onPreSearchResults = $base.static.createEvent('onPreSearchResults');
|
|
494
|
+
this.onRenderSearchResult = $base.static.createEvent('onRenderSearchResult');
|
|
495
|
+
this.onPostSearchResults = $base.static.createEvent('onPostSearchResults');
|
|
496
|
+
this.onResize = $base.static.createEvent('onResize');
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* AppSkin events
|
|
500
|
+
* @type {componyx.UI.AppSkin.AppSkinEvents}
|
|
501
|
+
*/
|
|
502
|
+
this.events = new AppSkinEvents(this.events);
|
|
503
|
+
|
|
504
|
+
// inherit base instance members
|
|
505
|
+
$base.Component.apply(this, [id, properties]);
|
|
506
|
+
_classOption = this.classOption;
|
|
507
|
+
|
|
508
|
+
// define ajax methods
|
|
509
|
+
this.ajax.addMethod('authenticate');
|
|
510
|
+
this.ajax.addMethod('search');
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Sets the header template. This template supports the below listed interpolations. Default value: {logo}{quickLaunchMenu}{menuButton}{topbar}{menu}{/topbar}
|
|
514
|
+
* - {topbar} This value will be replaced with the opening topbar element tag.
|
|
515
|
+
* - {/topbar} This value will be replaced with the closing topbar element tag.
|
|
516
|
+
* - {logo} This value will be replaced with the figure element.
|
|
517
|
+
* - {menuButton} This value will be replaced with the menu button.
|
|
518
|
+
* - {accountButton} When authenticated this value will be replaced with the account button otherwise it will open the login screen.
|
|
519
|
+
* - {menu} This value will be replaced with the header menu, containing all menu-items with menuSection set to either MAIN_HEADER or HEADER.
|
|
520
|
+
* - {quickLaunchMenu} This value will be replaced with the quick-launch menu, containing all menu-items with menuSection set to QUICKLAUNCH
|
|
521
|
+
* - {username} This value will be replaced with the username of the logged in user.
|
|
522
|
+
* - {searchBox} This value will be replaced with the search-box.
|
|
523
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
524
|
+
*/
|
|
525
|
+
this.setHeaderTemplate = function (content)
|
|
526
|
+
{
|
|
527
|
+
_instance.addTemplate('Header', content, false);
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Sets the footer template. This template supports the below listed interpolations. Default value: {menu}{username}{loginButton}
|
|
532
|
+
* - {logo} This value will be replaced with the figure element.
|
|
533
|
+
* - {accountButton} When authenticated this value will be replaced with the account button otherwise it will open the login screen.
|
|
534
|
+
* - {menu} This value will be replaced with the footer menu, containing all menu-items with menuSection set to FOOTER.
|
|
535
|
+
* - {quickLaunchMenu} This value will be replaced with the quick-launch menu, containing all menu-items with menuSection set to QUICKLAUNCH
|
|
536
|
+
* - {username} This value will be replaced with the username of the logged in user.
|
|
537
|
+
* - {searchBox} This value will be replaced with the search-box.
|
|
538
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
539
|
+
*/
|
|
540
|
+
this.setFooterTemplate = function (content)
|
|
541
|
+
{
|
|
542
|
+
_instance.addTemplate('Footer', content, false);
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Sets the sidebar template. This template supports the below listed interpolations.
|
|
547
|
+
* - {logo} This value will be replaced with the figure element.
|
|
548
|
+
* - {menuButton} This value will be replaced with the menu button.
|
|
549
|
+
* - {accountButton} When authenticated this value will be replaced with the account button otherwise it will open the login screen.
|
|
550
|
+
* - {quickLaunchMenu} This value will be replaced with the quick-launch menu, containing all menu-items with menuSection set to QUICKLAUNCH
|
|
551
|
+
* - {username} This value will be replaced with the username of the logged in user.
|
|
552
|
+
* - {searchBox} This value will be replaced with the search-box.
|
|
553
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
554
|
+
*/
|
|
555
|
+
this.setSidebarTemplate = function (content)
|
|
556
|
+
{
|
|
557
|
+
_instance.addTemplate('SidebarLeft', content, false);
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Sets the login template. This template supports the below listed interpolations. Default value: {logo}{username}{password}{rememberMe}{loginButton}{failedMessage}
|
|
562
|
+
* - {logo} This value will be replaced with the figure element.
|
|
563
|
+
* - {username} This value will be replaced with the username input field.
|
|
564
|
+
* - {password} This value will be replaced with the password input field.
|
|
565
|
+
* - {rememberMe} This value will be replaced with the remember-me checkbox.
|
|
566
|
+
* - {loginButton} This value will be replaced with the login button.
|
|
567
|
+
* - {failedMessage} This value will be replaced with the message displayed when a login attempt failed.
|
|
568
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
569
|
+
*/
|
|
570
|
+
this.setLoginTemplate = function (content)
|
|
571
|
+
{
|
|
572
|
+
_instance.addTemplate('Login', content, false);
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Sets the login verification template. This template supports the below listed interpolations. Default value: {logo}{verificationCode}{verificationButton}{failedMessage}
|
|
577
|
+
* - {logo} This value will be replaced with the figure element.
|
|
578
|
+
* - {verificationCode} This value will be replaced with the verification-code input field.
|
|
579
|
+
* - {verificationButton} This value will be replaced with the verification button.
|
|
580
|
+
* - {failedMessage} This value will be replaced with the message displayed when a verification attempt failed.
|
|
581
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
582
|
+
*/
|
|
583
|
+
this.setLoginVerificationTemplate = function (content)
|
|
584
|
+
{
|
|
585
|
+
_instance.addTemplate('LoginVerification', content, false);
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Sets the error template. The error template supports the below listed interpolations.
|
|
590
|
+
* - {message} This value will be replaced with the error message.
|
|
591
|
+
* - {timestamp} This value will be replaced with the error timestamp (optional).
|
|
592
|
+
* - {id} This value will be replaced with the error identifier (optional).
|
|
593
|
+
* - {stackTrace} This value will be replaced with the error stack trace (optional).
|
|
594
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
595
|
+
*/
|
|
596
|
+
this.setErrorTemplate = function (content)
|
|
597
|
+
{
|
|
598
|
+
_instance.addTemplate('Error', content, false);
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Sets the not found template, shown when the requested page does not exist: no route matches the URL, or the page request returns 404 or 410. The not found template supports the below listed interpolations.
|
|
603
|
+
* - {status} This value will be replaced with the HTTP status of the page request, when there was one (optional).
|
|
604
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
605
|
+
*/
|
|
606
|
+
this.setNotFoundTemplate = function (content)
|
|
607
|
+
{
|
|
608
|
+
_instance.addTemplate('NotFound', content, false);
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Sets the page header template.
|
|
613
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
614
|
+
*/
|
|
615
|
+
this.setPageHeaderTemplate = function (content)
|
|
616
|
+
{
|
|
617
|
+
_instance.addTemplate('PageHeader', content, false);
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Sets the page footer template.
|
|
622
|
+
* @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The HTML template.
|
|
623
|
+
*/
|
|
624
|
+
this.setPageFooterTemplate = function (content)
|
|
625
|
+
{
|
|
626
|
+
_instance.addTemplate('PageFooter', content, false);
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Sets a value indicating if the app skin utilizes the full width of the screen.
|
|
631
|
+
* @param {Boolean} value A value indicating if the appskin utilizes the full width of the screen.
|
|
632
|
+
*/
|
|
633
|
+
this.setFullscreen = function (value)
|
|
634
|
+
{
|
|
635
|
+
if (value)
|
|
636
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.FULL));
|
|
637
|
+
else
|
|
638
|
+
$lib.removeClass(_instance.element, _instance.getCssClass(_classOption.FULL));
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Sets a value indicating if the page content utilizes the full-screen width when not in full-screen mode.
|
|
643
|
+
* @param {Boolean} value A value indicating if the page content container utilizes the full width of the screen.
|
|
644
|
+
*/
|
|
645
|
+
this.setFullpage = function (value)
|
|
646
|
+
{
|
|
647
|
+
if (value)
|
|
648
|
+
$lib.addClass(_view.firstChild, _instance.getCssClass(_classOption.FULL));
|
|
649
|
+
else
|
|
650
|
+
$lib.removeClass(_view.firstChild, _instance.getCssClass(_classOption.FULL));
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Shows the intial page based upon the defined properties.
|
|
655
|
+
*/
|
|
656
|
+
this.launch = function ()
|
|
657
|
+
{
|
|
658
|
+
launch();
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Updates the menu state to the active route path. The corresponding menu items are selected / expanded based on the menuRoutePathMatching setting.
|
|
663
|
+
* @param {String} routePath The active route path. The route path may end with a page anchor.
|
|
664
|
+
* @param {String} [hashtagRoutes] A value indicating if hashtag routes are used, in other words, the route-path follows the first hashtag.
|
|
665
|
+
*/
|
|
666
|
+
this.updateMenuState = function (routePath, hashtagRoutes)
|
|
667
|
+
{
|
|
668
|
+
updateMenuState(routePath, hashtagRoutes);
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Gets the active screen.
|
|
673
|
+
* @returns {componyx.UI.AppSkin.ScreenOption} The active screen.
|
|
674
|
+
*/
|
|
675
|
+
this.activeScreen = function ()
|
|
676
|
+
{
|
|
677
|
+
return _activeScreen;
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Gets the main menu.
|
|
682
|
+
* @returns {componyx.UI.Menu} The main menu component.
|
|
683
|
+
*/
|
|
684
|
+
this.getMainMenu = function ()
|
|
685
|
+
{
|
|
686
|
+
return _mainMenu;
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Gets the header menu.
|
|
691
|
+
* @returns {componyx.UI.Menu} The header menu component.
|
|
692
|
+
*/
|
|
693
|
+
this.getHeaderMenu = function ()
|
|
694
|
+
{
|
|
695
|
+
return _headerMenu;
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Gets the footer menu.
|
|
700
|
+
* @returns {componyx.UI.Menu} The footer menu component.
|
|
701
|
+
*/
|
|
702
|
+
this.getFooterMenu = function ()
|
|
703
|
+
{
|
|
704
|
+
return _footerMenu;
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Gets the quick-launch menu.
|
|
709
|
+
* @returns {componyx.UI.Menu} The quick-launch menu component.
|
|
710
|
+
*/
|
|
711
|
+
this.getQuickLaunchMenu = function ()
|
|
712
|
+
{
|
|
713
|
+
return _quickLaunchMenu;
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Gets the preloader.
|
|
718
|
+
* @returns {componyx.UI.Box} The preloader box component.
|
|
719
|
+
*/
|
|
720
|
+
this.preloader = function ()
|
|
721
|
+
{
|
|
722
|
+
return _preloader;
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Shows the login page.
|
|
727
|
+
*/
|
|
728
|
+
this.showLogin = function ()
|
|
729
|
+
{
|
|
730
|
+
showLogin();
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Shows the login verification page.
|
|
735
|
+
*/
|
|
736
|
+
this.showLoginVerification = function ()
|
|
737
|
+
{
|
|
738
|
+
showLoginVerification();
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Toggles the display of the main menu.
|
|
743
|
+
*/
|
|
744
|
+
this.toggleMenu = function ()
|
|
745
|
+
{
|
|
746
|
+
toggleMenu();
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Shows the main menu.
|
|
751
|
+
* @param {Boolean} [instant] A value indicating if the menu should be shown instantly without animation. Only applicable for side menu.
|
|
752
|
+
*/
|
|
753
|
+
this.showMenu = function (instant)
|
|
754
|
+
{
|
|
755
|
+
showMenu(instant);
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Hides the main menu.
|
|
760
|
+
* @param {Boolean} [instant] A value indicating if the menu should be shown instantly without animation. Only applicable for side menu.
|
|
761
|
+
*/
|
|
762
|
+
this.hideMenu = function (instant)
|
|
763
|
+
{
|
|
764
|
+
hideMenu(instant);
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Processes the header overflow tasks.
|
|
769
|
+
*/
|
|
770
|
+
this.checkHeaderOverflow = function ()
|
|
771
|
+
{
|
|
772
|
+
checkHeaderOverflow();
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Shows the page.
|
|
777
|
+
* @param {Boolean} hideError Hides the error screen if active.
|
|
778
|
+
*/
|
|
779
|
+
this.showPage = function (hideError)
|
|
780
|
+
{
|
|
781
|
+
if (_launch && _instance.launchMenu && _instance.menuType == _menuTypeOption.PORTALMENU)
|
|
782
|
+
return;
|
|
783
|
+
|
|
784
|
+
let errorShowing = _error.style.display != 'none';
|
|
785
|
+
hideAll();
|
|
786
|
+
updateMenuButtonVisibility();
|
|
787
|
+
_page.style.display = '';
|
|
788
|
+
|
|
789
|
+
if (!errorShowing || hideError)
|
|
790
|
+
{
|
|
791
|
+
$lib.removeClass(_instance.element, _instance.getCssClass(_classOption.ERROR));
|
|
792
|
+
_error.style.display = 'none';
|
|
793
|
+
_view.style.display = '';
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
document.documentElement.style.overflow = "";
|
|
797
|
+
|
|
798
|
+
if (_topbar)
|
|
799
|
+
{
|
|
800
|
+
_topbar.style.display = '';
|
|
801
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.TOPBAR));
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
_instance.events.onShowPage.fire(_instance);
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Checks if the error screen is active.
|
|
809
|
+
* @returns {Boolean} A value indicating if an error occurred.
|
|
810
|
+
*/
|
|
811
|
+
this.hasError = function ()
|
|
812
|
+
{
|
|
813
|
+
return (_error.style.display != 'none');
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Initiates a search request.
|
|
818
|
+
* @param {String} terms The search terms.
|
|
819
|
+
*/
|
|
820
|
+
this.search = function (terms)
|
|
821
|
+
{
|
|
822
|
+
search(terms);
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Log's the user in.
|
|
827
|
+
* @param {Object} [settings] The login settings to send to the authentication handler. By default input values (string username, string password, boolean persistent) from the login-screen are sent to the authentication handler.
|
|
828
|
+
*/
|
|
829
|
+
this.login = function (settings)
|
|
830
|
+
{
|
|
831
|
+
login(settings);
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Verifies the login verification code.
|
|
836
|
+
* @param {Object} [settings] The login settings to send to the authentication handler. By default the input value (string verificationCode) from the login-verification-screen is sent to the authentication handler.
|
|
837
|
+
*/
|
|
838
|
+
this.verifyCode = function (settings)
|
|
839
|
+
{
|
|
840
|
+
verifyCode(settings);
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Log's the user out.
|
|
845
|
+
* @param {Object} [settings] The logout settings to send to the authentication handler. By default boolean logout:true is sent to the authentication handler.
|
|
846
|
+
*/
|
|
847
|
+
this.logout = function (settings)
|
|
848
|
+
{
|
|
849
|
+
logout(settings);
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Renders the component
|
|
854
|
+
*/
|
|
855
|
+
this.render = async function ()
|
|
856
|
+
{
|
|
857
|
+
if (_instance.renderState != $base.static.RenderState.RENDERING)
|
|
858
|
+
{
|
|
859
|
+
// call base render and return
|
|
860
|
+
$base.methods.render.call(_instance, preRender, 'app-skin');
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
if (componyx.UI.menu_modules)
|
|
865
|
+
await componyx.UI.menu_modules.loaded; // we wait before the menu and it's modules are loaded
|
|
866
|
+
|
|
867
|
+
// render logic after loading resources
|
|
868
|
+
if (!_instance.hasTemplate('Header'))
|
|
869
|
+
_instance.addTemplate('Header', '{logo}{quickLaunchMenu}{searchBox}{menuButton}{topbar}{menu}{/topbar}', false);
|
|
870
|
+
|
|
871
|
+
if (!_instance.hasTemplate('Footer'))
|
|
872
|
+
_instance.addTemplate('Footer', '{menu}{username}{accountButton}', false);
|
|
873
|
+
|
|
874
|
+
if (!_instance.hasTemplate('Login'))
|
|
875
|
+
_instance.addTemplate('Login', '{logo}{username}{password}{rememberMe}{loginButton}{failedMessage}', false);
|
|
876
|
+
|
|
877
|
+
if (!_instance.hasTemplate('LoginVerification'))
|
|
878
|
+
_instance.addTemplate('LoginVerification', '{logo}{verificationCode}{verificationButton}{failedMessage}', false);
|
|
879
|
+
|
|
880
|
+
if (!_instance.hasTemplate('Error'))
|
|
881
|
+
_instance.addTemplate('Error', '<p><b>Description:</b> {message}</p><p><b>Status:</b> {status}</p><p><b>Timestamp:</b> {timestamp}</p><p><b>Log Id:</b> {id}</p>', false);
|
|
882
|
+
|
|
883
|
+
if (!_instance.hasTemplate('NotFound'))
|
|
884
|
+
_instance.addTemplate('NotFound', '<p>The page you are looking for does not exist.</p>', false);
|
|
885
|
+
|
|
886
|
+
draw();
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* Handles the post render procedure.
|
|
891
|
+
*/
|
|
892
|
+
this.postRender = function ()
|
|
893
|
+
{
|
|
894
|
+
if (_instance.renderState != $base.static.RenderState.RENDERING) // extra safety to never execute a postRender when the component state is incorrect
|
|
895
|
+
return;
|
|
896
|
+
|
|
897
|
+
postRender();
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Destroys the component.
|
|
902
|
+
* @see {@link componyx.UI.base.methods#destroy}
|
|
903
|
+
*/
|
|
904
|
+
this.destroy = function (...args)
|
|
905
|
+
{
|
|
906
|
+
dispose();
|
|
907
|
+
$base.methods.destroy.call(this, ...args);
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
function preRender()
|
|
911
|
+
{
|
|
912
|
+
// initialize script and css
|
|
913
|
+
return ['AppSkin', ['Button', 'FormField', 'Box', 'Menu']];
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
async function postRender()
|
|
917
|
+
{
|
|
918
|
+
if (_instance.useBindary)
|
|
919
|
+
await handleRoutes();
|
|
920
|
+
|
|
921
|
+
if (!_instance.ajax.authenticate.isDefined())
|
|
922
|
+
_instance.ajax.authenticate.url = 'authenticate';
|
|
923
|
+
|
|
924
|
+
if (!_instance.ajax.search.isDefined())
|
|
925
|
+
_instance.ajax.search.url = 'search';
|
|
926
|
+
|
|
927
|
+
_login.style.display = 'none';
|
|
928
|
+
|
|
929
|
+
launch();
|
|
930
|
+
$base.methods.postRender.call(_instance);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
async function handleRoutes()
|
|
934
|
+
{
|
|
935
|
+
await componyx.bindary_modules.loaded; // make sure Bindary is loaded
|
|
936
|
+
|
|
937
|
+
if ($bindary.routes && $bindary.routes.length) // routes are handled by the Bindary framework
|
|
938
|
+
{
|
|
939
|
+
$bindary.onAnchorScroll.add(anchorScroll);
|
|
940
|
+
$bindary.onLoad.add(loadRoute);
|
|
941
|
+
|
|
942
|
+
if ($bindary.linkDispatching && !_instance.events.onRenderSearchResult.has(dispatchLink))
|
|
943
|
+
_instance.events.onRenderSearchResult.priorityAdd(dispatchLink);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
_view.firstChild.setAttribute($bindary.attributePrefix + 'view', '');
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
function loadRoute()
|
|
950
|
+
{
|
|
951
|
+
let routePath = $bindary.routePath,
|
|
952
|
+
anchor = $bindary.getAnchor();
|
|
953
|
+
|
|
954
|
+
if (anchor)
|
|
955
|
+
routePath += '#' + anchor;
|
|
956
|
+
|
|
957
|
+
if ($bindary.prettyURL)
|
|
958
|
+
{
|
|
959
|
+
let baseHref = $bindary.getBaseHref();
|
|
960
|
+
|
|
961
|
+
if (!$lib.isEmpty(baseHref) && $lib.startsWith(routePath, baseHref))
|
|
962
|
+
routePath = routePath.replace(baseHref, '');
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
updateMenuState(routePath, !$bindary.prettyURL);
|
|
966
|
+
_launch = false;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
function dispatchLink(instance, args)
|
|
970
|
+
{
|
|
971
|
+
$bindary.dispatchLink(args.anchor);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
function anchorScroll(el)
|
|
975
|
+
{
|
|
976
|
+
if (!_header)
|
|
977
|
+
return;
|
|
978
|
+
|
|
979
|
+
let height = _header.offsetHeight;
|
|
980
|
+
|
|
981
|
+
if (_topbar)
|
|
982
|
+
height += _topbar.offsetHeight;
|
|
983
|
+
|
|
984
|
+
$lib.scrollTo(el);
|
|
985
|
+
document.documentElement.scrollTop -= height;
|
|
986
|
+
|
|
987
|
+
return false;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
function updateMenuState(routePath, hashtagRoutes)
|
|
991
|
+
{
|
|
992
|
+
let routePathMatching = _instance.menuRoutePathMatching;
|
|
993
|
+
|
|
994
|
+
if (routePathMatching == _routePathMatchingOption.DISABLED)
|
|
995
|
+
return;
|
|
996
|
+
|
|
997
|
+
routePath = routePath.toLowerCase();
|
|
998
|
+
|
|
999
|
+
let anchorlessItem,
|
|
1000
|
+
hasAnchor = routePath.indexOf('#') > -1,
|
|
1001
|
+
anchorlessRoutePath = (hasAnchor) ? routePath.split('#')[0] : null;
|
|
1002
|
+
|
|
1003
|
+
let path = $lib.path(_instance.menu, 'itemList', function (item)
|
|
1004
|
+
{
|
|
1005
|
+
let href = (item.href || '').toLowerCase();
|
|
1006
|
+
|
|
1007
|
+
if ($lib.isEmpty(href))
|
|
1008
|
+
return false;
|
|
1009
|
+
|
|
1010
|
+
// a category whose own href equals a direct child's href should defer to that child, so the more specific item is selected, not the category
|
|
1011
|
+
if (item.itemList && item.itemList.some(child => (child.href || '').toLowerCase() === href))
|
|
1012
|
+
return false;
|
|
1013
|
+
|
|
1014
|
+
if (hashtagRoutes && href.indexOf('#') == 0)
|
|
1015
|
+
{
|
|
1016
|
+
href = href.substr(1);
|
|
1017
|
+
|
|
1018
|
+
if (href.indexOf('!') == 0) // hash-bang
|
|
1019
|
+
href = href.substr(1);
|
|
1020
|
+
|
|
1021
|
+
if ($lib.isEmpty(href))
|
|
1022
|
+
return false;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
if (hasAnchor && anchorlessRoutePath === href.toLowerCase())
|
|
1026
|
+
anchorlessItem = item;
|
|
1027
|
+
|
|
1028
|
+
if (routePathMatching == _routePathMatchingOption.PARTIAL)
|
|
1029
|
+
return (routePath === href || (routePath.indexOf(href) == 0 && '?/'.indexOf(routePath.split(href)[1][0]) > -1));
|
|
1030
|
+
else
|
|
1031
|
+
return (routePath === href);
|
|
1032
|
+
|
|
1033
|
+
}, true);
|
|
1034
|
+
|
|
1035
|
+
if (!path && anchorlessItem)
|
|
1036
|
+
path = $lib.path(_instance.menu, 'itemList', function (item) { return (item === anchorlessItem) }, true); // item was found without anchor
|
|
1037
|
+
|
|
1038
|
+
if (path && !path.item.selected)
|
|
1039
|
+
{
|
|
1040
|
+
let root = path.create().root(), headerPath;
|
|
1041
|
+
|
|
1042
|
+
if (root.item.menuSection == _menuSectionOption.HEADER)
|
|
1043
|
+
{
|
|
1044
|
+
headerPath = (root.item == path.item) ? path.create() : getLastHeaderItem(path.create());
|
|
1045
|
+
|
|
1046
|
+
if (headerPath && !headerPath.item.selected)
|
|
1047
|
+
{
|
|
1048
|
+
let headerItems = buildPath(headerPath.create());
|
|
1049
|
+
if (headerItems?.length)
|
|
1050
|
+
_headerMenu.expand(headerItems, null, false, true);
|
|
1051
|
+
|
|
1052
|
+
_headerMenu.collapseAll(true); // collapse all dynamic positioned item-groups
|
|
1053
|
+
selectItem(_headerMenu, headerPath.item);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
if (!path.item.selected)
|
|
1058
|
+
{
|
|
1059
|
+
if (isSideMenu())
|
|
1060
|
+
{
|
|
1061
|
+
let mainItems = buildPath(path.create(), true);
|
|
1062
|
+
if (mainItems?.length)
|
|
1063
|
+
_mainMenu.expand(mainItems, null, false, true);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
selectItem(_mainMenu, path.item, isSideMenu() && (!$lib.event || $lib.event.type != 'click' || !isMainMenuTarget($lib.event.target)));
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
else if (!path)
|
|
1070
|
+
{
|
|
1071
|
+
deselectItem(_mainMenu);
|
|
1072
|
+
deselectItem(_headerMenu);
|
|
1073
|
+
deselectItem(_footerMenu);
|
|
1074
|
+
deselectItem(_quickLaunchMenu);
|
|
1075
|
+
|
|
1076
|
+
if (_mainMenu)
|
|
1077
|
+
_mainMenu.showCategory(null, false, true); // main category
|
|
1078
|
+
|
|
1079
|
+
checkHeaderOverflow();
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
function deselectItem(menu)
|
|
1084
|
+
{
|
|
1085
|
+
if (menu)
|
|
1086
|
+
menu.deselectItem();
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
function isMainMenuTarget(target)
|
|
1090
|
+
{
|
|
1091
|
+
return ($lib.contains(_mainMenu.element, target));
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
function getLastHeaderItem(path)
|
|
1095
|
+
{
|
|
1096
|
+
let item;
|
|
1097
|
+
|
|
1098
|
+
while (path)
|
|
1099
|
+
{
|
|
1100
|
+
item = path.item;
|
|
1101
|
+
|
|
1102
|
+
if (item.isCategory && !item.categoryInHeader && _headerMenu.loadItem(item.id))
|
|
1103
|
+
return path;
|
|
1104
|
+
|
|
1105
|
+
path = (path.hasParent()) ? path.parent() : null;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
return null;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
function buildPath(path, includeCurrent)
|
|
1112
|
+
{
|
|
1113
|
+
let items = [];
|
|
1114
|
+
|
|
1115
|
+
if (includeCurrent && !$lib.isEmpty(path.children))
|
|
1116
|
+
items.push(path.item.id);
|
|
1117
|
+
|
|
1118
|
+
while (path.hasParent())
|
|
1119
|
+
{
|
|
1120
|
+
items.unshift(path.parent().item.id);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
return items;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
function launch()
|
|
1127
|
+
{
|
|
1128
|
+
_launch = true;
|
|
1129
|
+
hideAll();
|
|
1130
|
+
|
|
1131
|
+
if (_instance.authenticationRequired && !_instance.authenticated)
|
|
1132
|
+
{
|
|
1133
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.REQUIRED));
|
|
1134
|
+
_instance.showLogin();
|
|
1135
|
+
}
|
|
1136
|
+
else if (_instance.launchMenu)
|
|
1137
|
+
showMenu();
|
|
1138
|
+
else
|
|
1139
|
+
_instance.showPage();
|
|
1140
|
+
|
|
1141
|
+
checkHeaderOverflow();
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
function draw()
|
|
1145
|
+
{
|
|
1146
|
+
let el = _instance.element, htmlTag = $lib(null, '', 'html', true);
|
|
1147
|
+
|
|
1148
|
+
_instance.element.classList.forEach(c =>
|
|
1149
|
+
{
|
|
1150
|
+
if (c !== 'app-skin' && c !== 'hidden')
|
|
1151
|
+
htmlTag.classList.add(c);
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1154
|
+
if (_instance.menuLeft)
|
|
1155
|
+
$lib.addClass(el, _instance.getCssClass(_classOption.MENU_LEFT));
|
|
1156
|
+
|
|
1157
|
+
createLayout(el);
|
|
1158
|
+
|
|
1159
|
+
_instance.setFullscreen(_instance.fullscreen);
|
|
1160
|
+
_instance.setFullpage(_instance.fullpage);
|
|
1161
|
+
|
|
1162
|
+
if (_instance.footerDisplay == _footerDisplayOption.PERSISTENT)
|
|
1163
|
+
showFooter();
|
|
1164
|
+
|
|
1165
|
+
bindEvents();
|
|
1166
|
+
bindErrorEvent();
|
|
1167
|
+
_instance.renderChildren();
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
function createPreloader(container)
|
|
1171
|
+
{
|
|
1172
|
+
let div = document.createElement('div'),
|
|
1173
|
+
i = div.appendChild(document.createElement('i')),
|
|
1174
|
+
id = _instance.id + '_preloader', b;
|
|
1175
|
+
|
|
1176
|
+
b = div.appendChild(document.createElement('b'));
|
|
1177
|
+
b.appendChild(document.createTextNode(_instance.loadingLabel));
|
|
1178
|
+
i.className = _instance.getCssClass(_classOption.SPINNER);
|
|
1179
|
+
_preloader = $UI.createComponent(componyx.UI.Box, { id: id, containerElement: container });
|
|
1180
|
+
_instance.store.push(id);
|
|
1181
|
+
|
|
1182
|
+
_preloader.setContentTemplate(div);
|
|
1183
|
+
_preloader.cssClass = `${_instance.getCssClass(_classOption.BOX)} ${_instance.getCssClass(_classOption.PRELOADER)}`;
|
|
1184
|
+
_preloader.showing = false;
|
|
1185
|
+
_preloader.modal = true;
|
|
1186
|
+
_preloader.theme = $base.static.ThemeOption.NONE;
|
|
1187
|
+
_preloader.animation.showType = _preloader.animation.hideType = componyx.UI.Box.AnimationTypeOption.NONE;
|
|
1188
|
+
_preloader.autoPosition = componyx.UI.Box.AutoPositionOption.CENTER;
|
|
1189
|
+
_preloader.events.onPostRender.priorityAdd(function () { _instance.isReady.apply(_instance); }, null);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
function bindEvents()
|
|
1193
|
+
{
|
|
1194
|
+
$lib.on(window, 'resize', resize);
|
|
1195
|
+
$lib.on(document, 'click', hideSearchResult);
|
|
1196
|
+
|
|
1197
|
+
if (isSideMenu())
|
|
1198
|
+
$lib.on(_overlay, 'click', detectMenuToggle);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
function bindErrorEvent()
|
|
1202
|
+
{
|
|
1203
|
+
$lib.httpRequestHandlers.onSuccess.add(function (args)
|
|
1204
|
+
{
|
|
1205
|
+
let contentType = args.xhr.getResponseHeader('content-type'),
|
|
1206
|
+
data = args.data,
|
|
1207
|
+
parse = function (d) { return (typeof d == 'string') ? window.JSON.parse(d) : d };
|
|
1208
|
+
|
|
1209
|
+
if (contentType && contentType.toLowerCase().indexOf('application/json') > -1 && data)
|
|
1210
|
+
{
|
|
1211
|
+
data = parse(data);
|
|
1212
|
+
|
|
1213
|
+
if (data && data.d)
|
|
1214
|
+
data = parse(data.d);
|
|
1215
|
+
|
|
1216
|
+
return error(data);
|
|
1217
|
+
}
|
|
1218
|
+
});
|
|
1219
|
+
|
|
1220
|
+
if (!_instance.useBindary)
|
|
1221
|
+
return;
|
|
1222
|
+
|
|
1223
|
+
componyx.bindary_modules?.loaded.then(() =>
|
|
1224
|
+
{
|
|
1225
|
+
$bindary.onDataError.add(function (data)
|
|
1226
|
+
{
|
|
1227
|
+
return error(data);
|
|
1228
|
+
});
|
|
1229
|
+
|
|
1230
|
+
$bindary.onRouteError.add(function (args)
|
|
1231
|
+
{
|
|
1232
|
+
const notFound = (args.type === 'route' || args.status === 404 || args.status === 410);
|
|
1233
|
+
|
|
1234
|
+
if (notFound && !document.head.querySelector('meta[data-appskin-noindex]')) // avoid soft 404s: tell search engines not to index this result
|
|
1235
|
+
document.head.insertAdjacentHTML('beforeend', '<meta name="robots" content="noindex" data-appskin-noindex>');
|
|
1236
|
+
|
|
1237
|
+
showError({ status: args.status }, notFound ? 'NotFound' : 'Error');
|
|
1238
|
+
});
|
|
1239
|
+
|
|
1240
|
+
$bindary.onPreLoad.add(function () // a new route load starts, so hide a previous error again
|
|
1241
|
+
{
|
|
1242
|
+
_errorData = null;
|
|
1243
|
+
document.head.querySelector('meta[data-appskin-noindex]')?.remove();
|
|
1244
|
+
_instance.showPage(true);
|
|
1245
|
+
});
|
|
1246
|
+
}).catch(console.error);
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
function error(data)
|
|
1250
|
+
{
|
|
1251
|
+
if (!data || !data.isError)
|
|
1252
|
+
{
|
|
1253
|
+
_instance.showPage(true);
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
let errorData = (data.data && data.data.appData) ? data.data.appData : data;
|
|
1258
|
+
|
|
1259
|
+
if (_errorData != errorData)
|
|
1260
|
+
{
|
|
1261
|
+
_errorData = errorData;
|
|
1262
|
+
return showError(errorData);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
function showError(error, templateName = 'Error')
|
|
1267
|
+
{
|
|
1268
|
+
let divMessage,
|
|
1269
|
+
timestamp = error.timestamp;
|
|
1270
|
+
|
|
1271
|
+
if (timestamp && !(timestamp instanceof Date))
|
|
1272
|
+
timestamp = new Date(timestamp);
|
|
1273
|
+
|
|
1274
|
+
_instance.preloader().hide();
|
|
1275
|
+
_instance.showPage();
|
|
1276
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.ERROR));
|
|
1277
|
+
_view.style.display = 'none'; // hide view container
|
|
1278
|
+
|
|
1279
|
+
let el = _error.firstChild;
|
|
1280
|
+
el.innerHTML = '';
|
|
1281
|
+
_error.style.display = '';
|
|
1282
|
+
|
|
1283
|
+
divMessage = createElement(el, 'div');
|
|
1284
|
+
|
|
1285
|
+
_instance.applyTemplate(divMessage, templateName, {
|
|
1286
|
+
timestamp: (timestamp && !isNaN(timestamp)) ? $lib.formatDate(timestamp, 'dd-MM-yyyy HH:mm:ss') : '-',
|
|
1287
|
+
message: error.message || '-',
|
|
1288
|
+
stackTrace: error.stackTrace || '-',
|
|
1289
|
+
id: error.id || '-',
|
|
1290
|
+
status: error.status || '-'
|
|
1291
|
+
});
|
|
1292
|
+
|
|
1293
|
+
_instance.events.onShowError.fire(_instance);
|
|
1294
|
+
|
|
1295
|
+
return false;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
function createLayout(container)
|
|
1299
|
+
{
|
|
1300
|
+
let div = createElement(container, 'div', _instance.getCssClass(_classOption.BODY));
|
|
1301
|
+
|
|
1302
|
+
createMainMenu(container);
|
|
1303
|
+
createHeader(container);
|
|
1304
|
+
createSidebar(container);
|
|
1305
|
+
|
|
1306
|
+
_page = createElement(container, '', _instance.getCssClass(_classOption.PAGE));
|
|
1307
|
+
|
|
1308
|
+
if (_instance.hasTemplate('PageHeader'))
|
|
1309
|
+
{
|
|
1310
|
+
div = createElement(_page, 'header');
|
|
1311
|
+
_instance.applyTemplate(div, 'PageHeader');
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
_error = createElement(_page, '', _instance.getCssClass(_classOption.ERROR), createContent());
|
|
1315
|
+
_error.style.display = 'none';
|
|
1316
|
+
|
|
1317
|
+
_view = createElement(_page, '', _instance.getCssClass(_classOption.VIEW), createContent());
|
|
1318
|
+
|
|
1319
|
+
if (_instance.hasTemplate('PageFooter'))
|
|
1320
|
+
{
|
|
1321
|
+
div = createElement(_page, 'footer');
|
|
1322
|
+
_instance.applyTemplate(div, 'PageFooter');
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
if (_instance.useLoginTemplate)
|
|
1326
|
+
{
|
|
1327
|
+
createLoginScreen(container);
|
|
1328
|
+
createLoginVerificationScreen(container);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
if (_instance.footerDisplay > _footerDisplayOption.DISABLED)
|
|
1332
|
+
createFooter(container);
|
|
1333
|
+
|
|
1334
|
+
_overlay = createElement(container, 'div', _instance.getCssClass(_classOption.OVERLAY));
|
|
1335
|
+
|
|
1336
|
+
if (_instance.authenticated)
|
|
1337
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.AUTHENTICATED));
|
|
1338
|
+
|
|
1339
|
+
createPreloader(container);
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
function createSidebar(container)
|
|
1343
|
+
{
|
|
1344
|
+
let name = 'Sidebar';
|
|
1345
|
+
|
|
1346
|
+
if (!_instance.hasTemplate(name))
|
|
1347
|
+
return;
|
|
1348
|
+
|
|
1349
|
+
let id = $lib.format('{0}_{1}_', _instance.id, name),
|
|
1350
|
+
bar = createElement(container, '', _instance.getCssClass(_classOption.SIDEBAR), content);
|
|
1351
|
+
|
|
1352
|
+
_instance.applyTemplate(bar, name, getinterpolations(id));
|
|
1353
|
+
replacePlaceHolders(id);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
function createHeader(container)
|
|
1357
|
+
{
|
|
1358
|
+
let id = _instance.id + '_Header_', el;
|
|
1359
|
+
|
|
1360
|
+
_header = createElement(container, 'header'); // create header
|
|
1361
|
+
_instance.applyTemplate(_header, 'Header', getinterpolations(id));
|
|
1362
|
+
_header.appendChild(createContent($lib.extract(_header)));
|
|
1363
|
+
|
|
1364
|
+
_topbar = $lib('#' + id + 'TopBar');
|
|
1365
|
+
|
|
1366
|
+
if (_topbar)
|
|
1367
|
+
{
|
|
1368
|
+
_topbar.appendChild(createContent($lib.extract(_topbar)));
|
|
1369
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.TOPBAR));
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
if ((el = $lib('#' + id + 'Menu')) && hasMenu(_menuSectionOption.HEADER))
|
|
1373
|
+
_headerMenu = createMenu(el.parentNode, el.id, _instance.headerMenuId, _menuSectionOption.HEADER, getHeaderProps());
|
|
1374
|
+
|
|
1375
|
+
replacePlaceHolders(id);
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
function createFooter(container)
|
|
1379
|
+
{
|
|
1380
|
+
let id = _instance.id + '_Footer_', el;
|
|
1381
|
+
|
|
1382
|
+
_footer = createElement(container, 'footer'); // create footer
|
|
1383
|
+
_instance.applyTemplate(_footer, 'Footer', getinterpolations(id));
|
|
1384
|
+
_footer.appendChild(createContent($lib.extract(_footer)));
|
|
1385
|
+
|
|
1386
|
+
if ((el = $lib('#' + id + 'Menu')) && hasMenu(_menuSectionOption.FOOTER))
|
|
1387
|
+
_footerMenu = createMenu(el.parentNode, el.id, _instance.headerMenuId, _menuSectionOption.FOOTER, getFooterProps());
|
|
1388
|
+
|
|
1389
|
+
replacePlaceHolders(id);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
function replacePlaceHolders(id)
|
|
1393
|
+
{
|
|
1394
|
+
let el;
|
|
1395
|
+
|
|
1396
|
+
if ((el = $lib('#' + id + 'QuickLaunchMenu')) && hasMenu(_menuSectionOption.QUICKLAUNCH))
|
|
1397
|
+
_quickLaunchMenu = createMenu(el.parentNode, el.id, _instance.quickLaunchMenuId, _menuSectionOption.QUICKLAUNCH, getQuickLaunchProps());
|
|
1398
|
+
|
|
1399
|
+
if (el = $lib('#' + id + 'SearchBox'))
|
|
1400
|
+
_searchBox = createSearchBox(el);
|
|
1401
|
+
|
|
1402
|
+
if (el = $lib('#' + id + 'Username'))
|
|
1403
|
+
el.innerHTML = _instance.username;
|
|
1404
|
+
|
|
1405
|
+
createMenuButton($lib('#' + id + 'MenuButton'));
|
|
1406
|
+
createAccountButton($lib('#' + id + 'AccountButton'));
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
function hasMenu(menuSection)
|
|
1410
|
+
{
|
|
1411
|
+
let hasMenu = false;
|
|
1412
|
+
|
|
1413
|
+
$lib.each(_instance.menu, function (item)
|
|
1414
|
+
{
|
|
1415
|
+
if (item.menuSection === menuSection)
|
|
1416
|
+
return !(hasMenu = true); // stop iteration
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
return hasMenu;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
function createContent(content)
|
|
1423
|
+
{
|
|
1424
|
+
return createElement(null, '', _instance.getCssClass(_classOption.APP_CONTENT), content);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
function joinCssClasses(...classes)
|
|
1428
|
+
{
|
|
1429
|
+
return classes.filter(c => !$lib.isEmpty(c)).join(' ').replace(/\s+/g, ' ').trim();
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
function createElement(container, tagName, cssClass, content)
|
|
1433
|
+
{
|
|
1434
|
+
return $lib.element(container, '', tagName, content, (cssClass) ? { "class": cssClass } : null);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
function createSearchBox(placeHolder)
|
|
1438
|
+
{
|
|
1439
|
+
let div = createElement(null, 'div', _instance.getCssClass(_classOption.SEARCH)),
|
|
1440
|
+
input = createElement(div, 'input');
|
|
1441
|
+
placeHolder.parentNode.replaceChild(div, placeHolder);
|
|
1442
|
+
|
|
1443
|
+
div.setAttribute('tabindex', '0');
|
|
1444
|
+
input.placeholder = _instance.searchLabel;
|
|
1445
|
+
|
|
1446
|
+
$lib.on(div, 'focus', function ()
|
|
1447
|
+
{
|
|
1448
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.SEARCH_ACTIVE));
|
|
1449
|
+
input.focus();
|
|
1450
|
+
});
|
|
1451
|
+
$lib.on(input, 'blur', function ()
|
|
1452
|
+
{
|
|
1453
|
+
$lib.removeClass(_instance.element, _instance.getCssClass(_classOption.SEARCH_ACTIVE));
|
|
1454
|
+
});
|
|
1455
|
+
|
|
1456
|
+
$lib.on(input, 'keyup paste', function ()
|
|
1457
|
+
{
|
|
1458
|
+
clearTimeout(_searchTimerId);
|
|
1459
|
+
_searchTimerId = setTimeout(search, _instance.searchDelay);
|
|
1460
|
+
});
|
|
1461
|
+
$lib.on(input, 'focus', function ()
|
|
1462
|
+
{
|
|
1463
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.SEARCH_ACTIVE));
|
|
1464
|
+
|
|
1465
|
+
if (_searchResult && !$lib.isEmpty(_searchBox.value))
|
|
1466
|
+
_searchResult.style.display = '';
|
|
1467
|
+
});
|
|
1468
|
+
|
|
1469
|
+
return input;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
function createMenuButton(placeHolder)
|
|
1473
|
+
{
|
|
1474
|
+
if (!placeHolder)
|
|
1475
|
+
return;
|
|
1476
|
+
|
|
1477
|
+
_menuButton = createButton(placeHolder.parentNode, placeHolder.id, _instance.menuButtonId, { cssClass: _instance.getCssClass(_classOption.MENU_BUTTON), cssClassIcon: _instance.getCssClass(_classOption.ICON_MENU) }, function (button, args)
|
|
1478
|
+
{
|
|
1479
|
+
toggleMenu();
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
function createAccountButton(placeHolder)
|
|
1484
|
+
{
|
|
1485
|
+
if (!placeHolder)
|
|
1486
|
+
return;
|
|
1487
|
+
|
|
1488
|
+
let authenticated = _instance.authenticated,
|
|
1489
|
+
action = $base.static.getMethod(_instance.accountAction),
|
|
1490
|
+
item = {};
|
|
1491
|
+
|
|
1492
|
+
if (!action)
|
|
1493
|
+
action = (authenticated) ? _instance.showLogin : _instance.logout;
|
|
1494
|
+
|
|
1495
|
+
item.cssClass = _instance.getCssClass(_classOption.ACCOUNT);
|
|
1496
|
+
|
|
1497
|
+
if (authenticated && _instance.accountButtonAvatar)
|
|
1498
|
+
{
|
|
1499
|
+
item.cssClass = _instance.getCssClass(_classOption.ACCOUNT_AVATAR);
|
|
1500
|
+
_instance.element.style.setProperty("--avatar-initials", `'${_instance.avatarInitials}'`);
|
|
1501
|
+
}
|
|
1502
|
+
else if (authenticated)
|
|
1503
|
+
item.cssClassIcon = _instance.getCssClass(_classOption.ICON_USER);
|
|
1504
|
+
else
|
|
1505
|
+
{
|
|
1506
|
+
item.cssClassIcon = _instance.getCssClass(_classOption.ICON_LOCK);
|
|
1507
|
+
action = _instance.showLogin;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
createButton(placeHolder.parentNode, placeHolder.id, _instance.accountButtonId, item, action);
|
|
1511
|
+
|
|
1512
|
+
if (_instance.avatarImagePath)
|
|
1513
|
+
_instance.element.style.setProperty("--avatar-image", `url('${_instance.avatarImagePath}')`);
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
function createMainMenu(container)
|
|
1517
|
+
{
|
|
1518
|
+
let id = _instance.id + '_MainMenu';
|
|
1519
|
+
|
|
1520
|
+
if (isSideMenu())
|
|
1521
|
+
container = createSideMenuBox(container);
|
|
1522
|
+
|
|
1523
|
+
_mainMenu = createMenu(container, id, _instance.mainMenuId, _menuSectionOption.MAIN, getMainMenuProps());
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
function createMenu(container, id, cloneId, section, properties)
|
|
1527
|
+
{
|
|
1528
|
+
if (!container || !_instance.menu.length)
|
|
1529
|
+
return;
|
|
1530
|
+
|
|
1531
|
+
if (!properties)
|
|
1532
|
+
properties = {};
|
|
1533
|
+
|
|
1534
|
+
properties.id = id;
|
|
1535
|
+
properties.containerElement = container;
|
|
1536
|
+
|
|
1537
|
+
let menu = $UI.createComponent(componyx.UI.Menu, properties),
|
|
1538
|
+
groupSettings;
|
|
1539
|
+
|
|
1540
|
+
menu.clone($UI.store[cloneId], _instance);
|
|
1541
|
+
menu.templates = getMenuItemTemplates();
|
|
1542
|
+
menu.mainCategoryLabel = _instance.mainCategoryLabel;
|
|
1543
|
+
menu.events.onPostRender.priorityAdd(function () { _instance.isReady.apply(_instance); }, null);
|
|
1544
|
+
menu.showing = ((section == _menuSectionOption.MAIN && isSideMenu()) || section == _menuSectionOption.HEADER || section >= _menuSectionOption.FOOTER);
|
|
1545
|
+
|
|
1546
|
+
if (section == _menuSectionOption.HEADER)
|
|
1547
|
+
menu.itemGroupBoxId = createHeaderItemGroupBox(); // default root item-group box for the header menu
|
|
1548
|
+
|
|
1549
|
+
if (section == _menuSectionOption.MAIN)
|
|
1550
|
+
menu.events.onHide.priorityAdd(function () { $lib.removeClass(_instance.element, _instance.getCssClass(_classOption.PORTAL_MENU)); });
|
|
1551
|
+
|
|
1552
|
+
$lib.each(_instance.menu, function (item, index)
|
|
1553
|
+
{
|
|
1554
|
+
if (item.menuSection == section || (section == _menuSectionOption.MAIN && item.menuSection == _menuSectionOption.HEADER))
|
|
1555
|
+
{
|
|
1556
|
+
item.id = item.id || $lib.guid();
|
|
1557
|
+
|
|
1558
|
+
if (section == _menuSectionOption.HEADER)
|
|
1559
|
+
item = copyItem(item); // copy header menu-item
|
|
1560
|
+
|
|
1561
|
+
if (section == _menuSectionOption.HEADER
|
|
1562
|
+
|| (section == _menuSectionOption.MAIN && item.menuSection == _menuSectionOption.HEADER)
|
|
1563
|
+
|| (section == _menuSectionOption.MAIN && _instance.menuType == _menuTypeOption.PORTALMENU))
|
|
1564
|
+
{
|
|
1565
|
+
if (!item.selectable && !item.command && !item.href)
|
|
1566
|
+
item.cssClass = joinCssClasses(item.cssClass, _instance.getCssClass(_classOption.NO_ACTION));
|
|
1567
|
+
|
|
1568
|
+
// menu-item is in both header and main navigation
|
|
1569
|
+
if (item.__command === undefined)
|
|
1570
|
+
{
|
|
1571
|
+
item.__command = item.command || null;
|
|
1572
|
+
item.command = defaultCommand;
|
|
1573
|
+
}
|
|
1574
|
+
else
|
|
1575
|
+
item.command = defaultCommand;
|
|
1576
|
+
|
|
1577
|
+
if (item.itemList)
|
|
1578
|
+
setCommands(item.itemList);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
if (section == _menuSectionOption.MAIN && item.menuSection == _menuSectionOption.MAIN)
|
|
1582
|
+
_allInHeader = false;
|
|
1583
|
+
|
|
1584
|
+
if (section == _menuSectionOption.MAIN && _instance.menuType == _menuTypeOption.PORTALMENU)
|
|
1585
|
+
{
|
|
1586
|
+
groupSettings = createPortalItem(item, index, groupSettings);
|
|
1587
|
+
|
|
1588
|
+
if (item.isCategory)
|
|
1589
|
+
createPortalItems(item.itemList);
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
menu.itemList.push(item);
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1595
|
+
|
|
1596
|
+
return menu;
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
function copyItem(cloneItem)
|
|
1600
|
+
{
|
|
1601
|
+
let item = new componyx.UI.AppSkin.MenuItem(cloneItem);
|
|
1602
|
+
|
|
1603
|
+
item.selectable = true;
|
|
1604
|
+
item.command = item.__command;
|
|
1605
|
+
item.subGroupId = null;
|
|
1606
|
+
|
|
1607
|
+
if (item.__cssClass != undefined)
|
|
1608
|
+
item.cssClass = item.__cssClass;
|
|
1609
|
+
|
|
1610
|
+
if (item.isCategory && !item.categoryInHeader)
|
|
1611
|
+
{
|
|
1612
|
+
item.isCategory = false;
|
|
1613
|
+
item.itemList = [];
|
|
1614
|
+
return item;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
$lib.each(cloneItem.itemList, function (childItem, index)
|
|
1618
|
+
{
|
|
1619
|
+
item.itemList[index] = copyItem(childItem);
|
|
1620
|
+
});
|
|
1621
|
+
|
|
1622
|
+
return item;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
function createPortalItems(itemList)
|
|
1626
|
+
{
|
|
1627
|
+
let groupSettings;
|
|
1628
|
+
|
|
1629
|
+
$lib.each(itemList, function (item, index)
|
|
1630
|
+
{
|
|
1631
|
+
groupSettings = createPortalItem(item, index, groupSettings);
|
|
1632
|
+
|
|
1633
|
+
if (item.isCategory)
|
|
1634
|
+
createPortalItem(item.itemList);
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
function createPortalItem(item, index, groupSettings)
|
|
1639
|
+
{
|
|
1640
|
+
let cssStyles = ['1', '2', '3', '4'], cssStyle;
|
|
1641
|
+
|
|
1642
|
+
item.cssClass = item.cssClass || '';
|
|
1643
|
+
item.__cssClass = item.cssClass;
|
|
1644
|
+
|
|
1645
|
+
if (!item.groupTileSize)
|
|
1646
|
+
item.groupTileSize = null;
|
|
1647
|
+
|
|
1648
|
+
if (!groupSettings || (!$lib.isEmpty(item.groupTileSize) && item.groupTileSize != groupSettings.groupTileSize))
|
|
1649
|
+
{
|
|
1650
|
+
groupSettings = {};
|
|
1651
|
+
groupSettings.tileSize = 0;
|
|
1652
|
+
groupSettings.id = $lib.guid();
|
|
1653
|
+
groupSettings.groupTileSize = (item.groupTileSize) ? item.groupTileSize : (item.buttonTileSize <= _tileSizeOption.MEDIUM) ? _tileSizeOption.MEDIUM : _tileSizeOption.LARGE;
|
|
1654
|
+
item.cssClassSubGroup = joinCssClasses(_instance.getCssClass(_classOption.SUB_GROUP), _tileSizeOption.getName(groupSettings.groupTileSize).replace('_', '-'));
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
item.subGroupId = groupSettings.id; // item will be appended to the group container element
|
|
1658
|
+
item.buttonTileSize = item.buttonTileSize || _tileSizeOption.MEDIUM;
|
|
1659
|
+
item.cssClass = joinCssClasses(item.cssClass, _tileSizeOption.getName(item.buttonTileSize).replace('_', '-'));
|
|
1660
|
+
|
|
1661
|
+
cssStyle = cssStyles[(index % 4)];
|
|
1662
|
+
|
|
1663
|
+
if (cssStyle)
|
|
1664
|
+
item.cssClass = joinCssClasses(item.cssClass, _instance.getCssClass(_classOption.SHADE) + '-' + cssStyle);
|
|
1665
|
+
|
|
1666
|
+
if ((index % 4) == 3)
|
|
1667
|
+
cssStyles.reverse();
|
|
1668
|
+
|
|
1669
|
+
if (groupSettings.groupTileSize == _tileSizeOption.LARGE && item.buttonTileSize <= _tileSizeOption.SMALL_WIDE && (groupSettings.tileSize == 2 || groupSettings.tileSize == 10))
|
|
1670
|
+
item.cssClass = joinCssClasses(item.cssClass, _instance.getCssClass(_classOption.ROW_START));
|
|
1671
|
+
|
|
1672
|
+
groupSettings.tileSize += item.buttonTileSize;
|
|
1673
|
+
|
|
1674
|
+
if (groupSettings.tileSize >= groupSettings.groupTileSize)
|
|
1675
|
+
groupSettings = null; // group is filled
|
|
1676
|
+
|
|
1677
|
+
return groupSettings;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
function getMenuItemTemplates()
|
|
1681
|
+
{
|
|
1682
|
+
let templates = new Map(),
|
|
1683
|
+
reserved = 'Header Footer Login Error PageHeader PageFooter';
|
|
1684
|
+
|
|
1685
|
+
if (_instance.templates.size)
|
|
1686
|
+
{
|
|
1687
|
+
_instance.templates.forEach(function (template, id)
|
|
1688
|
+
{
|
|
1689
|
+
if (reserved.indexOf(id) == -1)
|
|
1690
|
+
templates.set(id, template);
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
return templates;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
function setCommands(itemList)
|
|
1698
|
+
{
|
|
1699
|
+
$lib.each(itemList, function (item, index)
|
|
1700
|
+
{
|
|
1701
|
+
item.id = item.id || $lib.guid();
|
|
1702
|
+
|
|
1703
|
+
if (!item.selectable && !item.command && !item.href)
|
|
1704
|
+
item.cssClass = joinCssClasses(item.cssClass, _instance.getCssClass(_classOption.NO_ACTION));
|
|
1705
|
+
|
|
1706
|
+
if (item.__command === undefined)
|
|
1707
|
+
{
|
|
1708
|
+
item.__command = item.command || null;
|
|
1709
|
+
item.command = defaultCommand;
|
|
1710
|
+
}
|
|
1711
|
+
else
|
|
1712
|
+
item.command = defaultCommand;
|
|
1713
|
+
|
|
1714
|
+
if (item.itemList)
|
|
1715
|
+
setCommands(item.itemList);
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
function defaultCommand(sender, args)
|
|
1720
|
+
{
|
|
1721
|
+
let isMain = (sender === _mainMenu),
|
|
1722
|
+
menu = (isMain) ? _headerMenu : _mainMenu;
|
|
1723
|
+
|
|
1724
|
+
if (isMain && args && args.event && args.event.type == 'click' && !args.item.isCategory && args.item.selectable && $lib.styleValue(_overlay, 'display', true) != 'none') // menu is in overlay-mode (small template)
|
|
1725
|
+
hideMenu();
|
|
1726
|
+
|
|
1727
|
+
if (!menu) // no header menu, handle portal-type case directly
|
|
1728
|
+
{
|
|
1729
|
+
if (_instance.menuType === _menuTypeOption.PORTALMENU)
|
|
1730
|
+
{
|
|
1731
|
+
let portalItemPath = _mainMenu.loadItem(args.item.id),
|
|
1732
|
+
portalItem = portalItemPath?.item;
|
|
1733
|
+
|
|
1734
|
+
if (!portalItem)
|
|
1735
|
+
return;
|
|
1736
|
+
|
|
1737
|
+
executeCommand(_mainMenu, portalItem);
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
let itemPath = menu.loadItem(args.item.id),
|
|
1744
|
+
item = itemPath?.item;
|
|
1745
|
+
|
|
1746
|
+
if (!item)
|
|
1747
|
+
{
|
|
1748
|
+
// item only exists in the main menu (e.g. child of a category not shown in the header): fire its original command
|
|
1749
|
+
if (isMain && args.item.__command)
|
|
1750
|
+
{
|
|
1751
|
+
let fn = $base.static.getMethod(args.item.__command);
|
|
1752
|
+
|
|
1753
|
+
if (fn)
|
|
1754
|
+
fn(sender, args);
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
executeCommand(menu, item);
|
|
1761
|
+
|
|
1762
|
+
if (!isMain)
|
|
1763
|
+
{
|
|
1764
|
+
if (item.isCategory) // header opens category in main-menu
|
|
1765
|
+
{
|
|
1766
|
+
_mainMenu.showCategory(item.id, false, !menuIsShowing());
|
|
1767
|
+
|
|
1768
|
+
if (!menuIsShowing())
|
|
1769
|
+
showMenu();
|
|
1770
|
+
|
|
1771
|
+
checkHeaderOverflow();
|
|
1772
|
+
}
|
|
1773
|
+
else if (menuIsShowing())
|
|
1774
|
+
{
|
|
1775
|
+
hideMenu(false, showMainCategory);
|
|
1776
|
+
}
|
|
1777
|
+
else
|
|
1778
|
+
{
|
|
1779
|
+
showMainCategory();
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
function executeCommand(menu, item)
|
|
1785
|
+
{
|
|
1786
|
+
item.command = item.__command; // original command
|
|
1787
|
+
selectItem(menu, item); // fire original command and set selected state
|
|
1788
|
+
item.command = defaultCommand; // reset command back to default
|
|
1789
|
+
|
|
1790
|
+
if (item.href && (_instance.menuType == _menuTypeOption.PORTALMENU || _error.style.display != 'none'))
|
|
1791
|
+
_instance.showPage(true);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
function showMainCategory()
|
|
1795
|
+
{
|
|
1796
|
+
_mainMenu.showCategory(null, false, true);
|
|
1797
|
+
checkHeaderOverflow();
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
function setHideMenuCallback(fn)
|
|
1801
|
+
{
|
|
1802
|
+
if (isSideMenu())
|
|
1803
|
+
_sideMenuBox.events.onHideComplete.priorityAdd(fn, null, true);
|
|
1804
|
+
else
|
|
1805
|
+
_mainMenu.events.onHide.priorityAdd(fn, null, true);
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
function selectItem(menu, item, scroll)
|
|
1809
|
+
{
|
|
1810
|
+
let href;
|
|
1811
|
+
|
|
1812
|
+
href = item.href || null;
|
|
1813
|
+
item.href = null; // item was matched on current routePath, there is no reason to re-set URL and re-setting can cause issues when there is a routePath and an anchor in the current URL
|
|
1814
|
+
|
|
1815
|
+
menu.selectItem(item.id);
|
|
1816
|
+
|
|
1817
|
+
if (href != undefined)
|
|
1818
|
+
item.href = href;
|
|
1819
|
+
|
|
1820
|
+
if (scroll)
|
|
1821
|
+
setTimeout($lib.scrollTo.bind(this, $UI.store[menu.id + '_' + item.id].element, _sideMenuBox.element), 0);
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
function createButton(container, id, cloneId, item, command)
|
|
1825
|
+
{
|
|
1826
|
+
let button = $UI.createComponent(componyx.UI.Button, { id: id, containerElement: container }), b;
|
|
1827
|
+
|
|
1828
|
+
button.clone($UI.store[cloneId], _instance);
|
|
1829
|
+
button.renderId = false;
|
|
1830
|
+
button.transparent = ($lib.isEmpty(item.transparent)) ? true : item.transparent;
|
|
1831
|
+
button.cssClass = joinCssClasses(_instance.getCssClass(_classOption.BUTTON), item.cssClass);
|
|
1832
|
+
button.cssClassIcon = ($lib.isEmpty(item.cssClassIcon)) ? '' : item.cssClassIcon;
|
|
1833
|
+
button.hasIcon = !$lib.isEmpty(item.cssClassIcon);
|
|
1834
|
+
button.command = (button.command) ? button.command : command;
|
|
1835
|
+
button.events.onPostRender.priorityAdd(function () { _instance.isReady.apply(_instance); }, null);
|
|
1836
|
+
button.showing = true;
|
|
1837
|
+
|
|
1838
|
+
if (!($lib.isEmpty(item.text)))
|
|
1839
|
+
{
|
|
1840
|
+
b = document.createElement('b');
|
|
1841
|
+
$lib.setText(b, item.text);
|
|
1842
|
+
button.text = b.outerHTML;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
return button;
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
function createSideMenuBox(container)
|
|
1849
|
+
{
|
|
1850
|
+
let id = _instance.id + '_SideMenuBox',
|
|
1851
|
+
cloneId = _instance.sideMenuBoxId,
|
|
1852
|
+
box = $UI.createComponent(componyx.UI.Box, { id: id, containerElement: container });
|
|
1853
|
+
|
|
1854
|
+
box.clone($UI.store[cloneId], _instance);
|
|
1855
|
+
box.theme = $base.static.ThemeOption.NONE;
|
|
1856
|
+
box.cssClass = `${_instance.getCssClass(_classOption.BOX)} ${_instance.getCssClass(_classOption.SIDE_MENU)}`;
|
|
1857
|
+
box.animation.showType = box.animation.hideType = 3;
|
|
1858
|
+
box.autoPosition = 0;
|
|
1859
|
+
box.autoFit = false;
|
|
1860
|
+
box.events.onHideComplete.priorityAdd(function () { $lib.removeClass(_instance.element, _instance.getCssClass(_classOption.SIDE_MENU)); });
|
|
1861
|
+
box.render(); // instant because there are no dependencies
|
|
1862
|
+
|
|
1863
|
+
_sideMenuBox = box;
|
|
1864
|
+
|
|
1865
|
+
return box.contentElement;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
function createHeaderItemGroupBox()
|
|
1869
|
+
{
|
|
1870
|
+
let id = _instance.id + '_HeaderMenuBox',
|
|
1871
|
+
box = $UI.createComponent(componyx.UI.Box, { id: id, containerElement: null });
|
|
1872
|
+
box.alignX = componyx.UI.Box.AlignXOption.CENTER;
|
|
1873
|
+
return box.id;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
function getHeaderProps()
|
|
1877
|
+
{
|
|
1878
|
+
let props = {};
|
|
1879
|
+
|
|
1880
|
+
props.cssClass = `${_instance.getCssClass(_classOption.MENU)} ${_instance.getCssClass(_classOption.HEADER_MENU)}`;
|
|
1881
|
+
return props;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
function getQuickLaunchProps()
|
|
1885
|
+
{
|
|
1886
|
+
let props = {};
|
|
1887
|
+
|
|
1888
|
+
props.cssClass = `${_instance.getCssClass(_classOption.MENU)} ${_instance.getCssClass(_classOption.QUICK_LAUNCH)}`;
|
|
1889
|
+
return props;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
function getFooterProps()
|
|
1893
|
+
{
|
|
1894
|
+
let props = {};
|
|
1895
|
+
|
|
1896
|
+
props.cssClass = `${_instance.getCssClass(_classOption.MENU)} ${_instance.getCssClass(_classOption.FOOTER_MENU)}`;
|
|
1897
|
+
return props;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
function getMainMenuProps()
|
|
1901
|
+
{
|
|
1902
|
+
let props = {};
|
|
1903
|
+
|
|
1904
|
+
props.cssClass = joinCssClasses(_instance.getCssClass(_classOption.MENU), _instance.getCssClass(_classOption.MAIN), (isSideMenu()) ? _instance.getCssClass(_classOption.SIDE) : _instance.getCssClass(_classOption.PORTAL));
|
|
1905
|
+
props.horizontalRoot = !isSideMenu();
|
|
1906
|
+
|
|
1907
|
+
if (isSideMenu())
|
|
1908
|
+
{
|
|
1909
|
+
let defaultButton = $UI.createComponent(componyx.UI.Button, { id: _instance.id + '_DefaultButton', decoration: 1 });
|
|
1910
|
+
props.buttonId = defaultButton.id;
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
return props;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
function getinterpolations(id)
|
|
1917
|
+
{
|
|
1918
|
+
// replacement values for template
|
|
1919
|
+
let values = {};
|
|
1920
|
+
values.topbar = '<div id="' + id + 'TopBar" class="topbar">';
|
|
1921
|
+
values['/topbar'] = '</div>';
|
|
1922
|
+
values.logo = '<figure id="' + id + 'Logo" class="logo"></figure>';
|
|
1923
|
+
values.menuButton = '<a id="' + id + 'MenuButton"></a>';
|
|
1924
|
+
values.accountButton = '<a id="' + id + 'AccountButton"></a>';
|
|
1925
|
+
values.loginButton = '<a id="' + id + 'LoginButton"></a>';
|
|
1926
|
+
values.menu = '<b id="' + id + 'Menu"></b>';
|
|
1927
|
+
values.quickLaunchMenu = '<b id="' + id + 'QuickLaunchMenu"></b>';
|
|
1928
|
+
values.searchBox = '<div id="' + id + 'SearchBox"></div>';
|
|
1929
|
+
values.username = '<b id="' + id + 'Username" class="username"></b>';
|
|
1930
|
+
values.password = '<b id="' + id + 'Password"></b>';
|
|
1931
|
+
values.rememberMe = '<b id="' + id + 'RememberMe"></b>';
|
|
1932
|
+
values.failedMessage = '<b id="' + id + 'FailedMessage"></b>';
|
|
1933
|
+
values.verificationCode = '<b id="' + id + 'VerificationCode"></b>';
|
|
1934
|
+
values.verificationButton = '<a id="' + id + 'VerificationButton"></a>';
|
|
1935
|
+
return values;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
function createLoginScreen(container)
|
|
1939
|
+
{
|
|
1940
|
+
let id = _instance.id + '_Login_', el, i, div;
|
|
1941
|
+
|
|
1942
|
+
_login = createElement(container, '', _instance.getCssClass(_classOption.LOGIN_SCREEN));
|
|
1943
|
+
_instance.applyTemplate(_login, 'Login', getinterpolations(id));
|
|
1944
|
+
createElement(_login, '', _instance.getCssClass(_classOption.CONTENT), $lib.extract(_login));
|
|
1945
|
+
|
|
1946
|
+
if (el = $lib('#' + id + 'Username'))
|
|
1947
|
+
{
|
|
1948
|
+
div = createElement(null, '', _instance.getCssClass(_classOption.USER));
|
|
1949
|
+
el.parentNode.replaceChild(div, el);
|
|
1950
|
+
|
|
1951
|
+
_user = createInput('username');
|
|
1952
|
+
createFormField(div, el.id, _instance.usernameFormFieldId, _instance.usernameLabel, _user);
|
|
1953
|
+
|
|
1954
|
+
i = createElement(div, 'i', _instance.getCssClass(_classOption.ICON_USER));
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
if (el = $lib('#' + id + 'Password'))
|
|
1958
|
+
{
|
|
1959
|
+
div = createElement(null, '', _instance.getCssClass(_classOption.PASS));
|
|
1960
|
+
el.parentNode.replaceChild(div, el);
|
|
1961
|
+
|
|
1962
|
+
_pass = createInput('password');
|
|
1963
|
+
createFormField(div, el.id, _instance.passwordFormFieldId, _instance.passwordLabel, _pass);
|
|
1964
|
+
|
|
1965
|
+
i = createElement(div, 'i', _instance.getCssClass(_classOption.ICON_KEY));
|
|
1966
|
+
i = createElement(div, 'i', _instance.getCssClass(_classOption.ICON_EYE));
|
|
1967
|
+
bindInputEvents(_pass);
|
|
1968
|
+
$lib.on(i, 'click', togglePasswordDisplay);
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
if (_instance.showRememberMe && (el = $lib('#' + id + 'RememberMe')))
|
|
1972
|
+
{
|
|
1973
|
+
div = createElement(null, '', _instance.getCssClass(_classOption.REMEMBER));
|
|
1974
|
+
el.parentNode.replaceChild(div, el);
|
|
1975
|
+
|
|
1976
|
+
_remember = createElement(null, 'input');
|
|
1977
|
+
_remember.type = 'checkbox';
|
|
1978
|
+
_remember.checked = true;
|
|
1979
|
+
createFormField(div, el.id, _instance.rememberMeFormFieldId, _instance.rememberMeLabel, _remember);
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
if (el = $lib('#' + id + 'LoginButton'))
|
|
1983
|
+
{
|
|
1984
|
+
div = createElement();
|
|
1985
|
+
el.parentNode.replaceChild(div, el);
|
|
1986
|
+
createButton(div, el.id, _instance.loginButtonId, { cssClass: _instance.getCssClass(_classOption.LOGIN), text: _instance.loginButtonLabel, transparent: false }, function () { login(); });
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
if (el = $lib('#' + id + 'FailedMessage'))
|
|
1990
|
+
{
|
|
1991
|
+
_loginFailedMessage = createElement(null, '', _instance.getCssClass(_classOption.MESSAGE));
|
|
1992
|
+
el.parentNode.replaceChild(_loginFailedMessage, el);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
function createLoginVerificationScreen(container)
|
|
1997
|
+
{
|
|
1998
|
+
let id = _instance.id + '_LoginVerification_', el, div;
|
|
1999
|
+
|
|
2000
|
+
_loginVerification = createElement(container, '', `${_instance.getCssClass(_classOption.LOGIN_SCREEN)} ${_instance.getCssClass(_classOption.LOGIN_VERIFICATION)}`);
|
|
2001
|
+
_loginVerification.style.display = 'none';
|
|
2002
|
+
_instance.applyTemplate(_loginVerification, 'LoginVerification', getinterpolations(id));
|
|
2003
|
+
createElement(_loginVerification, '', _instance.getCssClass(_classOption.CONTENT), $lib.extract(_loginVerification));
|
|
2004
|
+
|
|
2005
|
+
if (el = $lib('#' + id + 'VerificationCode'))
|
|
2006
|
+
{
|
|
2007
|
+
div = createElement(null, '', _instance.getCssClass(_classOption.CODE));
|
|
2008
|
+
el.parentNode.replaceChild(div, el);
|
|
2009
|
+
|
|
2010
|
+
_verificationCode = createInput('code');
|
|
2011
|
+
_verificationCode.maxLength = _instance.verificationCodeLength;
|
|
2012
|
+
createFormField(div, el.id, _instance.verificationCodeFormFieldId, _instance.verificationCodeLabel, _verificationCode);
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
if (el = $lib('#' + id + 'VerificationButton'))
|
|
2016
|
+
{
|
|
2017
|
+
div = createElement();
|
|
2018
|
+
el.parentNode.replaceChild(div, el);
|
|
2019
|
+
createButton(div, el.id, _instance.verificationButtonId, { cssClass: _instance.getCssClass(_classOption.VERIFICATION), text: _instance.verificationButtonLabel, transparent: false }, function () { verifyCode(); });
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
if (el = $lib('#' + id + 'FailedMessage'))
|
|
2023
|
+
{
|
|
2024
|
+
_verificationFailedMessage = createElement(null, '', _instance.getCssClass(_classOption.MESSAGE));
|
|
2025
|
+
el.parentNode.replaceChild(_verificationFailedMessage, el);
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
function createFormField(container, id, cloneId, label, input)
|
|
2030
|
+
{
|
|
2031
|
+
let field = $UI.createComponent(componyx.UI.FormField, { id: id, containerElement: container });
|
|
2032
|
+
|
|
2033
|
+
field.clone($UI.store[cloneId], _instance);
|
|
2034
|
+
|
|
2035
|
+
field.setFieldTemplate(input);
|
|
2036
|
+
field.label = label;
|
|
2037
|
+
field.labelDisplay = (input.type == 'checkbox') ? 0 : componyx.UI.FormField.LabelDisplayOption.INSIDE;
|
|
2038
|
+
field.events.onPostRender.priorityAdd(function () { _instance.isReady.apply(_instance); }, null);
|
|
2039
|
+
field.showing = true;
|
|
2040
|
+
field.render();
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
function createInput(name)
|
|
2044
|
+
{
|
|
2045
|
+
return $lib.element('', '', 'input', null, { type: 'text', name: name, autocomplete: 'off', spellcheck: 'false' });
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
function bindInputEvents(input)
|
|
2049
|
+
{
|
|
2050
|
+
if (input.name == 'pass')
|
|
2051
|
+
{
|
|
2052
|
+
$lib.on(input, 'keydown', function (e)
|
|
2053
|
+
{
|
|
2054
|
+
if (e.key == 'Enter')
|
|
2055
|
+
login();
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
function togglePasswordDisplay(e)
|
|
2061
|
+
{
|
|
2062
|
+
let el = this,
|
|
2063
|
+
showing = $lib.hasClass(el, _instance.getCssClass(_classOption.ICON_EYE_BLOCKED));
|
|
2064
|
+
|
|
2065
|
+
_pass.type = (showing) ? 'password' : 'text';
|
|
2066
|
+
el.className = (showing) ? _instance.getCssClass(_classOption.ICON_EYE) : _instance.getCssClass(_classOption.ICON_EYE_BLOCKED);
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
function search(terms)
|
|
2070
|
+
{
|
|
2071
|
+
terms = (terms != undefined) ? terms : _searchBox.value;
|
|
2072
|
+
let settings = { terms: terms };
|
|
2073
|
+
|
|
2074
|
+
if ($lib.isEmpty(terms))
|
|
2075
|
+
{
|
|
2076
|
+
if (_searchResult)
|
|
2077
|
+
_searchResult.style.display = 'none';
|
|
2078
|
+
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
_instance.ajaxCall('search', settings,
|
|
2083
|
+
{
|
|
2084
|
+
onSuccess: function (args)
|
|
2085
|
+
{
|
|
2086
|
+
showSearchResult(args.data);
|
|
2087
|
+
},
|
|
2088
|
+
onError: function (args)
|
|
2089
|
+
{
|
|
2090
|
+
createSearchResult(_instance.searchNoResultLabel);
|
|
2091
|
+
}
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
function showSearchResult(data)
|
|
2096
|
+
{
|
|
2097
|
+
let eventArgs = { data: data, container: _searchResult, cancel: false },
|
|
2098
|
+
categories = {};
|
|
2099
|
+
|
|
2100
|
+
createSearchResult('');
|
|
2101
|
+
_instance.events.onPreSearchResults.fire(_instance, eventArgs);
|
|
2102
|
+
|
|
2103
|
+
if (eventArgs.cancel === true)
|
|
2104
|
+
return;
|
|
2105
|
+
|
|
2106
|
+
if (data && data.length > 0)
|
|
2107
|
+
{
|
|
2108
|
+
$lib.each(data, function (item)
|
|
2109
|
+
{
|
|
2110
|
+
let route = item.route.replace(/\\/, '/').toLowerCase(),
|
|
2111
|
+
title = item.title,
|
|
2112
|
+
cat = getSearchCategory(route);
|
|
2113
|
+
|
|
2114
|
+
if (!categories[cat])
|
|
2115
|
+
{
|
|
2116
|
+
categories[cat] = createElement(_searchResult, 'nav');
|
|
2117
|
+
createElement(categories[cat], 'h2', '', cat);
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
let a = $lib.element(categories[cat], '', 'a', title, { href: route }),
|
|
2121
|
+
itemEventArgs = { ...eventArgs, item: item, anchor: a };
|
|
2122
|
+
|
|
2123
|
+
_instance.events.onRenderSearchResult.fire(_instance, itemEventArgs);
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
else
|
|
2127
|
+
_searchResult.innerHTML = _instance.searchNoResultLabel;
|
|
2128
|
+
|
|
2129
|
+
$lib.each(categories, function (nav)
|
|
2130
|
+
{
|
|
2131
|
+
nav.firstElementChild.textContent += ' (' + (nav.childNodes.length - 1) + ')';
|
|
2132
|
+
});
|
|
2133
|
+
|
|
2134
|
+
_searchResult.style.display = '';
|
|
2135
|
+
_instance.events.onPostSearchResults.fire(_instance, eventArgs);
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
function createSearchResult(text)
|
|
2139
|
+
{
|
|
2140
|
+
if (!_searchResult)
|
|
2141
|
+
_searchResult = createElement(_instance.element, 'div', _instance.getCssClass(_classOption.SEARCH_RESULT));
|
|
2142
|
+
|
|
2143
|
+
_searchResult.innerHTML = text;
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
function getSearchCategory(route)
|
|
2147
|
+
{
|
|
2148
|
+
if (route.indexOf('/') == -1)
|
|
2149
|
+
return _instance.searchCategoryLabels[''] || '';
|
|
2150
|
+
|
|
2151
|
+
let cat = route.substr(0, route.lastIndexOf('/'));
|
|
2152
|
+
return _instance.searchCategoryLabels[cat] || cat;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
function hideAll()
|
|
2156
|
+
{
|
|
2157
|
+
hide([_login, _page, _view, _error]);
|
|
2158
|
+
$lib.removeClass(_instance.element, `${_instance.getCssClass(_classOption.LOGIN)} ${_instance.getCssClass(_classOption.ERROR)}`);
|
|
2159
|
+
_activeScreen = _screenOption.PAGE;
|
|
2160
|
+
|
|
2161
|
+
if (!_launch && _instance.menuType != _menuTypeOption.SIDEMENU)
|
|
2162
|
+
{
|
|
2163
|
+
_mainMenu?.hide();
|
|
2164
|
+
_menuButton?.deselect();
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
if (_topbar && !_instance.persistentTopBar)
|
|
2168
|
+
{
|
|
2169
|
+
_topbar.style.display = 'none';
|
|
2170
|
+
$lib.removeClass(_instance.element, _instance.getCssClass(_classOption.TOPBAR));
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
if (_instance.footerDisplay != _footerDisplayOption.PERSISTENT && _footer)
|
|
2174
|
+
hideFooter();
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
function hide(elements)
|
|
2178
|
+
{
|
|
2179
|
+
for (let index = 0; index < elements.length; ++index)
|
|
2180
|
+
{
|
|
2181
|
+
if (elements[index])
|
|
2182
|
+
elements[index].style.display = 'none';
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
function toggleMenu()
|
|
2187
|
+
{
|
|
2188
|
+
if (_activeScreen == _screenOption.PORTAL && _launch)
|
|
2189
|
+
return; // only switch back to page when the menu was clicked
|
|
2190
|
+
|
|
2191
|
+
if (menuIsShowing())
|
|
2192
|
+
hideMenu();
|
|
2193
|
+
else
|
|
2194
|
+
showMenu();
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
function showMenu(instant)
|
|
2198
|
+
{
|
|
2199
|
+
if (!instant && menuIsShowing())
|
|
2200
|
+
return;
|
|
2201
|
+
|
|
2202
|
+
if (_instance.menuType == _menuTypeOption.PORTALMENU)
|
|
2203
|
+
{
|
|
2204
|
+
hideAll();
|
|
2205
|
+
_activeScreen = _screenOption.PORTAL; // page is not visible with portal-menu
|
|
2206
|
+
document.documentElement.style.overflow = "hidden"; // temporary disable scrollbar otherwise browser calculates available space for portal-menu with vertical-scrollbar
|
|
2207
|
+
_mainMenu.show(); // portal-menu display is always instant
|
|
2208
|
+
resize();
|
|
2209
|
+
}
|
|
2210
|
+
else
|
|
2211
|
+
{
|
|
2212
|
+
_instance.showPage(); // page is visible with side-menu
|
|
2213
|
+
_sideMenuBox.show(instant || _launch); // without animation when launching
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
if (_instance.footerDisplay == _footerDisplayOption.MENU)
|
|
2217
|
+
showFooter();
|
|
2218
|
+
|
|
2219
|
+
$lib.addClass(_instance.element, (_instance.menuType == _menuTypeOption.PORTALMENU) ? _instance.getCssClass(_classOption.PORTAL_MENU) : _instance.getCssClass(_classOption.SIDE_MENU));
|
|
2220
|
+
|
|
2221
|
+
if (_menuButton)
|
|
2222
|
+
{
|
|
2223
|
+
if (!_menuButton.showing)
|
|
2224
|
+
_menuButton.show();
|
|
2225
|
+
|
|
2226
|
+
_menuButton.select();
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
_instance.events.onShowMenu.fire(_instance);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
function hideMenu(instant, hideFn)
|
|
2233
|
+
{
|
|
2234
|
+
if (!instant && !menuIsShowing() || (_launch && _instance.launchMenu))
|
|
2235
|
+
return;
|
|
2236
|
+
|
|
2237
|
+
if (hideFn)
|
|
2238
|
+
setHideMenuCallback(function () { showMainCategory(); });
|
|
2239
|
+
|
|
2240
|
+
_instance.events.onHideMenu.fire(_instance);
|
|
2241
|
+
_instance.showPage(); // hides the portal-menu
|
|
2242
|
+
|
|
2243
|
+
if (isSideMenu()) // side-menu is not automatically hidden
|
|
2244
|
+
{
|
|
2245
|
+
_menuButton.deselect();
|
|
2246
|
+
_sideMenuBox.hide(instant);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
function menuIsShowing()
|
|
2251
|
+
{
|
|
2252
|
+
return ((isSideMenu() && _sideMenuBox.showing) || (!isSideMenu() && _mainMenu.showing));
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
function isSideMenu()
|
|
2256
|
+
{
|
|
2257
|
+
return (_instance.menuType === _menuTypeOption.SIDEMENU);
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
function showFooter()
|
|
2261
|
+
{
|
|
2262
|
+
_footer.style.display = '';
|
|
2263
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.FOOTER));
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
function hideFooter()
|
|
2267
|
+
{
|
|
2268
|
+
_footer.style.display = 'none';
|
|
2269
|
+
$lib.removeClass(_instance.element, _instance.getCssClass(_classOption.FOOTER));
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
function showLogin()
|
|
2273
|
+
{
|
|
2274
|
+
if (isSideMenu())
|
|
2275
|
+
hideMenu();
|
|
2276
|
+
|
|
2277
|
+
hideAll();
|
|
2278
|
+
|
|
2279
|
+
if (_instance.hideMenuButtonOnLogin)
|
|
2280
|
+
_menuButton?.hide();
|
|
2281
|
+
|
|
2282
|
+
_login.style.display = '';
|
|
2283
|
+
_activeScreen = _screenOption.LOGIN;
|
|
2284
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.LOGIN));
|
|
2285
|
+
_user.focus();
|
|
2286
|
+
_pass.type = 'password';
|
|
2287
|
+
|
|
2288
|
+
_instance.events.onShowLogin.fire(_instance);
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
function showLoginVerification()
|
|
2292
|
+
{
|
|
2293
|
+
if (isSideMenu())
|
|
2294
|
+
hideMenu();
|
|
2295
|
+
|
|
2296
|
+
hideAll();
|
|
2297
|
+
_loginVerification.style.display = '';
|
|
2298
|
+
_activeScreen = _screenOption.LOGIN_VERIFICATION;
|
|
2299
|
+
$lib.addClass(_instance.element, `${_instance.getCssClass(_classOption.LOGIN)} ${_instance.getCssClass(_classOption.VERIFICATION)}`);
|
|
2300
|
+
_verificationCode.focus();
|
|
2301
|
+
|
|
2302
|
+
_instance.events.onShowLoginVerification.fire(_instance);
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
function login(settings)
|
|
2306
|
+
{
|
|
2307
|
+
if (!settings)
|
|
2308
|
+
settings = { crsfToken: _instance.crsfToken, username: _user.value, password: _pass.value, persistent: (_remember) ? _remember.checked : false };
|
|
2309
|
+
|
|
2310
|
+
invokeAuthenticationMiddleware(settings, function (args)
|
|
2311
|
+
{
|
|
2312
|
+
args.data.cancel = false;
|
|
2313
|
+
_instance.events.onLoginAttempt.fire(_instance, args.data);
|
|
2314
|
+
|
|
2315
|
+
if (args.data.cancel === true) // we don't have to handle this further (custom handeling of args.data.redirectPath)
|
|
2316
|
+
return;
|
|
2317
|
+
|
|
2318
|
+
if (!args.data.authenticationState)
|
|
2319
|
+
{
|
|
2320
|
+
authenticationFailed([_pass], args.data, _loginFailedMessage);
|
|
2321
|
+
}
|
|
2322
|
+
else if (args.data.authenticationState == componyx.UI.AppSkin.AuthenticationStateOption.CREDENTIALS_VALIDATED)
|
|
2323
|
+
{
|
|
2324
|
+
if (args.data.redirectPath) // not handled in login attempt event
|
|
2325
|
+
{
|
|
2326
|
+
if (_instance.useBindary && $bindary && $bindary.routes && $bindary.routes.length) // we only handle default route behaviour
|
|
2327
|
+
$bindary.loadRoute(args.data.redirectPath);
|
|
2328
|
+
}
|
|
2329
|
+
else
|
|
2330
|
+
{
|
|
2331
|
+
_instance.showLoginVerification();
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
else
|
|
2335
|
+
{
|
|
2336
|
+
window.location.reload();
|
|
2337
|
+
}
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
function verifyCode(settings)
|
|
2342
|
+
{
|
|
2343
|
+
if (!settings)
|
|
2344
|
+
settings = { crsfToken: _instance.crsfToken, verificationCode: _verificationCode.value };
|
|
2345
|
+
|
|
2346
|
+
invokeAuthenticationMiddleware(settings, function (args)
|
|
2347
|
+
{
|
|
2348
|
+
args.data.cancel = false;
|
|
2349
|
+
_instance.events.onLoginVerificationAttempt.fire(_instance, args.data);
|
|
2350
|
+
|
|
2351
|
+
if (args.data.cancel === true) // we don't have to handle this further
|
|
2352
|
+
return;
|
|
2353
|
+
|
|
2354
|
+
if (!args.data.authenticationState)
|
|
2355
|
+
{
|
|
2356
|
+
let reason = args.data.failureReason;
|
|
2357
|
+
authenticationFailed([_verificationCode], args.data, _verificationFailedMessage);
|
|
2358
|
+
|
|
2359
|
+
if (reason == _failureReasonOption.VERIFICATION_CODE_EXPIRED || reason == _failureReasonOption.MAX_VERIFY_ATTEMPTS_EXCEEDED)
|
|
2360
|
+
setTimeout(function () { window.location.reload(); }, _instance.verificationFailedReloadDelay);
|
|
2361
|
+
|
|
2362
|
+
}
|
|
2363
|
+
else if (args.data.authenticationState == componyx.UI.AppSkin.AuthenticationStateOption.AUTHENTICATED)
|
|
2364
|
+
{
|
|
2365
|
+
window.location.reload();
|
|
2366
|
+
}
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
function logout(settings)
|
|
2371
|
+
{
|
|
2372
|
+
if (!settings)
|
|
2373
|
+
settings = { signout: true };
|
|
2374
|
+
|
|
2375
|
+
invokeAuthenticationMiddleware(settings, function (args)
|
|
2376
|
+
{
|
|
2377
|
+
args.data.cancel = false;
|
|
2378
|
+
_instance.events.onLogout.fire(_instance, args.data);
|
|
2379
|
+
|
|
2380
|
+
if (args.data.cancel === true) // we don't have to handle this further
|
|
2381
|
+
return;
|
|
2382
|
+
|
|
2383
|
+
if (args.data && args.data.failureMessage)
|
|
2384
|
+
$lib.log(args.data.failureMessage);
|
|
2385
|
+
|
|
2386
|
+
window.location.reload();
|
|
2387
|
+
});
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
function authenticationFailed(inputs, data, messageElement)
|
|
2391
|
+
{
|
|
2392
|
+
let label = getAuthenticationFailureLabel(data.failureReason);
|
|
2393
|
+
|
|
2394
|
+
if (messageElement)
|
|
2395
|
+
messageElement.innerHTML = data.failureMessage || label || '';
|
|
2396
|
+
|
|
2397
|
+
inputs.forEach((input) =>
|
|
2398
|
+
{
|
|
2399
|
+
input.value = '';
|
|
2400
|
+
});
|
|
2401
|
+
|
|
2402
|
+
inputs[0].focus();
|
|
2403
|
+
|
|
2404
|
+
let logMessage = 'Authentication failed. ';
|
|
2405
|
+
|
|
2406
|
+
if (data.failureReason)
|
|
2407
|
+
logMessage += `Reason: ${_failureReasonOption.getName(data.failureReason)}. `;
|
|
2408
|
+
|
|
2409
|
+
if (data.failureMessage)
|
|
2410
|
+
logMessage += `Message: ${data.failureMessage}.`;
|
|
2411
|
+
|
|
2412
|
+
$lib.log(logMessage);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
function getAuthenticationFailureLabel(reason)
|
|
2416
|
+
{
|
|
2417
|
+
if ($lib.isEmpty(reason))
|
|
2418
|
+
return _instance.authenticationFailureLabel;
|
|
2419
|
+
else
|
|
2420
|
+
return _instance.authenticationFailureReasonLabels[reason];
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
function invokeAuthenticationMiddleware(settings, onSuccess)
|
|
2424
|
+
{
|
|
2425
|
+
_instance.ajaxCall('authenticate', settings, { onSuccess: onSuccess });
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
function updateMenuButtonVisibility()
|
|
2429
|
+
{
|
|
2430
|
+
if (!_menuButton)
|
|
2431
|
+
return;
|
|
2432
|
+
|
|
2433
|
+
let shouldShow = _instance.persistentMenuButton
|
|
2434
|
+
|| !_allInHeader
|
|
2435
|
+
|| $lib.hasClass(_instance.element, _instance.getCssClass(_classOption.HEADER_MENU_HIDDEN))
|
|
2436
|
+
|| !$lib.isEmpty(_mainMenu?.getActiveCategoryId());
|
|
2437
|
+
|
|
2438
|
+
if (shouldShow && !_menuButton.showing)
|
|
2439
|
+
_menuButton.show();
|
|
2440
|
+
else if (!shouldShow && _menuButton.showing)
|
|
2441
|
+
_menuButton.hide();
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
|
|
2445
|
+
function resize(e)
|
|
2446
|
+
{
|
|
2447
|
+
clearTimeout(_resizeTimerId);
|
|
2448
|
+
_resizeTimerId = setTimeout(function ()
|
|
2449
|
+
{
|
|
2450
|
+
let docStyle = document.documentElement.style;
|
|
2451
|
+
|
|
2452
|
+
checkHeaderOverflow();
|
|
2453
|
+
docStyle.overflow = "";
|
|
2454
|
+
}, 0);
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
function checkHeaderOverflow()
|
|
2458
|
+
{
|
|
2459
|
+
if (!_headerMenu || !_headerMenu.itemList.length)
|
|
2460
|
+
{
|
|
2461
|
+
headerOverflowCheckComplete();
|
|
2462
|
+
return;
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
clearTimeout(_headerOverflowTimerId);
|
|
2466
|
+
|
|
2467
|
+
if (_allInHeader)
|
|
2468
|
+
$lib.addClass(_instance.element, _instance.getCssClass(_classOption.HEADER_ALL));
|
|
2469
|
+
|
|
2470
|
+
_headerOverflowTimerId = setTimeout(function ()
|
|
2471
|
+
{
|
|
2472
|
+
_headerMenu.show();
|
|
2473
|
+
|
|
2474
|
+
let nav = $lib(null, _headerMenu.element, 'nav', true), topbarDisplay = null;
|
|
2475
|
+
|
|
2476
|
+
if (!nav)
|
|
2477
|
+
return;
|
|
2478
|
+
|
|
2479
|
+
if (_topbar && $lib.contains(_topbar, _headerMenu.element)) // header menu in topbar
|
|
2480
|
+
{
|
|
2481
|
+
topbarDisplay = _topbar.style.display || '';
|
|
2482
|
+
_topbar.style.display = ''; // display topbar for overflow calculation
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
let fits = (nav.scrollWidth == nav.clientWidth),
|
|
2486
|
+
cssClass = _instance.getCssClass(_classOption.HEADER_OVERFLOW), el = _instance.element, retry,
|
|
2487
|
+
hasClass = $lib.hasClass(el, cssClass),
|
|
2488
|
+
obj = { headerOverflow: !fits, cancel: false };
|
|
2489
|
+
|
|
2490
|
+
_instance.events.onResize.fire(_instance, obj);
|
|
2491
|
+
|
|
2492
|
+
if (obj.cancel !== true)
|
|
2493
|
+
{
|
|
2494
|
+
if (fits)
|
|
2495
|
+
{
|
|
2496
|
+
let hasRoutes = _instance.useBindary && $bindary && $bindary.routes && $bindary.routes.length > 0;
|
|
2497
|
+
$lib.removeClass(el, _instance.getCssClass(_classOption.HEADER_MENU_HIDDEN));
|
|
2498
|
+
|
|
2499
|
+
if (_instance.menuType == _menuTypeOption.SIDEMENU && _allInHeader && (!_launch || !hasRoutes) && $lib.isEmpty(_mainMenu.getActiveCategoryId()))
|
|
2500
|
+
{
|
|
2501
|
+
updateMenuButtonVisibility();
|
|
2502
|
+
hideMenu(true);
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
else
|
|
2506
|
+
_headerMenu.hide();
|
|
2507
|
+
|
|
2508
|
+
if (!fits && hasClass)
|
|
2509
|
+
{
|
|
2510
|
+
$lib.addClass(el, _instance.getCssClass(_classOption.HEADER_MENU_HIDDEN));
|
|
2511
|
+
|
|
2512
|
+
if (_menuButton && !_menuButton.showing)
|
|
2513
|
+
_menuButton.show();
|
|
2514
|
+
}
|
|
2515
|
+
else if (!fits)
|
|
2516
|
+
{
|
|
2517
|
+
$lib.addClass(el, cssClass);
|
|
2518
|
+
_windowWidth = $lib.getWindowSize().width; // store window width to detect turning point
|
|
2519
|
+
retry = true; // check if the header overflows when the overflow class is applied
|
|
2520
|
+
}
|
|
2521
|
+
else if (fits && hasClass && $lib.getWindowSize().width > _windowWidth) // change in window size (turning point)
|
|
2522
|
+
{
|
|
2523
|
+
$lib.removeClass(el, cssClass);
|
|
2524
|
+
|
|
2525
|
+
if (nav.scrollWidth != nav.clientWidth)
|
|
2526
|
+
$lib.addClass(el, cssClass);
|
|
2527
|
+
else
|
|
2528
|
+
retry = true; // check if the header overflows when the overflow class is removed
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
if (topbarDisplay != null)
|
|
2533
|
+
_topbar.style.display = topbarDisplay;
|
|
2534
|
+
|
|
2535
|
+
if (retry)
|
|
2536
|
+
checkHeaderOverflow();
|
|
2537
|
+
else
|
|
2538
|
+
headerOverflowCheckComplete();
|
|
2539
|
+
}, 0);
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
function headerOverflowCheckComplete()
|
|
2543
|
+
{
|
|
2544
|
+
if (_instance.useBindary && $bindary && $bindary.routes && $bindary.routes.length > 0)
|
|
2545
|
+
return; // Bindary's own route load will clear _launch instead
|
|
2546
|
+
|
|
2547
|
+
_launch = false;
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
function detectMenuToggle(e)
|
|
2551
|
+
{
|
|
2552
|
+
let src = $lib.eventSource(e);
|
|
2553
|
+
|
|
2554
|
+
if (src == _menuButton.element || $lib.contains(_menuButton.element, src) || src == _mainMenu.element || $lib.contains(_mainMenu.element, src))
|
|
2555
|
+
return;
|
|
2556
|
+
|
|
2557
|
+
if (_sideMenuBox.showing)
|
|
2558
|
+
hideMenu();
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
function hideSearchResult(e)
|
|
2562
|
+
{
|
|
2563
|
+
let target = e.target;
|
|
2564
|
+
|
|
2565
|
+
if (!_searchResult)
|
|
2566
|
+
return;
|
|
2567
|
+
|
|
2568
|
+
if (target.nodeName.toLowerCase() == 'a' || (target != _searchBox && target != _searchBox.parentNode && target != _searchResult && !$lib.contains(_searchResult, target)))
|
|
2569
|
+
_searchResult.style.display = 'none';
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
function dispose()
|
|
2573
|
+
{
|
|
2574
|
+
$lib.off(window, 'resize', resize);
|
|
2575
|
+
$lib.off(_instance.element, 'click', detectMenuToggle);
|
|
2576
|
+
$lib.off(document, 'click', hideSearchResult);
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2579
|
+
|
|
2580
|
+
/**
|
|
2581
|
+
* @see {@link componyx.UI.base.methods}
|
|
2582
|
+
*/
|
|
2583
|
+
componyx.UI.AppSkin.prototype = Object.create($base.methods);
|
|
2584
|
+
componyx.UI.AppSkin.prototype.constructor = componyx.UI.AppSkin;
|
|
2585
|
+
|
|
2586
|
+
/**
|
|
2587
|
+
* ScreenOption
|
|
2588
|
+
* @readonly
|
|
2589
|
+
* @enum {number}
|
|
2590
|
+
*/
|
|
2591
|
+
componyx.UI.AppSkin.ScreenOption =
|
|
2592
|
+
{
|
|
2593
|
+
/** the login screen is visible */
|
|
2594
|
+
LOGIN: 0,
|
|
2595
|
+
/** the login verification screen is visible */
|
|
2596
|
+
LOGIN_VERIFICATION: 1,
|
|
2597
|
+
/** the portal navigation screen is visible */
|
|
2598
|
+
PORTAL: 2,
|
|
2599
|
+
/** the page is visible */
|
|
2600
|
+
PAGE: 3
|
|
2601
|
+
};
|
|
2602
|
+
|
|
2603
|
+
/**
|
|
2604
|
+
* MenuTypeOption
|
|
2605
|
+
* @readonly
|
|
2606
|
+
* @enum {number}
|
|
2607
|
+
*/
|
|
2608
|
+
componyx.UI.AppSkin.MenuTypeOption =
|
|
2609
|
+
{
|
|
2610
|
+
/** the main menu is displayed as portal navigation */
|
|
2611
|
+
PORTALMENU: 0,
|
|
2612
|
+
/** the main menu is displayed as side navigation */
|
|
2613
|
+
SIDEMENU: 1
|
|
2614
|
+
};
|
|
2615
|
+
|
|
2616
|
+
/**
|
|
2617
|
+
* MenuSectionOption
|
|
2618
|
+
* @readonly
|
|
2619
|
+
* @enum {number}
|
|
2620
|
+
*/
|
|
2621
|
+
componyx.UI.AppSkin.MenuSectionOption =
|
|
2622
|
+
{
|
|
2623
|
+
/** the menu-item will be rendered in the header and main menu-sections */
|
|
2624
|
+
HEADER: 0,
|
|
2625
|
+
/** the menu-item will be rendered in the main menu-section */
|
|
2626
|
+
MAIN: 1,
|
|
2627
|
+
/** the menu-item will be rendered in the footer menu-section */
|
|
2628
|
+
FOOTER: 2,
|
|
2629
|
+
/** the menu-item will be rendered in the quick-launch menu-section */
|
|
2630
|
+
QUICKLAUNCH: 3
|
|
2631
|
+
};
|
|
2632
|
+
|
|
2633
|
+
/**
|
|
2634
|
+
* ButtonTileSizeOption
|
|
2635
|
+
* @readonly
|
|
2636
|
+
* @enum {number}
|
|
2637
|
+
*/
|
|
2638
|
+
componyx.UI.AppSkin.TileSizeOption =
|
|
2639
|
+
{
|
|
2640
|
+
/** renders the menu-item button as small tile in the portal-menu */
|
|
2641
|
+
SMALL: 1,
|
|
2642
|
+
/** renders the menu-item button as small-wide tile in the portal-menu */
|
|
2643
|
+
SMALL_WIDE: 2,
|
|
2644
|
+
/** renders the menu-item button as medium tile in the portal-menu */
|
|
2645
|
+
MEDIUM: 4,
|
|
2646
|
+
/** renders the menu-item button as medium-wide tile in the portal-menu */
|
|
2647
|
+
MEDIUM_WIDE: 8,
|
|
2648
|
+
/** renders the menu-item button as large tile in the portal-menu */
|
|
2649
|
+
LARGE: 16,
|
|
2650
|
+
|
|
2651
|
+
getName: function (value) { return $base.static.getKeyByValue(this, value).toLowerCase(); }
|
|
2652
|
+
};
|
|
2653
|
+
|
|
2654
|
+
/**
|
|
2655
|
+
* RoutePathMatchingOption
|
|
2656
|
+
* @readonly
|
|
2657
|
+
* @enum {number}
|
|
2658
|
+
*/
|
|
2659
|
+
componyx.UI.AppSkin.RoutePathMatchingOption =
|
|
2660
|
+
{
|
|
2661
|
+
/** there is no menu-item route-path matching */
|
|
2662
|
+
DISABLED: 0,
|
|
2663
|
+
/** matches if the item's route-path equals the current URL route-path exactly */
|
|
2664
|
+
EXACT: 1,
|
|
2665
|
+
/** matches if the item's route-path equals the current URL route-path while ignoring possible parameters preceded by a question mark character. */
|
|
2666
|
+
PARTIAL: 2
|
|
2667
|
+
};
|
|
2668
|
+
|
|
2669
|
+
/**
|
|
2670
|
+
* FooterDisplayOption
|
|
2671
|
+
* @readonly
|
|
2672
|
+
* @enum {number}
|
|
2673
|
+
*/
|
|
2674
|
+
componyx.UI.AppSkin.FooterDisplayOption =
|
|
2675
|
+
{
|
|
2676
|
+
/** the footer is not visible */
|
|
2677
|
+
DISABLED: 0,
|
|
2678
|
+
/** the footer is visible when the menu is visible */
|
|
2679
|
+
MENU: 1,
|
|
2680
|
+
/** the footer is always visible */
|
|
2681
|
+
PERSISTENT: 2
|
|
2682
|
+
};
|
|
2683
|
+
|
|
2684
|
+
/**
|
|
2685
|
+
* FailureReasonOption
|
|
2686
|
+
* @readonly
|
|
2687
|
+
* @enum {number}
|
|
2688
|
+
*/
|
|
2689
|
+
componyx.UI.AppSkin.FailureReasonOption =
|
|
2690
|
+
{
|
|
2691
|
+
/** Provided CRSF Token does not match with token in Session object. */
|
|
2692
|
+
CRSF_TOKEN_MISMATCH: 0,
|
|
2693
|
+
/** Total attempts exceeded configured max sign-in attempts. */
|
|
2694
|
+
MAX_SIGNIN_ATTEMPTS_EXCEEDED: 1,
|
|
2695
|
+
/** Provided username and/or password do not match. */
|
|
2696
|
+
USERNAME_OR_PASSWORD_MISMATCH: 2,
|
|
2697
|
+
/** Provided verificatin code does not match.*/
|
|
2698
|
+
VERIFICATION_CODE_MISMATCH: 3,
|
|
2699
|
+
/** The generated verification-code has expired.*/
|
|
2700
|
+
VERIFICATION_CODE_EXPIRED: 4,
|
|
2701
|
+
/** Total attempts exceeded the configured max verify code attempts.*/
|
|
2702
|
+
MAX_VERIFY_ATTEMPTS_EXCEEDED: 5,
|
|
2703
|
+
/** Other reason */
|
|
2704
|
+
OTHER: 6,
|
|
2705
|
+
|
|
2706
|
+
getName: function (value) { return $base.static.getKeyByValue(this, value).toLowerCase(); }
|
|
2707
|
+
};
|
|
2708
|
+
|
|
2709
|
+
/**
|
|
2710
|
+
* AuthenticationStateOption
|
|
2711
|
+
* @readonly
|
|
2712
|
+
* @enum {number}
|
|
2713
|
+
*/
|
|
2714
|
+
componyx.UI.AppSkin.AuthenticationStateOption =
|
|
2715
|
+
{
|
|
2716
|
+
/** The user is not authenticated. */
|
|
2717
|
+
UNAUTHENTICATED: 0,
|
|
2718
|
+
/** The credentials have been successfully validated but the user is not yet authenticated (Step 1 in Two-Factor authentication). */
|
|
2719
|
+
CREDENTIALS_VALIDATED: 1,
|
|
2720
|
+
/** The user is successfully authenticated. */
|
|
2721
|
+
AUTHENTICATED: 2
|
|
2722
|
+
};
|
|
2723
|
+
|
|
2724
|
+
/**
|
|
2725
|
+
* Creates an instance of the AppSkin MenuItem.
|
|
2726
|
+
* @class
|
|
2727
|
+
* @param {Object} properties The properties used to initialize the object.
|
|
2728
|
+
* @property {componyx.UI.AppSkin.MenuSectionOption} menuSection=HEADER Gets or sets a value indicating in which menu-section the item is displayed.
|
|
2729
|
+
* @property {componyx.UI.AppSkin.TileSizeOption} groupTileSize Gets or sets the tile-size of the portal menu group.
|
|
2730
|
+
* @property {componyx.UI.AppSkin.TileSizeOption} buttonTileSize=MEDIUM Gets or sets the tile-size of the portal menu buttons.
|
|
2731
|
+
* @property {Boolean} categoryInHeader Gets or sets a value indicating if the category (isCategory:true) is shown in the header-menu when menuSection:HEADER. By default the category is always displayed in the main-menu.
|
|
2732
|
+
* @augments componyx.UI.Menu.Item
|
|
2733
|
+
* @see {@link componyx.UI.Menu.Item}
|
|
2734
|
+
* @see {@link componyx.UI.base.Item}
|
|
2735
|
+
*/
|
|
2736
|
+
componyx.UI.AppSkin.MenuItem = function (properties)
|
|
2737
|
+
{
|
|
2738
|
+
this.menuSection = componyx.UI.AppSkin.MenuSectionOption.HEADER;
|
|
2739
|
+
this.groupTileSize = null;
|
|
2740
|
+
this.buttonTileSize = componyx.UI.AppSkin.TileSizeOption.MEDIUM;
|
|
2741
|
+
this.categoryInHeader = false;
|
|
2742
|
+
componyx.UI.Menu.Item.call(this, properties);
|
|
2743
|
+
};
|
|
2744
|
+
})(window);
|
|
2745
|
+
|
|
2746
|
+
const AppSkin = componyx.UI.AppSkin;
|
|
2747
|
+
|
|
2748
|
+
export { AppSkin };
|