git.fiddlerwoaroof.com
src/index.cljs.hl
935cea7f
 (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)
 
             ))))