inviton-powerduck 0.0.179 → 0.0.181
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/common/dialog-utils.ts +9 -1
- package/components/_common/css/modal-mobile-control.css +3 -0
- package/components/input/daterange-picker.tsx +76 -25
- package/components/input/plugins/daterangepicker/daterangepicker.css +80 -11
- package/components/input/plugins/daterangepicker/jquery.daterangepicker.ts +284 -145
- package/components/modal/modal-utils.ts +94 -0
- package/components/modal/modal.tsx +4 -92
- package/package.json +1 -1
package/common/dialog-utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Modal as BootstrapModal } from 'bootstrap';
|
|
|
2
2
|
import { globalState } from '../app/global-state';
|
|
3
3
|
import PowerduckState from '../app/powerduck-state';
|
|
4
4
|
import { ButtonLayout } from '../components/button/button-layout';
|
|
5
|
+
import { ModalUtils } from '../components/modal/modal-utils';
|
|
5
6
|
import { DialogIcons } from './enums/dialog-icons';
|
|
6
7
|
import { isNullOrEmpty } from './utils/is-null-or-empty';
|
|
7
8
|
import { PortalUtils } from './utils/utils';
|
|
@@ -54,6 +55,7 @@ export interface AppDialogButton {
|
|
|
54
55
|
export interface AppDialogArgs {
|
|
55
56
|
title: string;
|
|
56
57
|
message: string;
|
|
58
|
+
mobileMode?: 'default' | 'bottom-sheet' | 'fullscreen';
|
|
57
59
|
icon?: DialogIcons;
|
|
58
60
|
autoHide?: boolean;
|
|
59
61
|
boxColor?: string;
|
|
@@ -123,10 +125,11 @@ class DialogBuilder {
|
|
|
123
125
|
this.builder
|
|
124
126
|
+= `<div id="${this.id}" key="${this.id
|
|
125
127
|
}" tabindex="-1" role="dialog" aria-labelledby="${this.labelId
|
|
126
|
-
}" data-bs-backdrop="true" data-bs-keyboard="true" class="modal fade${args.cssClass ? ` ${args.cssClass}` : ''
|
|
128
|
+
}" data-bs-backdrop="true" data-bs-keyboard="true" class="modal fade modal-bottom-sheet${args.cssClass ? ` ${args.cssClass}` : ''
|
|
127
129
|
}">`;
|
|
128
130
|
this.builder += ` <div role="document" class="modal-dialog${args.size != null ? ` ${args.size}` : ''}">`;
|
|
129
131
|
this.builder += ' <div class="modal-content">';
|
|
132
|
+
this.builder += ' <div class="drag-handle text-center"><div class="handle-bar"></div></div>';
|
|
130
133
|
|
|
131
134
|
this.builder += this._getHeader();
|
|
132
135
|
this.builder += this._getBody();
|
|
@@ -240,6 +243,11 @@ export class DialogUtils {
|
|
|
240
243
|
}, 50);
|
|
241
244
|
});
|
|
242
245
|
|
|
246
|
+
if (args.mobileMode == null || args.mobileMode == 'bottom-sheet') {
|
|
247
|
+
const modal = document.getElementById(builder.id);
|
|
248
|
+
ModalUtils.bindModalBottomSheetHandle(() => modal, () => ModalUtils.hideModal(modalContext));
|
|
249
|
+
}
|
|
250
|
+
|
|
243
251
|
const ensureIconAnimation = function (
|
|
244
252
|
selector: string,
|
|
245
253
|
icon: DialogIcons,
|
|
@@ -5,6 +5,7 @@ import { Prop, toNative } from 'vue-facing-decorator';
|
|
|
5
5
|
import { globalState } from '../../app/global-state';
|
|
6
6
|
import PowerduckState from '../../app/powerduck-state';
|
|
7
7
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
8
|
+
import { DialogUtils } from '../../common/dialog-utils';
|
|
8
9
|
import { utcEpochMilliseconds } from '../../common/extensions/temporal-extensions';
|
|
9
10
|
import DateUtils from '../../common/utils/date-utils';
|
|
10
11
|
import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
|
|
@@ -13,6 +14,7 @@ import { PortalUtils } from '../../common/utils/utils';
|
|
|
13
14
|
import FormItemWrapper from '../form/form-item-wrapper';
|
|
14
15
|
import DateInputHelper from './ts/dateInputHelper';
|
|
15
16
|
import './plugins/daterangepicker/jquery.daterangepicker';
|
|
17
|
+
import './../_common/css/modal-mobile-control.css';
|
|
16
18
|
import './css/daterange-picker.css';
|
|
17
19
|
|
|
18
20
|
export interface DaterangePickerArgsCustomCellRenderArgs {
|
|
@@ -31,6 +33,8 @@ export interface DaterangePickerArgsCustomCellRenderDay {
|
|
|
31
33
|
valid: boolean;
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
type CalendarPlacement = 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
|
|
37
|
+
|
|
34
38
|
interface DaterangePickerArgs extends FormItemWrapperArgs {
|
|
35
39
|
disabled?: boolean;
|
|
36
40
|
value?: DaterangeChangedArgs;
|
|
@@ -48,7 +52,7 @@ interface DaterangePickerArgs extends FormItemWrapperArgs {
|
|
|
48
52
|
nextIcon?: string;
|
|
49
53
|
hideYearInMonthName?: boolean;
|
|
50
54
|
singleMonth?: boolean;
|
|
51
|
-
calendarPlacement?:
|
|
55
|
+
calendarPlacement?: CalendarPlacement;
|
|
52
56
|
ensureMonthContinuity?: boolean;
|
|
53
57
|
monthSelect?: boolean;
|
|
54
58
|
yearSelect?: boolean;
|
|
@@ -107,7 +111,7 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
|
|
|
107
111
|
@Prop() prependIconClicked: () => void;
|
|
108
112
|
@Prop() appendIconClicked: () => void;
|
|
109
113
|
@Prop() marginType?: MarginType;
|
|
110
|
-
@Prop() calendarPlacement?:
|
|
114
|
+
@Prop() calendarPlacement?: CalendarPlacement;
|
|
111
115
|
@Prop() changed: (newValue: DaterangeChangedArgs) => void;
|
|
112
116
|
@Prop() format?: string;
|
|
113
117
|
@Prop() showClearValueButton!: boolean;
|
|
@@ -155,6 +159,10 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
|
|
|
155
159
|
}
|
|
156
160
|
|
|
157
161
|
beforeUnmount() {
|
|
162
|
+
this.tryDestroyPickerInstance();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
tryDestroyPickerInstance() {
|
|
158
166
|
try {
|
|
159
167
|
this.getInputElement().data('dateRangePicker').destroy();
|
|
160
168
|
} catch (error) { }
|
|
@@ -165,13 +173,71 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
|
|
|
165
173
|
return;
|
|
166
174
|
}
|
|
167
175
|
|
|
168
|
-
const self = this;
|
|
169
176
|
const $elem = this.getInputElement();
|
|
177
|
+
if (!this.useModalMode()) {
|
|
178
|
+
this.bindDateRangePicker(
|
|
179
|
+
$elem,
|
|
180
|
+
this.calendarPlacement,
|
|
181
|
+
this.singleMonth,
|
|
182
|
+
this.alwaysOpen,
|
|
183
|
+
() => this.raiseChangedEvent(),
|
|
184
|
+
(this.calendarPlacement == null || this.calendarPlacement == 'body') ? 'body' : $elem.parent(),
|
|
185
|
+
);
|
|
186
|
+
} else {
|
|
187
|
+
this.getInputElement().parent().on('click', async () => {
|
|
188
|
+
const uuid = `drp-modal-${PortalUtils.randomString(6)}`;
|
|
189
|
+
const handle = await DialogUtils.showDialogEx({
|
|
190
|
+
title: this.label || '',
|
|
191
|
+
cssClass: 'daterangepicker-modal pd-modal-mobile-input',
|
|
192
|
+
message: `<div><div id="${uuid}"></div></div>`,
|
|
193
|
+
buttons: [],
|
|
194
|
+
onHidden: () => {
|
|
195
|
+
this.tryDestroyPickerInstance();
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const $modalRoot = $(document.getElementById(uuid));
|
|
200
|
+
this.bindDateRangePicker(
|
|
201
|
+
$elem,
|
|
202
|
+
'inline',
|
|
203
|
+
true,
|
|
204
|
+
true,
|
|
205
|
+
() => {
|
|
206
|
+
this.raiseChangedEvent();
|
|
207
|
+
handle.hideModal();
|
|
208
|
+
},
|
|
209
|
+
$modalRoot,
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
beforeUpdate() {
|
|
216
|
+
if (!globalState.windowExists) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
this.handleModelValueChange();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
useModalMode(): boolean {
|
|
224
|
+
return PortalUtils.treatAsMobileDevice();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
bindDateRangePicker(
|
|
228
|
+
$elem: JQuery<HTMLElement>,
|
|
229
|
+
calendarPlacement: CalendarPlacement,
|
|
230
|
+
singleMonth: boolean,
|
|
231
|
+
alwaysOpen: boolean,
|
|
232
|
+
raiseChangedEvent: () => void,
|
|
233
|
+
container: JQuery<HTMLElement> | string,
|
|
234
|
+
) {
|
|
235
|
+
const self = this;
|
|
170
236
|
const now = Temporal.Now.plainDateTimeISO();
|
|
171
237
|
|
|
172
238
|
($elem as any).dateRangePicker({
|
|
173
|
-
singleMonth:
|
|
174
|
-
alwaysOpen:
|
|
239
|
+
singleMonth: singleMonth == true,
|
|
240
|
+
alwaysOpen: alwaysOpen == true,
|
|
175
241
|
singleDate: this.singleDate == true,
|
|
176
242
|
startOfWeek: DateInputHelper.getStartOfWeek() == 0 ? 'sunday' : 'monday',
|
|
177
243
|
separator: self.getSeparator(),
|
|
@@ -185,13 +251,9 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
|
|
|
185
251
|
yearSelect: this.yearSelect != false,
|
|
186
252
|
getCellHtml: this.getCellHtml,
|
|
187
253
|
maxDaysTooltip: this.maxDaysTooltip,
|
|
188
|
-
calendarPlacement
|
|
189
|
-
container
|
|
254
|
+
calendarPlacement,
|
|
255
|
+
container,
|
|
190
256
|
displayMode: () => {
|
|
191
|
-
if (PortalUtils.treatAsMobileDevice() && this.alwaysOpen != true) {
|
|
192
|
-
return 'modal';
|
|
193
|
-
}
|
|
194
|
-
|
|
195
257
|
return 'below-input';
|
|
196
258
|
},
|
|
197
259
|
leftOffset: () => {
|
|
@@ -244,8 +306,8 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
|
|
|
244
306
|
self._endDate = obj.date2 || obj.date1;
|
|
245
307
|
self._changed = true;
|
|
246
308
|
|
|
247
|
-
if (
|
|
248
|
-
|
|
309
|
+
if (alwaysOpen) {
|
|
310
|
+
raiseChangedEvent();
|
|
249
311
|
}
|
|
250
312
|
}).bind('datepicker-closed', () => {
|
|
251
313
|
const val = $elem.val() as string;
|
|
@@ -262,18 +324,10 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
|
|
|
262
324
|
}
|
|
263
325
|
|
|
264
326
|
self._opened = false;
|
|
265
|
-
|
|
327
|
+
raiseChangedEvent();
|
|
266
328
|
});
|
|
267
329
|
}
|
|
268
330
|
|
|
269
|
-
beforeUpdate() {
|
|
270
|
-
if (!globalState.windowExists) {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
this.handleModelValueChange();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
331
|
handleModelValueChange() {
|
|
278
332
|
if (this.value?.endTime && this.value?.startTime) {
|
|
279
333
|
if (this.enableTime) {
|
|
@@ -525,9 +579,6 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
|
|
|
525
579
|
render(h) {
|
|
526
580
|
return (
|
|
527
581
|
<FormItemWrapper label={this.label} cssClass={this.getCssClass()} mandatory={this.mandatory} wrap={this.wrap} appendIcon={this.appendIcon} prependIcon={this.prependIcon} hint={this.hint} marginType={this.marginType} appendClicked={this.appendClicked} prependClicked={this.prependClicked} prependIconClicked={this.prependIconClicked} appendIconClicked={this.appendIconClicked} validationState={this.validationState} labelButtons={this.labelButtons} subtitle={this.subtitle}>
|
|
528
|
-
{this.shouldAddModalClick()
|
|
529
|
-
&& <div class="pd-daterange-picker-modalclick" onClick={(e) => { this.handleModalOpenClick(e); }}></div>}
|
|
530
|
-
|
|
531
582
|
<div style="position: relative; display: flex; align-items: center; flex-grow:1">
|
|
532
583
|
{' '}
|
|
533
584
|
{/* Added a wrapper for input and clear button */}
|
|
@@ -91,6 +91,10 @@
|
|
|
91
91
|
pointer-events: none;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
.date-range-picker-root.inline-wrapper.drpc-inline {
|
|
95
|
+
position: static;
|
|
96
|
+
}
|
|
97
|
+
|
|
94
98
|
.date-range-picker-root.inline-wrapper.drpc-input-container-leftalign,
|
|
95
99
|
.date-range-picker-root.inline-wrapper.drpc-input-container-rightalign {
|
|
96
100
|
top: 100%;
|
|
@@ -165,7 +169,7 @@
|
|
|
165
169
|
height: 20px;
|
|
166
170
|
}
|
|
167
171
|
|
|
168
|
-
.date-range-picker-wrapper .month-wrapper
|
|
172
|
+
.date-range-picker-wrapper .month-wrapper>table {
|
|
169
173
|
padding-top: 15px;
|
|
170
174
|
}
|
|
171
175
|
|
|
@@ -264,15 +268,6 @@
|
|
|
264
268
|
background-color: rgb(112, 204, 213);
|
|
265
269
|
}
|
|
266
270
|
|
|
267
|
-
.date-range-picker-wrapper table .caption {
|
|
268
|
-
height: 40px;
|
|
269
|
-
color: #393562;
|
|
270
|
-
height: 36px;
|
|
271
|
-
font-size: 18px;
|
|
272
|
-
font-weight: 500;
|
|
273
|
-
font-family: sans-serif;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
271
|
.date-range-picker-wrapper table .caption .next,
|
|
277
272
|
.date-range-picker-wrapper table .caption .prev {
|
|
278
273
|
padding: 0 5px;
|
|
@@ -562,7 +557,7 @@
|
|
|
562
557
|
border-right: 0.667px solid #dfe3f1;
|
|
563
558
|
}
|
|
564
559
|
|
|
565
|
-
.date-range-picker-wrapper .month-wrapper table td
|
|
560
|
+
.date-range-picker-wrapper .month-wrapper table td>div {
|
|
566
561
|
background-color: inherit !important;
|
|
567
562
|
line-height: 1.9;
|
|
568
563
|
margin-left: 5px;
|
|
@@ -619,9 +614,83 @@
|
|
|
619
614
|
background-color: #b94c4c;
|
|
620
615
|
}
|
|
621
616
|
|
|
617
|
+
.date-range-picker-root .select-wrapper-selected-month {
|
|
618
|
+
display: none;
|
|
619
|
+
}
|
|
620
|
+
|
|
622
621
|
.drp-date-switch.month-name {
|
|
623
622
|
border: 0;
|
|
624
623
|
appearance: none;
|
|
625
624
|
-webkit-appearance: none;
|
|
626
625
|
-moz-appearance: none;
|
|
627
626
|
}
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
.date-range-picker-wrapper table .caption,
|
|
630
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>span.select-wrapper,
|
|
631
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>span.select-wrapper select {
|
|
632
|
+
height: 40px;
|
|
633
|
+
color: #393562;
|
|
634
|
+
height: 36px;
|
|
635
|
+
font-size: 18px;
|
|
636
|
+
font-weight: 400;
|
|
637
|
+
font-family: sans-serif;
|
|
638
|
+
background: white;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline {
|
|
642
|
+
border: 0;
|
|
643
|
+
background: transparent;
|
|
644
|
+
box-shadow: none;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper {
|
|
648
|
+
padding-left: 0;
|
|
649
|
+
padding-right: 0;
|
|
650
|
+
border: 0;
|
|
651
|
+
width: 100% !important;
|
|
652
|
+
padding: 0;
|
|
653
|
+
vertical-align: top;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common {}
|
|
657
|
+
|
|
658
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table {
|
|
659
|
+
width: 100%;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table td,
|
|
663
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th {
|
|
664
|
+
width: 99999px;
|
|
665
|
+
text-align: center;
|
|
666
|
+
font-weight: 400;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table td>div,
|
|
670
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>div,
|
|
671
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table td>span,
|
|
672
|
+
.daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>span {
|
|
673
|
+
margin: 0;
|
|
674
|
+
margin: auto;
|
|
675
|
+
font-size: 14px;
|
|
676
|
+
font-weight: 400;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
.daterangepicker-modal .date-range-picker-root .select-wrapper {
|
|
680
|
+
position: relative;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
.daterangepicker-modal .date-range-picker-root .select-wrapper-selected-month {
|
|
685
|
+
display: inline-block;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.daterangepicker-modal .date-range-picker-root select {
|
|
689
|
+
position: absolute;
|
|
690
|
+
top: 0;
|
|
691
|
+
left: 0;
|
|
692
|
+
right: 0;
|
|
693
|
+
bottom: 0;
|
|
694
|
+
height: auto !important;
|
|
695
|
+
opacity: 0.001;
|
|
696
|
+
}
|
|
@@ -260,6 +260,16 @@ import { globalState } from '../../../../app/global-state';
|
|
|
260
260
|
},
|
|
261
261
|
};
|
|
262
262
|
|
|
263
|
+
const MS_PER_DAY = 86_400_000;
|
|
264
|
+
|
|
265
|
+
// 1970 01 01 bol štvrtok. Pre weekday v rozsahu 0..6 kde 0 nedeľa:
|
|
266
|
+
const weekdayFromEpochDay = (epochDay: number) => (epochDay + 4) % 7; // 0 št 1 pia 2 so 3 ne 4 po 5 ut 6 st
|
|
267
|
+
// ak chceš 0 nedeľa:
|
|
268
|
+
const weekdaySun0 = (epochDay: number) => (epochDay + 4 + 3) % 7; // posun na nedeľu
|
|
269
|
+
|
|
270
|
+
const toEpochDayUTC = (msUTC: number) => Math.floor(msUTC / MS_PER_DAY);
|
|
271
|
+
const fromEpochDayUTC = (epochDay: number) => epochDay * MS_PER_DAY;
|
|
272
|
+
|
|
263
273
|
const dateNow = () => Temporal.Now.plainDateTimeISO();
|
|
264
274
|
const ensureTemporal = (date: Temporal.PlainDateTime | number | string): Temporal.PlainDateTime => {
|
|
265
275
|
if (date == null) {
|
|
@@ -441,7 +451,21 @@ import { globalState } from '../../../../app/global-state';
|
|
|
441
451
|
opt = {} as any
|
|
442
452
|
}
|
|
443
453
|
|
|
454
|
+
const getStartMs = () => {
|
|
455
|
+
if (opt.start) {
|
|
456
|
+
return opt.start[utcEpochMilliseconds]();
|
|
457
|
+
}
|
|
444
458
|
|
|
459
|
+
return 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const getEndMs = () => {
|
|
463
|
+
if (opt.end) {
|
|
464
|
+
return opt.end[utcEpochMilliseconds]();
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return 0;
|
|
468
|
+
}
|
|
445
469
|
|
|
446
470
|
opt = $.extend(
|
|
447
471
|
true,
|
|
@@ -509,7 +533,7 @@ import { globalState } from '../../../../app/global-state';
|
|
|
509
533
|
customArrowNextSymbol: null,
|
|
510
534
|
monthSelect: false,
|
|
511
535
|
yearSelect: false,
|
|
512
|
-
enableSwipeDebug:
|
|
536
|
+
enableSwipeDebug: location.href.includes('localhost'), // Enable mouse dragging to simulate touch swipe (for debugging)
|
|
513
537
|
},
|
|
514
538
|
opt,
|
|
515
539
|
);
|
|
@@ -533,9 +557,9 @@ import { globalState } from '../../../../app/global-state';
|
|
|
533
557
|
singleMonth = ($(window).width() < 480) as any;
|
|
534
558
|
}
|
|
535
559
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
560
|
+
if (($(window).width() < 480)) {
|
|
561
|
+
singleMonth = true;
|
|
562
|
+
}
|
|
539
563
|
|
|
540
564
|
if (singleMonth) {
|
|
541
565
|
opt.stickyMonths = false;
|
|
@@ -579,22 +603,6 @@ import { globalState } from '../../../../app/global-state';
|
|
|
579
603
|
open(0);
|
|
580
604
|
}
|
|
581
605
|
|
|
582
|
-
const getStartMs = () => {
|
|
583
|
-
if (opt.start) {
|
|
584
|
-
return opt.start[utcEpochMilliseconds]();
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
return 0;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
const getEndMs = () => {
|
|
591
|
-
if (opt.end) {
|
|
592
|
-
return opt.end[utcEpochMilliseconds]();
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
return 0;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
606
|
// expose some api
|
|
599
607
|
$(this).data('dateRangePicker', {
|
|
600
608
|
setStart(d1) {
|
|
@@ -658,7 +666,7 @@ import { globalState } from '../../../../app/global-state';
|
|
|
658
666
|
return this;
|
|
659
667
|
|
|
660
668
|
function isModalDisplayMode() {
|
|
661
|
-
return (box != null && box.hasClass('date-range-picker-modalmode'))
|
|
669
|
+
return (box != null && box.hasClass('date-range-picker-modalmode'))
|
|
662
670
|
}
|
|
663
671
|
|
|
664
672
|
function IsOwnDatePickerClicked(evt, selfObj) {
|
|
@@ -1303,12 +1311,7 @@ import { globalState } from '../../../../app/global-state';
|
|
|
1303
1311
|
|
|
1304
1312
|
const winWidth = $(window).width();
|
|
1305
1313
|
const timeEnabled = opt.time.enabled == true;
|
|
1306
|
-
|
|
1307
|
-
if (winWidth <= 992 && opt.alwaysOpen != true) {
|
|
1308
|
-
setModalDisplayMode();
|
|
1309
|
-
} else {
|
|
1310
|
-
setDisplayMode();
|
|
1311
|
-
}
|
|
1314
|
+
setDisplayMode();
|
|
1312
1315
|
|
|
1313
1316
|
if ($(window).height() < 550 && winWidth < DaterangePickerConfig.calendarsOneColThreshold && !timeEnabled) {
|
|
1314
1317
|
singleMonth = true;
|
|
@@ -1818,6 +1821,76 @@ import { globalState } from '../../../../app/global-state';
|
|
|
1818
1821
|
return true;
|
|
1819
1822
|
}
|
|
1820
1823
|
|
|
1824
|
+
function isValidTimeDate(date: Date) {
|
|
1825
|
+
// --- lokálne inliny bez sub-metód ---
|
|
1826
|
+
// prevod PlainDate na epochDay (UTC) bez časovej zóny
|
|
1827
|
+
const epochDay = (y, m, d) => Math.floor(Date.UTC(y, m - 1, d) / MS_PER_DAY);
|
|
1828
|
+
|
|
1829
|
+
// pomocné vyčítanie čísla dňa z Temporal.PlainDateTime-like objektu
|
|
1830
|
+
const d_epoch = epochDay(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
1831
|
+
|
|
1832
|
+
// hranice
|
|
1833
|
+
const hasStartDate = !!opt.startDate;
|
|
1834
|
+
const hasEndDate = !!opt.endDate;
|
|
1835
|
+
const startDate_epoch = hasStartDate ? epochDay(opt.startDate.year, opt.startDate.month, opt.startDate.day) : 0;
|
|
1836
|
+
const endDate_epoch = hasEndDate ? epochDay(opt.endDate.year, opt.endDate.month, opt.endDate.day) : 0;
|
|
1837
|
+
|
|
1838
|
+
// 1) mimo absolútnych hraníc
|
|
1839
|
+
if (hasStartDate && d_epoch < startDate_epoch) return false;
|
|
1840
|
+
if (hasEndDate && d_epoch > endDate_epoch) return false;
|
|
1841
|
+
|
|
1842
|
+
// Ak ešte nie je zvolený koniec a nie je singleDate, platia ďalšie pravidlá
|
|
1843
|
+
if (opt.start && !opt.end && !opt.singleDate) {
|
|
1844
|
+
const s = opt.start;
|
|
1845
|
+
const s_epoch = epochDay(s.year, s.month, s.day);
|
|
1846
|
+
|
|
1847
|
+
// 2) minDays / maxDays (počítané ako rozdiel v celých dňoch)
|
|
1848
|
+
if (opt.maxDays > 0) {
|
|
1849
|
+
const diff = Math.abs(d_epoch - s_epoch);
|
|
1850
|
+
if (diff > opt.maxDays) return false;
|
|
1851
|
+
}
|
|
1852
|
+
if (opt.minDays > 0) {
|
|
1853
|
+
const diff = Math.abs(d_epoch - s_epoch);
|
|
1854
|
+
if (diff < opt.minDays) return false;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
// 3) forward / backward
|
|
1858
|
+
if (opt.selectForward && d_epoch < s_epoch) return false;
|
|
1859
|
+
if (opt.selectBackward && d_epoch > s_epoch) return false;
|
|
1860
|
+
|
|
1861
|
+
// 4) disabled days cez beforeShowDay medzi start a date
|
|
1862
|
+
// Prechádzame smerom k start po 1 dni, ale bez volania ak je to zbytočné.
|
|
1863
|
+
if (opt.beforeShowDay && typeof opt.beforeShowDay === 'function') {
|
|
1864
|
+
// krok +1 alebo -1 podľa smeru
|
|
1865
|
+
const step = d_epoch === s_epoch ? 0 : (d_epoch > s_epoch ? -1 : +1);
|
|
1866
|
+
if (step !== 0) {
|
|
1867
|
+
let cur = d_epoch;
|
|
1868
|
+
// pôvodná logika mala while (countDays(...) > 1):
|
|
1869
|
+
// tu to čítaj ako "kým je medzi nimi aspoň 2-dňová vzdialenosť"
|
|
1870
|
+
while (Math.abs(cur - s_epoch) > 1) {
|
|
1871
|
+
cur += step;
|
|
1872
|
+
|
|
1873
|
+
// z cur vyrobíme PlainDateTime len vtedy keď ho naozaj voláme
|
|
1874
|
+
// inferuj rok-mesiac-deň cez dočasný Date, bez extra helperov
|
|
1875
|
+
const ms = cur * MS_PER_DAY;
|
|
1876
|
+
const tmp = new Date(ms);
|
|
1877
|
+
const y = tmp.getUTCFullYear();
|
|
1878
|
+
const m = tmp.getUTCMonth() + 1;
|
|
1879
|
+
const d = tmp.getUTCDate();
|
|
1880
|
+
|
|
1881
|
+
// PlainDateTime s nulovým časom pre kompatibilitu s existujúcim hookom
|
|
1882
|
+
const pdt = Temporal.PlainDateTime.from({ year: y, month: m, day: d, hour: 0, minute: 0, second: 0, millisecond: 0 });
|
|
1883
|
+
|
|
1884
|
+
const arr: any = opt.beforeShowDay(pdt);
|
|
1885
|
+
if (arr && arr[0] === false) return false;
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
return true;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1821
1894
|
function updateSelectableRange() {
|
|
1822
1895
|
box.find('.day.invalid.tmp').removeClass('tmp invalid').addClass('valid');
|
|
1823
1896
|
if (opt.start && !opt.end) {
|
|
@@ -2137,54 +2210,69 @@ import { globalState } from '../../../../app/global-state';
|
|
|
2137
2210
|
}
|
|
2138
2211
|
|
|
2139
2212
|
function showSelectedDays() {
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2213
|
+
const tz = 'UTC';
|
|
2214
|
+
const toStartOfDayMs = (dt: Temporal.PlainDateTime) =>
|
|
2215
|
+
dt.with({ hour: 0, minute: 0, second: 0, millisecond: 0 })
|
|
2216
|
+
.toZonedDateTime(tz).epochMilliseconds;
|
|
2217
|
+
|
|
2218
|
+
const toEndOfDayMs = (dt: Temporal.PlainDateTime) =>
|
|
2219
|
+
dt.with({ hour: 23, minute: 59, second: 59, millisecond: 999 })
|
|
2220
|
+
.toZonedDateTime(tz).epochMilliseconds;
|
|
2221
|
+
|
|
2222
|
+
const hasStart = !!opt.start;
|
|
2223
|
+
const hasEnd = !!opt.end;
|
|
2224
|
+
const startDayStartMs = hasStart ? toStartOfDayMs(opt.start) : NaN;
|
|
2225
|
+
const startDayEndMs = hasStart ? toEndOfDayMs(opt.start) : NaN;
|
|
2226
|
+
const endDayStartMs = hasEnd ? toStartOfDayMs(opt.end) : NaN;
|
|
2227
|
+
const endDayEndMs = hasEnd ? toEndOfDayMs(opt.end) : NaN;
|
|
2228
|
+
|
|
2229
|
+
const rangeStartMs = hasStart ? startDayStartMs : NaN;
|
|
2230
|
+
const rangeEndMs = hasEnd ? endDayEndMs : startDayEndMs; // ak nie je end, berie sa len deň start
|
|
2231
|
+
|
|
2232
|
+
const $days = box.find('.day');
|
|
2233
|
+
for (let i = 0; i < $days.length; i++) {
|
|
2234
|
+
const el = $days[i];
|
|
2235
|
+
const timeAttr = (el as HTMLElement).getAttribute('time');
|
|
2236
|
+
if (!timeAttr) continue;
|
|
2237
|
+
|
|
2238
|
+
const timeMs = Number(timeAttr); // očakáva sa epoch ms
|
|
2239
|
+
|
|
2240
|
+
const isInRange =
|
|
2241
|
+
hasStart && hasEnd
|
|
2242
|
+
? (timeMs >= rangeStartMs && timeMs <= rangeEndMs)
|
|
2243
|
+
: hasStart
|
|
2244
|
+
? (timeMs >= startDayStartMs && timeMs <= startDayEndMs)
|
|
2245
|
+
: false;
|
|
2246
|
+
|
|
2247
|
+
const isStartDay = hasStart && timeMs >= startDayStartMs && timeMs <= startDayEndMs;
|
|
2248
|
+
const isEndDay = hasEnd && timeMs >= endDayStartMs && timeMs <= endDayEndMs;
|
|
2249
|
+
|
|
2250
|
+
const $el = $(el);
|
|
2251
|
+
$el.toggleClass('checked', isInRange || isStartDay || isEndDay);
|
|
2252
|
+
$el.toggleClass('first-date-selected', isStartDay);
|
|
2253
|
+
$el.toggleClass('last-date-selected', isEndDay);
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
// ——— výpočet pre .week-number ———
|
|
2257
|
+
const startWeekNum = Number(opt.startWeek);
|
|
2258
|
+
const $weeks = box.find('.week-number');
|
|
2259
|
+
for (let i = 0; i < $weeks.length; i++) {
|
|
2260
|
+
const el = $weeks[i];
|
|
2261
|
+
const w = Number((el as HTMLElement).getAttribute('data-start-time'));
|
|
2262
|
+
if (w === startWeekNum) {
|
|
2263
|
+
$(el).addClass('week-number-selected');
|
|
2157
2264
|
} else {
|
|
2158
|
-
$(
|
|
2265
|
+
$(el).removeClass('week-number-selected');
|
|
2159
2266
|
}
|
|
2160
|
-
|
|
2161
|
-
// add first-date-selected class name to the first date selected
|
|
2162
|
-
if (opt.start && DateUtils.formatDate(start, 'yyyyMMdd') == DateUtils.formatDate(time, 'yyyyMMdd')) {
|
|
2163
|
-
$(this).addClass('first-date-selected');
|
|
2164
|
-
} else {
|
|
2165
|
-
$(this).removeClass('first-date-selected');
|
|
2166
|
-
}
|
|
2167
|
-
|
|
2168
|
-
// add last-date-selected
|
|
2169
|
-
if (opt.end && DateUtils.formatDate(end, 'yyyyMMdd') == DateUtils.formatDate(time, 'yyyyMMdd')) {
|
|
2170
|
-
$(this).addClass('last-date-selected');
|
|
2171
|
-
} else {
|
|
2172
|
-
$(this).removeClass('last-date-selected');
|
|
2173
|
-
}
|
|
2174
|
-
});
|
|
2175
|
-
|
|
2176
|
-
box.find('.week-number').each(function (this: any) {
|
|
2177
|
-
if ($(this).attr('data-start-time') == opt.startWeek) {
|
|
2178
|
-
$(this).addClass('week-number-selected');
|
|
2179
|
-
}
|
|
2180
|
-
});
|
|
2267
|
+
}
|
|
2181
2268
|
}
|
|
2182
2269
|
|
|
2183
2270
|
function showMonth(date: Temporal.PlainDateTime, month: 'month1' | 'month2') {
|
|
2184
2271
|
const monthName = nameMonth(date.month);
|
|
2185
2272
|
var selectableMonthElement = generateSelectableMonthElement(date, month);
|
|
2186
2273
|
var selectableYearElement = generateSelectableYearElement(date, month);
|
|
2187
|
-
|
|
2274
|
+
const html = `${opt.monthSelect ? selectableMonthElement : monthName}${opt.hideYearInMonthName ? '' : ` ${opt.yearSelect ? selectableYearElement : date.year}`}`;
|
|
2275
|
+
box.find(`.${month} .month-name`).first().html(html);
|
|
2188
2276
|
box.find(`.${month} tbody`).html(createMonthHTML(date));
|
|
2189
2277
|
opt[month] = date;
|
|
2190
2278
|
updateSelectableRange();
|
|
@@ -2284,7 +2372,8 @@ import { globalState } from '../../../../app/global-state';
|
|
|
2284
2372
|
return data;
|
|
2285
2373
|
}
|
|
2286
2374
|
function generateSelect(name: string, data: Array<{ value: number, text: string | number, selected: boolean, disabled: boolean }>): string {
|
|
2287
|
-
|
|
2375
|
+
const selectedItem = data.find(p => p.selected == true);
|
|
2376
|
+
var select = '<span class="select-wrapper">' + (selectedItem != null ? '<span class="select-wrapper-selected-month">' + selectedItem.text + '</span>' : '') + '<select class="drp-date-switch month-name ' + name + '" name="' + name + '">';
|
|
2288
2377
|
var current: string | number = '';
|
|
2289
2378
|
|
|
2290
2379
|
for (var i = 0, l = data.length; i < l; i++) {
|
|
@@ -2747,98 +2836,148 @@ import { globalState } from '../../../../app/global-state';
|
|
|
2747
2836
|
}
|
|
2748
2837
|
|
|
2749
2838
|
function createMonthHTML(d: Temporal.PlainDateTime) {
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
const
|
|
2753
|
-
const
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2839
|
+
// vstup prevedieme len raz na UTC Date bez časovej zóny
|
|
2840
|
+
// beriem prvý deň v mesiaci
|
|
2841
|
+
const y = d.year, m = d.month; // 1..12
|
|
2842
|
+
const firstMs = Date.UTC(y, m - 1, 1);
|
|
2843
|
+
const firstEpochDay = toEpochDayUTC(firstMs);
|
|
2844
|
+
|
|
2845
|
+
// start týždňa
|
|
2846
|
+
const weekStartsMonday = opt.startOfWeek === 'monday';
|
|
2847
|
+
const dowSun0 = weekdaySun0(firstEpochDay); // 0 nedeľa 1 pondelok ...
|
|
2848
|
+
const backDays = weekStartsMonday ? ((dowSun0 + 6) % 7) : dowSun0;
|
|
2849
|
+
const gridStartEpochDay = firstEpochDay - backDays;
|
|
2850
|
+
|
|
2851
|
+
// hranice iba ako čísla dní
|
|
2852
|
+
const hasStart = !!opt.startDate;
|
|
2853
|
+
const hasEnd = !!opt.endDate;
|
|
2854
|
+
const startEpochDay = hasStart ? toEpochDayUTC(Date.UTC(opt.startDate.year, opt.startDate.month - 1, opt.startDate.day)) : 0;
|
|
2855
|
+
const endEpochDay = hasEnd ? toEpochDayUTC(Date.UTC(opt.endDate.year, opt.endDate.month - 1, opt.endDate.day)) : 0;
|
|
2856
|
+
|
|
2857
|
+
// dnes
|
|
2858
|
+
const now = dateNow(); // očakávam Temporal.PlainDateTime
|
|
2859
|
+
const nowEpochDay = toEpochDayUTC(Date.UTC(now.year, now.month - 1, now.day));
|
|
2860
|
+
|
|
2861
|
+
// pomocná mutovateľná Date v UTC. Nepoužívaj ju na porovnávanie. Iba ak potrebuješ time alebo hooky
|
|
2862
|
+
const tmp = new Date(firstMs);
|
|
2863
|
+
|
|
2864
|
+
// zisti mesiac pre typ bunky rýchlo
|
|
2865
|
+
// posledný deň mesiaca
|
|
2866
|
+
const nextMonthMs = Date.UTC(y, m, 1);
|
|
2867
|
+
const thisMonthEndEpochDay = toEpochDayUTC(nextMonthMs - 1); // posledný deň
|
|
2868
|
+
|
|
2869
|
+
let sawToMonth = false;
|
|
2870
|
+
let weekCount = 0;
|
|
2871
|
+
const html: string[] = [];
|
|
2770
2872
|
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
type: 'lastMonth',
|
|
2774
|
-
day: day.day,
|
|
2775
|
-
time: day[utcEpochMilliseconds](),
|
|
2776
|
-
valid,
|
|
2777
|
-
});
|
|
2778
|
-
}
|
|
2779
|
-
}
|
|
2873
|
+
for (let week = 0; week < 6; week++) {
|
|
2874
|
+
const rowStart = gridStartEpochDay + week * 7;
|
|
2780
2875
|
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
let today = d.add({ milliseconds: (86400000 * i) });
|
|
2784
|
-
let valid = isValidTime(today);
|
|
2785
|
-
if (opt.startDate && compare_day(today, opt.startDate) < 0) {
|
|
2786
|
-
valid = false;
|
|
2787
|
-
} else if (opt.endDate && compare_day(today, opt.endDate) > 0) {
|
|
2788
|
-
valid = false;
|
|
2789
|
-
}
|
|
2876
|
+
// ak prvá bunka riadku je po mesiaci a už sme mali toMonth ukonči
|
|
2877
|
+
if (week > 0 && rowStart > thisMonthEndEpochDay && sawToMonth) break;
|
|
2790
2878
|
|
|
2791
|
-
|
|
2792
|
-
date: today,
|
|
2793
|
-
type: today.month == toMonth ? 'toMonth' : 'nextMonth',
|
|
2794
|
-
day: today.day,
|
|
2795
|
-
time: today[utcEpochMilliseconds](),
|
|
2796
|
-
valid,
|
|
2797
|
-
});
|
|
2798
|
-
}
|
|
2879
|
+
html.push('<tr>');
|
|
2799
2880
|
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
if (days[week * 7].type == 'nextMonth') {
|
|
2803
|
-
break;
|
|
2804
|
-
}
|
|
2881
|
+
for (let wd = 0; wd < 7; wd++) {
|
|
2882
|
+
const epochDay = rowStart + wd;
|
|
2805
2883
|
|
|
2806
|
-
|
|
2884
|
+
// čísla na rýchle rozhodnutia
|
|
2885
|
+
const inMonth = epochDay >= firstEpochDay && epochDay <= thisMonthEndEpochDay;
|
|
2886
|
+
if (inMonth) sawToMonth = true;
|
|
2887
|
+
|
|
2888
|
+
const type = inMonth ? 'toMonth' : (epochDay < firstEpochDay ? 'lastMonth' : 'nextMonth');
|
|
2807
2889
|
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
today.valid = _r[0];
|
|
2818
|
-
today.extraClass = _r[1] || '';
|
|
2819
|
-
today.tooltip = _r[2] || '';
|
|
2820
|
-
if (today.tooltip !== '') { today.extraClass += ' has-tooltip '; }
|
|
2890
|
+
// validácia bez Temporal
|
|
2891
|
+
let valid = true;
|
|
2892
|
+
if (hasStart && epochDay < startEpochDay) valid = false;
|
|
2893
|
+
if (valid && hasEnd && epochDay > endEpochDay) valid = false;
|
|
2894
|
+
if (valid) {
|
|
2895
|
+
// pre isValidTime potrebujeme skutočný čas. Použijeme tmp iba raz
|
|
2896
|
+
tmp.setTime(fromEpochDayUTC(epochDay));
|
|
2897
|
+
// ak vieš spraviť rýchlu vetvu pre isValidTime z čísel, urob to. Inak toto:
|
|
2898
|
+
valid = isValidTimeDate(tmp);
|
|
2821
2899
|
}
|
|
2822
2900
|
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2901
|
+
// week number bunku vlož ešte pred TD dňa
|
|
2902
|
+
if (wd === 0 && opt.showWeekNumbers) {
|
|
2903
|
+
tmp.setTime(fromEpochDayUTC(epochDay));
|
|
2904
|
+
const wn = opt.getWeekNumber ? opt.getWeekNumber(Temporal.PlainDate.from({
|
|
2905
|
+
year: tmp.getUTCFullYear(),
|
|
2906
|
+
month: tmp.getUTCMonth() + 1,
|
|
2907
|
+
day: tmp.getUTCDate()
|
|
2908
|
+
}) as any) : '';
|
|
2909
|
+
html.push('<td><div class="week-number" data-start-time="', String(tmp.getTime()), '">', String(wn), '</div></td>');
|
|
2910
|
+
}
|
|
2828
2911
|
|
|
2829
|
-
|
|
2830
|
-
|
|
2912
|
+
// hook beforeShowDay len ak valid
|
|
2913
|
+
let extraClass = '';
|
|
2914
|
+
let tooltip = '';
|
|
2915
|
+
if (valid && opt.beforeShowDay) {
|
|
2916
|
+
// vytvor Temporal iba tu kde to naozaj treba
|
|
2917
|
+
const tpd = Temporal.PlainDate.from(epochDayToYMD(epochDay));
|
|
2918
|
+
const tdt = Temporal.PlainDateTime.from({ ...tpd, hour: 0, minute: 0, second: 0, millisecond: 0 });
|
|
2919
|
+
const _r = opt.beforeShowDay(tdt);
|
|
2920
|
+
valid = !!_r[0];
|
|
2921
|
+
if (_r[1]) extraClass = _r[1];
|
|
2922
|
+
if (_r[2]) tooltip = _r[2];
|
|
2831
2923
|
}
|
|
2924
|
+
if (tooltip !== '') extraClass += ' has-tooltip';
|
|
2925
|
+
|
|
2926
|
+
const isToday = epochDay === nowEpochDay;
|
|
2927
|
+
|
|
2928
|
+
// priprava údajov pre TD a vnútro
|
|
2929
|
+
// tmp nastavíme na koniec dňa aby bol time konzistentný ak to tak používaš
|
|
2930
|
+
tmp.setTime(fromEpochDayUTC(epochDay));
|
|
2931
|
+
const ms = tmp.getTime();
|
|
2932
|
+
const dayNumber = utcDayOfMonth(tmp);
|
|
2933
|
+
|
|
2934
|
+
const divClass =
|
|
2935
|
+
'day ' + type +
|
|
2936
|
+
(extraClass ? ' ' + extraClass : '') +
|
|
2937
|
+
(valid ? ' valid' : ' invalid') +
|
|
2938
|
+
(isToday ? ' real-today' : '');
|
|
2939
|
+
|
|
2940
|
+
const tdAttrs = attributesCallbacks({}, opt.dayTdAttrs, {
|
|
2941
|
+
date: null, // ak front nepotrebuje Temporal ušetríš. Inak si sem vieš dohnať PlainDate len na klikanie
|
|
2942
|
+
type,
|
|
2943
|
+
day: dayNumber,
|
|
2944
|
+
time: ms,
|
|
2945
|
+
valid,
|
|
2946
|
+
extraClass,
|
|
2947
|
+
tooltip
|
|
2948
|
+
} as any);
|
|
2832
2949
|
|
|
2833
|
-
|
|
2834
|
-
{},
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2950
|
+
const inner = getInnerDayHtml(
|
|
2951
|
+
{ 'time': String(ms), 'data-tooltip': tooltip, 'class': divClass },
|
|
2952
|
+
{ day: dayNumber, type, time: ms, valid } as any
|
|
2953
|
+
);
|
|
2954
|
+
|
|
2955
|
+
html.push('<td ', tdAttrs, '>', inner, '</td>');
|
|
2838
2956
|
}
|
|
2957
|
+
|
|
2958
|
+
weekCount += 1;
|
|
2839
2959
|
html.push('</tr>');
|
|
2840
2960
|
}
|
|
2961
|
+
|
|
2962
|
+
while (weekCount < 6) {
|
|
2963
|
+
html.push('<tr><td colspan="7"><div color="transparent" class="day daterangepicker-dummy-row-item" time="-1" style="visibility:hidden;">42</div></td></tr>');
|
|
2964
|
+
weekCount += 1;
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2841
2967
|
return html.join('');
|
|
2968
|
+
|
|
2969
|
+
// pomôcky
|
|
2970
|
+
function utcDayOfMonth(dt: Date) { return dt.getUTCDate(); }
|
|
2971
|
+
|
|
2972
|
+
function epochDayToYMD(epochDay: number) {
|
|
2973
|
+
const ms = fromEpochDayUTC(epochDay);
|
|
2974
|
+
tmp.setTime(ms);
|
|
2975
|
+
return {
|
|
2976
|
+
year: tmp.getUTCFullYear(),
|
|
2977
|
+
month: tmp.getUTCMonth() + 1,
|
|
2978
|
+
day: tmp.getUTCDate()
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2842
2981
|
}
|
|
2843
2982
|
|
|
2844
2983
|
function getInnerDayHtml(attributes: any, today: any) {
|
|
@@ -136,6 +136,100 @@ export class ModalUtils {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
static bindModalBottomSheetHandle(getModal: () => HTMLElement, hideModal: () => void) {
|
|
140
|
+
if ((getModal() as any)?._dragBound) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
setTimeout(() => {
|
|
145
|
+
const modal = getModal() as HTMLElement;
|
|
146
|
+
const modalDialog = modal.querySelector('.modal-dialog') as HTMLElement;
|
|
147
|
+
const dragHandle = modal.querySelector('.drag-handle');
|
|
148
|
+
|
|
149
|
+
let startY = 0;
|
|
150
|
+
let currentY = 0;
|
|
151
|
+
let isDragging = false;
|
|
152
|
+
const threshold = 100;
|
|
153
|
+
const cancelDragging = () => {
|
|
154
|
+
isDragging = false;
|
|
155
|
+
modal.classList.remove('modal-is-dragging');
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const startDragging = () => {
|
|
159
|
+
isDragging = true;
|
|
160
|
+
modal.classList.add('modal-is-dragging');
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const onMove = (y) => {
|
|
164
|
+
const translateY = Math.max(y - startY, 0);
|
|
165
|
+
modalDialog.style.transform = `translateY(${translateY}px)`;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const endDrag = () => {
|
|
169
|
+
cancelDragging();
|
|
170
|
+
const dragDistance = currentY - startY;
|
|
171
|
+
|
|
172
|
+
if (dragDistance > threshold) {
|
|
173
|
+
hideModal();
|
|
174
|
+
} else {
|
|
175
|
+
modalDialog.style.transform = 'translateY(0)';
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Touch events
|
|
180
|
+
dragHandle.addEventListener('touchstart', (e) => {
|
|
181
|
+
startY = (e as TouchEvent).touches[0].clientY;
|
|
182
|
+
startDragging();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
dragHandle.addEventListener('touchmove', (e) => {
|
|
186
|
+
if (!isDragging) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
currentY = (e as TouchEvent).touches[0].clientY;
|
|
191
|
+
onMove(currentY);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
dragHandle.addEventListener('touchend', endDrag);
|
|
195
|
+
|
|
196
|
+
// Mouse events
|
|
197
|
+
dragHandle.addEventListener('mousedown', (e) => {
|
|
198
|
+
startY = (e as MouseEvent).clientY;
|
|
199
|
+
startDragging();
|
|
200
|
+
|
|
201
|
+
const onMouseMove = (e) => {
|
|
202
|
+
if (!isDragging) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
currentY = e.clientY;
|
|
207
|
+
onMove(currentY);
|
|
208
|
+
e.preventDefault();
|
|
209
|
+
e.stopPropagation();
|
|
210
|
+
e.stopImmediatePropagation();
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const onMouseUp = () => {
|
|
214
|
+
endDrag();
|
|
215
|
+
globalState.removeEventListener('mousemove', onMouseMove);
|
|
216
|
+
globalState.removeEventListener('mouseup', onMouseUp);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
globalState.addEventListener('mousemove', onMouseMove);
|
|
220
|
+
globalState.addEventListener('mouseup', onMouseUp);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Reset on modal hide
|
|
224
|
+
modal.addEventListener('hidden.bs.modal', () => {
|
|
225
|
+
cancelDragging();
|
|
226
|
+
modalDialog.style.transform = '';
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
(modal as any)._dragBound = true;
|
|
230
|
+
}, 100);
|
|
231
|
+
}
|
|
232
|
+
|
|
139
233
|
private static _getModalJquery(modalElem: Element | IVue): JQuery {
|
|
140
234
|
return globalState.jQuery(modalElem as any);
|
|
141
235
|
}
|
|
@@ -122,98 +122,10 @@ class ModalComponent extends TsxComponent<ModalArgs> implements ModalArgs {
|
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
setTimeout(() => {
|
|
131
|
-
const modal = this.$refs.modalRoot as HTMLElement;
|
|
132
|
-
const modalDialog = modal.querySelector('.modal-dialog') as HTMLElement;
|
|
133
|
-
const dragHandle = modal.querySelector('.drag-handle');
|
|
134
|
-
|
|
135
|
-
let startY = 0;
|
|
136
|
-
let currentY = 0;
|
|
137
|
-
let isDragging = false;
|
|
138
|
-
const threshold = 100;
|
|
139
|
-
const cancelDragging = () => {
|
|
140
|
-
isDragging = false;
|
|
141
|
-
modal.classList.remove('modal-is-dragging');
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const startDragging = () => {
|
|
145
|
-
isDragging = true;
|
|
146
|
-
modal.classList.add('modal-is-dragging');
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const onMove = (y) => {
|
|
150
|
-
const translateY = Math.max(y - startY, 0);
|
|
151
|
-
modalDialog.style.transform = `translateY(${translateY}px)`;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const endDrag = () => {
|
|
155
|
-
cancelDragging();
|
|
156
|
-
const dragDistance = currentY - startY;
|
|
157
|
-
|
|
158
|
-
if (dragDistance > threshold) {
|
|
159
|
-
this.hide();
|
|
160
|
-
} else {
|
|
161
|
-
modalDialog.style.transform = 'translateY(0)';
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
// Touch events
|
|
166
|
-
dragHandle.addEventListener('touchstart', (e) => {
|
|
167
|
-
startY = (e as TouchEvent).touches[0].clientY;
|
|
168
|
-
startDragging();
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
dragHandle.addEventListener('touchmove', (e) => {
|
|
172
|
-
if (!isDragging) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
currentY = (e as TouchEvent).touches[0].clientY;
|
|
177
|
-
onMove(currentY);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
dragHandle.addEventListener('touchend', endDrag);
|
|
181
|
-
|
|
182
|
-
// Mouse events
|
|
183
|
-
dragHandle.addEventListener('mousedown', (e) => {
|
|
184
|
-
startY = (e as MouseEvent).clientY;
|
|
185
|
-
startDragging();
|
|
186
|
-
|
|
187
|
-
const onMouseMove = (e) => {
|
|
188
|
-
if (!isDragging) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
currentY = e.clientY;
|
|
193
|
-
onMove(currentY);
|
|
194
|
-
e.preventDefault();
|
|
195
|
-
e.stopPropagation();
|
|
196
|
-
e.stopImmediatePropagation();
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
const onMouseUp = () => {
|
|
200
|
-
endDrag();
|
|
201
|
-
globalState.removeEventListener('mousemove', onMouseMove);
|
|
202
|
-
globalState.removeEventListener('mouseup', onMouseUp);
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
globalState.addEventListener('mousemove', onMouseMove);
|
|
206
|
-
globalState.addEventListener('mouseup', onMouseUp);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
// Reset on modal hide
|
|
210
|
-
modal.addEventListener('hidden.bs.modal', () => {
|
|
211
|
-
cancelDragging();
|
|
212
|
-
modalDialog.style.transform = '';
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
(modal as any)._dragBound = true;
|
|
216
|
-
}, 100);
|
|
125
|
+
ModalUtils.bindModalBottomSheetHandle(
|
|
126
|
+
() => this.$refs.modalRoot as HTMLElement,
|
|
127
|
+
() => this.hide()
|
|
128
|
+
)
|
|
217
129
|
}
|
|
218
130
|
|
|
219
131
|
treatMobileAsBottomSheet(): boolean {
|