aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2020-07-14 12:54:05 +0200
committerHugo Hörnquist <hugo@lysator.liu.se>2020-07-14 13:03:28 +0200
commit982ec24a4ff33513391e860d2c04d1b11271a62f (patch)
tree6de9420fc2260f6a143610028090b4090f04126f
parentAdd functions for TZ dates in JS. (diff)
downloadcalp-982ec24a4ff33513391e860d2c04d1b11271a62f.tar.gz
calp-982ec24a4ff33513391e860d2c04d1b11271a62f.tar.xz
Javascripts date should now work for both local and UTC dates.
-rw-r--r--module/output/html.scm19
-rw-r--r--static/script.js66
2 files changed, 46 insertions, 39 deletions
diff --git a/module/output/html.scm b/module/output/html.scm
index 307f18e5..6265b189 100644
--- a/module/output/html.scm
+++ b/module/output/html.scm
@@ -335,8 +335,8 @@
(lambda (e) (event-length/day day-date e)))
`(div (@ (class "events event-container") (id ,(date-link day-date))
- (data-start ,(date->string day-date) "T00:00Z")
- (data-end ,(date->string (add-day day-date)) "T00:00Z"))
+ (data-start ,(date->string day-date))
+ (data-end ,(date->string (add-day day-date)) ))
,@(map (lambda (time)
`(div (@ (class "clock clock-" ,time))))
(iota 12 0 2))
@@ -371,8 +371,8 @@
(div (@ (class "days"))
,@(time-marker-div)
(div (@ (class "longevents event-container")
- (data-start ,(date->string start-date) "T00:00Z")
- (data-end ,(date->string (add-day end-date)) "T00:00Z")
+ (data-start ,(date->string start-date) )
+ (data-end ,(date->string (add-day end-date)) )
(style "grid-column-end: span " ,(days-in-interval start-date end-date)))
,@(lay-out-long-events start-date end-date long-events))
,@(map (lambda (day-date)
@@ -441,16 +441,16 @@
(div
,(call-with-values (lambda () (fmt-time-span ev))
(case-lambda [(start) `(div (span (@ (class "dtstart")
- (data-fmt "%H:%M"))
+ (data-fmt "%L%H:%M"))
,start))]
[(start end) `(div (span (@ (class "dtstart")
;; TODO same format string
;; as fmt-time-span used
- (data-fmt "%H:%M"))
+ (data-fmt "%L%H:%M"))
,start)
" — "
(span (@ (class "dtend")
- (data-fmt "%H:%M"))
+ (data-fmt "%L%H:%M"))
,end))]))
,(when (and=> (prop ev 'LOCATION) (negate string-null?))
`(div (b "Plats: ")
@@ -827,7 +827,10 @@
;; This would idealy be a <template> element, but there is some
;; form of special case with those in xhtml, but I can't find
;; the documentation for it.
- (div (@ (class "template") (id "event-template"))
+ (div (@ (class "template event-container") (id "event-template")
+ ;; Only needed to create a duration.
+ (data-start "2020-01-01")
+ (data-end "2020-01-02"))
,(let ((cal (vcalendar
name: "Generated"
children: (list (vevent
diff --git a/static/script.js b/static/script.js
index 51289881..6400a2b1 100644
--- a/static/script.js
+++ b/static/script.js
@@ -71,15 +71,18 @@ function makeElement (name, attr={}) {
return element;
}
-/* -------------------------------------------------- */
-
function round_time (time, fraction) {
let scale = 1 / fraction;
return Math.round (time * scale) / scale;
}
+/* only used by the bar.
+ Events use the start and end time of their container, but since the bar
+ is moving between containers that is clumsy.
+ Just doing (new Date()/(86400*1000)) would be nice, but there's no good
+ way to get the time in the current day.
+ */
function date_to_percent (date) {
- // Decimal time
return (date.getHours() + (date.getMinutes() / 60)) * 100/24;
}
@@ -143,7 +146,6 @@ class EventCreator {
= that.event
= document.getElementById("event-template")
.firstChild.cloneNode(true);
- bind_properties(event, wide_element);
/* [0, 1) -- where are we in the container */
/* Ronud to force steps of quarters */
@@ -156,6 +158,12 @@ class EventCreator {
/* ---------------------------------------- */
+ this.appendChild(event);
+
+ /* requires that event is child of an '.event-container'. */
+ bind_properties(event, wide_element);
+
+ /* requires that dtstart and dtend properties are initialized */
place_in_edit_mode(event);
/* ---------------------------------------- */
@@ -167,7 +175,6 @@ class EventCreator {
e.style.pointerEvents = "none";
}
- this.appendChild(event);
}
let time1 = Number(that.event.dataset.time1);
@@ -180,8 +187,8 @@ class EventCreator {
let event_container = that.event.closest(".event-container");
/* These two are in UTC */
- let container_start = new Date(event_container.dataset.start);
- let container_end = new Date(event_container.dataset.end);
+ let container_start = parseDate(event_container.dataset.start);
+ let container_end = parseDate(event_container.dataset.end);
/* ---------------------------------------- */
@@ -195,8 +202,9 @@ class EventCreator {
in utc, and I only really care about local time (which a specific local
timezone doesn't give me)
*/
- let d1 = new Date(container_start.getTime() + start_in_duration).untc();
- let d2 = new Date(container_start.getTime() + end_in_duration).untc();
+ /* TODO Should these inherit UTC from container_*? */
+ let d1 = new Date(container_start.getTime() + start_in_duration)
+ let d2 = new Date(container_start.getTime() + end_in_duration)
that.event.properties.dtstart = d1;
that.event.properties.dtend = d2;
@@ -322,7 +330,7 @@ function place_in_edit_mode (event) {
onchange: function (e) {
let [hour, minute] = this.value.split(":").map(Number);
/* retain the year, month, and day information */
- let d = new Date(event.properties[fieldname]);
+ let d = copyDate(event.properties[fieldname]);
d.setHours(hour);
d.setMinutes(minute);
event.properties[fieldname] = d;
@@ -536,12 +544,15 @@ function format_date(date, str) {
for (var i = 0; i < str.length; i++) {
if (fmtmode) {
switch (str[i]) {
+ /* Moves the date into local time. */
+ case 'L': date = to_local(date); break;
case 'Y': outstr += datepad(date.getFullYear(), 4); break;
case 'm': outstr += datepad(date.getMonth() + 1); break;
case 'd': outstr += datepad(date.getDate()); break;
case 'H': outstr += datepad(date.getHours()); break;
case 'M': outstr += datepad(date.getMinutes()); break;
case 'S': outstr += datepad(date.getSeconds()); break;
+ case 'Z': if (date.utc) outstr += 'Z'; break;
}
fmtmode = false;
} else if (str[i] == '%') {
@@ -556,15 +567,7 @@ Object.prototype.format = function () { return this; } /* any number of argument
Date.prototype.format = function (str) { return format_date (this, str); }
/*
- As far as I can tell Date objects lack timezone information, and just
- use the local time (while internally storing everything in seconds since
- the epoch). This subtracts the local offset from the time, giving a time object
- where the human components hopefully are in UTC (even though the object still
- reports it being in local time).
*/
-Date.prototype.untc = function () {
- return new Date(this.getTime() + this.getTimezoneOffset() * 60 * 1000);
-}
function bind_properties (el, wide_event=false) {
@@ -585,7 +588,7 @@ function bind_properties (el, wide_event=false) {
case 'date':
lst.push([s, (s, v) => s.innerHTML = v.format("%Y-%m-%d")]); break;
case 'date-time':
- lst.push([s, (s, v) => s.innerHTML = v.format("%Y-%m-%dT%H:%M:%SZ")]); break;
+ lst.push([s, (s, v) => s.innerHTML = v.format("%Y-%m-%dT%H:%M:%S%Z")]); break;
default:
lst.push([s, (s, v) => s.innerHTML = v]);
}
@@ -609,24 +612,25 @@ function bind_properties (el, wide_event=false) {
});
}
+ let container = el.closest(".event-container");
+ let start = parseDate(container.dataset.start);
+ let end = parseDate(container.dataset.end);
+
if (el.properties.dtstart) {
- el.properties.dtstart = new Date(el.properties.dtstart);
+ el.properties.dtstart = parseDate(el.properties.dtstart);
el.properties["_slot_dtstart"].push(
- [el.style,
- wide_event
- ? (s, v) => s.left = 100 * (v - start_time)/(end_time - start_time) + "%"
- : (s, v) => s.top = date_to_percent(v) + "%"]);
+ [el.style, (s, v) =>
+ s[wide_event?'left':'top'] = 100 * (to_local(v) - start)/(end - start) + "%"]);
}
+
if (el.properties.dtend) {
- el.properties.dtend = new Date(el.properties.dtend);
+ el.properties.dtend = parseDate(el.properties.dtend);
el.properties["_slot_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,
- wide_event
- // 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.
- ? (s, v) => s.right = 100 * (1 - (v-start_time)/(end_time-start_time)) + "%"
- : (s, v) => s.bottom = (100 - date_to_percent(v)) + "%"]);
+ (s, v) => s[wide_event?'right':'bottom'] = 100 * (1 - (to_local(v)-start)/(end-start)) + "%"]);
}
}