git.fiddlerwoaroof.com
Raw Blame History
(page "index.html"
  (:require [cuerdas.core :as str]
            [hoplon.svg :as svg]
            [clojure.pprint :refer [cl-format]]))

(defc state
  {:elapsed-time 0
   :total-time 300
   :date-range [1776 2076]
   :selected-date 1926
   :topics ["American History" "European History"]})

(defn fraction-to-date [fraction start-date end-date]
  (.floor js/Math
          (+ start-date
             (* fraction
                (- end-date
                   start-date)))))


(defc= start-date (get-in state [:date-range 0]))
(defc= end-date (get-in state [:date-range 1]))
(defc= date-range (- end-date start-date))

(defc hovering nil)
(defc hovered-fraction 0)
(defc= hovered-date
  (fraction-to-date hovered-fraction start-date end-date))
(defc= hovered-date-as-fraction
  (/ (- hovered-date start-date)
     date-range))

(defc= selected-date
  (:selected-date state)
  (partial swap! state assoc-in [:selected-date]))

(defc= selected-fraction (/ (- selected-date
                               start-date)
                            date-range))

(defc= topics
  (:topics state))

(defc= elapsed-time
  (:elapsed-time state)
  (partial swap! state assoc-in [:elapsed-time]))

;;; Update total-time with the _difference_ between current and desired;
(defc= total-time
  (:total-time state)
  (partial swap! state update-in [:total-time] +))

(defc= remaining-time
  (- total-time elapsed-time))

(defc= time-percentage
  (* 100 (/ elapsed-time total-time)))

(defn num-to-time [num]
  (cl-format nil "~2d:~2,'0d" (quot num 60) (mod num 60)))

(defelem time-display [_ _ _]
  (div (div :class "remaining-time" :style "display: inline-block; margin: 0 1em;"
            (cell= (str "Remaining Time: " (num-to-time remaining-time))))
       (div :class "elapsed-time" :style "display: inline-block; margin: 0 1em;"
            (cell= (str "Time Spent:" (num-to-time elapsed-time))))))

(defelem progress-bar [_ _ _]
  (div {:style (cell= (str "background: hsl(" (- 117 (* 115 (/ time-percentage 100))) ", 75%, 50%); "
                           "height: 0.2em; position: fixed;top:0;left:0;width: "
                           (.floor js/Math (+ 1 (/ (* 99 time-percentage) 100))) "vw;"))}))

(defmethod do! :viewBox
    [elem _ value]
    (if (= false value)
        (.removeAttribute elem "viewBox")
        (.setAttribute elem "viewBox" value)))

(defmethod do! :preserveAspectRatio
    [elem _ value]
    (if (= false value)
        (.removeAttribute elem "preserveAspectRatio")
        (.setAttribute elem "preserveAspectRatio" value)))

(definterval elapsed-update-interval-id 1000
  (swap! elapsed-time inc))

(cell= (print "The state is:" state))

(html
 (head
  (link :href "app.css" :rel "stylesheet")
  (style "#line { width: 100%; display: block;}"))
 
 (body
  (progress-bar)
  (div :id "container"
       (h1 "You're bad at history")
       (time-display)
       (h2 "When did World War 1 start?")
       (div :class "timeline"
            :style "position: relative;"
            (svg/svg :id "line" :height "20"
                     :click #(this-as this
                               (let* [bbox-width (.-width (.getBBox this))
                                      bbox-left (.-x (.getBBox this))
                                      click-x (.-offsetX %)]
                                 (reset! selected-date
                                         (fraction-to-date
                                          (/ (- click-x bbox-left)
                                             bbox-width)
                                          @start-date
                                          @end-date))))
                     :mousemove #(this-as this
                                   (reset! hovering true)
                                   (let* [bbox-width (.-width (.getBBox this))
                                          bbox-left (.-x (.getBBox this))
                                          click-x (.-offsetX %)]
                                     (reset! hovered-fraction
                                             (/ (- click-x bbox-left)
                                                bbox-width))))
                     (svg/line :x1 "0" :y1 "12" :x2 "100%" :y2 "12" :stroke "blue")
                     (when-tpl hovering
                       (let [hovered-percentage (cell= (cl-format nil "~d%" (* 100 hovered-date-as-fraction)))]
                         (svg/g (svg/circle :id "date-cursor"
                                            {:cx hovered-percentage}
                                            :cy "12" :r "10" :fill "transparent" :stroke-width 2 :stroke "red")
                                (svg/text :id "cursor-text" {:x hovered-percentage} :y "32" :dx "-0.75em"
                                          hovered-date ))))
                     (svg/circle :id "date-sel" {:cx (cell= (str (* 100 selected-fraction) "%"))}
                                 :cy "12" :r "9" :fill "#88f")
                     (svg/text :id "cursor-text" {:x (cell= (cl-format nil "~d%" (* 100 selected-fraction)))} :y "32" :dx "-0.75em"
                                          selected-date))
            
            (div :style "position: absolute; display:inline-block; margin-top: 1em;left: 0%" 1776)
            (div :style "position: absolute; display:inline-block; margin-top: 1em; left: 33%" 1876)
            (div :style "position: absolute; display:inline-block; margin-top: 1em; right: 33%" 1976)
            (div :style "position: absolute; display:inline-block; margin-top: 1em; right: 0%" 2076)

            ))))