core.cljs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. (ns microtables-frontend.core
  2. (:require
  3. [reagent.core :as r]))
  4. ; to generate random values
  5. ;for(let i = 0, s = new Set(); i < 10; i++){ let r = Math.floor(Math.random() * 15)+1, c = a[Math.floor(Math.random() * a.length)], k = `${c}${r}`; if(s.has(k)){ i--; continue; } s.add(k); v.push(`{:row ${r} :col "${c}" :value "${Math.floor(Math.random() * 10000)}"}`); }
  6. (def sample-data [{:row 1 :col "A" :value "59"}
  7. {:row 5 :col "C" :value "269"}
  8. {:row 4 :col "B" :value "7893"}
  9. {:row 2 :col "F" :value "8650"}
  10. {:row 6 :col "D" :value "4065"}
  11. {:row 7 :col "F" :value "5316"}
  12. {:row 1 :col "A" :value "4910"}
  13. {:row 12 :col "A" :value "2405"}
  14. {:row 5 :col "B" :value "7863"}
  15. {:row 9 :col "E" :value "3144"}
  16. {:row 10 :col "D" :value "8272"}
  17. {:row 2 :col "F" :value "3013"}
  18. {:row 11 :col "D" :value "2495"}
  19. {:row 15 :col "E" :value "8968"}])
  20. (def data-atom (r/atom sample-data))
  21. (defn highest [dir data] (apply max (map dir data)))
  22. ; COLUMN NAMES
  23. (defn upgrade-letter-code [s]
  24. (let [l (last s)]
  25. (cond
  26. (empty? s) [65]
  27. (= l 90) (conj (upgrade-letter-code (subvec s 0 (dec (count s)))) 65)
  28. :else (conj (subvec s 0 (dec (count s))) (inc l)))))
  29. (defn next-letter [lc]
  30. (apply str (map char (upgrade-letter-code (mapv #(.charCodeAt % 0) lc)))))
  31. (def col-letters (iterate next-letter "A"))
  32. ; CHANGE VALUE FUNCTIONS
  33. (defn update-value [c r datum value]
  34. (if (nil? datum)
  35. (swap! data-atom conj {:row r :col c :value value})
  36. (swap! data-atom (fn [d] (map #(if (and (= r (:row %)) (= c (:col %))) (assoc % :value value) %) d)))))
  37. ;; -------------------------
  38. ;; Views
  39. (defn cell [c r data]
  40. (let [datum (some #(if (and (= c (:col %)) (= r (:row %))) %) data)]
  41. ^{:key (str c r)} [:td [:input {:value (or (:value datum) "")
  42. :on-change #(update-value c r datum (.. % -target -value))
  43. :on-blur (fn [e] (println (str "blur! " c r)))
  44. :on-focus (fn [e] (println (str "focus! " c r)))}]]
  45. )
  46. )
  47. (defn row [r cols data]
  48. ^{:key (str "row-" r)} [:tr
  49. (cons
  50. ^{:key (str "row-head-" r)} [:th (str r)]
  51. (map #(cell % r data) cols))])
  52. (defn header-row [cols]
  53. ^{:key "header"} [:tr
  54. (cons
  55. ^{:key "corner"} [:th]
  56. (map (fn [c] ^{:key (str "col-head-" c)} [:th c]) cols))])
  57. (defn sheet [data]
  58. [:table [:tbody
  59. (let [maxrow (highest :row data)
  60. cols (take-while (partial not= (next-letter (highest :col data))) col-letters)]
  61. (cons
  62. (header-row cols)
  63. (map #(row % cols data) (range 1 (inc maxrow)))))
  64. ]])
  65. (defn app []
  66. [:div
  67. [:h3 "Microtables"]
  68. [sheet @data-atom]])
  69. ;; -------------------------
  70. ;; Initialize app
  71. (defn mount-root []
  72. (r/render [app] (.getElementById js/document "app")))
  73. (defn init! []
  74. (mount-root))