aboutsummaryrefslogtreecommitdiff
path: root/static/components
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2021-11-26 15:32:41 +0100
committerHugo Hörnquist <hugo@lysator.liu.se>2021-11-26 15:32:41 +0100
commit1df15b2ceaef09b48a39aa6046b577da11ea2f72 (patch)
treecf8dd5340703961c53daae1b2e7d0535d785f6d4 /static/components
parentSlightly better error hnadling in directory-table. (diff)
downloadcalp-1df15b2ceaef09b48a39aa6046b577da11ea2f72.tar.gz
calp-1df15b2ceaef09b48a39aa6046b577da11ea2f72.tar.xz
Got categories working.
Diffstat (limited to 'static/components')
-rw-r--r--static/components/input-list.ts101
-rw-r--r--static/components/vevent-edit.ts8
2 files changed, 88 insertions, 21 deletions
diff --git a/static/components/input-list.ts b/static/components/input-list.ts
index 326cb2b5..899e8f4f 100644
--- a/static/components/input-list.ts
+++ b/static/components/input-list.ts
@@ -2,11 +2,15 @@ export { InputList }
/* This file replaces input_list.js */
+/*
+ TODO allow each item to be a larger unit, possibly containing multiple input
+ fields.
+*/
class InputList extends HTMLElement {
el: HTMLInputElement;
- values: [HTMLInputElement, any][] = [];
+ _listeners: [string, (e: Event) => void][] = [];
constructor() {
super();
@@ -14,20 +18,27 @@ class InputList extends HTMLElement {
}
connectedCallback() {
+ for (let child of this.children) {
+ child.remove();
+ }
this.addInstance();
}
- addInstance() {
+ createInstance(): HTMLInputElement {
let new_el = this.el.cloneNode(true) as HTMLInputElement
let that = this;
new_el.addEventListener('input', function() {
+ /* TODO .value is empty both if it's actually empty, but also
+ for invalid input. Check new_el.validity, and new_el.validationMessage
+ */
if (new_el.value === '') {
- let sibling = this.previousElementSibling || this.nextElementSibling;
- // this.remove();
- // that.values = that.values.filter((p) => p[0] == this)
- that.values = that.values.filter((p) => p[0] != this);
- this.remove();
- (sibling as HTMLInputElement).focus();
+ let sibling = (this.previousElementSibling || this.nextElementSibling)
+ /* Only remove ourselves if we have siblings
+ Otherwise we just linger */
+ if (sibling) {
+ this.remove();
+ (sibling as HTMLInputElement).focus();
+ }
} else {
if (!this.nextElementSibling) {
that.addInstance();
@@ -36,24 +47,76 @@ class InputList extends HTMLElement {
}
}
});
- this.values.push([new_el, ''])
- // this.appendChild(new_el);
- this.replaceChildren(... this.values.map((p) => p[0]))
+
+ for (let [type, proc] of this._listeners) {
+ new_el.addEventListener(type, proc);
+ }
+
+ return new_el;
+ }
+
+ addInstance() {
+ let new_el = this.createInstance();
+ this.appendChild(new_el);
}
get value(): any[] {
- return []
+ let value_list = []
+ for (let child of this.children) {
+ value_list.push((child as any).value);
+ }
+ if (value_list[value_list.length - 1] === '') {
+ value_list.pop();
+ }
+ return value_list
}
set value(new_value: any[]) {
- let els = [];
+
+ let all_equal = true;
+ for (let i = 0; i < this.children.length; i++) {
+ let sv = (this.children[i] as any).value
+ all_equal
+ &&= (sv == new_value[i])
+ || (sv === '' && new_value[i] == undefined)
+ }
+ if (all_equal) return;
+
+ /* Copy our current input elements into a dictionary.
+ This allows us to only create new elements where needed
+ */
+ let values = new Map;
+ for (let child of this.children) {
+ values.set((child as HTMLInputElement).value, child);
+ }
+
+ let output_list: HTMLInputElement[] = []
for (let value of new_value) {
- let new_el = this.el.cloneNode() as HTMLInputElement;
- new_el.value = value;
- els.push(new_el);
+ let element;
+ /* Only create element if needed */
+ if ((element = values.get(value))) {
+ output_list.push(element)
+ /* clear dictionary */
+ values.set(value, false);
+ } else {
+ let new_el = this.createInstance();
+ new_el.value = value;
+ output_list.push(new_el);
+ }
+ }
+ /* final, trailing, element */
+ output_list.push(this.createInstance());
+
+ this.replaceChildren(...output_list);
+ }
+
+ addEventListener(type: string, proc: ((e: Event) => void)) {
+ // if (type != 'input') throw "Only input supported";
+
+ this._listeners.push([type, proc])
+
+ for (let child of this.children) {
+ child.addEventListener(type, proc);
}
- /* Final element (empty) */
- els.push(this.el.cloneNode() as HTMLInputElement);
- this.replaceChildren(...els);
}
}
diff --git a/static/components/vevent-edit.ts b/static/components/vevent-edit.ts
index 4408cbb8..b9b733a0 100644
--- a/static/components/vevent-edit.ts
+++ b/static/components/vevent-edit.ts
@@ -1,9 +1,10 @@
export { ComponentEdit }
import { ComponentVEvent } from './vevent'
+import { InputList } from './input-list'
import { DateTimeInput } from './date-time-input'
-import { vcal_objects, event_calendar_mapping } from '../globals'
+import { vcal_objects } from '../globals'
import { VEvent } from '../vevent'
import { create_event } from '../server_connect'
@@ -55,18 +56,21 @@ class ComponentEdit extends ComponentVEvent {
// for (let el of this.getElementsByClassName("interactive")) {
for (let el of this.querySelectorAll("[data-property]")) {
// console.log(el);
- el.addEventListener('input', () => {
+ 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)