From 7949fcdc683d07689bad5da5d20bfa3eeb5a6a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Tue, 5 Sep 2023 01:25:00 +0200 Subject: Move frontend code to subdirectories, to simplify command line flags. --- static/ts/clock.ts | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 static/ts/clock.ts (limited to 'static/ts/clock.ts') diff --git a/static/ts/clock.ts b/static/ts/clock.ts new file mode 100644 index 00000000..bbd15de0 --- /dev/null +++ b/static/ts/clock.ts @@ -0,0 +1,136 @@ +export { + SmallcalCellHighlight, Timebar, + initialize_clock_components +} + +import { makeElement, date_to_percent } from './lib' + +abstract class Clock { + abstract update(now: Date): void; +} + + +class Timebar extends Clock { + + // start_time: Date + // end_time: Date + bar_object: HTMLElement | null + + constructor(/*start_time: Date, end_time: Date*/) { + super(); + // this.start_time = start_time; + // this.end_time = end_time; + this.bar_object = null + } + + + update(now: Date) { + // if (! (this.start_time <= now.getTime() && now.getTime() < this.end_time)) + // return; + + var event_area = document.getElementById(now.format("~Y-~m-~d")) + + if (event_area) { + if (this.bar_object !== null && this.bar_object.parentNode !== null) { + this.bar_object.parentNode.removeChild(this.bar_object) + } else { + this.bar_object = makeElement('div', { + id: 'bar', + className: 'eventlike current-time', + }); + } + + this.bar_object.style.top = date_to_percent(now) + "%"; + event_area.append(this.bar_object) + } + } +} + +class SmallcalCellHighlight extends Clock { + + small_cal: HTMLElement + current_cell: HTMLElement | null + + constructor(small_cal: HTMLElement) { + super(); + this.small_cal = small_cal; + this.current_cell = null + } + + update(now: Date) { + if (this.current_cell) { + this.current_cell.style.border = ""; + } + + /* This is expeced to fail if the current date is not + currently on screen. */ + this.current_cell = this.small_cal.querySelector( + "time[datetime='" + now.format("~Y-~m-~d") + "']"); + + if (this.current_cell) { + this.current_cell.style.border = "1px solid black"; + } + } +} + +/* -------------------------------------------------- */ + +class ClockElement extends HTMLElement { + + timer_id: number + + constructor() { + super(); + + this.timer_id = 0 + } + + connectedCallback() { + let interval = this.hasAttribute('interval') + ? +(this.getAttribute('interval') as string) + : 60; + interval *= 1000 /* ms */ + + this.timer_id = window.setInterval(() => this.update(new Date), interval) + this.update(new Date) + } + + static get observedAttributes() { + return ['timer_id'] + } + + update(_: Date) { /* noop */ } +} + + +class TodayButton extends ClockElement { + a: HTMLAnchorElement; + + constructor() { + super(); + this.a = document.createElement('a'); + this.a.textContent = 'Idag'; + this.a.classList.add('btn'); + } + + connectedCallback() { + super.connectedCallback(); + this.replaceChildren(this.a); + } + + update(now: Date) { + this.a.href = now.format("~Y-~m-~d.html") + } +} + + +class CurrentTime extends ClockElement { + update(now: Date) { + this.textContent = now.format('~H:~M:~S') + } +} + +function initialize_clock_components() { + customElements.define('today-button', TodayButton) + customElements.define('current-time', CurrentTime) +} -- cgit v1.2.3 From f653a01328be3b8be6af35c0c96867623765ca5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Tue, 5 Sep 2023 11:41:46 +0200 Subject: Move JS documentation into the JS-code. Texinfo was a bad match for how TypeScript is structured. This also allows generation of jsdoc pages, which can be nice. Another large win is that this opens up for the texinfo pages to replace the Guile heading with different subheadings, including - external library - internal library - C library - ... --- static/ts/clock.ts | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'static/ts/clock.ts') diff --git a/static/ts/clock.ts b/static/ts/clock.ts index bbd15de0..a0e4670a 100644 --- a/static/ts/clock.ts +++ b/static/ts/clock.ts @@ -1,3 +1,18 @@ +/** + * Components for working with things which depend on the current time. + * + * Also introduces two web components: + * + * ```html + * + * + * ``` + * + * TODO shouldn't these be defined with the rest of the components? + * + * @module + */ + export { SmallcalCellHighlight, Timebar, initialize_clock_components @@ -5,11 +20,17 @@ export { import { makeElement, date_to_percent } from './lib' -abstract class Clock { +/** + * Interface for `things` which wants to get updated on a human timescale. + */ +export abstract class Clock { + /** Called every now and then + * @param now Called with the current time + */ abstract update(now: Date): void; } - +/** The (blue) vertical line which show the current time in the current day. */ class Timebar extends Clock { // start_time: Date @@ -23,7 +44,6 @@ class Timebar extends Clock { this.bar_object = null } - update(now: Date) { // if (! (this.start_time <= now.getTime() && now.getTime() < this.end_time)) // return; @@ -46,11 +66,21 @@ class Timebar extends Clock { } } +/** + * Highlights the current date in the small calendar to the side. + * Currently directly sets a border + * + * @TODO{but should preferably set a class instead}. +*/ class SmallcalCellHighlight extends Clock { small_cal: HTMLElement current_cell: HTMLElement | null + /** + * @param small_cal the DOM-node of the calendar widget. It must support + * querySelector. + */ constructor(small_cal: HTMLElement) { super(); this.small_cal = small_cal; @@ -103,6 +133,14 @@ class ClockElement extends HTMLElement { } +/** + * Updates the ``Today'' link in the side panel to point directly to the + * correct web-address. The link works without JavaScript, but then + * requires a redirect from the server. + * + * All actual updating logic is already abstracted away. It would be + * desirable if something more was done with this. + */ class TodayButton extends ClockElement { a: HTMLAnchorElement; -- cgit v1.2.3 From e753d721519f72014241b3d2fc804a919f655769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Thu, 7 Sep 2023 02:58:41 +0200 Subject: Document remaining javascript items. --- static/ts/clock.ts | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'static/ts/clock.ts') diff --git a/static/ts/clock.ts b/static/ts/clock.ts index a0e4670a..11b2b2c5 100644 --- a/static/ts/clock.ts +++ b/static/ts/clock.ts @@ -10,6 +10,8 @@ * * TODO shouldn't these be defined with the rest of the components? * + * TODO why isn't Timebar and SmallCellHighlight also Web Components? + * * @module */ @@ -35,6 +37,8 @@ class Timebar extends Clock { // start_time: Date // end_time: Date + + /** The bar to update */ bar_object: HTMLElement | null constructor(/*start_time: Date, end_time: Date*/) { @@ -74,7 +78,12 @@ class Timebar extends Clock { */ class SmallcalCellHighlight extends Clock { + /** The calendar which a cell should be highlighted in */ small_cal: HTMLElement + /** + The currently highlighted cell, or `null` if no cell should be + should be highlighted (such as if a non-current month is selected + */ current_cell: HTMLElement | null /** @@ -105,8 +114,16 @@ class SmallcalCellHighlight extends Clock { /* -------------------------------------------------- */ +/** + Base class for custom HTML elements which wants to be updated for a human + timescale. + + When creating, the attribute `interval` can be given, which specifies (in + seconds) how often the component should be updated. +*/ class ClockElement extends HTMLElement { + /** Javascript timer id. Used if the timer needs to be canceled */ timer_id: number constructor() { @@ -125,21 +142,24 @@ class ClockElement extends HTMLElement { this.update(new Date) } - static get observedAttributes() { - return ['timer_id'] - } - + /** + Method which is called each "tick" (see interval) + @param date + The current timestamp when the function is called. + */ update(_: Date) { /* noop */ } } /** - * Updates the ``Today'' link in the side panel to point directly to the - * correct web-address. The link works without JavaScript, but then - * requires a redirect from the server. - * - * All actual updating logic is already abstracted away. It would be - * desirable if something more was done with this. + A "button" which always points to the link "~Y-~m-~d.html". + + This class is bound to the web component + + In the backend code, a `/today` endpoint exists. That however requires that + we ask the server for the correct URL, and follow a 300 (series) redirect. + + Since the URL:s are stable, it's possible to jump directly to the given page. */ class TodayButton extends ClockElement { a: HTMLAnchorElement; @@ -162,12 +182,26 @@ class TodayButton extends ClockElement { } +/** + A component which displays the current time + + This class is bound to the web component + + It currently is hard-coded to display time on the format ~H:~M:~S. +*/ class CurrentTime extends ClockElement { update(now: Date) { this.textContent = now.format('~H:~M:~S') } } +/** + Create Web Components mentioned on this page. + + MUST be called early on in the execution. + + TODO this should be merged with other web component declarations. +*/ function initialize_clock_components() { customElements.define('today-button', TodayButton) customElements.define('current-time', CurrentTime) -- cgit v1.2.3