]> Lady’s Gitweb - WWW/commitdiff
Initial attempt at a calendar widget
authorLady <redacted>
Sat, 6 Jan 2024 19:37:41 +0000 (14:37 -0500)
committerLady <redacted>
Sat, 6 Jan 2024 19:37:41 +0000 (14:37 -0500)
This is still a demo; more functionality will be added over time but
this at least displays the days correctly.

sources/calendar/index.xhtml [new file with mode: 0644]

diff --git a/sources/calendar/index.xhtml b/sources/calendar/index.xhtml
new file mode 100644 (file)
index 0000000..cf55a00
--- /dev/null
@@ -0,0 +1,170 @@
+<?xml version="1.0"?>
+<article xmlns="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4" lang="en" xml:lang="en">
+       <style><![CDATA[@charset "UTF-8";
+#widget h2{ Margin-Inline: Auto; Margin-Block-End: 1REM; Border-Block-End: Thin Solid; Padding-Inline: 1CH; Max-Inline-Size: Max-Content }
+#widget>footer{ Display: Grid; Margin-Block: 1REM; Margin-Inline: Auto; Max-Inline-Size: Max-Content; Grid-Template-Columns: 1FR 1FR 1FR; Gap: 1CH }
+#widget>div{ Display: Flex; Margin-Block: 1REM; Flex-Flow: Row Wrap; Gap: 1REM }
+#widget>div>div:First-Child{ Min-Inline-Size: Max-Content; Inline-Size: 27REM; Flex: Auto;}
+#widget>div>div:First-Child>table{ Margin-Inline: Auto; Font-Variant-Numeric: Lining-Nums Tabular-Nums; Text-Align-Last: Auto }
+#widget>div>div:First-Child>table th{ Border-Block-End: Thin Solid; Text-Align: Center }
+#widget>div>div:First-Child>table td{ Position: Relative; Border: Thin Solid; Padding: 0; Block-Size: 3.5EM; Inline-Size: 3.5EM; Vertical-Align: Top; Background: #1A1A1A; Text-Align: Start }
+#widget>div>div:First-Child>table td:Nth-Child(n+6){ Background-Image: Repeating-Linear-Gradient(To Bottom Right, Transparent 0PX, Transparent .5PX, #686868 1PX, #686868 1.5PX, Transparent 2PX) }
+#widget>div>div:First-Child>table td>b{ Display: Block; Margin-Inline-End: Auto; Border: Thin #F3DEE3 Solid; Padding: 2PX; Width: 3CH; Color: #1A1A1A; Background: #F3DEE3; Box-Shadow: Inset -1PX -1PX CurrentColor; Font-Style: Italic; Text-Align: Center }
+#widget>div>div:First-Child>table td>small{ Display: Block; Position: Absolute; Inset-Block-End: 0; Inset-Inline-End: 0; Margin-Block-Start: Auto; Margin-Inline-Start: Auto; Border-Block-Start: Thin Dashed; Border-Inline-Start: Thin Dashed; Padding-Inline: .5CH; Width: Max-Content; Max-Width: 100%; Color: #F3DEE3; Background: #1A1A1A; Font-Size: .75EM; Font-Style: Italic }
+#widget>div>div:First-Child>table td.today{ Box-Shadow: 1PX 1PX #700020 }
+#widget>div>div:First-Child>table td.today>b{ Color: #992244 }
+#widget>div>div:First-Child>table td.today>small{ Background: #700020 }
+#widget>div>div{ Width: 16REM Flex: None}
+]]></style>
+       <meta itemprop="urn:fdc:ladys.computer:20231231:Shu1She4:title" content="Calendar | Lady’s Computer"/>
+       <h1><small><a href="/">Lady’s Computer</a> ∷ </small>Calendar</h1>
+       <!--<details>
+               <summary>About this calendar…</summary>
+       </details>-->
+       <aside id="widget">
+               <template>
+                       <h2/>
+                       <div>
+                               <div>
+                                       <table>
+                                               <thead>
+                                                       <tr>
+                                                               <th scope="col">Ⅰ</th>
+                                                               <th scope="col">Ⅱ</th>
+                                                               <th scope="col">Ⅲ</th>
+                                                               <th scope="col">Ⅳ</th>
+                                                               <th scope="col">Ⅴ</th>
+                                                               <th scope="col">Ⅵ</th>
+                                                               <th scope="col">Ⅶ</th>
+                                                               <th scope="col">Ⅷ</th>
+                                                       </tr>
+                                               </thead>
+                                               <tbody>
+                                                       <tr/>
+                                                       <tr/>
+                                                       <tr/>
+                                                       <tr/>
+                                                       <tr/>
+                                               </tbody>
+                                       </table>
+                               </div>
+                               <div/>
+                       </div>
+                       <footer>
+                               <button type="button">Previous</button>
+                               <button type="button">Current</button>
+                               <button type="button">Next</button>
+                       </footer>
+               </template>
+               <noscript>Calendar widget requires Javascript!</noscript>
+               <script><![CDATA[#!js
+const widget= document.getElementById("widget")
+const template= widget.querySelector("#widget>template")
+const day= +Date.UTC(1970, 0, 2)
+const today = new Date();
+const dateForDay= (start, month, dayInMonth) => new Date
+(      +start + ((month - 1) * 40 + dayInMonth - 1) * day)
+const td= (start, month, dayInMonth) =>
+{      const elt= document.createElement("td")
+       const date= dateForDay(start, month, dayInMonth)
+       const label= document.createElement("b")
+       label.textContent= `${dayInMonth}`.padStart(2, "0")
+       const caption= document.createElement("small")
+       caption.textContent= `${date.getUTCDate()}`.padStart(2, "0")
+       +       [       " Jan"
+               ,       " Feb"
+               ,       " Mar"
+               ,       " Apr"
+               ,       " May"
+               ,       " Jun"
+               ,       " Jul"
+               ,       " Aug"
+               ,       " Sep"
+               ,       " Oct"
+               ,       " Nov"
+               ,       " Dec"][date.getUTCMonth()]
+       elt.replaceChildren(label, " ", caption)
+       if
+       (       date.getUTCFullYear() == today.getFullYear()
+       &&      date.getUTCMonth() == today.getMonth()
+       &&      date.getUTCDate() == today.getDate())
+       {       elt.className= "today"}
+       return elt}
+const renderCalendarIncludingDate= (date) =>
+{      const start= new Date
+       (       Date.UTC
+               (       date.getUTCFullYear()
+               -       !       (       date.getUTCMonth() > 8
+                               ||      date.getUTCMonth() == 8 && date.getUTCDate() >= 22)
+               ,       8
+               ,       22))
+       const dayInYear= Math.floor
+       (       (       Date.UTC
+                       (       date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())
+               -       start)
+       /       day)
+       const month= Math.floor(dayInYear / 40) + 1
+       const view= template.content.cloneNode(true)
+       const year= start.getUTCFullYear() - 1999
+       if (month == 10)
+       { const title= document.createElement("i")
+               title.textContent= "Fetes"
+               view.querySelector("h2").replaceChildren(title, ` ${year}`)}
+       else
+       {       const tide= document.createElement("i")
+               tide.textContent= month == 5 ? "·en·tide" : "·tide"
+               view.querySelector("h2").replaceChildren
+               (       [       "Lake"
+                       , "Hallow"
+                       , "Yule"
+                       , "Carnival"
+                       , "Lent"
+                       , "Eastre"
+                       , "Lithe"
+                       , "Lammas"
+                       , "Weod"][month - 1] ?? month
+               ,       tide
+               ,       ` ${year}`)}
+       const calendar= view.querySelector("table")
+       const intercalaryDays= 5
+       +       (       new Date
+                       (       Date.UTC(start.getUTCFullYear() + 1) + Date.UTC(1970, 2, 1))
+                       .       getUTCMonth()
+               ===     1)
+       if (month == 10)
+       {       calendar.tHead.rows[0].replaceChildren
+               (       ...[    ...calendar.tHead.rows[0].cells].slice(0, intercalaryDays))
+               calendar.tBodies[0].rows[0].replaceChildren
+               (       ...new Array(intercalaryDays).fill().map
+                       (       (_, n) => td(start, 10, n + 1)))
+               calendar.tBodies[0].replaceChildren(calendar.tBodies[0].rows[0])}
+       else
+       {       [...calendar.tBodies[0].rows].forEach
+               (       (row, m) => row.replaceChildren
+                       (       ...new Array(8).fill().map
+                               (       (_, n) => td(start, month, m * 8 + n + 1))))}
+       view.querySelector("button:First-Child").addEventListener
+       (       "click"
+       ,       () => renderCalendarIncludingDate
+               (       new Date(+dateForDay(start, month, 1) - 1 * day)))
+       view.querySelector
+       (       "button:Not(:First-Child):Not(:Last-Child)")
+       .       addEventListener
+               (       "click"
+               ,       () => renderCalendarIncludingDate
+                       (       new Date
+                               (       Date.UTC
+                                       (       today.getFullYear(), today.getMonth(), today.getDate()))))
+       view.querySelector("button:Last-Child").addEventListener
+       (       "click"
+       ,       () => renderCalendarIncludingDate
+               (       new Date
+                       (       +dateForDay(start, month, 1)
+                       +       (month == 10 ? intercalaryDays : 40) * day)))
+       widget.replaceChildren(view)}
+renderCalendarIncludingDate
+(      new Date
+       (       Date.UTC(today.getFullYear(), today.getMonth(), today.getDate())))
+]]></script>
+       </aside>
+</article>
This page took 0.025146 seconds and 4 git commands to generate.