aboutsummaryrefslogtreecommitdiff
path: root/static/script.js
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2021-03-02 23:34:14 +0100
committerHugo Hörnquist <hugo@lysator.liu.se>2021-03-02 23:34:14 +0100
commitcbe3c46a898822b6ee0f10366e561c6a8055a1b6 (patch)
tree3ceb9ecfb97b0d8a6db6f2c3cc17f59b5c117f63 /static/script.js
parentLook at mapping in vcal types to js types. (diff)
downloadcalp-cbe3c46a898822b6ee0f10366e561c6a8055a1b6.tar.gz
calp-cbe3c46a898822b6ee0f10366e561c6a8055a1b6.tar.xz
Start moving vcal stuff to own class.
Diffstat (limited to '')
-rw-r--r--static/script.js307
1 files changed, 14 insertions, 293 deletions
diff --git a/static/script.js b/static/script.js
index 68773231..d809cc25 100644
--- a/static/script.js
+++ b/static/script.js
@@ -19,6 +19,8 @@ class EventCreator {
let popup = document.getElementById("popup-template")
.firstChild.cloneNode(true);
+ /* TODO shouldn't this use transferListeners (or similar)?
+ See input_list.js:transferListeners */
popup.getElementsByClassName("edit-form")[0].onsubmit = function () {
create_event(event);
return false; /* stop default */
@@ -113,7 +115,10 @@ class EventCreator {
this.appendChild(event);
/* requires that event is child of an '.event-container'. */
- bind_properties(event, wide_element);
+ event.properties = new VComponent(
+ event,
+ wide_element=wide_element);
+ // bind_properties(event, wide_element);
/* requires that dtstart and dtend properties are initialized */
@@ -159,6 +164,8 @@ class EventCreator {
let d1 = new Date(container_start.getTime() + start_in_duration)
let d2 = new Date(container_start.getTime() + end_in_duration)
+ // console.log(that.event);
+ console.log(d1, d2);
that.event.properties.dtstart = d1;
that.event.properties.dtend = d2;
}
@@ -187,6 +194,8 @@ class EventCreator {
}
}
+
+
/* This incarnation of this function only adds the calendar switcher dropdown.
All events are already editable by switching to that tab.
@@ -227,6 +236,8 @@ function place_in_edit_mode (event) {
tab.querySelector("input[name='summary']").focus();
}
+
+
window.onload = function () {
// let start_time = document.querySelector("meta[name='start-time']").content;
// let end_time = document.querySelector("meta[name='end-time']").content;
@@ -309,9 +320,9 @@ window.onload = function () {
/* Bind all vcomponent properties into javascript. */
if (el.closest(".longevents")) {
- bind_properties(el, true);
+ el.properties = new VComponent(el, true);
} else {
- bind_properties(el, false);
+ el.properties = new VComponent(el, true);
}
}
@@ -373,293 +384,3 @@ window.onload = function () {
}
-
-/*
- Returns the _value_ slot of given field in event, creating it if needed .
- el - the event to work on
- field - name of the field
- default_value - default value when creating
- bind_to_ical - should this property be added to the icalendar subtree?
-*/
-function get_property(el, field, default_value) {
- if (! el.properties) {
- /* TODO only have construction once */
- el.properties = {};
- el.properties.ical_properties = new Set()
- }
-
- if (! el.properties["_slot_" + field]) {
- el.properties["_slot_" + field] = [];
- el.properties["_value_" + field] = default_value;
-
- Object.defineProperty(
- el.properties, field,
- {
- get: function () {
- return this["_value_" + field];
- },
- set: function (value) {
- this["_value_" + field] = value;
- for (let [slot,updater] of el.properties["_slot_" + field]) {
- updater(slot, value);
- }
- }
- });
- }
-
- return el.properties["_slot_" + field];
-}
-
-
-
-/*
- Properties are icalendar properties.
-
- p['name'] to get and set value (also updates any connected slots)
-
- p['_value_name'] for raw value
- p['_slot_name'] for connected slots, Vector of pairs, where the
- car should be a reference to the slot, and the
- cdr a procedure which takes a slot and a value
- and binds the value to the slot.
- */
-function bind_properties (el, wide_event=false) {
-
- el.properties = {}
- el.properties.ical_properties = new Set()
- let popup = popup_from_event(el);
- // let children = el.getElementsByTagName("properties")[0].children;
-
- /* actual component (not popup) */
- /*
- for (let e of el.querySelectorAll(".bind")) {
- }
- */
-
- /* bind_recur */
-
- /* primary display tab */
-
- let p;
- let lst = [...popup.querySelectorAll(".bind"),
- ...el.querySelectorAll('.bind')];
- for (let e of lst) {
- if ((p = e.closest('[data-bindby]'))) {
- // console.log(p.dataset.bindby);
- eval(p.dataset.bindby)(el, e);
- } else {
- let f = ((s, v) => s.innerHTML = v.format(s.dataset && s.dataset.fmt));
- get_property(el, e.dataset.property).push([e, f]);
- }
- }
-
- // for (let e of popup.querySelectorAll(".summary-tab .bind")) {
- // /* bind_view
- // let f = (s, v) => s.innerHTML = v.format(s.dataset && s.dataset.fmt);
- // get_property(el, e.dataset.property).push([e, f]);
- // */
- // }
-
- /* edit tab */
- // for (let e of popup.querySelectorAll(".edit-tab .bind")) {
- // /* bind-edit
- // let p = get_property(el, e.dataset.property);
- // e.addEventListener('input', function () {
- // el.properties[e.dataset.property] = this.value;
- // });
- // let f;
- // switch (e.tagName) {
- // case 'input':
- // switch (e.type) {
- // case 'time': f = (s, v) => s.value = v.format("~H:~M"); break;
- // case 'date': f = (s, v) => s.value = v.format("~Y-~m-~d"); break;
- // // TODO remaining types cases
- // default: f = (s, v) => s.value = v;
- // }
- // p.push([e, f])
- // break;
- // case 'textarea':
- // f = (s, v) => s.innerHTML = v;
- // p.push([e, f])
- // break;
- // default:
- // alert("How did you get here??? " + e.tagName)
- // break;
- // }
- // */
- // }
-
- /* checkbox for whole day */
-
- for (let field of ['dtstart', 'dtend']) {
-
- get_property(el, `--${field}-time`).push(
- [el, (el, v) => { let date = el.properties[field];
- if (v == '') return;
- let [h,m,s] = v.split(':')
- date.setHours(Number(h));
- date.setMinutes(Number(m));
- date.setSeconds(0);
- el.properties[field] = date; }])
- get_property(el, `--${field}-date`).push(
- [el, (el, v) => { let date = el.properties[field];
- if (v == '') return;
- let [y,m,d] = v.split('-')
- date.setYear(Number(y)/* - 1900*/);
- date.setMonth(Number(m) - 1);
- date.setDate(d);
- el.properties[field] = date; }])
-
-
- /* Manual fetch of the fields instead of the general method,
- to avoid an infinite loop of dtstart setting --dtstart-time,
- and vice versa.
- NOTE if many more fields require special treatment then a
- general solution is required.
- */
- get_property(el, field).push(
- [el, (el, v) => { popup
- .querySelector(`.edit-tab input[name='${field}-time']`)
- .value = v.format("~H:~M");
- popup
- .querySelector(`.edit-tab input[name='${field}-date']`)
- .value = v.format("~Y-~m-~d");
- }]);
- }
-
- for (let property of property_names) {
- el.properties.ical_properties.add(property)
- }
-
- /* icalendar properties */
- for (let child of el.querySelector("vevent > properties").children) {
- /* child ≡ <dtstart><date-time>...</date-time></dtstart> */
-
- let field = child.tagName;
- let lst = get_property(el, field);
-
- el.properties.ical_properties.add(field)
-
- /* Bind vcomponent fields for this event */
- for (let s of el.querySelectorAll(`${field} > :not(parameters)`)) {
- /* s ≡ <date-time>...</date-time> */
-
- /* Binds value from XML-tree to javascript object
- [parsedate]
-
- TODO capture xcal type here, to enable us to output it to jcal later.
- */
- let parsedValue;
- let type = s.tagName.toLowerCase();
- switch (type) {
- case 'float':
- case 'integer':
- parsedValue = new Number(s.innerHTML);
- parsedValue.type = type;
- break;
-
- case 'date-time':
- case 'date':
- parsedValue = parseDate(s.innerHTML);
- break;
-
- /* TODO */
- case 'duration':
- let start = s.getElementsByTagName('start');
- let end = s.getElementsByTagName('end, duration');
- if (end.tagName === 'period') {
- parsePeriod(end.innerHTML);
- }
- break;
- /* TODO */
- case 'period':
- parsePeriod(s.innerHTML);
- break;
- /* TODO */
- case 'utc-offset':
- break;
-
- case 'recur':
- parsedValue = recur_xml_to_rrule(s);
- break;
-
- case 'boolean':
- switch (s.innerHTML) {
- case 'true': parsedValue = true; break;
- case 'false': parsedValue = false; break;
- default: throw "Value error"
- }
- break;
-
-
- case 'binary':
- /* Binary is going to be BASE64 decoded, allowing us to ignore
- it and handle it as a string for the time being */
- case 'cal-address':
- case 'text':
- case 'uri':
- /* TODO Attributes on strings doesn't work
- They do however work on String:s
- */
- parsedValue = s.innerHTML;
- // parsedValue.type = type;
- break;
-
- default:
- parsedValue.type = 'unknown';
- parsedValue = s.innerHTML;
- }
- el.properties['_value_rrule'] = parsedValue;
- }
- }
-
- /* set up graphical display changes */
- let container = el.closest(".event-container");
- if (container === null) {
- console.log("No enclosing event container for", el);
- return;
- }
- let start = parseDate(container.dataset.start);
- let end = parseDate(container.dataset.end);
-
- if (el.properties.dtstart) {
- /* [parsedate] */
- // el.properties.dtstart = parseDate(el.properties.dtstart);
- get_property(el, 'dtstart').push(
- [el.style, (s, v) =>
- s[wide_event?'left':'top'] = 100 * (to_local(v) - start)/(end - start) + "%"]);
- }
-
-
- if (el.properties.dtend) {
- // el.properties.dtend = parseDate(el.properties.dtend);
- get_property(el, 'dtend').push(
- // TODO right and bottom only works if used from the start. However,
- // events from the backend instead use top/left and width/height.
- // Normalize so all use the same, or find a way to convert between.
- [el.style,
- (s, v) => s[wide_event?'right':'bottom'] = 100 * (1 - (to_local(v)-start)/(end-start)) + "%"]);
- }
-
-
- /* ---------- Calendar ------------------------------ */
-
- if (! el.dataset.calendar) {
- el.dataset.calendar = "Unknown";
- }
-
- let calprop = get_property(el, 'calendar', el.dataset.calendar);
-
- const rplcs = (s, v) => {
- let [_, calclass] = s.classList.find(/^CAL_/);
- s.classList.replace(calclass, "CAL_" + v);
- }
-
- calprop.push([popup, rplcs]);
- calprop.push([el, rplcs]);
- calprop.push([el, (s, v) => s.dataset.calendar = v]);
-
-
-
- /* ---------- Calendar ------------------------------ */
-}