1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
export { ComponentEdit }
import { ComponentVEvent } from './vevent'
import { InputList } from './input-list'
import { DateTimeInput } from './date-time-input'
import { vcal_objects } from '../globals'
import { VEvent, RecurrenceRule } from '../vevent'
import { create_event } from '../server_connect'
import { to_boolean } from '../lib'
/* <vevent-edit />
Edit form for a given VEvent. Used as the edit tab of popups.
*/
class ComponentEdit extends ComponentVEvent {
constructor(uid?: string) {
super(uid);
if (!this.template) {
throw 'vevent-edit template required';
}
let frag = this.template.content.cloneNode(true) as DocumentFragment
let body = frag.firstElementChild!
this.replaceChildren(body);
}
connectedCallback() {
/* Edit tab is rendered here. It's left blank server-side, since
it only makes sense to have something here if we have javascript */
let data = vcal_objects.get(this.uid)
if (!data) {
throw `Data missing for uid ${this.dataset.uid}.`
}
// return;
/* Handle calendar dropdown */
for (let el of this.getElementsByClassName('calendar-selection')) {
for (let opt of el.getElementsByTagName('option')) {
opt.selected = false;
}
if (data.calendar) {
(el as HTMLSelectElement).value = data.calendar;
}
el.addEventListener('change', (e) => {
let v = (e.target as HTMLSelectElement).selectedOptions[0].value
let obj = vcal_objects.get(this.uid)!
obj.calendar = v;
});
}
this.redraw(data);
// for (let el of this.getElementsByClassName("interactive")) {
for (let el of this.querySelectorAll("[data-property]")) {
// console.log(el);
el.addEventListener('input', (e) => {
let obj = vcal_objects.get(this.uid)
// console.log(el, e);
if (obj === undefined) {
throw 'No object with uid ' + this.uid
}
if (!(el instanceof HTMLInputElement
|| el instanceof DateTimeInput
|| el instanceof HTMLTextAreaElement
|| el instanceof InputList
)) {
console.log(el, 'not an HTMLInputElement');
return;
}
// console.log(`obj[${el.dataset.property!}] = `, el.value);
obj.setProperty(
el.dataset.property!,
el.value)
});
}
let wholeday_ = this.querySelector('[name="wholeday"]')
if (wholeday_) {
let wholeday = wholeday_ as HTMLInputElement
if (data.getProperty('dtstart')?.dateonly) {
wholeday.checked = true;
}
wholeday.addEventListener('click', () => {
let chk = wholeday.checked
let start = data!.getProperty('dtstart')
let end = data!.getProperty('dtend')
start.dateonly = chk
end.dateonly = chk
data!.setProperty('dtstart', start);
data!.setProperty('dtend', end);
});
}
let has_repeats_ = this.querySelector('[name="has_repeats"]')
if (has_repeats_) {
let has_repeats = has_repeats_ as HTMLInputElement;
has_repeats.addEventListener('click', () => {
/* TODO unselecting and reselecting this checkbox deletes all entered data.
Cache it somewhere */
if (has_repeats.checked) {
vcal_objects.get(this.uid)!.setProperty('rrule', new RecurrenceRule())
} else {
/* TODO is this a good way to remove a property ? */
vcal_objects.get(this.uid)!.setProperty('rrule', undefined)
}
})
}
let submit = this.querySelector('form') as HTMLFormElement
submit.addEventListener('submit', (e) => {
console.log(submit, e);
create_event(vcal_objects.get(this.uid)!);
e.preventDefault();
return false;
});
}
redraw(data: VEvent) {
/* We only update our fields, instead of reinstansiating
ourselves from the template, in hope that it's faster */
for (let el of this.querySelectorAll("[data-property]")) {
if (!(el instanceof HTMLElement)) continue;
let p = el.dataset.property!;
let d: any;
if ((d = data.getProperty(p))) {
/*
https://stackoverflow.com/questions/57157830/how-can-i-specify-the-sequence-of-running-nested-web-components-constructors
*/
window.setTimeout(() => {
/* NOTE Some specific types might require special formatting
here. But due to my custom components implementing custom
`.value' procedures, we might not need any special cases
here */
/* Technically we just want to cast to HTMLElement with
value field here, but multiple types implement it
sepparately, and no common interface exist */
(el as HTMLInputElement).value = d;
});
}
}
let el = this.querySelector('[name="has_repeats"]')
if (el) {
(el as HTMLInputElement).checked = to_boolean(data.getProperty('rrule'))
}
if (data.calendar) {
for (let el of this.getElementsByClassName('calendar-selection')) {
(el as HTMLSelectElement).value = data.calendar;
}
}
}
}
|