core.cljs 3.2 KB

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