underpost 2.8.82 → 2.8.85
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/.env.development +1 -0
- package/.env.production +1 -0
- package/.env.test +1 -0
- package/.github/workflows/{ghpkg.yml → ghpkg.ci.yml} +5 -5
- package/.github/workflows/{npmpkg.yml → npmpkg.ci.yml} +5 -5
- package/.github/workflows/{publish.yml → publish.ci.yml} +1 -1
- package/.github/workflows/{pwa-microservices-template.page.yml → pwa-microservices-template-page.cd.yml} +1 -1
- package/.github/workflows/{pwa-microservices-template.test.yml → pwa-microservices-template-test.ci.yml} +1 -1
- package/.vscode/extensions.json +1 -1
- package/.vscode/settings.json +0 -44
- package/README.md +62 -2
- package/bin/build.js +15 -5
- package/bin/deploy.js +42 -92
- package/bin/file.js +33 -9
- package/bin/vs.js +12 -4
- package/cli.md +90 -42
- package/conf.js +1 -1
- package/docker-compose.yml +1 -1
- package/manifests/deployment/dd-template-development/deployment.yaml +2 -2
- package/manifests/deployment/tensorflow/tf-gpu-test.yaml +65 -0
- package/manifests/maas/device-scan.sh +3 -3
- package/manifests/maas/gpu-diag.sh +19 -0
- package/manifests/maas/maas-setup.sh +10 -10
- package/manifests/maas/snap-clean.sh +26 -0
- package/package.json +4 -6
- package/src/api/user/user.router.js +24 -1
- package/src/api/user/user.service.js +1 -4
- package/src/cli/baremetal.js +105 -73
- package/src/cli/cloud-init.js +21 -12
- package/src/cli/cluster.js +227 -133
- package/src/cli/deploy.js +34 -0
- package/src/cli/index.js +28 -1
- package/src/cli/monitor.js +8 -12
- package/src/cli/repository.js +7 -4
- package/src/cli/run.js +367 -0
- package/src/cli/ssh.js +32 -0
- package/src/cli/test.js +1 -1
- package/src/client/Default.index.js +7 -3
- package/src/client/components/core/Account.js +1 -1
- package/src/client/components/core/Chat.js +1 -1
- package/src/client/components/core/CommonJs.js +24 -22
- package/src/client/components/core/Content.js +1 -5
- package/src/client/components/core/Css.js +258 -18
- package/src/client/components/core/CssCore.js +8 -8
- package/src/client/components/core/Docs.js +14 -61
- package/src/client/components/core/DropDown.js +137 -82
- package/src/client/components/core/EventsUI.js +92 -5
- package/src/client/components/core/LoadingAnimation.js +8 -15
- package/src/client/components/core/Modal.js +597 -136
- package/src/client/components/core/NotificationManager.js +2 -2
- package/src/client/components/core/ObjectLayerEngine.js +638 -0
- package/src/client/components/core/Panel.js +158 -34
- package/src/client/components/core/PanelForm.js +12 -3
- package/src/client/components/core/Recover.js +1 -1
- package/src/client/components/core/Router.js +77 -17
- package/src/client/components/core/SocketIo.js +3 -3
- package/src/client/components/core/Translate.js +6 -2
- package/src/client/components/core/VanillaJs.js +0 -3
- package/src/client/components/core/Worker.js +3 -1
- package/src/client/components/default/CssDefault.js +17 -3
- package/src/client/components/default/MenuDefault.js +264 -45
- package/src/client/components/default/RoutesDefault.js +6 -12
- package/src/client/public/default/android-chrome-144x144.png +0 -0
- package/src/client/public/default/android-chrome-192x192.png +0 -0
- package/src/client/public/default/android-chrome-256x256.png +0 -0
- package/src/client/public/default/android-chrome-36x36.png +0 -0
- package/src/client/public/default/android-chrome-48x48.png +0 -0
- package/src/client/public/default/android-chrome-72x72.png +0 -0
- package/src/client/public/default/android-chrome-96x96.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon.png +0 -0
- package/src/client/public/default/assets/background/dark.jpg +0 -0
- package/src/client/public/default/assets/background/dark.svg +557 -0
- package/src/client/public/default/assets/logo/base-icon.png +0 -0
- package/src/client/public/default/assets/logo/underpost.gif +0 -0
- package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
- package/src/client/public/default/favicon-16x16.png +0 -0
- package/src/client/public/default/favicon-32x32.png +0 -0
- package/src/client/public/default/favicon.ico +0 -0
- package/src/client/public/default/mstile-144x144.png +0 -0
- package/src/client/public/default/mstile-150x150.png +0 -0
- package/src/client/public/default/mstile-310x150.png +0 -0
- package/src/client/public/default/mstile-310x310.png +0 -0
- package/src/client/public/default/mstile-70x70.png +0 -0
- package/src/client/public/default/safari-pinned-tab.svg +24 -0
- package/src/client/ssr/body/DefaultSplashScreen.js +2 -2
- package/src/index.js +34 -17
- package/src/monitor.js +24 -0
- package/src/runtime/lampp/Dockerfile +30 -39
- package/src/runtime/lampp/Lampp.js +11 -2
- package/src/server/client-build-docs.js +205 -0
- package/src/server/client-build.js +16 -166
- package/src/server/conf.js +18 -8
- package/src/server/process.js +16 -19
- package/src/server/valkey.js +102 -41
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
renderStatus,
|
|
25
25
|
renderCssAttr,
|
|
26
26
|
} from './Css.js';
|
|
27
|
-
import { setDocTitle } from './Router.js';
|
|
27
|
+
import { setDocTitle, closeModalRouteChangeEvent, handleModalViewRoute } from './Router.js';
|
|
28
28
|
import { NotificationManager } from './NotificationManager.js';
|
|
29
29
|
import { EventsUI } from './EventsUI.js';
|
|
30
30
|
import { Translate } from './Translate.js';
|
|
@@ -39,6 +39,7 @@ const logger = loggerFactory(import.meta);
|
|
|
39
39
|
|
|
40
40
|
const Modal = {
|
|
41
41
|
Data: {},
|
|
42
|
+
|
|
42
43
|
Render: async function (
|
|
43
44
|
options = {
|
|
44
45
|
id: '',
|
|
@@ -86,14 +87,14 @@ const Modal = {
|
|
|
86
87
|
onBarUiOpen: {},
|
|
87
88
|
onBarUiClose: {},
|
|
88
89
|
onHome: {},
|
|
90
|
+
homeModals: options.homeModals ? options.homeModals : [],
|
|
89
91
|
query: options.query ? `${window.location.search}` : undefined,
|
|
90
92
|
};
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
top = `${
|
|
94
|
-
left = `${
|
|
95
|
-
}
|
|
96
|
-
if (idModal !== 'main-body') setCenterRestore();
|
|
93
|
+
|
|
94
|
+
if (idModal !== 'main-body' && options.mode !== 'view') {
|
|
95
|
+
top = `${window.innerHeight / 2 - height / 2}px`;
|
|
96
|
+
left = `${window.innerWidth / 2 - width / 2}px`;
|
|
97
|
+
}
|
|
97
98
|
if (options && 'mode' in options) {
|
|
98
99
|
this.Data[idModal][options.mode] = {};
|
|
99
100
|
switch (options.mode) {
|
|
@@ -104,6 +105,7 @@ const Modal = {
|
|
|
104
105
|
options.style = {
|
|
105
106
|
...options.style,
|
|
106
107
|
'min-width': `${minWidth}px`,
|
|
108
|
+
width: '100%',
|
|
107
109
|
};
|
|
108
110
|
|
|
109
111
|
if (this.mobileModal()) {
|
|
@@ -124,25 +126,84 @@ const Modal = {
|
|
|
124
126
|
};
|
|
125
127
|
Responsive.Event[`view-${idModal}`]();
|
|
126
128
|
|
|
127
|
-
//
|
|
128
|
-
if (options.route)
|
|
129
|
-
(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (path !== newPath) {
|
|
135
|
-
// console.warn('SET MODAL URI', newPath);
|
|
136
|
-
setPath(`${newPath}`); // ${location.search}
|
|
137
|
-
setDocTitle({ ...options.RouterInstance, route: options.route });
|
|
138
|
-
}
|
|
139
|
-
})();
|
|
129
|
+
// Handle view mode modal route
|
|
130
|
+
if (options.route) {
|
|
131
|
+
handleModalViewRoute({
|
|
132
|
+
route: options.route,
|
|
133
|
+
RouterInstance: options.RouterInstance,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
140
136
|
|
|
141
137
|
break;
|
|
142
138
|
case 'slide-menu':
|
|
143
139
|
case 'slide-menu-right':
|
|
144
140
|
case 'slide-menu-left':
|
|
145
141
|
(async () => {
|
|
142
|
+
if (!options.slideMenuTopBarBannerFix) {
|
|
143
|
+
options.slideMenuTopBarBannerFix = async () => {
|
|
144
|
+
let style = html``;
|
|
145
|
+
if (options.barMode === 'top-bottom-bar') {
|
|
146
|
+
style = html`<style>
|
|
147
|
+
.default-slide-menu-top-bar-fix-logo-container {
|
|
148
|
+
width: 50px;
|
|
149
|
+
height: 50px;
|
|
150
|
+
}
|
|
151
|
+
.default-slide-menu-top-bar-fix-logo {
|
|
152
|
+
width: 40px;
|
|
153
|
+
height: 40px;
|
|
154
|
+
padding: 5px;
|
|
155
|
+
}
|
|
156
|
+
.default-slide-menu-top-bar-fix-title-container-text {
|
|
157
|
+
font-size: 26px;
|
|
158
|
+
top: 8px;
|
|
159
|
+
color: ${darkTheme ? '#ffffff' : '#000000'};
|
|
160
|
+
}
|
|
161
|
+
</style>`;
|
|
162
|
+
} else {
|
|
163
|
+
style = html`<style>
|
|
164
|
+
.default-slide-menu-top-bar-fix-logo-container {
|
|
165
|
+
width: 100px;
|
|
166
|
+
height: 100px;
|
|
167
|
+
}
|
|
168
|
+
.default-slide-menu-top-bar-fix-logo {
|
|
169
|
+
width: 50px;
|
|
170
|
+
height: 50px;
|
|
171
|
+
padding: 24px;
|
|
172
|
+
}
|
|
173
|
+
.default-slide-menu-top-bar-fix-title-container-text {
|
|
174
|
+
font-size: 30px;
|
|
175
|
+
top: 30px;
|
|
176
|
+
color: ${darkTheme ? '#ffffff' : '#000000'};
|
|
177
|
+
}
|
|
178
|
+
</style>`;
|
|
179
|
+
}
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
if (s(`.top-bar-app-icon`) && s(`.top-bar-app-icon`).src) {
|
|
182
|
+
s(`.default-slide-menu-top-bar-fix-logo`).src = s(`.top-bar-app-icon`).src;
|
|
183
|
+
if (s(`.top-bar-app-icon`).classList.contains('negative-color'))
|
|
184
|
+
s(`.default-slide-menu-top-bar-fix-logo`).classList.add('negative-color');
|
|
185
|
+
htmls(
|
|
186
|
+
`.default-slide-menu-top-bar-fix-title-container`,
|
|
187
|
+
html`
|
|
188
|
+
<div class="inl default-slide-menu-top-bar-fix-title-container-text">
|
|
189
|
+
${options.RouterInstance.NameApp}
|
|
190
|
+
</div>
|
|
191
|
+
`,
|
|
192
|
+
);
|
|
193
|
+
} else
|
|
194
|
+
htmls(
|
|
195
|
+
`.default-slide-menu-top-bar-fix-logo-container`,
|
|
196
|
+
html`<div class="abs center">${s(`.action-btn-app-icon-render`).innerHTML}</div>`,
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return html`${style}
|
|
201
|
+
<div class="in fll default-slide-menu-top-bar-fix-logo-container">
|
|
202
|
+
<img class="default-slide-menu-top-bar-fix-logo in fll" />
|
|
203
|
+
</div>
|
|
204
|
+
<div class="in fll default-slide-menu-top-bar-fix-title-container"></div>`;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
146
207
|
const { barConfig } = options;
|
|
147
208
|
options.style = {
|
|
148
209
|
position: 'absolute',
|
|
@@ -247,8 +308,17 @@ const Modal = {
|
|
|
247
308
|
style="top: ${options.heightTopBar + 50}px; z-index: 9; ${true ||
|
|
248
309
|
(options.mode && options.mode.match('right'))
|
|
249
310
|
? 'right'
|
|
250
|
-
: 'left'}: 50px; width: 50px; height:
|
|
311
|
+
: 'left'}: 50px; width: 50px; height: 150px; transition: .3s"
|
|
251
312
|
>
|
|
313
|
+
<div
|
|
314
|
+
class="abs main-body-btn main-body-btn-ui"
|
|
315
|
+
style="top: 0px; ${true || (options.mode && options.mode.match('right')) ? 'right' : 'left'}: 0px"
|
|
316
|
+
>
|
|
317
|
+
<div class="abs center">
|
|
318
|
+
<i class="fas fa-caret-down main-body-btn-ui-open hide"></i>
|
|
319
|
+
<i class="fas fa-caret-up main-body-btn-ui-close"></i>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
252
322
|
<div
|
|
253
323
|
class="abs main-body-btn main-body-btn-menu"
|
|
254
324
|
style="top: 50px; ${true || (options.mode && options.mode.match('right'))
|
|
@@ -261,15 +331,18 @@ const Modal = {
|
|
|
261
331
|
</div>
|
|
262
332
|
</div>
|
|
263
333
|
<div
|
|
264
|
-
class="abs main-body-btn main-body-btn-
|
|
265
|
-
|
|
334
|
+
class="abs main-body-btn main-body-btn-bar-custom ${options?.slideMenuTopBarBannerFix
|
|
335
|
+
? ''
|
|
336
|
+
: 'hide'}"
|
|
337
|
+
style="top: 100px; ${true || (options.mode && options.mode.match('right'))
|
|
338
|
+
? 'right'
|
|
339
|
+
: 'left'}: 0px"
|
|
266
340
|
>
|
|
267
341
|
<div class="abs center">
|
|
268
|
-
<i class="
|
|
269
|
-
<i class="
|
|
342
|
+
<i class="fa-solid fa-magnifying-glass main-body-btn-ui-bar-custom-open"></i>
|
|
343
|
+
<i class="fa-solid fa-home hide main-body-btn-ui-bar-custom-close"></i>
|
|
270
344
|
</div>
|
|
271
345
|
</div>
|
|
272
|
-
<div class="main-body-btn-container-custom"></div>
|
|
273
346
|
</div>
|
|
274
347
|
`,
|
|
275
348
|
);
|
|
@@ -278,6 +351,22 @@ const Modal = {
|
|
|
278
351
|
Modal.actionBtnCenter();
|
|
279
352
|
};
|
|
280
353
|
|
|
354
|
+
s(`.main-body-btn-bar-custom`).onclick = () => {
|
|
355
|
+
if (s(`.main-body-btn-ui-close`).classList.contains('hide')) {
|
|
356
|
+
s(`.main-body-btn-ui`).click();
|
|
357
|
+
}
|
|
358
|
+
if (s(`.main-body-btn-ui-bar-custom-open`).classList.contains('hide')) {
|
|
359
|
+
s(`.main-body-btn-ui-bar-custom-open`).classList.remove('hide');
|
|
360
|
+
s(`.main-body-btn-ui-bar-custom-close`).classList.add('hide');
|
|
361
|
+
s(`.slide-menu-top-bar-fix`).style.top = '0px';
|
|
362
|
+
} else {
|
|
363
|
+
s(`.main-body-btn-ui-bar-custom-open`).classList.add('hide');
|
|
364
|
+
s(`.main-body-btn-ui-bar-custom-close`).classList.remove('hide');
|
|
365
|
+
s(`.slide-menu-top-bar-fix`).style.top = '-100px';
|
|
366
|
+
s(`.top-bar-search-box-container`).click();
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
281
370
|
let _heightTopBar, _heightBottomBar, _topMenu;
|
|
282
371
|
s(`.main-body-btn-ui`).onclick = () => {
|
|
283
372
|
if (s(`.main-body-btn-ui-open`).classList.contains('hide')) {
|
|
@@ -323,6 +412,7 @@ const Modal = {
|
|
|
323
412
|
);
|
|
324
413
|
}
|
|
325
414
|
};
|
|
415
|
+
Modal.setTopBannerLink();
|
|
326
416
|
});
|
|
327
417
|
|
|
328
418
|
const inputSearchBoxId = `top-bar-search-box`;
|
|
@@ -407,9 +497,14 @@ const Modal = {
|
|
|
407
497
|
})}
|
|
408
498
|
</div>
|
|
409
499
|
</div>
|
|
410
|
-
${options?.
|
|
411
|
-
? html`<div
|
|
412
|
-
|
|
500
|
+
${options?.slideMenuTopBarBannerFix
|
|
501
|
+
? html`<div
|
|
502
|
+
class="abs modal slide-menu-top-bar-fix"
|
|
503
|
+
style="height: ${options.heightTopBar}px; top: 0px"
|
|
504
|
+
>
|
|
505
|
+
<a class="a-link-top-banner">
|
|
506
|
+
<div class="inl">${await options.slideMenuTopBarBannerFix()}</div></a
|
|
507
|
+
>
|
|
413
508
|
</div>`
|
|
414
509
|
: ''}
|
|
415
510
|
</div>`,
|
|
@@ -434,8 +529,14 @@ const Modal = {
|
|
|
434
529
|
rules: [] /*{ type: 'isEmpty' }, { type: 'isEmail' }*/,
|
|
435
530
|
},
|
|
436
531
|
];
|
|
437
|
-
|
|
438
|
-
let
|
|
532
|
+
// Reusable hover/focus controller for search history panel
|
|
533
|
+
let unbindDocSearch = null;
|
|
534
|
+
const hoverFocusCtl = EventsUI.HoverFocusController({
|
|
535
|
+
inputSelector: `.top-bar-search-box-container`,
|
|
536
|
+
panelSelector: `.${id}`,
|
|
537
|
+
activeElementId: inputSearchBoxId,
|
|
538
|
+
onDismiss: () => dismissSearchBox(),
|
|
539
|
+
});
|
|
439
540
|
let currentKeyBoardSearchBoxIndex = 0;
|
|
440
541
|
let results = [];
|
|
441
542
|
let historySearchBox = [];
|
|
@@ -592,17 +693,29 @@ const Modal = {
|
|
|
592
693
|
const isSearchBoxActiveElement = isActiveElement(inputSearchBoxId);
|
|
593
694
|
checkHistoryBoxTitleStatus();
|
|
594
695
|
checkShortcutContainerInfoEnabled();
|
|
595
|
-
if (!isSearchBoxActiveElement && !
|
|
696
|
+
if (!isSearchBoxActiveElement && !hoverFocusCtl.shouldStay()) {
|
|
596
697
|
Modal.removeModal(searchBoxHistoryId);
|
|
597
698
|
return;
|
|
598
699
|
}
|
|
599
|
-
setTimeout(() =>
|
|
700
|
+
setTimeout(() => {
|
|
701
|
+
getResultSearchBox(validatorData);
|
|
702
|
+
|
|
703
|
+
if (
|
|
704
|
+
s(`.slide-menu-top-bar-fix`) &&
|
|
705
|
+
!s(`.main-body-btn-ui-bar-custom-open`).classList.contains('hide')
|
|
706
|
+
) {
|
|
707
|
+
s(`.main-body-btn-bar-custom`).click();
|
|
708
|
+
}
|
|
709
|
+
});
|
|
600
710
|
};
|
|
601
711
|
|
|
602
712
|
const getDefaultSearchBoxSelector = () => `.search-result-btn-${currentKeyBoardSearchBoxIndex}`;
|
|
603
713
|
|
|
604
714
|
const updateSearchBoxValue = (selector) => {
|
|
605
715
|
if (!selector) selector = getDefaultSearchBoxSelector();
|
|
716
|
+
// check exist childNodes
|
|
717
|
+
if (!s(selector) || !s(selector).hasChildNodes()) return;
|
|
718
|
+
|
|
606
719
|
if (s(selector).childNodes) {
|
|
607
720
|
if (
|
|
608
721
|
s(selector).childNodes[s(selector).childNodes.length - 1] &&
|
|
@@ -626,6 +739,10 @@ const Modal = {
|
|
|
626
739
|
|
|
627
740
|
const setSearchValue = (selector) => {
|
|
628
741
|
if (!selector) selector = getDefaultSearchBoxSelector();
|
|
742
|
+
|
|
743
|
+
// check exist childNodes
|
|
744
|
+
if (!s(selector) || !s(selector).hasChildNodes()) return;
|
|
745
|
+
|
|
629
746
|
historySearchBox = historySearchBox.filter(
|
|
630
747
|
(h) => h.routerId !== results[currentKeyBoardSearchBoxIndex].routerId,
|
|
631
748
|
);
|
|
@@ -676,27 +793,19 @@ const Modal = {
|
|
|
676
793
|
barMode: options.barMode,
|
|
677
794
|
});
|
|
678
795
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
796
|
+
// Bind hover/focus and click-outside to dismiss
|
|
797
|
+
hoverFocusCtl.bind();
|
|
798
|
+
unbindDocSearch = EventsUI.bindDismissOnDocumentClick({
|
|
799
|
+
shouldStay: hoverFocusCtl.shouldStay,
|
|
800
|
+
onDismiss: () => dismissSearchBox(),
|
|
801
|
+
anchors: [`.top-bar-search-box-container`, `.${id}`],
|
|
802
|
+
});
|
|
803
|
+
// Ensure cleanup when modal closes
|
|
804
|
+
Modal.Data[id].onCloseListener[`unbind-doc-${id}`] = () => unbindDocSearch && unbindDocSearch();
|
|
684
805
|
|
|
685
|
-
|
|
806
|
+
Modal.MoveTitleToBar(id);
|
|
686
807
|
|
|
687
|
-
|
|
688
|
-
hoverInputBox = true;
|
|
689
|
-
};
|
|
690
|
-
s(`.top-bar-search-box-container`).onmouseout = () => {
|
|
691
|
-
hoverInputBox = false;
|
|
692
|
-
};
|
|
693
|
-
s(`.${id}`).onmouseover = () => {
|
|
694
|
-
hoverHistBox = true;
|
|
695
|
-
};
|
|
696
|
-
s(`.${id}`).onmouseout = () => {
|
|
697
|
-
hoverHistBox = false;
|
|
698
|
-
s(`.${inputSearchBoxId}`).focus();
|
|
699
|
-
};
|
|
808
|
+
prepend(`.btn-bar-modal-container-${id}`, html`<div class="hide">${inputInfoNode.outerHTML}</div>`);
|
|
700
809
|
}
|
|
701
810
|
};
|
|
702
811
|
|
|
@@ -708,14 +817,23 @@ const Modal = {
|
|
|
708
817
|
searchBoxHistoryOpen();
|
|
709
818
|
searchBoxCallBack(formDataInfoNode[0]);
|
|
710
819
|
};
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
820
|
+
|
|
821
|
+
const dismissSearchBox = () => {
|
|
822
|
+
if (unbindDocSearch) {
|
|
823
|
+
try {
|
|
824
|
+
unbindDocSearch();
|
|
825
|
+
} catch (e) {}
|
|
714
826
|
}
|
|
827
|
+
Modal.removeModal(searchBoxHistoryId);
|
|
828
|
+
};
|
|
829
|
+
s('.top-bar-search-box').onblur = () => {
|
|
830
|
+
hoverFocusCtl.checkDismiss();
|
|
715
831
|
};
|
|
716
832
|
EventsUI.onClick(`.top-bar-search-box-container`, () => {
|
|
717
833
|
searchBoxHistoryOpen();
|
|
718
834
|
searchBoxCallBack(formDataInfoNode[0]);
|
|
835
|
+
const inputEl = s(`.${inputSearchBoxId}`);
|
|
836
|
+
if (inputEl && inputEl.focus) inputEl.focus();
|
|
719
837
|
});
|
|
720
838
|
|
|
721
839
|
const timePressDelay = 100;
|
|
@@ -881,6 +999,9 @@ const Modal = {
|
|
|
881
999
|
],
|
|
882
1000
|
eventCallBack: () => {
|
|
883
1001
|
if (s(`.top-bar-search-box`)) {
|
|
1002
|
+
if (s(`.main-body-btn-ui-close`).classList.contains('hide')) {
|
|
1003
|
+
s(`.main-body-btn-ui-open`).click();
|
|
1004
|
+
}
|
|
884
1005
|
s(`.top-bar-search-box`).blur();
|
|
885
1006
|
s(`.top-bar-search-box`).focus();
|
|
886
1007
|
s(`.top-bar-search-box`).select();
|
|
@@ -897,8 +1018,10 @@ const Modal = {
|
|
|
897
1018
|
barConfig.buttons.menu.disabled = true;
|
|
898
1019
|
barConfig.buttons.close.disabled = true;
|
|
899
1020
|
const id = 'bottom-bar';
|
|
900
|
-
if (
|
|
901
|
-
|
|
1021
|
+
if (!this.Data[idModal].homeModals) this.Data[idModal].homeModals = [];
|
|
1022
|
+
if (!this.Data[idModal].homeModals.includes(id)) {
|
|
1023
|
+
this.Data[idModal].homeModals.push(id);
|
|
1024
|
+
}
|
|
902
1025
|
const html = async () => html`
|
|
903
1026
|
<style>
|
|
904
1027
|
.top-bar-search-box-container {
|
|
@@ -1015,7 +1138,7 @@ const Modal = {
|
|
|
1015
1138
|
await Modal.onHomeRouterEvent();
|
|
1016
1139
|
Object.keys(this.Data[idModal].onHome).map((keyListener) => this.Data[idModal].onHome[keyListener]());
|
|
1017
1140
|
});
|
|
1018
|
-
EventsUI.onClick(`.action-btn-app-icon`, () =>
|
|
1141
|
+
EventsUI.onClick(`.action-btn-app-icon`, () => s(`.action-btn-home`).click());
|
|
1019
1142
|
Keyboard.instanceMultiPressKey({
|
|
1020
1143
|
id: 'input-shortcut-global-escape',
|
|
1021
1144
|
keys: ['Escape'],
|
|
@@ -1026,11 +1149,18 @@ const Modal = {
|
|
|
1026
1149
|
}
|
|
1027
1150
|
|
|
1028
1151
|
{
|
|
1029
|
-
ThemeEvents['action-btn-theme'] = () => {
|
|
1152
|
+
ThemeEvents['action-btn-theme'] = async () => {
|
|
1030
1153
|
htmls(
|
|
1031
1154
|
`.action-btn-theme-render`,
|
|
1032
1155
|
html` ${darkTheme ? html` <i class="fas fa-moon"></i>` : html`<i class="far fa-sun"></i>`}`,
|
|
1033
1156
|
);
|
|
1157
|
+
if (s(`.slide-menu-top-bar-fix`)) {
|
|
1158
|
+
htmls(
|
|
1159
|
+
`.slide-menu-top-bar-fix`,
|
|
1160
|
+
html`<a class="a-link-top-banner">${await options.slideMenuTopBarBannerFix()}</a>`,
|
|
1161
|
+
);
|
|
1162
|
+
Modal.setTopBannerLink();
|
|
1163
|
+
}
|
|
1034
1164
|
};
|
|
1035
1165
|
ThemeEvents['action-btn-theme']();
|
|
1036
1166
|
|
|
@@ -1048,13 +1178,80 @@ const Modal = {
|
|
|
1048
1178
|
|
|
1049
1179
|
{
|
|
1050
1180
|
htmls(`.action-btn-lang-render`, html` ${s('html').lang}`);
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1181
|
+
// old method
|
|
1182
|
+
// EventsUI.onClick(`.action-btn-lang`, () => {
|
|
1183
|
+
// let lang = 'en';
|
|
1184
|
+
// if (s('html').lang === 'en') lang = 'es';
|
|
1185
|
+
// if (s(`.dropdown-option-${lang}`))
|
|
1186
|
+
// DropDown.Tokens['settings-lang'].onClickEvents[`dropdown-option-${lang}`]();
|
|
1187
|
+
// else Translate.renderLang(lang);
|
|
1188
|
+
// });
|
|
1189
|
+
|
|
1190
|
+
// Open lightweight empty modal on language button, with shared dismiss logic
|
|
1191
|
+
EventsUI.onClick(
|
|
1192
|
+
`.action-btn-lang`,
|
|
1193
|
+
async () => {
|
|
1194
|
+
const id = 'action-btn-lang-modal';
|
|
1195
|
+
if (s(`.${id}`)) {
|
|
1196
|
+
return s(`.btn-close-${id}`).click();
|
|
1197
|
+
}
|
|
1198
|
+
const { barConfig } = await Themes[Css.currentTheme]();
|
|
1199
|
+
barConfig.buttons.maximize.disabled = true;
|
|
1200
|
+
barConfig.buttons.minimize.disabled = true;
|
|
1201
|
+
barConfig.buttons.restore.disabled = true;
|
|
1202
|
+
barConfig.buttons.menu.disabled = true;
|
|
1203
|
+
barConfig.buttons.close.disabled = false;
|
|
1204
|
+
await Modal.Render({
|
|
1205
|
+
id,
|
|
1206
|
+
barConfig,
|
|
1207
|
+
title: html`${renderViewTitle({
|
|
1208
|
+
icon: html`<i class="fas fa-language mini-title"></i>`,
|
|
1209
|
+
text: Translate.Render('select lang'),
|
|
1210
|
+
})}`,
|
|
1211
|
+
html: async () => html`${await Translate.RenderSetting('action-drop-modal' + id)}`,
|
|
1212
|
+
titleClass: 'mini-title',
|
|
1213
|
+
style: {
|
|
1214
|
+
resize: 'none',
|
|
1215
|
+
width: '100% !important',
|
|
1216
|
+
height: '350px !important',
|
|
1217
|
+
'max-width': '350px !important',
|
|
1218
|
+
'z-index': 7,
|
|
1219
|
+
},
|
|
1220
|
+
dragDisabled: true,
|
|
1221
|
+
maximize: true,
|
|
1222
|
+
heightBottomBar: 0,
|
|
1223
|
+
heightTopBar: originHeightTopBar,
|
|
1224
|
+
barMode: options.barMode,
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1227
|
+
// Move title inside the bar container to align with control buttons
|
|
1228
|
+
Modal.MoveTitleToBar(id);
|
|
1229
|
+
|
|
1230
|
+
// Position the language selection modal relative to the language button
|
|
1231
|
+
Modal.positionRelativeToAnchor({
|
|
1232
|
+
modalSelector: `.${id}`,
|
|
1233
|
+
anchorSelector: '.action-btn-lang',
|
|
1234
|
+
align: 'right',
|
|
1235
|
+
offset: { x: 0, y: 6 },
|
|
1236
|
+
autoVertical: true,
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
// Hover/focus controller uses the button as input anchor
|
|
1240
|
+
const hoverFocusCtl = EventsUI.HoverFocusController({
|
|
1241
|
+
inputSelector: `.action-btn-lang`,
|
|
1242
|
+
panelSelector: `.${id}`,
|
|
1243
|
+
onDismiss: () => Modal.removeModal(id),
|
|
1244
|
+
});
|
|
1245
|
+
hoverFocusCtl.bind();
|
|
1246
|
+
const unbindDoc = EventsUI.bindDismissOnDocumentClick({
|
|
1247
|
+
shouldStay: hoverFocusCtl.shouldStay,
|
|
1248
|
+
onDismiss: () => Modal.removeModal(id),
|
|
1249
|
+
anchors: [`.action-btn-lang`, `.${id}`],
|
|
1250
|
+
});
|
|
1251
|
+
Modal.Data[id].onCloseListener[`unbind-doc-${id}`] = () => unbindDoc();
|
|
1252
|
+
},
|
|
1253
|
+
{ context: 'modal', noGate: true, noLoading: true },
|
|
1254
|
+
);
|
|
1058
1255
|
}
|
|
1059
1256
|
|
|
1060
1257
|
{
|
|
@@ -1348,19 +1545,18 @@ const Modal = {
|
|
|
1348
1545
|
this.onHomeRouterEvent = async () => {
|
|
1349
1546
|
for (const keyModal of Object.keys(this.Data)) {
|
|
1350
1547
|
if (
|
|
1351
|
-
![idModal, 'main-body-top', 'main-body']
|
|
1352
|
-
.concat(options?.homeModals ? options.homeModals : [])
|
|
1353
|
-
.includes(keyModal)
|
|
1548
|
+
![idModal, 'main-body-top', 'main-body'].concat(this.Data[idModal]?.homeModals || []).includes(keyModal)
|
|
1354
1549
|
)
|
|
1355
|
-
s(`.btn-close-${keyModal}`).click();
|
|
1550
|
+
if (s(`.btn-close-${keyModal}`)) s(`.btn-close-${keyModal}`).click();
|
|
1356
1551
|
backMenuButtonEvent();
|
|
1357
1552
|
}
|
|
1358
|
-
s(`.btn-close-modal-menu`).click();
|
|
1553
|
+
if (s(`.btn-close-modal-menu`)) s(`.btn-close-modal-menu`).click();
|
|
1359
1554
|
setPath(getProxyPath());
|
|
1360
|
-
setDocTitle(
|
|
1555
|
+
setDocTitle();
|
|
1361
1556
|
};
|
|
1362
1557
|
s(`.main-btn-home`).onclick = async () => {
|
|
1363
|
-
await this.onHomeRouterEvent();
|
|
1558
|
+
// await this.onHomeRouterEvent();
|
|
1559
|
+
s(`.action-btn-home`).click();
|
|
1364
1560
|
};
|
|
1365
1561
|
EventsUI.onClick(`.btn-icon-menu-back`, backMenuButtonEvent);
|
|
1366
1562
|
EventsUI.onClick(`.btn-icon-menu-mode`, () => {
|
|
@@ -1429,42 +1625,139 @@ const Modal = {
|
|
|
1429
1625
|
default:
|
|
1430
1626
|
break;
|
|
1431
1627
|
}
|
|
1628
|
+
// Track drag position for consistency
|
|
1629
|
+
let dragPosition = { x: 0, y: 0 };
|
|
1630
|
+
|
|
1631
|
+
// Initialize drag options with proper bounds and smooth transitions
|
|
1432
1632
|
let dragOptions = {
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1633
|
+
handle: handle,
|
|
1634
|
+
bounds: {
|
|
1635
|
+
top: 0,
|
|
1636
|
+
left: 0,
|
|
1637
|
+
right: 0,
|
|
1638
|
+
bottom: 0,
|
|
1639
|
+
},
|
|
1640
|
+
preventDefault: true,
|
|
1641
|
+
position: { x: 0, y: 0 },
|
|
1642
|
+
onDragStart: () => {
|
|
1643
|
+
const modal = s(`.${idModal}`);
|
|
1644
|
+
if (!modal) return false; // Prevent drag if modal not found
|
|
1645
|
+
|
|
1646
|
+
// Store current position
|
|
1647
|
+
const computedStyle = window.getComputedStyle(modal);
|
|
1648
|
+
const matrix = new DOMMatrixReadOnly(computedStyle.transform);
|
|
1649
|
+
dragPosition = {
|
|
1650
|
+
x: matrix.m41 || 0,
|
|
1651
|
+
y: matrix.m42 || 0,
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1654
|
+
modal.style.transition = 'none';
|
|
1655
|
+
modal.style.willChange = 'transform';
|
|
1656
|
+
return true; // Allow drag to start
|
|
1439
1657
|
},
|
|
1440
1658
|
onDrag: (data) => {
|
|
1441
|
-
|
|
1442
|
-
|
|
1659
|
+
// Update position based on drag delta
|
|
1660
|
+
dragPosition = { x: data.x, y: data.y };
|
|
1443
1661
|
},
|
|
1444
|
-
onDragEnd: (
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1662
|
+
onDragEnd: () => {
|
|
1663
|
+
const modal = s(`.${idModal}`);
|
|
1664
|
+
if (!modal) return;
|
|
1665
|
+
|
|
1666
|
+
modal.style.willChange = '';
|
|
1667
|
+
modal.style.transition = transition;
|
|
1668
|
+
|
|
1669
|
+
// Update drag instance with current position
|
|
1670
|
+
if (dragInstance) {
|
|
1671
|
+
dragInstance.updateOptions({
|
|
1672
|
+
position: dragPosition,
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
// Notify listeners
|
|
1677
|
+
Object.keys(this.Data[idModal].onDragEndListener || {}).forEach((keyListener) => {
|
|
1678
|
+
this.Data[idModal].onDragEndListener[keyListener]?.();
|
|
1679
|
+
});
|
|
1451
1680
|
},
|
|
1452
1681
|
};
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1682
|
+
|
|
1683
|
+
let dragInstance = null;
|
|
1684
|
+
|
|
1685
|
+
// Initialize or update drag instance
|
|
1686
|
+
const setDragInstance = () => {
|
|
1687
|
+
if (options?.dragDisabled) {
|
|
1688
|
+
if (dragInstance) {
|
|
1689
|
+
dragInstance.destroy();
|
|
1690
|
+
dragInstance = null;
|
|
1691
|
+
}
|
|
1692
|
+
return null;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
const modal = s(`.${idModal}`);
|
|
1696
|
+
if (!modal) {
|
|
1697
|
+
console.warn(`Modal element .${idModal} not found for drag initialization`);
|
|
1698
|
+
return null;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// Ensure the modal has position: absolute for proper dragging
|
|
1702
|
+
if (window.getComputedStyle(modal).position !== 'absolute') {
|
|
1703
|
+
modal.style.position = 'absolute';
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
// Clean up existing instance
|
|
1707
|
+
if (dragInstance) {
|
|
1708
|
+
dragInstance.destroy();
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
try {
|
|
1712
|
+
// Create new instance with updated options
|
|
1713
|
+
dragInstance = new Draggable(modal, dragOptions);
|
|
1714
|
+
return dragInstance;
|
|
1715
|
+
} catch (error) {
|
|
1716
|
+
console.error('Failed to initialize draggable:', error);
|
|
1717
|
+
return null;
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1720
|
+
|
|
1721
|
+
// Expose method to update drag options
|
|
1456
1722
|
this.Data[idModal].setDragInstance = (updateDragOptions) => {
|
|
1457
|
-
|
|
1458
|
-
...dragOptions,
|
|
1459
|
-
|
|
1460
|
-
};
|
|
1723
|
+
if (updateDragOptions) {
|
|
1724
|
+
dragOptions = { ...dragOptions, ...updateDragOptions };
|
|
1725
|
+
}
|
|
1461
1726
|
dragInstance = setDragInstance();
|
|
1462
1727
|
this.Data[idModal].dragInstance = dragInstance;
|
|
1463
1728
|
this.Data[idModal].dragOptions = dragOptions;
|
|
1464
1729
|
};
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1730
|
+
// Initialize modal with proper transitions
|
|
1731
|
+
const modal = s(`.${idModal}`);
|
|
1732
|
+
if (modal) {
|
|
1733
|
+
// Initial state
|
|
1734
|
+
modal.style.transition = 'opacity 0.15s ease, transform 0.3s ease';
|
|
1735
|
+
modal.style.opacity = '0';
|
|
1736
|
+
|
|
1737
|
+
// Trigger fade-in after a small delay to allow initial render
|
|
1738
|
+
requestAnimationFrame(() => {
|
|
1739
|
+
if (!modal) return;
|
|
1740
|
+
modal.style.opacity = '1';
|
|
1741
|
+
|
|
1742
|
+
// Set final transition after initial animation completes
|
|
1743
|
+
setTimeout(() => {
|
|
1744
|
+
if (modal) {
|
|
1745
|
+
modal.style.transition = transition;
|
|
1746
|
+
|
|
1747
|
+
// Initialize drag after transitions are set
|
|
1748
|
+
if (!options.dragDisabled) {
|
|
1749
|
+
setDragInstance();
|
|
1750
|
+
if (!options.mode) {
|
|
1751
|
+
dragInstance.updateOptions({
|
|
1752
|
+
position: { x: 0, y: 0 },
|
|
1753
|
+
disabled: false, // Ensure drag is enabled after restore
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}, 150);
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1468
1761
|
|
|
1469
1762
|
const btnCloseEvent = () => {
|
|
1470
1763
|
Object.keys(this.Data[idModal].onCloseListener).map((keyListener) =>
|
|
@@ -1480,62 +1773,122 @@ const Modal = {
|
|
|
1480
1773
|
setTimeout(() => {
|
|
1481
1774
|
if (!s(`.${idModal}`)) return;
|
|
1482
1775
|
this.removeModal(idModal);
|
|
1483
|
-
//
|
|
1484
|
-
if (options.route)
|
|
1485
|
-
(
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
if (this.Data[subIdModal].options.route) {
|
|
1492
|
-
newPath = `${newPath}${this.Data[subIdModal].options.route}`;
|
|
1493
|
-
// console.warn('SET MODAL URI', newPath);
|
|
1494
|
-
setPath(newPath);
|
|
1495
|
-
this.setTopModalCallback(subIdModal);
|
|
1496
|
-
return setDocTitle({ ...options.RouterInstance, route: this.Data[subIdModal].options.route });
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
// console.warn('SET MODAL URI', newPath);
|
|
1500
|
-
setPath(`${newPath}${Modal.homeCid ? `?cid=${Modal.homeCid}` : ''}`);
|
|
1501
|
-
return setDocTitle({ ...options.RouterInstance, route: '' });
|
|
1502
|
-
}
|
|
1503
|
-
})();
|
|
1776
|
+
// Handle modal route change
|
|
1777
|
+
if (options.route) {
|
|
1778
|
+
closeModalRouteChangeEvent({
|
|
1779
|
+
route: options.route,
|
|
1780
|
+
RouterInstance: options.RouterInstance,
|
|
1781
|
+
homeCid: Modal.homeCid,
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1504
1784
|
}, 300);
|
|
1505
1785
|
};
|
|
1506
1786
|
s(`.btn-close-${idModal}`).onclick = btnCloseEvent;
|
|
1507
1787
|
|
|
1788
|
+
// Minimize button handler
|
|
1508
1789
|
s(`.btn-minimize-${idModal}`).onclick = () => {
|
|
1509
|
-
|
|
1510
|
-
|
|
1790
|
+
const modal = s(`.${idModal}`);
|
|
1791
|
+
if (!modal) return;
|
|
1792
|
+
|
|
1793
|
+
if (options.slideMenu) {
|
|
1794
|
+
delete this.Data[idModal].slideMenu;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
// Keep drag enabled when minimized
|
|
1798
|
+
if (dragInstance) {
|
|
1799
|
+
dragInstance.updateOptions({ disabled: false });
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
// Set up transition
|
|
1803
|
+
modal.style.transition = 'height 0.3s ease, transform 0.3s ease';
|
|
1804
|
+
|
|
1805
|
+
// Update button states
|
|
1511
1806
|
s(`.btn-minimize-${idModal}`).style.display = 'none';
|
|
1512
1807
|
s(`.btn-maximize-${idModal}`).style.display = null;
|
|
1513
1808
|
s(`.btn-restore-${idModal}`).style.display = null;
|
|
1514
|
-
|
|
1515
|
-
|
|
1809
|
+
|
|
1810
|
+
// Collapse to header height
|
|
1811
|
+
const header = s(`.bar-default-modal-${idModal}`);
|
|
1812
|
+
if (header) {
|
|
1813
|
+
modal.style.height = `${header.clientHeight}px`;
|
|
1814
|
+
modal.style.overflow = 'hidden';
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
// Restore transition after animation
|
|
1818
|
+
setTimeout(() => {
|
|
1819
|
+
if (modal) {
|
|
1820
|
+
modal.style.transition = transition;
|
|
1821
|
+
}
|
|
1822
|
+
}, 300);
|
|
1516
1823
|
};
|
|
1824
|
+
// Restore button handler
|
|
1517
1825
|
s(`.btn-restore-${idModal}`).onclick = () => {
|
|
1518
|
-
|
|
1519
|
-
|
|
1826
|
+
const modal = s(`.${idModal}`);
|
|
1827
|
+
if (!modal) return;
|
|
1828
|
+
|
|
1829
|
+
if (options.slideMenu) {
|
|
1830
|
+
delete this.Data[idModal].slideMenu;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
// Re-enable dragging
|
|
1834
|
+
if (dragInstance) {
|
|
1835
|
+
dragInstance.updateOptions({ disabled: false });
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
// Set up transition
|
|
1839
|
+
modal.style.transition = 'all 0.3s ease';
|
|
1840
|
+
|
|
1841
|
+
// Update button states
|
|
1520
1842
|
s(`.btn-restore-${idModal}`).style.display = 'none';
|
|
1521
1843
|
s(`.btn-minimize-${idModal}`).style.display = null;
|
|
1522
1844
|
s(`.btn-maximize-${idModal}`).style.display = null;
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1845
|
+
|
|
1846
|
+
// Restore original dimensions and position
|
|
1847
|
+
modal.style.transform = '';
|
|
1848
|
+
modal.style.height = '';
|
|
1849
|
+
left = 0;
|
|
1850
|
+
width = 300;
|
|
1851
|
+
modal.style.left = `${left}px`;
|
|
1852
|
+
modal.style.width = `${width}px`;
|
|
1853
|
+
modal.style.overflow = '';
|
|
1854
|
+
|
|
1855
|
+
// Reset drag position
|
|
1856
|
+
dragPosition = { x: 0, y: 0 };
|
|
1857
|
+
|
|
1858
|
+
// Set new position
|
|
1859
|
+
modal.style.transform = `translate(0, 0)`;
|
|
1860
|
+
|
|
1861
|
+
// Adjust top position based on top bar visibility
|
|
1862
|
+
const heightDefaultTopBar = 40; // Default top bar height if not specified
|
|
1863
|
+
s(`.${idModal}`).style.top = s(`.main-body-btn-ui-close`).classList.contains('hide')
|
|
1864
|
+
? `0px`
|
|
1865
|
+
: `${options.heightTopBar ? options.heightTopBar : heightDefaultTopBar}px`;
|
|
1866
|
+
|
|
1867
|
+
// Re-enable drag after restore
|
|
1868
|
+
if (dragInstance) {
|
|
1869
|
+
dragInstance.updateOptions({
|
|
1870
|
+
position: { x: 0, y: 0 },
|
|
1871
|
+
disabled: false, // Ensure drag is enabled after restore
|
|
1872
|
+
});
|
|
1873
|
+
}
|
|
1874
|
+
setTimeout(() => (s(`.${idModal}`) ? (s(`.${idModal}`).style.transition = transition) : null), 300);
|
|
1531
1875
|
};
|
|
1532
1876
|
s(`.btn-maximize-${idModal}`).onclick = () => {
|
|
1533
|
-
s(`.${idModal}`)
|
|
1534
|
-
|
|
1877
|
+
const modal = s(`.${idModal}`);
|
|
1878
|
+
if (!modal) return;
|
|
1879
|
+
|
|
1880
|
+
// Disable drag when maximizing
|
|
1881
|
+
if (dragInstance) {
|
|
1882
|
+
dragInstance.updateOptions({ disabled: true });
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
modal.style.transition = '0.3s';
|
|
1886
|
+
setTimeout(() => (modal ? (modal.style.transition = transition) : null), 300);
|
|
1887
|
+
|
|
1535
1888
|
s(`.btn-maximize-${idModal}`).style.display = 'none';
|
|
1536
1889
|
s(`.btn-restore-${idModal}`).style.display = null;
|
|
1537
1890
|
s(`.btn-minimize-${idModal}`).style.display = null;
|
|
1538
|
-
|
|
1891
|
+
modal.style.transform = null;
|
|
1539
1892
|
|
|
1540
1893
|
if (options.slideMenu) {
|
|
1541
1894
|
const idSlide = this.Data[options.slideMenu]['slide-menu']
|
|
@@ -1770,6 +2123,114 @@ const Modal = {
|
|
|
1770
2123
|
};
|
|
1771
2124
|
});
|
|
1772
2125
|
},
|
|
2126
|
+
// Move modal title element into the bar's render container so it aligns with control buttons
|
|
2127
|
+
/**
|
|
2128
|
+
* Position a modal relative to an anchor element
|
|
2129
|
+
* @param {Object} options - Positioning options
|
|
2130
|
+
* @param {string} options.modalSelector - CSS selector for the modal element
|
|
2131
|
+
* @param {string} options.anchorSelector - CSS selector for the anchor element
|
|
2132
|
+
* @param {Object} [options.offset={x: 0, y: 6}] - Offset from anchor
|
|
2133
|
+
* @param {string} [options.align='right'] - Horizontal alignment ('left' or 'right')
|
|
2134
|
+
* @param {boolean} [options.autoVertical=true] - Whether to automatically determine vertical position
|
|
2135
|
+
* @param {boolean} [options.placeAbove] - Force position above/below anchor (overrides autoVertical)
|
|
2136
|
+
*/
|
|
2137
|
+
positionRelativeToAnchor({
|
|
2138
|
+
modalSelector,
|
|
2139
|
+
anchorSelector,
|
|
2140
|
+
offset = { x: 0, y: 6 },
|
|
2141
|
+
align = 'right',
|
|
2142
|
+
autoVertical = true,
|
|
2143
|
+
placeAbove,
|
|
2144
|
+
}) {
|
|
2145
|
+
try {
|
|
2146
|
+
const modal = s(modalSelector);
|
|
2147
|
+
const anchor = s(anchorSelector);
|
|
2148
|
+
|
|
2149
|
+
if (!modal || !anchor || !anchor.getBoundingClientRect) return;
|
|
2150
|
+
|
|
2151
|
+
// First, position the modal near its final position but off-screen
|
|
2152
|
+
const arect = anchor.getBoundingClientRect();
|
|
2153
|
+
const vh = window.innerHeight;
|
|
2154
|
+
const vw = window.innerWidth;
|
|
2155
|
+
const safeMargin = 6;
|
|
2156
|
+
|
|
2157
|
+
// Determine vertical position
|
|
2158
|
+
let finalPlaceAbove = placeAbove;
|
|
2159
|
+
if (autoVertical && placeAbove === undefined) {
|
|
2160
|
+
const inBottomBar = anchor.closest && anchor.closest('.bottom-bar');
|
|
2161
|
+
const inTopBar = anchor.closest && anchor.closest('.slide-menu-top-bar');
|
|
2162
|
+
|
|
2163
|
+
if (inBottomBar) finalPlaceAbove = true;
|
|
2164
|
+
else if (inTopBar) finalPlaceAbove = false;
|
|
2165
|
+
else finalPlaceAbove = arect.top > vh / 2; // heuristic fallback
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
// Set initial position (slightly offset from final position)
|
|
2169
|
+
const initialOffset = finalPlaceAbove ? 20 : -20;
|
|
2170
|
+
modal.style.position = 'fixed';
|
|
2171
|
+
modal.style.opacity = '0';
|
|
2172
|
+
modal.style.transition = 'opacity 150ms ease-out, transform 150ms ease-out';
|
|
2173
|
+
|
|
2174
|
+
// Position near the anchor but slightly offset
|
|
2175
|
+
modal.style.top = `${finalPlaceAbove ? arect.top - 40 : arect.bottom + 20}px`;
|
|
2176
|
+
modal.style.left = `${align === 'right' ? arect.right - 200 : arect.left}px`;
|
|
2177
|
+
modal.style.transform = 'translateY(0)';
|
|
2178
|
+
|
|
2179
|
+
// Force reflow to ensure initial styles are applied
|
|
2180
|
+
modal.offsetHeight;
|
|
2181
|
+
|
|
2182
|
+
// Now calculate final position
|
|
2183
|
+
const mrect = modal.getBoundingClientRect();
|
|
2184
|
+
|
|
2185
|
+
// Calculate final top position
|
|
2186
|
+
const top = finalPlaceAbove ? arect.top - mrect.height - offset.y : arect.bottom + offset.y;
|
|
2187
|
+
|
|
2188
|
+
// Calculate final left position based on alignment
|
|
2189
|
+
let left;
|
|
2190
|
+
if (align === 'right') {
|
|
2191
|
+
left = arect.right - mrect.width - offset.x; // align right edges
|
|
2192
|
+
} else {
|
|
2193
|
+
left = arect.left + offset.x; // align left edges
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
// Ensure modal stays within viewport bounds
|
|
2197
|
+
left = Math.max(safeMargin, Math.min(left, vw - mrect.width - safeMargin));
|
|
2198
|
+
const finalTop = Math.max(safeMargin, Math.min(top, vh - mrect.height - safeMargin));
|
|
2199
|
+
|
|
2200
|
+
// Apply final position with smooth transition
|
|
2201
|
+
requestAnimationFrame(() => {
|
|
2202
|
+
modal.style.top = `${Math.round(finalTop)}px`;
|
|
2203
|
+
modal.style.left = `${Math.round(left)}px`;
|
|
2204
|
+
modal.style.opacity = '1';
|
|
2205
|
+
});
|
|
2206
|
+
} catch (e) {
|
|
2207
|
+
console.error('Error positioning modal:', e);
|
|
2208
|
+
}
|
|
2209
|
+
},
|
|
2210
|
+
|
|
2211
|
+
MoveTitleToBar(idModal) {
|
|
2212
|
+
try {
|
|
2213
|
+
const titleEl = s(`.title-modal-${idModal}`);
|
|
2214
|
+
const container = s(`.btn-bar-modal-container-render-${idModal}`);
|
|
2215
|
+
if (!titleEl || !container) return;
|
|
2216
|
+
const titleNode = titleEl.cloneNode(true);
|
|
2217
|
+
titleEl.remove();
|
|
2218
|
+
container.classList.add('in');
|
|
2219
|
+
container.classList.add('fll');
|
|
2220
|
+
container.appendChild(titleNode);
|
|
2221
|
+
} catch (e) {
|
|
2222
|
+
// non-fatal: keep default placement if structure not present
|
|
2223
|
+
}
|
|
2224
|
+
},
|
|
2225
|
+
setTopBannerLink: function () {
|
|
2226
|
+
if (s(`.a-link-top-banner`)) {
|
|
2227
|
+
s(`.a-link-top-banner`).setAttribute('href', `${location.origin}${getProxyPath()}`);
|
|
2228
|
+
EventsUI.onClick(`.a-link-top-banner`, (e) => {
|
|
2229
|
+
e.preventDefault();
|
|
2230
|
+
s(`.action-btn-home`).click();
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2233
|
+
},
|
|
1773
2234
|
headerTitleHeight: 40,
|
|
1774
2235
|
actionBtnCenter: function () {
|
|
1775
2236
|
if (!s(`.btn-close-modal-menu`).classList.contains('hide')) {
|