aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2021-05-17 00:53:51 +0200
committerHugo Hörnquist <hugo@lysator.liu.se>2021-05-17 00:54:41 +0200
commit24e06a13894f885bbb75b79beaa43d1c6fdfbae5 (patch)
tree35fe5c358ce3a13bf3700f341e8fe65eeee8790c
parentCalendar setting working again! (diff)
downloadcalp-24e06a13894f885bbb75b79beaa43d1c6fdfbae5.tar.gz
calp-24e06a13894f885bbb75b79beaa43d1c6fdfbae5.tar.xz
Rework date-time input to be cleaner + work again.
-rw-r--r--doc/ref/javascript/binders.texi10
-rw-r--r--doc/ref/javascript/date_time.texi2
-rw-r--r--module/calp/html/vcomponent.scm63
-rw-r--r--static/binders.js34
-rw-r--r--static/date_time.js54
-rw-r--r--static/script.js26
-rw-r--r--static/style.scss28
-rw-r--r--static/vcal.js39
8 files changed, 124 insertions, 132 deletions
diff --git a/doc/ref/javascript/binders.texi b/doc/ref/javascript/binders.texi
index 2b64b230..0e38411b 100644
--- a/doc/ref/javascript/binders.texi
+++ b/doc/ref/javascript/binders.texi
@@ -1,5 +1,7 @@
@node binders
+@cindex binder
+@cindex binders
@subsection binders.js
The bind system allows HTML-elements to specify that they want to be
@@ -45,3 +47,11 @@ Binder for the wholeday toggle button.
While CSS would suffice, this sets the disabled flags on the time
inputs, giving a better user experience.
@end defun
+
+@defun bind_date_time el e
+@anchor{bind_date_time}
+For @code{date_time} dummy component. Propagates gets and sets to
+underlying input fields.
+
+Note: @emph{Must} be called @emph{after} @code{init_date_time}.
+@end defun
diff --git a/doc/ref/javascript/date_time.texi b/doc/ref/javascript/date_time.texi
index fb2563f1..b2c5db92 100644
--- a/doc/ref/javascript/date_time.texi
+++ b/doc/ref/javascript/date_time.texi
@@ -36,4 +36,6 @@ components. We nevertheless use it here since we are emulating an
input element.
@end defivar
+See also @pxref{bind_date_time}
+
@end defun
diff --git a/module/calp/html/vcomponent.scm b/module/calp/html/vcomponent.scm
index 4852390c..7530de91 100644
--- a/module/calp/html/vcomponent.scm
+++ b/module/calp/html/vcomponent.scm
@@ -160,44 +160,35 @@
(end (prop ev 'DTEND)))
`(div (@ (class "timeinput"))
- (input (@ (type "date")
- (name "dtstart-date")
- (style "grid-column:1;grid-row:2")
- (class "bind")
- (data-property "--dtstart-date")
- (value ,(date->string (as-date start)))))
-
- (input (@ (type "date")
- (name "dtend-date")
- (style "grid-column:1;grid-row:3")
- (class "bind")
- (data-property "--dtend-date")
- ,@(when end `((value ,(date->string (as-date end)))))))
+ ,@(with-label
+ "Starttid"
+ `(div (@ (class "date-time bind")
+ (data-bindby "bind_date_time")
+ (name "dtstart"))
+ (input (@ (type "date")
+ (value ,(date->string (as-date start)))))
+ (input (@ (type "time")
+ (value ,(time->string (as-time start)))))))
,@(with-label
- "Heldag?"
- `(input (@ (type "checkbox")
- (class "bind")
- (data-bindby "bind_wholeday")
- (style "display:none")
- (name "wholeday"))))
-
- (input (@ (type "time")
- (name "dtstart-time")
- (class "bind")
- (data-property "--dtstart-time")
- (style "grid-column:3;grid-row:2;"
- ,(when (date? start) "display:none"))
- (value ,(time->string (as-time start)))))
-
- (input (@ (type "time")
- (name "dtend-time")
- (class "bind")
- (data-property "--dtend-time")
- (style "grid-column:3;grid-row:3;"
- ,(when (date? end) "display:none"))
- ,@(when end `((value ,(time->string (as-time end)))))
- ))))
+ "Sluttid"
+ `(div (@ (class "date-time bind")
+ (data-bindby "bind_date_time")
+ (name "dtend"))
+ (input (@ (type "date")
+ ,@(when end `((value ,(date->string (as-date end)))))))
+ (input (@ (type "time")
+ ,@(when end `((value ,(time->string (as-time end)))))))))
+
+ (div
+ ,@(with-label
+ "Heldag?"
+ `(input (@ (type "checkbox")
+ (class "bind")
+ (data-bindby "bind_wholeday")
+ (name "wholeday")))))
+
+ ))
,@(with-label
"Plats"
diff --git a/static/binders.js b/static/binders.js
index f6c306bd..72550191 100644
--- a/static/binders.js
+++ b/static/binders.js
@@ -110,3 +110,37 @@ function bind_wholeday(el, e) {
}
});
}
+
+
+/* used for dtstart and dtend input boxes
+ init_date_time MUST be called beforehand
+*/
+function bind_date_time(el, e) {
+ e.addEventListener('input', function () {
+ let dt = el.properties[e.name].value;
+ if (e.value == '') return;
+ let y, m, d, h, s;
+ switch (this.type) {
+ case 'date':
+ [y,m,d] = this.value.split('-')
+ dt.setYear(Number(y)/* - 1900 */);
+ dt.setMonth(Number(m) - 1);
+ dt.setDate(d);
+ break;
+ case 'time':
+ [h,m,s] = this.value.split(':')
+ dt.setHours(Number(h));
+ dt.setMinutes(Number(m));
+ dt.setSeconds(0);
+ break;
+ default:
+ console.log("How did you get here??? ", e);
+ }
+
+ el.properties[e.name] = dt;
+ });
+
+ el.properties.get_callback_list(e.name).push(
+ [e, (s, v) => s.value = v.format("~Y-~m-~dT~H:~M")]);
+
+}
diff --git a/static/date_time.js b/static/date_time.js
index 274d476f..8b7249dd 100644
--- a/static/date_time.js
+++ b/static/date_time.js
@@ -1,30 +1,36 @@
-function init_date_time() {
- for (let dt of document.getElementsByClassName("date-time")) {
- dt.time = dt.querySelector('[type=time]');
- dt.date = dt.querySelector('[type=date]');
+function init_date_time_single(dt) {
+ dt.time = dt.querySelector('[type=time]');
+ dt.date = dt.querySelector('[type=date]');
- Object.defineProperty(dt, 'value', {
- get: () => (dt.date.value && dt.time.value)
- // TODO wrapping <date-time/> tag
- ? dt.date.value + "T" + dt.time.value
- : "",
- set: (v) => [dt.date.value, dt.time.value] = v.split("T"),
- });
+ Object.defineProperty(dt, 'value', {
+ get: () => (dt.date.value && dt.time.value)
+ // TODO wrapping <date-time/> tag
+ ? dt.date.value + "T" + dt.time.value
+ : "",
+ set: (v) => [dt.date.value, dt.time.value] = v.split("T"),
+ });
- Object.defineProperty(dt, 'name', {
- get: () => dt.attributes.name.value
- });
+ Object.defineProperty(dt, 'name', {
+ get: () => dt.attributes.name.value
+ });
- dt._addEventListener = dt.addEventListener;
- dt.addEventListener = function (field, proc) {
- switch (field) {
- case 'input':
- dt.time.addEventListener(field, proc);
- dt.date.addEventListener(field, proc);
- break;
- default:
- dt._addEventListener(field, proc);
- }
+ dt._addEventListener = dt.addEventListener;
+ dt.addEventListener = function (field, proc) {
+ /* input events are propagated to children
+ other events target ourselves */
+ switch (field) {
+ case 'input':
+ dt.time.addEventListener(field, proc);
+ dt.date.addEventListener(field, proc);
+ break;
+ default:
+ dt._addEventListener(field, proc);
}
}
}
+
+function init_date_time() {
+ for (let dt of document.getElementsByClassName("date-time")) {
+ init_date_time_single(dt);
+ }
+}
diff --git a/static/script.js b/static/script.js
index 6a561757..8042c341 100644
--- a/static/script.js
+++ b/static/script.js
@@ -14,18 +14,30 @@ class EventCreator {
}
create_empty_event () {
+ /* TODO this doesn't clone JS attributes */
+
let event = document.getElementById("event-template")
.firstChild.cloneNode(true);
let popup = document.getElementById("popup-template")
.firstChild.cloneNode(true);
- /* TODO shouldn't this use transferListeners (or similar)?
+ /* -------------------- */
+ /* Manually transfer or recreate attributes which we still need */
+ /* TODO shouldn't these use transferListeners (or similar)?
See input_list.js:transferListeners */
+
+ for (let dt of popup.getElementsByClassName("date-time")) {
+ init_date_time_single(dt);
+ }
+
popup.getElementsByClassName("edit-form")[0].onsubmit = function () {
create_event(event);
return false; /* stop default */
}
+ /* -------------------- */
+ /* Fix tabs for newly created popup */
+
let id = gensym ("__js_event");
// TODO remove button?
@@ -43,8 +55,12 @@ class EventCreator {
let nav = popup.getElementsByClassName("popup-control")[0];
bind_popup_control(nav);
+ /* -------------------- */
+
// TODO download links
+ /* -------------------- */
+
event.id = id;
popup.id = "popup" + id;
@@ -261,6 +277,8 @@ window.onload = function () {
sch.update(d);
}, 1000 * 60);
+ init_date_time();
+
/* Is event creation active? */
if (EDIT_MODE) {
let eventCreator = new EventCreator;
@@ -294,7 +312,7 @@ window.onload = function () {
let popupElement = document.getElementById("popup" + event.id);
open_popup(popupElement);
- popupElement.querySelector("input[name='summary']").focus();
+ popupElement.querySelector("input[name='summary']").focus();
});
}
@@ -311,7 +329,6 @@ window.onload = function () {
*/
el.parentElement.removeAttribute("href");
- /* TODO this doesn't yet apply to newly created events */
let popup = document.getElementById("popup" + el.id);
popup.getElementsByClassName("edit-form")[0].onsubmit = function () {
create_event(el);
@@ -322,7 +339,7 @@ window.onload = function () {
if (el.closest(".longevents")) {
new VComponent(el, true);
} else {
- new VComponent(el, true);
+ new VComponent(el, false);
}
}
@@ -379,7 +396,6 @@ window.onload = function () {
// init_arbitary_kv();
- init_date_time();
init_input_list();
}
diff --git a/static/style.scss b/static/style.scss
index 202e3a34..052c9a93 100644
--- a/static/style.scss
+++ b/static/style.scss
@@ -881,34 +881,6 @@ along with their colors.
}
.timeinput {
-
- display: grid;
- grid-template-columns: 1fr [lbl-start] 1ch 1fr 1ch [lbl-end];
- grid-template-rows: [lbl-start] 0.7fr 1fr 1fr 0.3fr [lbl-end];
-
- label {
- background-color: rgba(10,20,30,0.7);
- color: white;
- border-radius: 1em;
-
- grid-column: lbl-start / lbl-end;
- grid-row: lbl-start / lbl-end;
-
- text-align: center;
-
- user-select: none;
-
- z-index: 1;
-
- }
-
- input {
- z-index: 2;
- }
-
- input:checked ~ input {
- z-index: 0;
- }
}
}
diff --git a/static/vcal.js b/static/vcal.js
index 366b879a..13c489b8 100644
--- a/static/vcal.js
+++ b/static/vcal.js
@@ -80,45 +80,6 @@ class VComponent {
/* checkbox for whole day */
- for (let field of ['dtstart', 'dtend']) {
-
- this.get_callback_list(`--${field}-time`).push(
- [el, (el, v) => { let date = this[field];
- if (v == '') return;
- let [h,m,s] = v.split(':')
- date.setHours(Number(h));
- date.setMinutes(Number(m));
- date.setSeconds(0);
- this[field] = date; }])
- this.get_callback_list(`--${field}-date`).push(
- [el, (el, v) => { let date = this[field];
- if (v == '') return;
- let [y,m,d] = v.split('-')
- date.setYear(Number(y)/* - 1900*/);
- date.setMonth(Number(m) - 1);
- date.setDate(d);
- this[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.
- */
- let l = this.get_callback_list(field);
- console.log(l);
- l.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");
- }]);
- console.log(l);
- }
-
/* Popuplate default types, see types.js for property_names */
for (let property of property_names) {
this.ical_properties.add(property)